gmyth-stream/server/plugins/media/gstreamer.py
branchtrunk
changeset 525 d616e308f6b6
parent 484 27e83a8f68d7
child 534 cb1c3e2988b9
     1.1 --- a/gmyth-stream/server/plugins/media/gstreamer.py	Tue Apr 03 16:42:04 2007 +0100
     1.2 +++ b/gmyth-stream/server/plugins/media/gstreamer.py	Wed Apr 11 19:34:21 2007 +0100
     1.3 @@ -1,82 +1,105 @@
     1.4 +#vim:ts=4:sw=4:et
     1.5  import pygst
     1.6  pygst.require("0.10")
     1.7  import gst
     1.8  import gobject
     1.9  import socket
    1.10 +from threading import Thread
    1.11  
    1.12  class Media:
    1.13 +	class StreamListener(Thread):
    1.14 +		def __init__ (self, stream_data):
    1.15 +			Thread.__init__(self)
    1.16 +			self.stream = stream_data
    1.17 +			print "Thread Created"
    1.18 +
    1.19 +		def run (self):
    1.20 +			#Create socket
    1.21 +			print "Waiting connection"
    1.22 +			self.stream.Socket.listen(1)
    1.23 +			self.stream.Connection, self.stream.Addr = self.stream.Socket.accept ()
    1.24 +			print "Connection requested"
    1.25 +			self.stream.Sink.set_property ("fd", self.stream.Connection.fileno())
    1.26 +			self.stream.Pipe.set_state(gst.STATE_PLAYING)
    1.27 +			print "PLAYING"
    1.28 +
    1.29 +
    1.30      class StreamData:
    1.31          stream_count = 0
    1.32 -		
    1.33 -        def __init__ (self, pipe, abin, vbin, sink):
    1.34  
    1.35 -	    self.stream_count += 1
    1.36 -	    self.Id = self.stream_count
    1.37 -	    self.Pipe = pipe
    1.38 -	    self.Abin = abin
    1.39 -	    self.Vbin = vbin
    1.40 -            self.Sink = sink
    1.41 -	    self.Loop = gobject.MainLoop()
    1.42 -	    self.ACaps = ""
    1.43 -	    self.VCaps = ""
    1.44 -	    self.Ready = False
    1.45 -
    1.46 +		def __init__ (self, pipe, abin, vbin, sink):
    1.47 +			self.stream_count += 1
    1.48 +			self.Id = self.stream_count
    1.49 +			self.Pipe = pipe
    1.50 +			self.Abin = abin
    1.51 +			self.Vbin = vbin
    1.52 +			self.Sink = sink
    1.53 +			self.Loop = gobject.MainLoop()
    1.54 +			self.ACaps = ""
    1.55 +			self.VCaps = ""
    1.56 +			self.Ready = False
    1.57 +			self.Socket = None
    1.58 +			self.Connection = None
    1.59 +			self.Addr = None
    1.60  
    1.61      def __init__(self, config):
    1.62          # set gstreamer basic options
    1.63          self.config = config
    1.64 -        self.pipe = None
    1.65          self.streams = []
    1.66 -	self.socket = None
    1.67 -	self.connection = None
    1.68 -	self.addr = None
    1.69 +        self.socket = None
    1.70 +        self.connection = None
    1.71 +        self.addr = None
    1.72 +		self.ready = False
    1.73  
    1.74  
    1.75 -    def setup(self, filename, mux, vcodec, vbitrate,
    1.76 +    def setup(self, uri, mux, vcodec, vbitrate,
    1.77                fps, acodec, abitrate, width, height, port, options):
    1.78  
    1.79          ## Pipelines
    1.80 -        self.pipe = gst.Pipeline ()
    1.81 -        uri = "file://" + filename
    1.82 +        pipe = gst.Pipeline ()
    1.83          print "Opening Uri:" + uri
    1.84          src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
    1.85          if (src is None):
    1.86 +            print "Fail to create src element"
    1.87              return None
    1.88 -        
    1.89 +
    1.90          decode = gst.element_factory_make ("decodebin", "decode")
    1.91          if (decode is None):
    1.92 +            print "Fail to create decodebin"
    1.93              return None
    1.94  
    1.95 -	mux = gst.element_factory_make ("avimux", "mux")
    1.96 +        mux = gst.element_factory_make ("avimux", "mux")
    1.97          if (mux is None):
    1.98 +            print "Fail to create mux"
    1.99              return None
   1.100  
   1.101          sink = gst.element_factory_make ("fdsink", "sink")
   1.102          if (sink is None):
   1.103 +            print "Fail to create fdsink"
   1.104              return None
   1.105  
   1.106 -        #Create socket
   1.107 -        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   1.108 -	self.socket.bind(('', int (port)))
   1.109 -        
   1.110 -        #video encode 
   1.111 +
   1.112 +        #video encode
   1.113          #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
   1.114          vbin = gst.Bin ()
   1.115          vqueue = gst.element_factory_make ("queue", "vqueue")
   1.116          vscale = gst.element_factory_make ("videoscale", "vscale")
   1.117 +        colorspace = gst.element_factory_make ("ffmpegcolorspace", "")
   1.118          vrate = gst.element_factory_make ("videorate", "vrate")
   1.119          vencode = gst.element_factory_make ("ffenc_h263p", "vencode")
   1.120  
   1.121 +
   1.122          if (None in [vbin, vqueue, vscale, vrate, vencode]):
   1.123              print "Fail to create video encode elements."
   1.124              return None
   1.125  
   1.126 +        '''
   1.127          vscale_pad = vscale.get_pad("sink")
   1.128          if (vscale_pad is None):
   1.129              print "Fail to get vscale sink pad."
   1.130              return None
   1.131  
   1.132 -        vscale_caps = gst.caps_from_string ("video/x-raw-yuv, width=%s, height=%s" % (width, height))
   1.133 +        vscale_caps = gst.caps_from_string ("video/x-raw-yuv,width=%d,height=(int)%d" % (int(width), int(height)))
   1.134          if (vscale_caps is None):
   1.135              print "Fail to create video caps"
   1.136              return None
   1.137 @@ -84,21 +107,32 @@
   1.138          if (not vscale_pad.set_caps (vscale_caps)):
   1.139              print "Fail to set video output caps"
   1.140              return None
   1.141 -        
   1.142 -        vbin.add (vqueue, vscale, vrate, vencode)
   1.143 -        if (not gst.element_link_many (vqueue,  vscale, vrate, vencode)):
   1.144 +        '''
   1.145 +
   1.146 +        vbin.add (vqueue, vscale, colorspace, vrate, vencode)
   1.147 +        if (not vqueue.link (vscale)):
   1.148              print "Fail to link video elements"
   1.149              return None
   1.150 -        
   1.151 +
   1.152 +        if (not vscale.link (colorspace, \
   1.153 +            gst.caps_from_string ("video/x-raw-yuv,width=%d,height=(int)%d" % (int(width), int(height))))):
   1.154 +            print "Fail to link video elements"
   1.155 +            return None
   1.156 +
   1.157 +        if (not gst.element_link_many (colorspace, vrate, vencode)):
   1.158 +            print "Fail to link video elements"
   1.159 +            return None
   1.160 +
   1.161          vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
   1.162 -	vbin.add_pad (gst.GhostPad ("src", vencode.get_pad ("src")))
   1.163 +        vbin.add_pad (gst.GhostPad ("src", vencode.get_pad ("src")))
   1.164  
   1.165          #audio encode
   1.166          #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay !  udpsink name=upd_audio host=224.0.0.1 port=5002
   1.167          abin = gst.Bin ()
   1.168          aqueue = gst.element_factory_make ("queue", "vqueue")
   1.169          aconvert = gst.element_factory_make ("audioconvert", "aconvert")
   1.170 -        aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
   1.171 +        #aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
   1.172 +        aencode = gst.element_factory_make ("lame", "aencode")
   1.173  
   1.174          if (None in [abin, aqueue, aconvert, aencode]):
   1.175              print "Fail to create video encode elements."
   1.176 @@ -108,81 +142,66 @@
   1.177          if (not gst.element_link_many (aqueue, aconvert, aencode)):
   1.178              print "Fail to link video elements"
   1.179              return None
   1.180 -        
   1.181 +
   1.182          abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
   1.183          abin.add_pad (gst.GhostPad ("src", aencode.get_pad ("src")))
   1.184  
   1.185          #Finish Pipeline
   1.186  
   1.187 -	self.pipe.add (src, decode, abin, vbin, mux, sink)
   1.188 -	gst.element_link_many (src, decode)
   1.189 +        pipe.add (src, decode, abin, vbin, mux, sink)
   1.190 +        gst.element_link_many (src, decode)
   1.191          gst.element_link_many (mux, sink)
   1.192  
   1.193          #Linking decode with mux
   1.194          mux_audio = mux.get_pad ("audio_0")
   1.195          mux_video = mux.get_pad ("video_0")
   1.196  
   1.197 -	audio_pad = abin.get_pad ("src")
   1.198 +        audio_pad = abin.get_pad ("src")
   1.199          video_pad = vbin.get_pad ("src")
   1.200  
   1.201          if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
   1.202              print "Fail to link audio with mux"
   1.203              return None
   1.204 - 
   1.205 +
   1.206          if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
   1.207              print "Fail to link audio with mux"
   1.208              return None
   1.209  
   1.210 -	stream_data = self.StreamData (self.pipe, abin, vbin, sink)
   1.211 +        stream_data = self.StreamData (pipe, abin, vbin, sink)
   1.212 +        bus = pipe.get_bus()
   1.213 +        bus.add_signal_watch()
   1.214 +        bus.connect ("message", self.__on_bus_message, stream_data)
   1.215  
   1.216 -	bus = self.pipe.get_bus()
   1.217 -	bus.add_signal_watch()
   1.218 -	bus.connect("message", self.__on_bus_message, stream_data)
   1.219 -	
   1.220 -	decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
   1.221 -	decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
   1.222 +        decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
   1.223 +        decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
   1.224  
   1.225 -	
   1.226 -	self.pipe.set_state (gst.STATE_PAUSED)
   1.227 +        pipe.set_state (gst.STATE_PAUSED)
   1.228          print "Running Pipe"
   1.229 -	stream_data.Loop.run ()
   1.230 +        stream_data.Loop.run ()
   1.231          print "End run"
   1.232  
   1.233 -	a_caps = stream_data.ACaps
   1.234 -	v_caps = stream_data.VCaps
   1.235 -	stream_id = stream_data.Id
   1.236 +
   1.237 +		#Create socket
   1.238 +		stream_data.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   1.239 +		print "Bind on port %d" % port
   1.240 +		stream_data.Socket.bind(('', int (port)))
   1.241  
   1.242          self.streams.append (stream_data)
   1.243 +        return True
   1.244  
   1.245 -    def play(self):
   1.246 -
   1.247 -        print "Trying to play pipeline: %s" % self.pipe
   1.248 -        try:
   1.249 -            if (self.pipe):
   1.250 -		print "Waiting for connection"
   1.251 -		self.socket.listen(1)
   1.252 -		print "Connection Requested"
   1.253 -	        #Create socket
   1.254 -		self.connection, self.addr = self.socket.accept ()
   1.255 -
   1.256 -		stream_data = self.streams[0]
   1.257 -		stream_data.Sink.set_property ("fd", self.connection.fileno());
   1.258 -                print "Connected"
   1.259 -
   1.260 -                self.pipe.set_state(gst.STATE_PLAYING)
   1.261 -        except gobject.GError, e:
   1.262 -            print "Error: " + str(e)
   1.263 -
   1.264 +	def play(self):
   1.265 +		stream = self.streams[0]
   1.266 +		current = self.StreamListener(stream)
   1.267 +		current.start ()
   1.268 +		print "Saindo"
   1.269 +		return True
   1.270  
   1.271      def stop(self):
   1.272 +		stream = self.streams[0]
   1.273 +		stream.Pipe.set_state(gst.STATE_NULL)
   1.274 +		stream.Connection.close ()
   1.275 +		return True
   1.276  
   1.277 -        print "Trying to stop pipeline: %s" % self.pipe
   1.278 -        try:
   1.279 -            if (self.pipeline):
   1.280 -                self.connection.close ()
   1.281 -                self.pipeline.set_state(gst.STATE_NULL)
   1.282 -        except gobject.GError, e:
   1.283 -            print "Error: " + str(e)
   1.284  
   1.285      def __on_bus_message (self, bus, message, stream_data):
   1.286  
   1.287 @@ -196,30 +215,30 @@
   1.288                  (newstate == gst.STATE_PAUSED) and \
   1.289                  (pending == gst.STATE_VOID_PENDING) and \
   1.290                  (stream_data.Ready == False)):
   1.291 -                state_changed_status, current_state, pending_state = stream_data.Pipe.get_state () 
   1.292 -		if ((current_state == gst.STATE_PAUSED) and \
   1.293 +                state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
   1.294 +                if ((current_state == gst.STATE_PAUSED) and \
   1.295                      (pending_state == gst.STATE_VOID_PENDING)):
   1.296                      print "Pipe paused"
   1.297                      stream_data.Loop.quit ()
   1.298                      stream_data.Ready = True
   1.299          elif (t == gst.MESSAGE_ERROR):
   1.300              err, debug = message.parse_error()
   1.301 -	    print "Error: %s" % err, debug
   1.302 +            print "Error: %s" % err, debug
   1.303              stream_data.Loop.quit ()
   1.304              stream_data.Ready = False
   1.305  
   1.306          return True
   1.307 - 
   1.308 +
   1.309      def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
   1.310  
   1.311          print "Unknown Type"
   1.312          return None
   1.313  
   1.314      def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
   1.315 -        
   1.316 +
   1.317          caps = pad.get_caps().to_string()
   1.318          print "New pad " + caps
   1.319 -	if (caps.rfind ("audio") != -1):
   1.320 +        if (caps.rfind ("audio") != -1):
   1.321              apad = stream_data.Abin.get_pad ("sink")
   1.322              if (pad.link (apad) != gst.PAD_LINK_OK):
   1.323                  print "Error on link audio pad"
   1.324 @@ -232,4 +251,3 @@
   1.325          else:
   1.326              print "Invalid caps"
   1.327  
   1.328 -