gmyth-stream/server/plugins/media/gstreamer.py
author rosfran
Mon Apr 16 16:02:22 2007 +0100 (2007-04-16)
branchtrunk
changeset 553 424babd6b788
parent 534 cb1c3e2988b9
permissions -rw-r--r--
[svn r558] Sets the mythtv source "location" property, with the new pathname.
     1 #vim:ts=4:sw=4:et
     2 import pygst
     3 pygst.require("0.10")
     4 import gst
     5 import gobject
     6 import socket
     7 import time
     8 from threading import Thread
     9 
    10 class Media:
    11     class StreamListener(Thread):
    12         def __init__ (self, stream_data):
    13             Thread.__init__(self)
    14             self.stream = stream_data
    15             print "Thread Created"
    16 
    17         def run (self):
    18             #Create socket
    19             print "Waiting connection"
    20             self.stream.Socket.listen(1)
    21             self.stream.Connection, self.stream.Addr = self.stream.Socket.accept ()
    22             print "Connection requested"
    23             self.stream.Sink.set_property ("fd", self.stream.Connection.fileno())
    24             self.stream.Pipe.set_state(gst.STATE_PLAYING)
    25             print "PLAYING"
    26 
    27 
    28     class StreamData:
    29         stream_count = 0
    30 
    31         def __init__ (self, pipe, abin, vbin, sink):
    32             self.stream_count += 1
    33             self.Id = self.stream_count
    34             self.Pipe = pipe
    35             self.Abin = abin
    36             self.Vbin = vbin
    37             self.Sink = sink
    38             self.Loop = gobject.MainLoop()
    39             self.ACaps = ""
    40             self.VCaps = ""
    41             self.Ready = False
    42             self.Socket = None
    43             self.Connection = None
    44             self.Addr = None
    45 
    46     def __init__(self, config):
    47         # set gstreamer basic options
    48         self.config = config
    49         self.streams = []
    50         self.socket = None
    51         self.connection = None
    52         self.addr = None
    53         self.ready = False
    54 		self.current = None
    55 
    56 
    57     def setup(self, uri, mux, vcodec, vbitrate,
    58               fps, acodec, abitrate, width, height, port, options):
    59 
    60         ## Pipelines
    61         pipe = gst.Pipeline ()
    62         print "Opening Uri:" + uri
    63         src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
    64         #src = gst.element_factory_make ("gnomevfssrc", "src")
    65         src.set_property ("location", uri)
    66         if (src is None):
    67             print "Fail to create src element"
    68             return None
    69 
    70         print ("Create source")
    71         decode = gst.element_factory_make ("decodebin", "decode")
    72         if (decode is None):
    73             print "Fail to create decodebin"
    74             return None
    75 
    76         print ("Create source")
    77         mux = gst.element_factory_make ("avimux", "mux")
    78         if (mux is None):
    79             print "Fail to create mux"
    80             return None
    81 
    82         sink = gst.element_factory_make ("fdsink", "sink")
    83         if (sink is None):
    84             print "Fail to create fdsink"
    85             return None
    86 
    87         print ("Create source")
    88 
    89         #video encode
    90         #queue ! videoscale ! video/x-raw-yuv,width=240,height=144 ! videorate ! ffenc_h263p bitrate=256000 me-method=2 ! rtph263ppay ! udpsink  host=224.0.0.1 port=5000
    91         vbin = gst.Bin ()
    92         vqueue = gst.element_factory_make ("queue", "vqueue")
    93         colorspace = gst.element_factory_make ("ffmpegcolorspace", "")
    94         vrate = gst.element_factory_make ("videorate", "vrate")
    95         vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
    96         #vencode = gst.element_factory_make ("ffenc_msmpeg4v1", "vencode")
    97         vqueue_src = gst.element_factory_make ("queue", "vqueue_src")
    98 
    99         #if (int(vbitrate) > 0):
   100         vencode.set_property ("bitrate", 200)
   101         #vencode.set_property ("quant-type", 1)
   102         vencode.set_property ("pass", 2)
   103         vencode.set_property ("quantizer", 5)
   104         #vencode.set_property ("me-method", 1)
   105 
   106 
   107         if (None in [vbin, vqueue, vrate, vencode, vqueue_src]):
   108             print "Fail to create video encode elements."
   109             return None
   110 
   111         vbin.add (vqueue)
   112         if ((int(width) > 0) and (int(height) > 0)):
   113             print ("formating output to %d / %d" % (int(width), int(height)))
   114   
   115             vscale = gst.element_factory_make ("ffvideoscale", "vscale")
   116 
   117             vbin.add (vscale);
   118             if (not vqueue.link (vscale)):
   119                 print "Fail to link video elements"
   120                 return None
   121 
   122             vbin.add (colorspace)
   123 
   124             if (not vscale.link (colorspace, \
   125                 gst.caps_from_string ("video/x-raw-yuv,width=(int)%d,height=(int)%d" % (int(width), int(height))))):
   126                 print "Fail to link video elements"
   127                 return None
   128         else:                
   129             vbin.add (colorspace)
   130             vqueue.link (colorspace)
   131         
   132         vbin.add (vrate, vencode, vqueue_src)
   133         if (not colorspace.link (vrate)):
   134             print "Fail to colorspace with vrate"
   135             return None
   136 
   137 
   138         if (not vrate.link (vencode, \
   139             gst.caps_from_string ("video/x-raw-yuv,framerate=(fraction)10/1"))):
   140             print "Fail to link vrate element"
   141             return None
   142 
   143         if (not vencode.link (vqueue_src)):
   144             print "Fail to link video encode with queue"
   145             return None
   146 
   147         vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
   148         vbin.add_pad (gst.GhostPad ("src", vqueue_src.get_pad ("src")))
   149 
   150         #audio encode
   151         #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002
   152         abin = gst.Bin ()
   153         aqueue = gst.element_factory_make ("queue", "aqueue")
   154         aconvert = gst.element_factory_make ("audioconvert", "aconvert")
   155         arate = gst.element_factory_make ("audioresample", "arate")
   156         #aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
   157         aencode = gst.element_factory_make ("queue", "aencode")
   158         #aencode = gst.element_factory_make ("lame", "aencode")
   159         #aencode = gst.element_factory_make ("ffenc_mp2", "aencode")
   160         aqueue_src = gst.element_factory_make ("queue", "aqueue_src")
   161 
   162         if (None in [abin, aqueue, arate, aencode, aqueue_src]):
   163             print "Fail to create video encode elements."
   164             return None
   165 
   166         abin.add (aqueue, aconvert, arate, aencode, aqueue_src)
   167         if (not gst.element_link_many (aqueue,  aconvert, arate, aencode, aqueue_src)):
   168             print "Fail to link video elements"
   169             return None
   170 
   171         abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
   172         abin.add_pad (gst.GhostPad ("src", aqueue_src.get_pad ("src")))
   173 
   174         #Finish Pipeline
   175         pipe.add (src, decode, abin, vbin, mux, sink)
   176         gst.element_link_many (src, decode)
   177         gst.element_link_many (mux, sink)
   178 
   179         #Linking decode with mux
   180         mux_audio = mux.get_pad ("audio_0")
   181         mux_video = mux.get_pad ("video_0")
   182 
   183         audio_pad = abin.get_pad ("src")
   184         video_pad = vbin.get_pad ("src")
   185 
   186         if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
   187             print "Fail to link audio with mux"
   188             return None
   189 
   190         if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
   191             print "Fail to link audio with mux"
   192             return None
   193 
   194         stream_data = self.StreamData (pipe, abin, vbin, sink)
   195         bus = pipe.get_bus()
   196         bus.add_signal_watch()
   197         bus.connect ("message", self.__on_bus_message, stream_data)
   198 
   199         decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
   200         decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
   201 
   202         print ("Create source")
   203         pipe.set_state (gst.STATE_PAUSED)
   204         print "Running Pipe"
   205         stream_data.Loop.run ()
   206         print "End run"
   207 
   208 
   209         #Create socket
   210         stream_data.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   211         print "Bind on port %d" % port
   212         stream_data.Socket.bind(('', int (port)))
   213         self.streams.append (stream_data)
   214         return (True, "")
   215 
   216     def play(self):
   217         print "Play"
   218         stream = self.streams[0]
   219         self.current = self.StreamListener(stream)
   220         self.current.start ()
   221         time.sleep (1)
   222         return (True, "")
   223 
   224     def stop(self):
   225 		self.current.join ()
   226         self.current = None
   227         stream = self.streams[0]
   228         stream.Pipe.set_state(gst.STATE_NULL)
   229         del (stream.Pipe)
   230         stream.Pipe = None
   231         stream.Abin = None
   232         stream.Vbin = None
   233         stream.Sink = None
   234 		if (stream.Connection != None):
   235 	        stream.Connection.close ()
   236 
   237         self.streams = []
   238         time.sleep (5)             
   239         return (True, "")
   240 
   241 
   242     def __on_bus_message (self, bus, message, stream_data):
   243 
   244         t = message.type
   245         if (t == gst.MESSAGE_STATE_CHANGED):
   246             oldstate = -1
   247             newstate = -1
   248             pending = -1
   249             oldstate, newstate, pending = message.parse_state_changed ()
   250             if ((oldstate == gst.STATE_READY) and \
   251                 (newstate == gst.STATE_PAUSED) and \
   252                 (pending == gst.STATE_VOID_PENDING) and \
   253                 (stream_data.Ready == False)):
   254                 state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
   255                 if ((current_state == gst.STATE_PAUSED) and \
   256                     (pending_state == gst.STATE_VOID_PENDING)):
   257                     print "Pipe paused"
   258                     stream_data.Loop.quit ()
   259                     stream_data.Ready = True
   260         elif (t == gst.MESSAGE_ERROR):
   261             err, debug = message.parse_error()
   262             print "Error: %s" % err, debug
   263             stream_data.Loop.quit ()
   264             stream_data.Ready = False
   265 
   266         return True
   267 
   268     def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
   269 
   270         print "Unknown Type"
   271         return None
   272 
   273     def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
   274 
   275         caps = pad.get_caps().to_string()
   276         print "New pad " + caps
   277         if (caps.rfind ("audio") != -1):
   278             apad = stream_data.Abin.get_pad ("sink")
   279             if (pad.link (apad) != gst.PAD_LINK_OK):
   280                 print "Error on link audio pad"
   281                 return None
   282         elif (caps.rfind ("video") != -1):
   283             vpad = stream_data.Vbin.get_pad ("sink")
   284             if (pad.link (vpad) != gst.PAD_LINK_OK):
   285                 print "Error on link video pad"
   286                 return None
   287         else:
   288             print "Invalid caps"
   289         print "Linked"            
   290