diff options
-rwxr-xr-x | voctocore/experiments/failovertest.py | 83 | ||||
-rw-r--r-- | voctocore/experiments/shmsrc.py | 27 | ||||
-rwxr-xr-x | voctocore/experiments/test-grabber-src.sh | 10 | ||||
-rw-r--r-- | voctocore/experiments/videodisplay.py | 53 |
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')) + ) |