1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/server/plugins/media/gstreamer.py Tue Apr 03 19:39:23 2007 +0100
1.3 @@ -0,0 +1,235 @@
1.4 +import pygst
1.5 +pygst.require("0.10")
1.6 +import gst
1.7 +import gobject
1.8 +import socket
1.9 +
1.10 +class Media:
1.11 + class StreamData:
1.12 + stream_count = 0
1.13 +
1.14 + def __init__ (self, pipe, abin, vbin, sink):
1.15 +
1.16 + self.stream_count += 1
1.17 + self.Id = self.stream_count
1.18 + self.Pipe = pipe
1.19 + self.Abin = abin
1.20 + self.Vbin = vbin
1.21 + self.Sink = sink
1.22 + self.Loop = gobject.MainLoop()
1.23 + self.ACaps = ""
1.24 + self.VCaps = ""
1.25 + self.Ready = False
1.26 +
1.27 +
1.28 + def __init__(self, config):
1.29 + # set gstreamer basic options
1.30 + self.config = config
1.31 + self.pipe = None
1.32 + self.streams = []
1.33 + self.socket = None
1.34 + self.connection = None
1.35 + self.addr = None
1.36 +
1.37 +
1.38 + def setup(self, filename, mux, vcodec, vbitrate,
1.39 + fps, acodec, abitrate, width, height, port, options):
1.40 +
1.41 + ## Pipelines
1.42 + self.pipe = gst.Pipeline ()
1.43 + uri = "file://" + filename
1.44 + print "Opening Uri:" + uri
1.45 + src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
1.46 + if (src is None):
1.47 + return None
1.48 +
1.49 + decode = gst.element_factory_make ("decodebin", "decode")
1.50 + if (decode is None):
1.51 + return None
1.52 +
1.53 + mux = gst.element_factory_make ("avimux", "mux")
1.54 + if (mux is None):
1.55 + return None
1.56 +
1.57 + sink = gst.element_factory_make ("fdsink", "sink")
1.58 + if (sink is None):
1.59 + return None
1.60 +
1.61 + #Create socket
1.62 + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1.63 + self.socket.bind(('', int (port)))
1.64 +
1.65 + #video encode
1.66 + #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.67 + vbin = gst.Bin ()
1.68 + vqueue = gst.element_factory_make ("queue", "vqueue")
1.69 + vscale = gst.element_factory_make ("videoscale", "vscale")
1.70 + vrate = gst.element_factory_make ("videorate", "vrate")
1.71 + vencode = gst.element_factory_make ("ffenc_h263p", "vencode")
1.72 +
1.73 + if (None in [vbin, vqueue, vscale, vrate, vencode]):
1.74 + print "Fail to create video encode elements."
1.75 + return None
1.76 +
1.77 + vscale_pad = vscale.get_pad("sink")
1.78 + if (vscale_pad is None):
1.79 + print "Fail to get vscale sink pad."
1.80 + return None
1.81 +
1.82 + vscale_caps = gst.caps_from_string ("video/x-raw-yuv, width=%s, height=%s" % (width, height))
1.83 + if (vscale_caps is None):
1.84 + print "Fail to create video caps"
1.85 + return None
1.86 +
1.87 + if (not vscale_pad.set_caps (vscale_caps)):
1.88 + print "Fail to set video output caps"
1.89 + return None
1.90 +
1.91 + vbin.add (vqueue, vscale, vrate, vencode)
1.92 + if (not gst.element_link_many (vqueue, vscale, vrate, vencode)):
1.93 + print "Fail to link video elements"
1.94 + return None
1.95 +
1.96 + vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
1.97 + vbin.add_pad (gst.GhostPad ("src", vencode.get_pad ("src")))
1.98 +
1.99 + #audio encode
1.100 + #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
1.101 + abin = gst.Bin ()
1.102 + aqueue = gst.element_factory_make ("queue", "vqueue")
1.103 + aconvert = gst.element_factory_make ("audioconvert", "aconvert")
1.104 + aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
1.105 +
1.106 + if (None in [abin, aqueue, aconvert, aencode]):
1.107 + print "Fail to create video encode elements."
1.108 + return None
1.109 +
1.110 + abin.add (aqueue, aconvert, aencode)
1.111 + if (not gst.element_link_many (aqueue, aconvert, aencode)):
1.112 + print "Fail to link video elements"
1.113 + return None
1.114 +
1.115 + abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
1.116 + abin.add_pad (gst.GhostPad ("src", aencode.get_pad ("src")))
1.117 +
1.118 + #Finish Pipeline
1.119 +
1.120 + self.pipe.add (src, decode, abin, vbin, mux, sink)
1.121 + gst.element_link_many (src, decode)
1.122 + gst.element_link_many (mux, sink)
1.123 +
1.124 + #Linking decode with mux
1.125 + mux_audio = mux.get_pad ("audio_0")
1.126 + mux_video = mux.get_pad ("video_0")
1.127 +
1.128 + audio_pad = abin.get_pad ("src")
1.129 + video_pad = vbin.get_pad ("src")
1.130 +
1.131 + if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
1.132 + print "Fail to link audio with mux"
1.133 + return None
1.134 +
1.135 + if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
1.136 + print "Fail to link audio with mux"
1.137 + return None
1.138 +
1.139 + stream_data = self.StreamData (self.pipe, abin, vbin, sink)
1.140 +
1.141 + bus = self.pipe.get_bus()
1.142 + bus.add_signal_watch()
1.143 + bus.connect("message", self.__on_bus_message, stream_data)
1.144 +
1.145 + decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
1.146 + decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
1.147 +
1.148 +
1.149 + self.pipe.set_state (gst.STATE_PAUSED)
1.150 + print "Running Pipe"
1.151 + stream_data.Loop.run ()
1.152 + print "End run"
1.153 +
1.154 + a_caps = stream_data.ACaps
1.155 + v_caps = stream_data.VCaps
1.156 + stream_id = stream_data.Id
1.157 +
1.158 + self.streams.append (stream_data)
1.159 +
1.160 + def play(self):
1.161 +
1.162 + print "Trying to play pipeline: %s" % self.pipe
1.163 + try:
1.164 + if (self.pipe):
1.165 + print "Waiting for connection"
1.166 + self.socket.listen(1)
1.167 + print "Connection Requested"
1.168 + #Create socket
1.169 + self.connection, self.addr = self.socket.accept ()
1.170 +
1.171 + stream_data = self.streams[0]
1.172 + stream_data.Sink.set_property ("fd", self.connection.fileno());
1.173 + print "Connected"
1.174 +
1.175 + self.pipe.set_state(gst.STATE_PLAYING)
1.176 + except gobject.GError, e:
1.177 + print "Error: " + str(e)
1.178 +
1.179 +
1.180 + def stop(self):
1.181 +
1.182 + print "Trying to stop pipeline: %s" % self.pipe
1.183 + try:
1.184 + if (self.pipeline):
1.185 + self.connection.close ()
1.186 + self.pipeline.set_state(gst.STATE_NULL)
1.187 + except gobject.GError, e:
1.188 + print "Error: " + str(e)
1.189 +
1.190 + def __on_bus_message (self, bus, message, stream_data):
1.191 +
1.192 + t = message.type
1.193 + if (t == gst.MESSAGE_STATE_CHANGED):
1.194 + oldstate = -1
1.195 + newstate = -1
1.196 + pending = -1
1.197 + oldstate, newstate, pending = message.parse_state_changed ()
1.198 + if ((oldstate == gst.STATE_READY) and \
1.199 + (newstate == gst.STATE_PAUSED) and \
1.200 + (pending == gst.STATE_VOID_PENDING) and \
1.201 + (stream_data.Ready == False)):
1.202 + state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
1.203 + if ((current_state == gst.STATE_PAUSED) and \
1.204 + (pending_state == gst.STATE_VOID_PENDING)):
1.205 + print "Pipe paused"
1.206 + stream_data.Loop.quit ()
1.207 + stream_data.Ready = True
1.208 + elif (t == gst.MESSAGE_ERROR):
1.209 + err, debug = message.parse_error()
1.210 + print "Error: %s" % err, debug
1.211 + stream_data.Loop.quit ()
1.212 + stream_data.Ready = False
1.213 +
1.214 + return True
1.215 +
1.216 + def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
1.217 +
1.218 + print "Unknown Type"
1.219 + return None
1.220 +
1.221 + def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
1.222 +
1.223 + caps = pad.get_caps().to_string()
1.224 + print "New pad " + caps
1.225 + if (caps.rfind ("audio") != -1):
1.226 + apad = stream_data.Abin.get_pad ("sink")
1.227 + if (pad.link (apad) != gst.PAD_LINK_OK):
1.228 + print "Error on link audio pad"
1.229 + return None
1.230 + elif (caps.rfind ("video") != -1):
1.231 + vpad = stream_data.Vbin.get_pad ("sink")
1.232 + if (pad.link (vpad) != gst.PAD_LINK_OK):
1.233 + print "Error on link video pad"
1.234 + return None
1.235 + else:
1.236 + print "Invalid caps"
1.237 +
1.238 +