gmyth-stream/server/plugins/media/gstreamer.py
author rosfran
Thu Apr 12 14:58:13 2007 +0100 (2007-04-12)
branchtrunk
changeset 530 ad51640dd2cd
parent 484 27e83a8f68d7
child 534 cb1c3e2988b9
permissions -rw-r--r--
[svn r535] Fixed to the older GMythFileTransfer revision (no GObject inheritance).
     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 
   189         self.streams.append (stream_data)
   190         return True
   191 
   192 	def play(self):
   193 		stream = self.streams[0]
   194 		current = self.StreamListener(stream)
   195 		current.start ()
   196 		print "Saindo"
   197 		return True
   198 
   199     def stop(self):
   200 		stream = self.streams[0]
   201 		stream.Pipe.set_state(gst.STATE_NULL)
   202 		stream.Connection.close ()
   203 		return True
   204 
   205 
   206     def __on_bus_message (self, bus, message, stream_data):
   207 
   208         t = message.type
   209         if (t == gst.MESSAGE_STATE_CHANGED):
   210             oldstate = -1
   211             newstate = -1
   212             pending = -1
   213             oldstate, newstate, pending = message.parse_state_changed ()
   214             if ((oldstate == gst.STATE_READY) and \
   215                 (newstate == gst.STATE_PAUSED) and \
   216                 (pending == gst.STATE_VOID_PENDING) and \
   217                 (stream_data.Ready == False)):
   218                 state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
   219                 if ((current_state == gst.STATE_PAUSED) and \
   220                     (pending_state == gst.STATE_VOID_PENDING)):
   221                     print "Pipe paused"
   222                     stream_data.Loop.quit ()
   223                     stream_data.Ready = True
   224         elif (t == gst.MESSAGE_ERROR):
   225             err, debug = message.parse_error()
   226             print "Error: %s" % err, debug
   227             stream_data.Loop.quit ()
   228             stream_data.Ready = False
   229 
   230         return True
   231 
   232     def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
   233 
   234         print "Unknown Type"
   235         return None
   236 
   237     def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
   238 
   239         caps = pad.get_caps().to_string()
   240         print "New pad " + caps
   241         if (caps.rfind ("audio") != -1):
   242             apad = stream_data.Abin.get_pad ("sink")
   243             if (pad.link (apad) != gst.PAD_LINK_OK):
   244                 print "Error on link audio pad"
   245                 return None
   246         elif (caps.rfind ("video") != -1):
   247             vpad = stream_data.Vbin.get_pad ("sink")
   248             if (pad.link (vpad) != gst.PAD_LINK_OK):
   249                 print "Error on link video pad"
   250                 return None
   251         else:
   252             print "Invalid caps"
   253