Starting implementing backup pipeline.(Need to be finished)
[libre-streamer.git] / stream_2016 / gstconf.py
index 2f564fad7c9e28590368d385e82ccb0299e66c0d..254da74f603c1ccc3a23794bb0f1562560b21894 100755 (executable)
@@ -18,6 +18,7 @@
 # Copyright (c) 2016 David Testé
 
 from os import rename
+from os import listdir
 
 import gi
 from gi.repository import Gst
@@ -28,37 +29,56 @@ PATHNAME = ''
 AUDIO_DEFAULT = PATHNAME + 'AUDIO_DEFAULT'
 RAWVIDEO_DEFAULT = PATHNAME + 'RAWVIDEO_DEFAULT'
 STREAM_DEFAULT = PATHNAME + 'STREAM_DEFAULT'
-WEBCAMUSB_DEFAULT =  '/dev/video1'
 
 
 class New_user_pipeline():
 
     
-    def __init__(self):
-        self.user_pipeline = self.create_gstreamer_pipeline()
-        
+    def __init__(self, feed='main'):
+        self.feed = feed
+        if self.feed == 'main':
+            self.user_pipeline = self.create_gstreamer_pipeline()
+        elif self.feed == 'backup':
+            self.user_pipeline = self.create_gstreamer_pipeline(feed='backup')
+            
     def create_video_sources(self):
         """Create video inputs from various sources."""
         self.videosrc = Gst.ElementFactory.make('rtspsrc', 'videosrc')
         self.videosrc.set_property('location', 'rtsp://192.168.48.2:554')
         self.videosrc.set_property('latency', 0)
-##        self.videosrc = Gst.ElementFactory.make('v4l2src', 'videosrc')
-##        self.videosrc.set_property('device', '/dev/video1')
+        if self.feed == 'backup':
+            self.videosrc_backup = Gst.ElementFactory.make('v4l2src',
+                                                           'videosrc_backup')
+            device_location = self.find_webcam_device()
+            print ('[INFO] Webcam device location: ', device_location)
+            self.videosrc_backup.set_property('device', device_location)
+        
+    def find_webcam_device(self):
+        """Look out for the USB webcam device."""
+        devices = [dev for dev in listdir('/dev/') if 'video' in dev]
+        for item in devices:
+            # In case of computer having a built-in webcam
+            if item != 'video0' and len(devices) > 1:
+                return '/dev/' + item
+            # Without built-in webcam
+            elif len(devices) == 1:
+                return '/dev/video0'
+        print('[ERROR] No webcam device found.')
         
-    def create_audio_sources(self):
-        """Create audio inputs from various sources."""
-        self.audiosrc = Gst.ElementFactory.make('pulsesrc', 'audiosrc')
-##        self.videosrc.set_property('latency', 0)
-
     def create_pipeline_callbacks(self):
         """Callbacks to connect dynamically created pads."""
-        self.videosrc.connect("pad-added", self.on_pad_added_to_rtspsrc)
+        self.videosrc.connect('pad-added', self.on_pad_added_to_rtspsrc)
 
     def on_pad_added_to_rtspsrc(self, rtspsrc, pad):
         """Connect the dynamic 'src'pad of an RTSP source."""
         sinkpad = self.queuev_1.get_static_pad('sink')
         pad.link(sinkpad)
 
+    def create_audio_sources(self):
+        """Create audio inputs from various sources."""
+        self.audiosrc = Gst.ElementFactory.make('pulsesrc', 'audiosrc')
+##        self.videosrc.set_property('latency', 0)
+
     def create_audiolevel_plugin(self):
         """Create audio level plugin to feed a vu-meter."""
         self.audiolevel = Gst.ElementFactory.make('level', 'audiolevel')
@@ -78,6 +98,7 @@ class New_user_pipeline():
         """Create streamable output elements."""
         # To local screen:
         self.screensink = Gst.ElementFactory.make('xvimagesink', 'screensink')
+        self.screensink.set_property('sync', False)
         # To icecast server:
         self.icecastsink_audio = Gst.ElementFactory.make('shout2send', 'icecastsink_audio')
 ## Configuration should be written on a file locally to keep safe private addresses
@@ -127,6 +148,10 @@ class New_user_pipeline():
         caps = Gst.caps_from_string('video/x-raw, width=(int)640, height=(int)360')
         self.capsfilter = Gst.ElementFactory.make('capsfilter', 'capsfilter')
         self.capsfilter.set_property('caps', caps)
+
+        caps_backup = Gst.caps_from_string('video/x-raw, width=(int)640, height=(int)360')
+        self.capsfilter_backup = Gst.ElementFactory.make('capsfilter', 'capsfilter_backup')
+        self.capsfilter_backup.set_property('caps', caps_backup)
         
     def create_tee_elements(self):
         """Create tee elements to divide feeds."""
