From 3a030c1f1a623ab7f6e4f807f929d6b7d709123b Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20Test=C3=A9?= Date: Thu, 25 Feb 2016 00:19:25 +0100 Subject: [PATCH] Adding the audio feed (for streaming and disk storing) --- stream_2016/libre-streamer.py | 149 +++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 37 deletions(-) diff --git a/stream_2016/libre-streamer.py b/stream_2016/libre-streamer.py index 86dadc2..25da323 100755 --- a/stream_2016/libre-streamer.py +++ b/stream_2016/libre-streamer.py @@ -36,7 +36,7 @@ # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # INFO: run the following command in a terminal before launching libre-streamer to get a error log. -# GST_DEBUG=3,python:5,gnl*:5 ./libre-streamer.py | tee -a log 2>&1 +# GST_DEBUG=4,python:5,gnl*:5 ./libre-streamer.py | tee -a log 2>&1 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! __author__ = 'David Testé' @@ -52,6 +52,7 @@ import sys import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk +gi.require_version('Gst', '1.0') from gi.repository import Gst from gi.repository import GdkX11 from gi.repository import GstVideo @@ -63,7 +64,6 @@ class Streamgui(object): def __init__(self): self.multimedia_file="" - # Create the global pipeline (might wanna use a general bin instead) self.pipel = self.constructpipeline() # Create the GUI self.win = Gtk.Window() @@ -99,31 +99,34 @@ class Streamgui(object): bus.connect("message", self.on_message) # Used for connecting video to your application. bus.connect("sync-message::element", self.on_sync_message) - # Connect the rtpdepay signal + # Connect the rtpjpegdepay signal self.videosrc.connect("pad-added", self.on_pad_added_to_rtspsrc) - if self.decodebin: - self.decodebin.connect("pad-added", self.on_pad_added_to_decodebin) -## elif self.jpegdec: -## self.jpegdec.connect("pad-added", self.on_pad_added_to_jpegdec) + def on_pad_added_to_rtspsrc(self, rtspsrc, pad): -## if self.decodebin: -## sinkpad = self.decodebin.get_static_pad('sink') -## elif self.rtpjpegdepay: -## sinkpad = self.rtpjpegdepay.get_static_pad('sink') sinkpad = self.queuev_1.get_static_pad('sink') pad.link(sinkpad) print('[DEBUG] rtspsrc LINKED') - def on_pad_added_to_decodebin(self, decodebin, pad): - screen_sinkpad = self.screensink.get_static_pad('sink') - pad.link(screen_sinkpad) - print('[DEBUG] decodebin LINKED') - def on_pad_added_to_jpegdec(self, jpegdec, pad): screen_sinkpad = self.screensink.get_static_pad('sink') pad.link(screen_sinkpad) print('[DEBUG] decodebin LINKED') + + def connect_tee(self, tee_element, input_element, output_element_1, output_element_2): + """Links input and outputs of a given Gst tee element.""" + # Find a way to check if the element given are in the pipeline + # then pass the result to the 'if' statement. +## argcheck = [True for arg in locals() if arg in 'the_list_of_elements_added'] +## print('[DEBUG] ArgList check: ', argcheck) +## if False not in argcheck + if True: + input_element.link(tee_element) + tee_element.link(output_element_1) + tee_element.link(output_element_2) + print('[DEBUG] Elements linked to tee') + else: + print('[ERROR] Couldn\'t link the tee. Element(s) probably not in the pipeline ') def constructpipeline (self): """Add and link elements in a GStreamer pipeline""" @@ -163,8 +166,13 @@ class Streamgui(object): #--------------------------------------------------------------------------- self.audiosrc = Gst.ElementFactory.make('pulsesrc', 'audiosrc') self.vorbisenc = Gst.ElementFactory.make('vorbisenc', 'vorbisenc') -## scaling_caps = Gst.Caps('video/x-raw, width=640, height=360') + self.oggmux = Gst.ElementFactory.make('oggmux', 'oggmux') self.scaling = Gst.ElementFactory.make('videoscale', 'scaling') +## scaling_caps = Gst.caps_from_string('video/x-raw, width=640, height=360') +## self.scaling.set_property('width', 640) +## self.scaling.set_property('height', 360) +## self.scalefilter = Gst.ElementFactory.make('capsfilter') +## self.scalefilter.set_property('caps', scaling_caps) self.vp8enc = Gst.ElementFactory.make('vp8enc', 'vp8enc') self.vp8enc.set_property('min_quantizer', 1) self.vp8enc.set_property('max_quantizer', 13) @@ -174,34 +182,41 @@ class Streamgui(object): self.vp8enc.set_property('sharpness', 7) self.webmmux = Gst.ElementFactory.make('webmmux', 'webmmux') self.webmmux.set_property('streamable', True) - - self.tee_streamvideo = Gst.ElementFactory.make('tee', 'tee_streamvideo') + + self.tee_videodecoded = Gst.ElementFactory.make('tee', 'tee_videodecoded') + self.tee_streamfull = Gst.ElementFactory.make('tee', 'tee_streamfull') self.tee_streamaudio = Gst.ElementFactory.make('tee', 'tee_streamaudio') self.queuea_1 = Gst.ElementFactory.make('queue', 'queuea_1') self.queuea_2 = Gst.ElementFactory.make('queue', 'queuea_2') + self.queuea_3 = Gst.ElementFactory.make('queue', 'queuea_3') + self.queuea_4 = Gst.ElementFactory.make('queue', 'queuea_4') + self.queuev_5 = Gst.ElementFactory.make('queue', 'queuev_5') + self.queuev_6 = Gst.ElementFactory.make('queue', 'queuev_6') + self.queuev_7 = Gst.ElementFactory.make('queue', 'queuev_7') + self.queuem_1 = Gst.ElementFactory.make('queue', 'queuem_1') + self.queuem_2 = Gst.ElementFactory.make('queue', 'queuem_2') self.disksink_audio = Gst.ElementFactory.make('filesink') self.disksink_audio.set_property('location', 'popo_audio') self.disksink_stream = Gst.ElementFactory.make('filesink') self.disksink_stream.set_property('location', 'popo_stream') - + self.icecastsink_audio = Gst.ElementFactory.make('shout2send', 'icecastsink_audio') # Configuration should be written on a file locally to keep safe private addresses self.icecastsink_audio.set_property('ip', 'live2.fsf.org') self.icecastsink_audio.set_property('port', 80) self.icecastsink_audio.set_property('mount', 'testaudio.ogv') - self.icecastsink_audio.set_property('password', '') + self.icecastsink_audio.set_property('password', 'thahw3Wiez') self.icecastsink_stream = Gst.ElementFactory.make('shout2send', 'icecastsink_stream') self.icecastsink_stream.set_property('ip', 'live2.fsf.org') self.icecastsink_stream.set_property('port', 80) self.icecastsink_stream.set_property('mount', 'teststream.ogv') - self.icecastsink_stream.set_property('password', '') + self.icecastsink_stream.set_property('password', 'thahw3Wiez') #--------------------------------------------------------------------------- # Add the elements to the pipeline. - # Test of the first two lines of quidam's pipeline: + # + Raw video and screen monitoring feed: self.streampipe.add(self.videosrc) -## self.streampipe.add(self.decodebin) self.streampipe.add(self.queuev_1) self.streampipe.add(self.rtpjpegdepay) self.streampipe.add(self.queuev_2) @@ -210,30 +225,90 @@ class Streamgui(object): self.streampipe.add(self.queuev_3) self.streampipe.add(self.mkvmux) self.streampipe.add(self.queuev_4) +## self.streampipe.add(self.tee_videodecoded) self.streampipe.add(self.disksink_rawvideo) self.streampipe.add(self.screensink) - + # + Audio feed: + self.streampipe.add(self.audiosrc) + self.streampipe.add(self.queuea_1) + self.streampipe.add(self.vorbisenc) + self.streampipe.add(self.tee_streamaudio) + self.streampipe.add(self.queuea_2) + self.streampipe.add(self.oggmux) + self.streampipe.add(self.queuea_3) + self.streampipe.add(self.disksink_audio) + self.streampipe.add(self.queuea_4) + self.streampipe.add(self.icecastsink_audio) + # + Stream (audio and video) feed: + """ + self.streampipe.add(self.queuev_6) + self.streampipe.add(self.scaling) + self.streampipe.add(self.scalefilter) + self.streampipe.add(self.vp8enc) + self.streampipe.add(self.queuev_5) + self.streampipe.add(self.webmmux) + self.streampipe.add(self.tee_streamfull) + self.streampipe.add(self.queuev_7) + self.streampipe.add(self.queuem_1) + self.streampipe.add(self.queuem_2) + self.streampipe.add(self.disksink_stream) +## self.streampipe.add(self.icecastsink_stream) + """ + # Link the elements in the pipeline. -## self.videosrc.link(self.decodebin) + # + Raw video and screen monitoring feed: self.queuev_1.link(self.rtpjpegdepay) -## self.rtpjpegdepay.link(self.queuev_2) -## self.rtpjpegdepay.link(self.jpegdec) - self.rtpjpegdepay.link(self.tee_rawvideo) -## self.queuev_2.link(self.jpegdec) -## self.jpegdec.link(self.tee_rawvideo) -## self.jpegdec.link(self.queuev_3) - self.tee_rawvideo.link(self.queuev_2) - self.tee_rawvideo.link(self.jpegdec) -## self.tee_rawvideo.link(self.queuev_3) +## self.rtpjpegdepay.link(self.tee_rawvideo) +## self.tee_rawvideo.link(self.queuev_2) +## self.tee_rawvideo.link(self.jpegdec) + self.connect_tee(self.tee_rawvideo, + self.rtpjpegdepay, + self.queuev_2, + self.jpegdec,) self.queuev_2.link(self.mkvmux) self.mkvmux.link(self.queuev_4) self.queuev_4.link(self.disksink_rawvideo) -## self.decodebin.link(self.screensink) -## self.queuev_3.link(self.disksink_rawvideo) + """ + self.connect_tee(self.tee_videodecoded, + self.jpegdec, + self.queuev_3, + self.queuev_6,) + """ self.jpegdec.link(self.queuev_3) self.queuev_3.link(self.screensink) + # + Audio feed: + self.audiosrc.link(self.queuea_1) + self.queuea_1.link(self.vorbisenc) + self.vorbisenc.link(self.queuea_2) + self.vorbisenc.link(self.queuea_2) + self.queuea_2.link(self.oggmux) + self.connect_tee(self.tee_streamaudio, + self.oggmux, + self.queuea_3, + self.queuea_4,) + self.queuea_3.link(self.disksink_audio) + self.queuea_4.link(self.icecastsink_audio) + # + Linking Stream (audio and video) feed: +## self.queuev_6.link(self.scalefilter) +## self.scalefilter.link(self.scaling) +## self.scaling.link(self.vp8enc) + """ + self.queuev_6.link(self.vp8enc) + self.vp8enc.link(self.queuev_7) + self.queuev_7.link(self.webmmux) + self.webmmux.link(self.queuem_1) +## self.queuea_4.link(self.webmmux) + self.connect_tee(self.tee_streamfull, + self.webmmux, + self.queuem_1, + self.queuem_2,) +## self.webmmux.link(self.queuem_1) +## self.webmmux.link(self.queuem_2) + self.queuem_1.link(self.disksink_stream) +## self.queuem_2.link(self.icecastsink_stream) + """ return self.streampipe def on_message(self, bus, message): -- 2.25.1