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