@@ -197,51 +222,53 @@ class New_user_pipeline():
         print('Pipeline creation state: adding elements... ', end='')        
 
         if feed == 'main':
-            pass
             # Add here the elments associated with the RTSP feed
+            # Inputs elements:
+            self.streampipe.add(self.videosrc)
+            self.streampipe.add(self.audiosrc)
+            # Middle elements:
+            self.streampipe.add(self.audiolevel)
+            self.streampipe.add(self.rtpjpegdepay)
+            self.streampipe.add(self.jpegdec)
+            self.streampipe.add(self.tee_rawvideo)
+            self.streampipe.add(self.mkvmux)
+            self.streampipe.add(self.vorbisenc)
+            self.streampipe.add(self.oggmux)
+            self.streampipe.add(self.scaling)
+            self.streampipe.add(self.capsfilter)
+            self.streampipe.add(self.vp8enc)
+            self.streampipe.add(self.webmmux)
+            self.streampipe.add(self.tee_rawaudio)
+            self.streampipe.add(self.tee_streamaudio)
+            self.streampipe.add(self.tee_videodecoded)
+            self.streampipe.add(self.tee_streamfull)
+            self.streampipe.add(self.queuev_1)
+            self.streampipe.add(self.queuev_2)
+            self.streampipe.add(self.queuev_3)
+            self.streampipe.add(self.queuev_4)
+            self.streampipe.add(self.queuev_5)
+            self.streampipe.add(self.queuev_6)
+            self.streampipe.add(self.queuea_1)
+            self.streampipe.add(self.queuea_2)
+            self.streampipe.add(self.queuea_3)
+            self.streampipe.add(self.queuea_4)
+            self.streampipe.add(self.queuea_5)
+            self.streampipe.add(self.queuem_1)
+            self.streampipe.add(self.queuem_2)
+            # Outputs elements:
+            self.streampipe.add(self.screensink)
+            self.streampipe.add(self.disksink_rawvideo)
+            self.streampipe.add(self.disksink_audio)
+            self.streampipe.add(self.disksink_stream)
+            self.streampipe.add(self.icecastsink_audio)
+            self.streampipe.add(self.icecastsink_stream)
         elif feed == 'backup':
-            pass
             # Add here the elments associated with the WEBCAM feed
-
-        # Inputs elements:
-        self.streampipe.add(self.videosrc)
-        self.streampipe.add(self.audiosrc)
-        # Middle elements:
-        self.streampipe.add(self.audiolevel)
-        self.streampipe.add(self.rtpjpegdepay)
-        self.streampipe.add(self.jpegdec)
-        self.streampipe.add(self.tee_rawvideo)
-        self.streampipe.add(self.mkvmux)
-        self.streampipe.add(self.vorbisenc)
-        self.streampipe.add(self.oggmux)
-        self.streampipe.add(self.scaling)
-        self.streampipe.add(self.capsfilter)
-        self.streampipe.add(self.vp8enc)
-        self.streampipe.add(self.webmmux)
-        self.streampipe.add(self.tee_rawaudio)
-        self.streampipe.add(self.tee_streamaudio)
-        self.streampipe.add(self.tee_videodecoded)
-        self.streampipe.add(self.tee_streamfull)
-        self.streampipe.add(self.queuev_1)
-        self.streampipe.add(self.queuev_2)
-        self.streampipe.add(self.queuev_3)
-        self.streampipe.add(self.queuev_4)
-        self.streampipe.add(self.queuev_5)
-        self.streampipe.add(self.queuev_6)
-        self.streampipe.add(self.queuea_1)
-        self.streampipe.add(self.queuea_2)
-        self.streampipe.add(self.queuea_3)
-        self.streampipe.add(self.queuea_4)
-        self.streampipe.add(self.queuea_5)
-        self.streampipe.add(self.queuem_1)
-        self.streampipe.add(self.queuem_2)
-        # Outputs elements:
-        self.streampipe.add(self.screensink)
-        self.streampipe.add(self.disksink_rawvideo)
-        self.streampipe.add(self.disksink_audio)
-        self.streampipe.add(self.disksink_stream)
-        self.streampipe.add(self.icecastsink_audio)
-        self.streampipe.add(self.icecastsink_stream)
+            self.streampipe.add(self.videosrc_backup)
+            self.streampipe.add(self.capsfilter_backup)
+            self.streampipe.add(self.queuev_1)
+            self.streampipe.add(self.screensink)
+            print ('BACKUP OK...', end='')
         print('added')
         
     def link_pipeline_elements(self, feed='main'):
