Adding the audio feed (for streaming and disk storing)
authorDavid Testé <soonum@gnu.org>
Wed, 24 Feb 2016 23:19:25 +0000 (00:19 +0100)
committerDavid Testé <soonum@gnu.org>
Wed, 24 Feb 2016 23:19:25 +0000 (00:19 +0100)
stream_2016/libre-streamer.py

index 86dadc22abb380bc99236c851ec7e704c30a0115..25da323e36232c9ed487404a5ef11dc03f041e0f 100755 (executable)
@@ -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):