summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xvoctocore/experiments/failovertest.py83
-rw-r--r--voctocore/experiments/shmsrc.py27
-rwxr-xr-xvoctocore/experiments/test-grabber-src.sh10
-rw-r--r--voctocore/experiments/videodisplay.py53
4 files changed, 120 insertions, 53 deletions
diff --git a/voctocore/experiments/failovertest.py b/voctocore/experiments/failovertest.py
index 5ebaa9a..ee9198b 100755
--- a/voctocore/experiments/failovertest.py
+++ b/voctocore/experiments/failovertest.py
@@ -1,10 +1,5 @@
#!/usr/bin/python3
import gi
-import time
-import signal
-from http.client import HTTPConnection
-from termcolor import colored
-from threading import Timer, Thread
# import GStreamer and GTK-Helper classes
gi.require_version('Gst', '1.0')
@@ -13,62 +8,44 @@ from gi.repository import GLib, Gst, Gtk, GObject
# init GObject before importing local classes
GObject.threads_init()
Gst.init(None)
-loop = GLib.MainLoop()
-# make killable by ctrl-c
-signal.signal(signal.SIGINT, signal.SIG_DFL)
+from videodisplay import VideomixerWithDisplay
+from shmsrc import ShmSrc
-# parse_launch
-p = Gst.parse_launch("""
- input-selector name=failover ! autovideosink
+class Example:
+ def __init__(self):
+ self.mainloop = GObject.MainLoop()
+ self.pipeline = Gst.Pipeline()
- appsrc name=src blocksize=4096 is-live=true block=true ! multipartdemux name=demux ! jpegparse ! jpegdec ! videoconvert ! failover.sink_1
- videotestsrc ! video/x-raw,width=500,height=375 ! failover.sink_0
-""")
+ self.bus = self.pipeline.get_bus()
+ self.bus.add_signal_watch()
+ self.bus.connect('message::eos', self.on_eos)
+ self.bus.connect('message::error', self.on_error)
-def failsafeVideoSource():
- src = p.get_by_name('src')
- dec = p.get_by_name('dec')
- demux = p.get_by_name('demux')
- failover = p.get_by_name('failover')
- srcActive = True
+ self.mixdisplay = VideomixerWithDisplay()
+ self.grabbersrc = ShmSrc('/tmp/grabber', Gst.Caps.from_string('video/x-raw,width=1280,height=720,framerate=25/1,format=BGRA'))
- while True:
- print('connecting to framegrabber')
- try:
- con = HTTPConnection('beachcam.kdhnc.com', 80, timeout=3)
- req = con.request('GET', '/mjpg/video.mjpg?camera=1')
- res = con.getresponse()
- srcActive = True
+ # Add elements to pipeline
+ self.pipeline.add(self.mixdisplay)
+ self.pipeline.add(self.grabbersrc)
- print('connected, switching to video')
- failover.set_property('active-pad', failover.get_static_pad('sink_1'))
+ self.grabbersrc.link(self.mixdisplay)
- while srcActive:
- chunk = res.read(4094)
- chunklen = len(chunk)
- print('read ', len(chunk), ' of ', 4096, ', closed=', res.isclosed())
-
- if chunklen > 0:
- src.emit('push-buffer', Gst.Buffer.new_wrapped(chunk))
- else:
- srcActive = False
- except:
- print('exception')
- srcActive = False
+ def run(self):
+ self.pipeline.set_state(Gst.State.PLAYING)
+ self.mainloop.run()
- print('switching to failsave')
- failover.set_property('active-pad', failover.get_static_pad('sink_0'))
+ def kill(self):
+ self.pipeline.set_state(Gst.State.NULL)
+ self.mainloop.quit()
- print('sleeping before retry')
- time.sleep(1)
+ def on_eos(self, bus, msg):
+ print('on_eos()')
+ #self.kill()
-fsThread = Thread(target=failsafeVideoSource)
-fsThread.deamon = True
-fsThread.start()
+ def on_error(self, bus, msg):
+ print('on_error():', msg.parse_error())
+ #self.kill()
-# set playing
-p.set_state(Gst.State.PLAYING)
-
-# start mainloop
-loop.run()
+example = Example()
+example.run()
diff --git a/voctocore/experiments/shmsrc.py b/voctocore/experiments/shmsrc.py
new file mode 100644
index 0000000..e9dd23a
--- /dev/null
+++ b/voctocore/experiments/shmsrc.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python3
+from gi.repository import GObject, Gst
+
+class ShmSrc(Gst.Bin):
+ def __init__(self, socket, caps):
+ super().__init__()
+
+ # Create elements
+ self.shmsrc = Gst.ElementFactory.make('shmsrc', None)
+ self.caps = Gst.ElementFactory.make('capsfilter', None)
+
+ # Add elements to Bin
+ self.add(self.shmsrc)
+ self.add(self.caps)
+
+ # Set properties
+ self.shmsrc.set_property('socket-path', socket)
+ self.shmsrc.set_property('is-live', True)
+ self.shmsrc.set_property('do-timestamp', True)
+
+ self.caps.set_property('caps', caps)
+ self.shmsrc.link(self.caps)
+
+ # Add Ghost Pads
+ self.add_pad(
+ Gst.GhostPad.new('sink', self.caps.get_static_pad('src'))
+ )
diff --git a/voctocore/experiments/test-grabber-src.sh b/voctocore/experiments/test-grabber-src.sh
new file mode 100755
index 0000000..e298faf
--- /dev/null
+++ b/voctocore/experiments/test-grabber-src.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+gst-launch-1.0 -vm \
+ videotestsrc !\
+ video/x-raw,width=1280,height=720,framerate=25/1,format=BGRA !\
+ queue !\
+ shmsink \
+ sync=true \
+ socket-path=/tmp/grabber \
+ wait-for-connection=false \
+ shm-size=100000000
diff --git a/voctocore/experiments/videodisplay.py b/voctocore/experiments/videodisplay.py
new file mode 100644
index 0000000..57087da
--- /dev/null
+++ b/voctocore/experiments/videodisplay.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python3
+from gi.repository import GObject, Gst
+
+class VideomixerWithDisplay(Gst.Bin):
+ def __init__(self):
+ super().__init__()
+
+ # Create elements
+ self.secondsrc = Gst.ElementFactory.make('videotestsrc', None)
+ self.mixer = Gst.ElementFactory.make('videomixer', None)
+ self.ident = Gst.ElementFactory.make('identity', None)
+ self.conv = Gst.ElementFactory.make('videoconvert', None)
+ self.q1 = Gst.ElementFactory.make('queue', None)
+ self.q2 = Gst.ElementFactory.make('queue', None)
+ self.display = Gst.ElementFactory.make('ximagesink', None)
+
+ # Add elements to Bin
+ self.add(self.secondsrc)
+ self.add(self.mixer)
+ self.add(self.ident)
+ self.add(self.conv)
+ self.add(self.display)
+ self.add(self.q1)
+ self.add(self.q2)
+
+ # Set properties
+ self.secondsrc.set_property('pattern', 'ball')
+ self.ident.set_property('sync', True)
+ self.display.set_property('sync', False)
+
+ # Request Pads
+ self.firstpad = self.mixer.get_request_pad('sink_%u')
+ self.secondpad = self.mixer.get_request_pad('sink_%u')
+
+ # Set pad-properties
+ self.secondpad.set_property('alpha', 0.75)
+ self.secondpad.set_property('xpos', 50)
+ self.secondpad.set_property('ypos', 50)
+
+ # Link elements
+ self.q1.get_static_pad('src').link(self.firstpad)
+
+ self.q2.get_static_pad('src').link(self.secondpad)
+ self.secondsrc.link_filtered(self.ident, Gst.Caps.from_string('video/x-raw,format=BGRA,width=400,height=400,framerate=25/1'))
+ self.ident.link(self.q2)
+
+ self.mixer.link(self.conv)
+ self.conv.link(self.display)
+
+ # Add Ghost Pads
+ self.add_pad(
+ Gst.GhostPad.new('sink', self.q1.get_static_pad('sink'))
+ )