aboutsummaryrefslogtreecommitdiff
path: root/voctocore/lib
diff options
context:
space:
mode:
Diffstat (limited to 'voctocore/lib')
-rw-r--r--voctocore/lib/backgroundsource.py51
-rw-r--r--voctocore/lib/pipeline.py4
-rw-r--r--voctocore/lib/videomix.py52
3 files changed, 87 insertions, 20 deletions
diff --git a/voctocore/lib/backgroundsource.py b/voctocore/lib/backgroundsource.py
new file mode 100644
index 0000000..1f3da54
--- /dev/null
+++ b/voctocore/lib/backgroundsource.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python3
+import logging
+from gi.repository import Gst
+
+from lib.config import Config
+from lib.tcpsingleconnection import TCPSingleConnection
+
+class BackgroundSource(TCPSingleConnection):
+ def __init__(self, port):
+ self.log = logging.getLogger('BackgroundSource')
+ super().__init__(port)
+
+ def on_accepted(self, conn, addr):
+ pipeline = """
+ fdsrc fd={fd} !
+ matroskademux !
+ {vcaps} !
+ intervideosink channel=mixer_background
+ """.format(
+ fd=conn.fileno(),
+ vcaps=Config.get('mix', 'videocaps')
+ )
+
+ self.log.debug('Launching Source-Pipeline:\n%s', pipeline)
+ self.receiverPipeline = Gst.parse_launch(pipeline)
+
+ self.log.debug('Binding End-of-Stream-Signal on Source-Pipeline')
+ self.receiverPipeline.bus.add_signal_watch()
+ self.receiverPipeline.bus.connect("message::eos", self.on_eos)
+ self.receiverPipeline.bus.connect("message::error", self.on_error)
+
+ self.receiverPipeline.set_state(Gst.State.PLAYING)
+
+
+ def on_eos(self, bus, message):
+ self.log.debug('Received End-of-Stream-Signal on Source-Pipeline')
+ if self.currentConnection is not None:
+ self.disconnect()
+
+ def on_error(self, bus, message):
+ self.log.debug('Received Error-Signal on Source-Pipeline')
+ (error, debug) = message.parse_error()
+ self.log.debug('Error-Details: #%u: %s', error.code, debug)
+
+ if self.currentConnection is not None:
+ self.disconnect()
+
+ def disconnect(self):
+ self.receiverPipeline.set_state(Gst.State.NULL)
+ self.receiverPipeline = None
+ self.close_connection()
diff --git a/voctocore/lib/pipeline.py b/voctocore/lib/pipeline.py
index 9addca0..a45ea53 100644
--- a/voctocore/lib/pipeline.py
+++ b/voctocore/lib/pipeline.py
@@ -7,6 +7,7 @@ from lib.config import Config
from lib.avsource import AVSource
from lib.avrawoutput import AVRawOutput
from lib.avpreviewoutput import AVPreviewOutput
+from lib.backgroundsource import BackgroundSource
from lib.videomix import VideoMix
from lib.audiomix import AudioMix
@@ -56,6 +57,9 @@ class Pipeline(object):
self.log.info('Creating Videmixer')
self.amix = AudioMix()
+ port = 16000
+ self.bgsrc = BackgroundSource(port)
+
port = 11000
self.log.info('Creating Mixer-Output at tcp-port %u', port)
self.mixout = AVRawOutput('mix_out', port)
diff --git a/voctocore/lib/videomix.py b/voctocore/lib/videomix.py
index d5349c5..1bee90a 100644
--- a/voctocore/lib/videomix.py
+++ b/voctocore/lib/videomix.py
@@ -26,6 +26,10 @@ class VideoMix(object):
queue !
tee name=tee
+ intervideosrc channel=mixer_background !
+ {caps} !
+ mix.
+
tee. ! queue ! intervideosink channel=video_mix_out
""".format(
caps=self.caps
@@ -63,6 +67,9 @@ class VideoMix(object):
self.sourceB = 1
self.updateMixerState()
+ bgMixerpad = self.mixingPipeline.get_by_name('mix').get_static_pad('sink_0')
+ bgMixerpad.set_property('zorder', 0)
+
self.log.debug('Launching Mixing-Pipeline')
self.mixingPipeline.set_state(Gst.State.PLAYING)
@@ -87,6 +94,12 @@ class VideoMix(object):
elif self.compositeMode == CompositeModes.picture_in_picture:
self.updateMixerStatePictureInPicture()
+ def getMixerpadAndCapsfilter(self, idx):
+ # mixerpad 0 = background
+ mixerpad = self.mixingPipeline.get_by_name('mix').get_static_pad('sink_%u' % (idx+1))
+ capsfilter = self.mixingPipeline.get_by_name('caps_%u' % idx)
+ return mixerpad, capsfilter
+
def updateMixerStateFullscreen(self):
self.log.info('Updating Mixer-State for Fullscreen-Composition')
@@ -94,15 +107,15 @@ class VideoMix(object):
for idx, name in enumerate(self.names):
alpha = int(idx == self.sourceA)
+ mixerpad, capsfilter = self.getMixerpadAndCapsfilter(idx)
- self.log.debug('Setting Mixerpad %u to x/y=0 and alpha=%0.2f', idx, alpha)
- mixerpad = self.mixingPipeline.get_by_name('mix').get_static_pad('sink_%u' % idx)
- mixerpad.set_property('alpha', alpha )
+ self.log.debug('Setting Mixerpad %u to x/y=0 and alpha=%0.2f, zorder=%u', idx, alpha, 1)
+ mixerpad.set_property('alpha', alpha)
mixerpad.set_property('xpos', 0)
mixerpad.set_property('ypos', 0)
+ mixerpad.set_property('zorder', 1)
self.log.debug('Resetting Scaler %u to non-scaling', idx)
- capsfilter = self.mixingPipeline.get_by_name('caps_%u' % idx)
capsfilter.set_property('caps', noScaleCaps)
def updateMixerStateSideBySideEqual(self):
@@ -129,25 +142,26 @@ class VideoMix(object):
noScaleCaps = Gst.Caps.from_string('video/x-raw')
for idx, name in enumerate(self.names):
- mixerpad = self.mixingPipeline.get_by_name('mix').get_static_pad('sink_%u' % idx)
- capsfilter = self.mixingPipeline.get_by_name('caps_%u' % idx)
+ mixerpad, capsfilter = self.getMixerpadAndCapsfilter(idx)
if idx == self.sourceA:
mixerpad.set_property('alpha', 1)
mixerpad.set_property('xpos', xa)
mixerpad.set_property('ypos', y)
+ mixerpad.set_property('zorder', 1)
capsfilter.set_property('caps', scaleCaps)
- self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f', idx, xa, y, 1)
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f, zorder=%u', idx, xa, y, 1, 1)
self.log.debug('Setting Scaler %u to %u/%u', idx, targetWidth, targetHeight)
elif idx == self.sourceB:
mixerpad.set_property('alpha', 1)
mixerpad.set_property('xpos', xb)
mixerpad.set_property('ypos', y)
+ mixerpad.set_property('zorder', 1)
capsfilter.set_property('caps', scaleCaps)
- self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f', idx, xb, y, 1)
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f, zorder=%u', idx, xb, y, 1, 1)
self.log.debug('Setting Scaler %u to %u/%u', idx, targetWidth, targetHeight)
else:
@@ -210,27 +224,26 @@ class VideoMix(object):
noScaleCaps = Gst.Caps.from_string('video/x-raw')
for idx, name in enumerate(self.names):
- mixerpad = self.mixingPipeline.get_by_name('mix').get_static_pad('sink_%u' % idx)
- capsfilter = self.mixingPipeline.get_by_name('caps_%u' % idx)
+ mixerpad, capsfilter = self.getMixerpadAndCapsfilter(idx)
if idx == self.sourceA:
mixerpad.set_property('alpha', 1)
mixerpad.set_property('xpos', apos[1])
mixerpad.set_property('ypos', apos[1])
- mixerpad.set_property('zorder', 0)
+ mixerpad.set_property('zorder', 1)
capsfilter.set_property('caps', aCaps)
- self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f, zorder=%u', idx, apos[0], apos[1], 1, 0)
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f, zorder=%u', idx, apos[0], apos[1], 1, 1)
self.log.debug('Setting Scaler %u to %u/%u', idx, asize[0], asize[1])
elif idx == self.sourceB:
mixerpad.set_property('alpha', 1)
mixerpad.set_property('xpos', bpos[0])
mixerpad.set_property('ypos', bpos[1])
- mixerpad.set_property('zorder', 1)
+ mixerpad.set_property('zorder', 2)
capsfilter.set_property('caps', bCaps)
- self.log.debug('Setting Mixerpad %u to x/y=%u/%u, alpha=%0.2f, zorder=%u', idx, bpos[0], bpos[1], 1, 1)
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u, alpha=%0.2f, zorder=%u', idx, bpos[0], bpos[1], 1, 2)
self.log.debug('Setting Scaler %u to %u/%u', idx, bsize[0], bsize[1])
else:
@@ -272,27 +285,26 @@ class VideoMix(object):
noScaleCaps = Gst.Caps.from_string('video/x-raw')
for idx, name in enumerate(self.names):
- mixerpad = self.mixingPipeline.get_by_name('mix').get_static_pad('sink_%u' % idx)
- capsfilter = self.mixingPipeline.get_by_name('caps_%u' % idx)
+ mixerpad, capsfilter = self.getMixerpadAndCapsfilter(idx)
if idx == self.sourceA:
mixerpad.set_property('alpha', 1)
mixerpad.set_property('xpos', 0)
mixerpad.set_property('ypos', 0)
- mixerpad.set_property('zorder', 0)
+ mixerpad.set_property('zorder', 1)
capsfilter.set_property('caps', noScaleCaps)
- self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f, zorder=%u', idx, 0, 0, 1, 0)
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f, zorder=%u', idx, 0, 0, 1, 1)
self.log.debug('Resetting Scaler %u to non-scaling', idx)
elif idx == self.sourceB:
mixerpad.set_property('alpha', 1)
mixerpad.set_property('xpos', pippos[0])
mixerpad.set_property('ypos', pippos[1])
- mixerpad.set_property('zorder', 1)
+ mixerpad.set_property('zorder', 2)
capsfilter.set_property('caps', scaleCaps)
- self.log.debug('Setting Mixerpad %u to x/y=%u/%u, alpha=%0.2f, zorder=%u', idx, pippos[0], pippos[1], 1, 1)
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u, alpha=%0.2f, zorder=%u', idx, pippos[0], pippos[1], 1, 2)
self.log.debug('Setting Scaler %u to %u/%u', idx, pipsize[0], pipsize[1])
else: