1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/server/0.1/plugins/media/gstreamer.py Thu May 17 14:07:27 2007 +0100
1.3 @@ -0,0 +1,290 @@
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 +import time
1.11 +from threading import Thread
1.12 +
1.13 +class Media:
1.14 + class StreamListener(Thread):
1.15 + def __init__ (self, stream_data):
1.16 + Thread.__init__(self)
1.17 + self.stream = stream_data
1.18 + print "Thread Created"
1.19 +
1.20 + def run (self):
1.21 + #Create socket
1.22 + print "Waiting connection"
1.23 + self.stream.Socket.listen(1)
1.24 + self.stream.Connection, self.stream.Addr = self.stream.Socket.accept ()
1.25 + print "Connection requested"
1.26 + self.stream.Sink.set_property ("fd", self.stream.Connection.fileno())
1.27 + self.stream.Pipe.set_state(gst.STATE_PLAYING)
1.28 + print "PLAYING"
1.29 +
1.30 +
1.31 + class StreamData:
1.32 + stream_count = 0
1.33 +
1.34 + def __init__ (self, pipe, abin, vbin, sink):
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 + self.Socket = None
1.46 + self.Connection = None
1.47 + self.Addr = None
1.48 +
1.49 + def __init__(self, config):
1.50 + # set gstreamer basic options
1.51 + self.config = config
1.52 + self.streams = []
1.53 + self.socket = None
1.54 + self.connection = None
1.55 + self.addr = None
1.56 + self.ready = False
1.57 + self.current = None
1.58 +
1.59 +
1.60 + def setup(self, uri, mux, vcodec, vbitrate,
1.61 + fps, acodec, abitrate, width, height, port, options):
1.62 +
1.63 + ## Pipelines
1.64 + pipe = gst.Pipeline ()
1.65 + print "Opening Uri:" + uri
1.66 + src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
1.67 + #src = gst.element_factory_make ("gnomevfssrc", "src")
1.68 + src.set_property ("location", uri)
1.69 + if (src is None):
1.70 + print "Fail to create src element"
1.71 + return None
1.72 +
1.73 + print ("Create source")
1.74 + decode = gst.element_factory_make ("decodebin", "decode")
1.75 + if (decode is None):
1.76 + print "Fail to create decodebin"
1.77 + return None
1.78 +
1.79 + print ("Create source")
1.80 + mux = gst.element_factory_make ("avimux", "mux")
1.81 + if (mux is None):
1.82 + print "Fail to create mux"
1.83 + return None
1.84 +
1.85 + sink = gst.element_factory_make ("fdsink", "sink")
1.86 + if (sink is None):
1.87 + print "Fail to create fdsink"
1.88 + return None
1.89 +
1.90 + print ("Create source")
1.91 +
1.92 + #video encode
1.93 + #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.94 + vbin = gst.Bin ()
1.95 + vqueue = gst.element_factory_make ("queue", "vqueue")
1.96 + colorspace = gst.element_factory_make ("ffmpegcolorspace", "")
1.97 + vrate = gst.element_factory_make ("videorate", "vrate")
1.98 + vencode = gst.element_factory_make ("ffenc_mpeg4", "vencode")
1.99 + #vencode = gst.element_factory_make ("ffenc_msmpeg4v1", "vencode")
1.100 + vqueue_src = gst.element_factory_make ("queue", "vqueue_src")
1.101 +
1.102 + #if (int(vbitrate) > 0):
1.103 + vencode.set_property ("bitrate", 200)
1.104 + #vencode.set_property ("quant-type", 1)
1.105 + vencode.set_property ("pass", 2)
1.106 + vencode.set_property ("quantizer", 5)
1.107 + #vencode.set_property ("me-method", 1)
1.108 +
1.109 +
1.110 + if (None in [vbin, vqueue, vrate, vencode, vqueue_src]):
1.111 + print "Fail to create video encode elements."
1.112 + return None
1.113 +
1.114 + vbin.add (vqueue)
1.115 + if ((int(width) > 0) and (int(height) > 0)):
1.116 + print ("formating output to %d / %d" % (int(width), int(height)))
1.117 +
1.118 + vscale = gst.element_factory_make ("ffvideoscale", "vscale")
1.119 +
1.120 + vbin.add (vscale);
1.121 + if (not vqueue.link (vscale)):
1.122 + print "Fail to link video elements"
1.123 + return None
1.124 +
1.125 + vbin.add (colorspace)
1.126 +
1.127 + if (not vscale.link (colorspace, \
1.128 + gst.caps_from_string ("video/x-raw-yuv,width=(int)%d,height=(int)%d" % (int(width), int(height))))):
1.129 + print "Fail to link video elements"
1.130 + return None
1.131 + else:
1.132 + vbin.add (colorspace)
1.133 + vqueue.link (colorspace)
1.134 +
1.135 + vbin.add (vrate, vencode, vqueue_src)
1.136 + if (not colorspace.link (vrate)):
1.137 + print "Fail to colorspace with vrate"
1.138 + return None
1.139 +
1.140 +
1.141 + if (not vrate.link (vencode, \
1.142 + gst.caps_from_string ("video/x-raw-yuv,framerate=(fraction)10/1"))):
1.143 + print "Fail to link vrate element"
1.144 + return None
1.145 +
1.146 + if (not vencode.link (vqueue_src)):
1.147 + print "Fail to link video encode with queue"
1.148 + return None
1.149 +
1.150 + vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
1.151 + vbin.add_pad (gst.GhostPad ("src", vqueue_src.get_pad ("src")))
1.152 +
1.153 + #audio encode
1.154 + #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
1.155 + abin = gst.Bin ()
1.156 + aqueue = gst.element_factory_make ("queue", "aqueue")
1.157 + aconvert = gst.element_factory_make ("audioconvert", "aconvert")
1.158 + arate = gst.element_factory_make ("audioresample", "arate")
1.159 + #aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
1.160 + aencode = gst.element_factory_make ("queue", "aencode")
1.161 + #aencode = gst.element_factory_make ("lame", "aencode")
1.162 + #aencode = gst.element_factory_make ("ffenc_mp2", "aencode")
1.163 + aqueue_src = gst.element_factory_make ("queue", "aqueue_src")
1.164 +
1.165 + if (None in [abin, aqueue, arate, aencode, aqueue_src]):
1.166 + print "Fail to create video encode elements."
1.167 + return None
1.168 +
1.169 + abin.add (aqueue, aconvert, arate, aencode, aqueue_src)
1.170 + if (not gst.element_link_many (aqueue, aconvert, arate, aencode, aqueue_src)):
1.171 + print "Fail to link video elements"
1.172 + return None
1.173 +
1.174 + abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
1.175 + abin.add_pad (gst.GhostPad ("src", aqueue_src.get_pad ("src")))
1.176 +
1.177 + #Finish Pipeline
1.178 + pipe.add (src, decode, abin, vbin, mux, sink)
1.179 + gst.element_link_many (src, decode)
1.180 + gst.element_link_many (mux, sink)
1.181 +
1.182 + #Linking decode with mux
1.183 + mux_audio = mux.get_pad ("audio_0")
1.184 + mux_video = mux.get_pad ("video_0")
1.185 +
1.186 + audio_pad = abin.get_pad ("src")
1.187 + video_pad = vbin.get_pad ("src")
1.188 +
1.189 + if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
1.190 + print "Fail to link audio with mux"
1.191 + return None
1.192 +
1.193 + if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
1.194 + print "Fail to link audio with mux"
1.195 + return None
1.196 +
1.197 + stream_data = self.StreamData (pipe, abin, vbin, sink)
1.198 + bus = pipe.get_bus()
1.199 + bus.add_signal_watch()
1.200 + bus.connect ("message", self.__on_bus_message, stream_data)
1.201 +
1.202 + decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
1.203 + decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
1.204 +
1.205 + print ("Create source")
1.206 + pipe.set_state (gst.STATE_PAUSED)
1.207 + print "Running Pipe"
1.208 + stream_data.Loop.run ()
1.209 + print "End run"
1.210 +
1.211 +
1.212 + #Create socket
1.213 + stream_data.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1.214 + print "Bind on port %d" % port
1.215 + stream_data.Socket.bind(('', int (port)))
1.216 + self.streams.append (stream_data)
1.217 + return (True, "")
1.218 +
1.219 + def play(self):
1.220 + print "Play"
1.221 + stream = self.streams[0]
1.222 + self.current = self.StreamListener(stream)
1.223 + self.current.start ()
1.224 + time.sleep (1)
1.225 + return (True, "")
1.226 +
1.227 + def stop(self):
1.228 + self.current.join ()
1.229 + self.current = None
1.230 + stream = self.streams[0]
1.231 + stream.Pipe.set_state(gst.STATE_NULL)
1.232 + del (stream.Pipe)
1.233 + stream.Pipe = None
1.234 + stream.Abin = None
1.235 + stream.Vbin = None
1.236 + stream.Sink = None
1.237 + if (stream.Connection != None):
1.238 + stream.Connection.close ()
1.239 +
1.240 + self.streams = []
1.241 + time.sleep (5)
1.242 + return (True, "")
1.243 +
1.244 +
1.245 + def __on_bus_message (self, bus, message, stream_data):
1.246 +
1.247 + t = message.type
1.248 + if (t == gst.MESSAGE_STATE_CHANGED):
1.249 + oldstate = -1
1.250 + newstate = -1
1.251 + pending = -1
1.252 + oldstate, newstate, pending = message.parse_state_changed ()
1.253 + if ((oldstate == gst.STATE_READY) and \
1.254 + (newstate == gst.STATE_PAUSED) and \
1.255 + (pending == gst.STATE_VOID_PENDING) and \
1.256 + (stream_data.Ready == False)):
1.257 + state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
1.258 + if ((current_state == gst.STATE_PAUSED) and \
1.259 + (pending_state == gst.STATE_VOID_PENDING)):
1.260 + print "Pipe paused"
1.261 + stream_data.Loop.quit ()
1.262 + stream_data.Ready = True
1.263 + elif (t == gst.MESSAGE_ERROR):
1.264 + err, debug = message.parse_error()
1.265 + print "Error: %s" % err, debug
1.266 + stream_data.Loop.quit ()
1.267 + stream_data.Ready = False
1.268 +
1.269 + return True
1.270 +
1.271 + def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
1.272 +
1.273 + print "Unknown Type"
1.274 + return None
1.275 +
1.276 + def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
1.277 +
1.278 + caps = pad.get_caps().to_string()
1.279 + print "New pad " + caps
1.280 + if (caps.rfind ("audio") != -1):
1.281 + apad = stream_data.Abin.get_pad ("sink")
1.282 + if (pad.link (apad) != gst.PAD_LINK_OK):
1.283 + print "Error on link audio pad"
1.284 + return None
1.285 + elif (caps.rfind ("video") != -1):
1.286 + vpad = stream_data.Vbin.get_pad ("sink")
1.287 + if (pad.link (vpad) != gst.PAD_LINK_OK):
1.288 + print "Error on link video pad"
1.289 + return None
1.290 + else:
1.291 + print "Invalid caps"
1.292 + print "Linked"
1.293 +