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