gmyth-stream/server/0.1/plugins/media/gstreamer-rtp.py
author melunko
Tue Apr 24 00:43:20 2007 +0100 (2007-04-24)
branchtrunk
changeset 590 1c421f2531d3
permissions -rw-r--r--
[svn r596] Fixed memory leak when dealocating GMythChannelInfo.
     1 import pygst
     2 pygst.require("0.10")
     3 import gst
     4 import gobject
     5 
     6 class Media:
     7     class StreamData:
     8         stream_count = 0
     9 		
    10         def __init__ (self, pipe, abin, vbin):
    11 
    12 	    self.stream_count += 1
    13 	    self.Id = self.stream_count
    14 	    self.Pipe = pipe
    15 	    self.Abin = abin
    16 	    self.Vbin = vbin
    17 	    self.Loop = gobject.MainLoop()
    18 	    self.ACaps = ""
    19 	    self.VCaps = ""
    20 	    self.Ready = False
    21 
    22 
    23     def __init__(self, config):
    24         # set gstreamer basic options
    25         self.config = config
    26         self.pipe = None
    27         self.streams = []
    28 
    29 
    30     def setup(self, filename, mux, vcodec, vbitrate,
    31               fps, acodec, abitrate, width, height, port, options):
    32 
    33         ## Pipelines
    34         self.pipe = gst.Pipeline ()
    35         uri = "file://" + filename
    36         print "Opening Uri:" + uri
    37         src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
    38         if (src is None):
    39             return None
    40         
    41         decode = gst.element_factory_make ("decodebin", "decode")
    42         if (decode is None):
    43             return None
    44         
    45         
    46         #video encode 
    47         #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
    48         vbin = gst.Bin ()
    49         vqueue = gst.element_factory_make ("queue", "vqueue")
    50         vscale = gst.element_factory_make ("videoscale", "vscale")
    51         vrate = gst.element_factory_make ("videorate", "vrate")
    52         vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
    53         vpay = gst.element_factory_make ("rtpmp4vpay", "vpay")
    54         vsink = gst.element_factory_make ("udpsink", "vsink")
    55 
    56         if (None in [vbin, vqueue, vscale, vrate, vencode, vpay, vsink]):
    57             print "Fail to create video encode elements."
    58             return None
    59 
    60         vscale_pad = vscale.get_pad("sink")
    61         if (vscale_pad is None):
    62             print "Fail to get vscale sink pad."
    63             return None
    64 
    65         vscale_caps = gst.caps_from_string ("video/x-raw-yuv, width=%s, height=%s" % (width, height))
    66         if (vscale_caps is None):
    67             print "Fail to create video caps"
    68             return None
    69 
    70         if (not vscale_pad.set_caps (vscale_caps)):
    71             print "Fail to set video output caps"
    72             return None
    73         
    74         vencode.set_property ("bitrate", 256000)
    75         vencode.set_property ("me-method", 2)
    76         
    77         vsink.set_property ("host", "224.0.0.1")
    78         vsink.set_property ("port", 5000)
    79         
    80         vbin.add (vqueue, vscale, vrate, vencode, vpay, vsink)
    81         if (not gst.element_link_many (vqueue,  vscale, vrate, vencode, vpay, vsink)):
    82             print "Fail to link video elements"
    83             return None
    84         
    85         vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
    86 
    87         #audio encode
    88         #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002
    89         abin = gst.Bin ()
    90         aqueue = gst.element_factory_make ("queue", "vqueue")
    91         aconvert = gst.element_factory_make ("audioconvert", "aconvert")
    92         aencode = gst.element_factory_make ("faac", "aencode")
    93         apay = gst.element_factory_make ("rtpmp4gpay", "apay")
    94         asink = gst.element_factory_make ("udpsink", "asink")
    95 
    96         if (None in [abin, aqueue, aconvert, aencode, apay, asink]):
    97             print "Fail to create video encode elements."
    98             return None
    99 
   100         asink.set_property ("host", "224.0.0.1")
   101         asink.set_property ("port", 5002)
   102         
   103         abin.add (aqueue, aconvert, aencode, apay, asink)
   104         if (not gst.element_link_many (aqueue, aconvert, aencode, apay, asink)):
   105             print "Fail to link video elements"
   106             return None
   107         
   108         abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
   109 
   110 	self.pipe.add (src, decode, abin, vbin)
   111 	gst.element_link_many (src, decode)
   112 
   113 	stream_data = self.StreamData (self.pipe, abin, vbin)
   114 
   115 	bus = self.pipe.get_bus()
   116 	bus.add_signal_watch()
   117 	bus.connect("message", self.__on_bus_message, stream_data)
   118 	
   119 	decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
   120 	decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
   121 
   122 	
   123 	self.pipe.set_state (gst.STATE_PAUSED)
   124         print "Running Pipe"
   125 	stream_data.Loop.run ()
   126         print "End run"
   127 
   128 	a_caps = stream_data.ACaps
   129 	v_caps = stream_data.VCaps
   130 	stream_id = stream_data.Id
   131 
   132         self.streams.append (stream_data)
   133 
   134     def play(self):
   135 
   136         print "Trying to play pipeline: %s" % self.pipe
   137         try:
   138             if (self.pipe):
   139                 self.pipe.set_state(gst.STATE_PLAYING)
   140         except gobject.GError, e:
   141             print "Error: " + str(e)
   142 
   143 
   144     def stop(self):
   145 
   146         print "Trying to stop pipeline: %s" % self.pipe
   147         try:
   148             if (self.pipeline):
   149                 self.pipeline.set_state(gst.STATE_NULL)
   150         except gobject.GError, e:
   151             print "Error: " + str(e)
   152 
   153     def __on_bus_message (self, bus, message, stream_data):
   154 
   155         t = message.type
   156         if (t == gst.MESSAGE_STATE_CHANGED):
   157             oldstate = -1
   158             newstate = -1
   159             pending = -1
   160             oldstate, newstate, pending = message.parse_state_changed ()
   161             if ((oldstate == gst.STATE_READY) and \
   162                 (newstate == gst.STATE_PAUSED) and \
   163                 (pending == gst.STATE_VOID_PENDING) and \
   164                 (stream_data.Ready == False)):
   165                 state_changed_status, current_state, pending_state = stream_data.Pipe.get_state () 
   166 		if ((current_state == gst.STATE_PAUSED) and \
   167                     (pending_state == gst.STATE_VOID_PENDING)):
   168                     print "Pipe paused"
   169                     self.__fill_sink_pads (stream_data)
   170                     stream_data.Loop.quit ()
   171                     stream_data.Ready = True
   172         elif (t == gst.MESSAGE_ERROR):
   173             err, debug = message.parse_error()
   174 	    print "Error: %s" % err, debug
   175             stream_data.Loop.quit ()
   176             stream_data.Ready = False
   177 
   178         return True
   179  
   180 
   181     def __fill_sink_pads (self, stream_data):
   182         
   183         asink = stream_data.Abin.get_by_name ("asink")
   184         vsink = stream_data.Vbin.get_by_name ("vsink")
   185 
   186         asink_pad = asink.get_pad ("sink")
   187         stream_data.ACaps = asink_pad.get_negotiated_caps().to_string()
   188         print "ACAPS " + stream_data.ACaps
   189 
   190         vsink_pad = vsink.get_pad ("sink")
   191         stream_data.VCaps = vsink_pad.get_negotiated_caps().to_string()
   192         print "ACAPS " + stream_data.VCaps
   193  
   194  
   195 
   196     def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
   197 
   198         print "Unknown Type"
   199         return None
   200 
   201     def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
   202         
   203         caps = pad.get_caps().to_string()
   204         print "New pad " + caps
   205 	if (caps.rfind ("audio") != -1):
   206             apad = stream_data.Abin.get_pad ("sink")
   207             if (pad.link (apad) != gst.PAD_LINK_OK):
   208                 print "Error on link audio pad"
   209                 return None
   210         elif (caps.rfind ("video") != -1):
   211             vpad = stream_data.Vbin.get_pad ("sink")
   212             if (pad.link (vpad) != gst.PAD_LINK_OK):
   213                 print "Error on link video pad"
   214                 return None
   215         else:
   216             print "Invalid caps"
   217 
   218