1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gmyth-stream/plugins/media/gstreamer-rtp.py Tue Apr 03 16:05:00 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 +
2.1 --- a/gmyth-stream/plugins/media/gstreamer.py Tue Apr 03 14:58:30 2007 +0100
2.2 +++ b/gmyth-stream/plugins/media/gstreamer.py Tue Apr 03 16:05:00 2007 +0100
2.3 @@ -2,59 +2,174 @@
2.4 pygst.require("0.10")
2.5 import gst
2.6 import gobject
2.7 +import socket
2.8
2.9 class Media:
2.10 + class StreamData:
2.11 + stream_count = 0
2.12 +
2.13 + def __init__ (self, pipe, abin, vbin, sink):
2.14 +
2.15 + self.stream_count += 1
2.16 + self.Id = self.stream_count
2.17 + self.Pipe = pipe
2.18 + self.Abin = abin
2.19 + self.Vbin = vbin
2.20 + self.Sink = sink
2.21 + self.Loop = gobject.MainLoop()
2.22 + self.ACaps = ""
2.23 + self.VCaps = ""
2.24 + self.Ready = False
2.25 +
2.26
2.27 def __init__(self, config):
2.28 -
2.29 # set gstreamer basic options
2.30 self.config = config
2.31 - self.pipe = ""
2.32 + self.pipe = None
2.33 + self.streams = []
2.34 + self.socket = None
2.35 + self.connection = None
2.36 + self.addr = None
2.37
2.38
2.39 - def setup(self, filename, mux, vcodec, vbitrate,\
2.40 - fps, acodec, abitrate, width, height, port):
2.41 -
2.42 - self.filename = filename
2.43 - self.mux = mux
2.44 - self.vcodec = vcodec
2.45 - self.vbitrate = int(vbitrate)
2.46 - self.fps = int(fps)
2.47 - self.acodec = acodec
2.48 - self.abitrate = int(abitrate)
2.49 - self.width = int(width)
2.50 - self.height = int(height)
2.51 -
2.52 - self.port = int(port)
2.53 + def setup(self, filename, mux, vcodec, vbitrate,
2.54 + fps, acodec, abitrate, width, height, port, options):
2.55
2.56 ## Pipelines
2.57 + self.pipe = gst.Pipeline ()
2.58 + uri = "file://" + filename
2.59 + print "Opening Uri:" + uri
2.60 + src = gst.element_make_from_uri (gst.URI_SRC, uri, "src")
2.61 + if (src is None):
2.62 + return None
2.63 +
2.64 + decode = gst.element_factory_make ("decodebin", "decode")
2.65 + if (decode is None):
2.66 + return None
2.67
2.68 - #queue ! videoscale ! video/x-raw-yuv,width=240,height=144\
2.69 - #! videorate ! ffenc_h263p bitrate=256000 me-method=2 \
2.70 - #! rtph263ppay ! udpsink host=224.0.0.1 port=5000
2.71 + mux = gst.element_factory_make ("avimux", "mux")
2.72 + if (mux is None):
2.73 + return None
2.74
2.75 + sink = gst.element_factory_make ("fdsink", "sink")
2.76 + if (sink is None):
2.77 + return None
2.78
2.79 - #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay\
2.80 - #! udpsink name=upd_audio host=224.0.0.1 port=5002
2.81 + #Create socket
2.82 + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
2.83 + self.socket.bind(('', int (port)))
2.84 +
2.85 + #video encode
2.86 + #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
2.87 + vbin = gst.Bin ()
2.88 + vqueue = gst.element_factory_make ("queue", "vqueue")
2.89 + vscale = gst.element_factory_make ("videoscale", "vscale")
2.90 + vrate = gst.element_factory_make ("videorate", "vrate")
2.91 + vencode = gst.element_factory_make ("ffenc_h263p", "vencode")
2.92
2.93 - self.pipe = "filesrc location=%s ! decodebin name=d ! queue ! videoscale !"\
2.94 - "video/x-raw-yuv,width=(int)%d,height=(int)%d ! ffenc_h263p bitrate=%d"\
2.95 - " me-method=2 ! rtph263ppay ! udpsink host=224.0.0.1 port=%d d. ! "\
2.96 - "queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=udp_audio "\
2.97 - "host=224.0.0.1 port=%d" % (self.filename, self.width, self.height,\
2.98 - self.vbitrate, self.port, self.port+2)
2.99 + if (None in [vbin, vqueue, vscale, vrate, vencode]):
2.100 + print "Fail to create video encode elements."
2.101 + return None
2.102
2.103 - #self.pipe = "filesrc location=/tmp/mpg/cpm.mpg ! decodebin ! ffmpegcolorspace ! ximagesink"
2.104 + vscale_pad = vscale.get_pad("sink")
2.105 + if (vscale_pad is None):
2.106 + print "Fail to get vscale sink pad."
2.107 + return None
2.108
2.109 - self.pipeline = gst.parse_launch(self.pipe)
2.110 + vscale_caps = gst.caps_from_string ("video/x-raw-yuv, width=%s, height=%s" % (width, height))
2.111 + if (vscale_caps is None):
2.112 + print "Fail to create video caps"
2.113 + return None
2.114
2.115 + if (not vscale_pad.set_caps (vscale_caps)):
2.116 + print "Fail to set video output caps"
2.117 + return None
2.118 +
2.119 + vbin.add (vqueue, vscale, vrate, vencode)
2.120 + if (not gst.element_link_many (vqueue, vscale, vrate, vencode)):
2.121 + print "Fail to link video elements"
2.122 + return None
2.123 +
2.124 + vbin.add_pad (gst.GhostPad ("sink", vqueue.get_pad ("sink")))
2.125 + vbin.add_pad (gst.GhostPad ("src", vencode.get_pad ("src")))
2.126 +
2.127 + #audio encode
2.128 + #audio/x-raw-int ! queue ! audioconvert ! faac ! rtpmp4gpay ! udpsink name=upd_audio host=224.0.0.1 port=5002
2.129 + abin = gst.Bin ()
2.130 + aqueue = gst.element_factory_make ("queue", "vqueue")
2.131 + aconvert = gst.element_factory_make ("audioconvert", "aconvert")
2.132 + aencode = gst.element_factory_make ("ffenc_ac3", "aencode")
2.133 +
2.134 + if (None in [abin, aqueue, aconvert, aencode]):
2.135 + print "Fail to create video encode elements."
2.136 + return None
2.137 +
2.138 + abin.add (aqueue, aconvert, aencode)
2.139 + if (not gst.element_link_many (aqueue, aconvert, aencode)):
2.140 + print "Fail to link video elements"
2.141 + return None
2.142 +
2.143 + abin.add_pad (gst.GhostPad ("sink", aqueue.get_pad ("sink")))
2.144 + abin.add_pad (gst.GhostPad ("src", aencode.get_pad ("src")))
2.145 +
2.146 + #Finish Pipeline
2.147 +
2.148 + self.pipe.add (src, decode, abin, vbin, mux, sink)
2.149 + gst.element_link_many (src, decode)
2.150 + gst.element_link_many (mux, sink)
2.151 +
2.152 + #Linking decode with mux
2.153 + mux_audio = mux.get_pad ("audio_0")
2.154 + mux_video = mux.get_pad ("video_0")
2.155 +
2.156 + audio_pad = abin.get_pad ("src")
2.157 + video_pad = vbin.get_pad ("src")
2.158 +
2.159 + if (audio_pad.link (mux_audio) != gst.PAD_LINK_OK):
2.160 + print "Fail to link audio with mux"
2.161 + return None
2.162 +
2.163 + if (video_pad.link (mux_video) != gst.PAD_LINK_OK):
2.164 + print "Fail to link audio with mux"
2.165 + return None
2.166 +
2.167 + stream_data = self.StreamData (self.pipe, abin, vbin, sink)
2.168 +
2.169 + bus = self.pipe.get_bus()
2.170 + bus.add_signal_watch()
2.171 + bus.connect("message", self.__on_bus_message, stream_data)
2.172 +
2.173 + decode.connect("new-decoded-pad", self.__on_decode_new_pad, stream_data)
2.174 + decode.connect("unknown-type", self.__on_decode_unknown_type, stream_data)
2.175 +
2.176 +
2.177 + self.pipe.set_state (gst.STATE_PAUSED)
2.178 + print "Running Pipe"
2.179 + stream_data.Loop.run ()
2.180 + print "End run"
2.181 +
2.182 + a_caps = stream_data.ACaps
2.183 + v_caps = stream_data.VCaps
2.184 + stream_id = stream_data.Id
2.185 +
2.186 + self.streams.append (stream_data)
2.187
2.188 def play(self):
2.189
2.190 print "Trying to play pipeline: %s" % self.pipe
2.191 try:
2.192 - if (self.pipeline):
2.193 - self.pipeline.set_state(gst.STATE_PLAYING)
2.194 + if (self.pipe):
2.195 + print "Waiting for connection"
2.196 + self.socket.listen(1)
2.197 + print "Connection Requested"
2.198 + #Create socket
2.199 + self.connection, self.addr = self.socket.accept ()
2.200 +
2.201 + stream_data = self.streams[0]
2.202 + stream_data.Sink.set_property ("fd", self.connection.fileno());
2.203 + print "Connected"
2.204 +
2.205 + self.pipe.set_state(gst.STATE_PLAYING)
2.206 except gobject.GError, e:
2.207 print "Error: " + str(e)
2.208
2.209 @@ -64,7 +179,57 @@
2.210 print "Trying to stop pipeline: %s" % self.pipe
2.211 try:
2.212 if (self.pipeline):
2.213 + self.connection.close ()
2.214 self.pipeline.set_state(gst.STATE_NULL)
2.215 except gobject.GError, e:
2.216 print "Error: " + str(e)
2.217
2.218 + def __on_bus_message (self, bus, message, stream_data):
2.219 +
2.220 + t = message.type
2.221 + if (t == gst.MESSAGE_STATE_CHANGED):
2.222 + oldstate = -1
2.223 + newstate = -1
2.224 + pending = -1
2.225 + oldstate, newstate, pending = message.parse_state_changed ()
2.226 + if ((oldstate == gst.STATE_READY) and \
2.227 + (newstate == gst.STATE_PAUSED) and \
2.228 + (pending == gst.STATE_VOID_PENDING) and \
2.229 + (stream_data.Ready == False)):
2.230 + state_changed_status, current_state, pending_state = stream_data.Pipe.get_state ()
2.231 + if ((current_state == gst.STATE_PAUSED) and \
2.232 + (pending_state == gst.STATE_VOID_PENDING)):
2.233 + print "Pipe paused"
2.234 + stream_data.Loop.quit ()
2.235 + stream_data.Ready = True
2.236 + elif (t == gst.MESSAGE_ERROR):
2.237 + err, debug = message.parse_error()
2.238 + print "Error: %s" % err, debug
2.239 + stream_data.Loop.quit ()
2.240 + stream_data.Ready = False
2.241 +
2.242 + return True
2.243 +
2.244 + def __on_decode_unknown_type (self, decode, pad, caps, stream_data):
2.245 +
2.246 + print "Unknown Type"
2.247 + return None
2.248 +
2.249 + def __on_decode_new_pad (self, decode, pad, arg1, stream_data):
2.250 +
2.251 + caps = pad.get_caps().to_string()
2.252 + print "New pad " + caps
2.253 + if (caps.rfind ("audio") != -1):
2.254 + apad = stream_data.Abin.get_pad ("sink")
2.255 + if (pad.link (apad) != gst.PAD_LINK_OK):
2.256 + print "Error on link audio pad"
2.257 + return None
2.258 + elif (caps.rfind ("video") != -1):
2.259 + vpad = stream_data.Vbin.get_pad ("sink")
2.260 + if (pad.link (vpad) != gst.PAD_LINK_OK):
2.261 + print "Error on link video pad"
2.262 + return None
2.263 + else:
2.264 + print "Invalid caps"
2.265 +
2.266 +