@@ -249,63 +276,68 @@ class New_user_pipeline():
         print('Pipeline creation state: linking elements... ', end='')
         
         if feed == 'main':
-            pass
             # linking here RTSP feed
+            # Video feed:
+            self.queuev_1.link(self.rtpjpegdepay)
+            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.connect_tee(self.tee_videodecoded,
+                             self.jpegdec,
+                             self.queuev_3,
+                             self.scaling,)
+            self.queuev_3.link(self.screensink)
+            # Audio feed:
+            self.audiosrc.link(self.audiolevel)
+            self.audiolevel.link(self.queuea_1)
+            self.queuea_1.link(self.vorbisenc)
+            self.connect_tee(self.tee_rawaudio,
+                             self.vorbisenc,
+                             self.queuea_2,
+                             self.queuea_5,)
+            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)
+            self.queuea_5.link(self.webmmux)
+            # Stream (audio+video) feed:
+            self.scaling.link(self.capsfilter)
+            self.capsfilter.link(self.vp8enc)
+            self.vp8enc.link(self.queuev_6)
+            self.queuev_6.link(self.webmmux)
+            self.connect_tee(self.tee_streamfull,
+                             self.webmmux,
+                             self.queuem_1,
+                             self.queuem_2,)
+            self.queuem_1.link(self.disksink_stream)
+            self.queuem_2.link(self.icecastsink_stream)
         elif feed == 'backup':
-            pass
             # linking here backup feed (WEBCAM)
-
-        # Video feed:
-        self.queuev_1.link(self.rtpjpegdepay)
-        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.connect_tee(self.tee_videodecoded,
-                         self.jpegdec,
-                         self.queuev_3,
-                         self.scaling,)
-        self.queuev_3.link(self.screensink)
-        # Audio feed:
-        self.audiosrc.link(self.audiolevel)
-        self.audiolevel.link(self.queuea_1)
-        self.queuea_1.link(self.vorbisenc)
-        self.connect_tee(self.tee_rawaudio,
-                         self.vorbisenc,
-                         self.queuea_2,
-                         self.queuea_5,)
-        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)
-        self.queuea_5.link(self.webmmux)
-        # Stream (audio+video) feed:
-        self.scaling.link(self.capsfilter)
-        self.capsfilter.link(self.vp8enc)
-        self.vp8enc.link(self.queuev_6)
-        self.queuev_6.link(self.webmmux)
-        self.connect_tee(self.tee_streamfull,
-                         self.webmmux,
-                         self.queuem_1,
-                         self.queuem_2,)
-        self.queuem_1.link(self.disksink_stream)
-        self.queuem_2.link(self.icecastsink_stream)
+            self.videosrc_backup.link(self.capsfilter_backup)
+            self.capsfilter_backup.link(self.queuev_1)
+            self.queuev_1.link(self.screensink)
+            print('BACKUP OK...', end='')
         print('linked')
 
-    def create_gstreamer_pipeline(self):
+    def create_gstreamer_pipeline(self, feed='main'):
         # New empty pipeline:
         self.streampipe = Gst.Pipeline()
-        # Setting-up:
         self.create_pipeline_elements()
-        self.add_elements_to_pipeline()
-        self.link_pipeline_elements()
-        self.create_pipeline_callbacks()
+        # Setting-up:
+        if feed == 'main':
+            self.add_elements_to_pipeline()
+            self.link_pipeline_elements()
+            self.create_pipeline_callbacks()
+        elif feed == 'backup':
+            self.add_elements_to_pipeline(feed='backup')
+            self.link_pipeline_elements(feed='backup')
 
         global bus
         bus = self.streampipe.get_bus()
@@ -322,18 +354,22 @@ class New_user_pipeline():
         print("CREATE HERE A BACKUP PIPELINE")
         
     def on_message(self, bus, message):
+        #
+##        print("[MESSAGE]", message.get_structure().get_name()) # [DEBUG]
+        #
         t = message.type
         if t == Gst.MessageType.EOS:
             self.streampipe.set_state(Gst.State.NULL)
-            self.stream_button.set_label('Stream')
         elif t == Gst.MessageType.ERROR:
             err, debug = message.parse_error()
             print ("Error: %s" % err, debug)
             self.streampipe.set_state(Gst.State.NULL)
-            self.create_gstreamer_backup_pipeline()
-
+##            self.create_gstreamer_backup_pipeline()
+##            return 'ERROR'
+            
     def stream_play(self):
         self.streampipe.set_state(Gst.State.PLAYING)
+        print('[INFO] PLAYING State resquested')
         
     def stream_stop(self):
         self.streampipe.set_state(Gst.State.NULL)