aboutsummaryrefslogtreecommitdiff
path: root/voctocore
diff options
context:
space:
mode:
authorMaZderMind <github@mazdermind.de>2015-05-23 13:19:51 +0200
committerMaZderMind <github@mazdermind.de>2015-05-23 13:19:51 +0200
commitc7755226facb125af1fc154dd0a4ee5e6659d428 (patch)
treedb004f0d150f30d85ae5cae1add5df783d96ab3a /voctocore
parent73c26dc57606299cd0cb3ce99ed67a1cfe8cd9f4 (diff)
Side-by-Side Preview composition mode
Diffstat (limited to 'voctocore')
-rw-r--r--voctocore/default-config.ini6
-rw-r--r--voctocore/lib/videomix.py89
-rwxr-xr-xvoctocore/scripts/demo-cycle-modes.sh3
-rwxr-xr-xvoctocore/scripts/set-composite-side-by-side-preview.sh2
4 files changed, 99 insertions, 1 deletions
diff --git a/voctocore/default-config.ini b/voctocore/default-config.ini
index c3a867e..eb2de84 100644
--- a/voctocore/default-config.ini
+++ b/voctocore/default-config.ini
@@ -9,6 +9,12 @@ sources=cam1,cam2,grabber
; defaults to 1% of the video width
;gutter=12
+[side-by-side-preview]
+;asize=1024x576
+;apos=12/12
+;bsize=320x180
+;bpos=948/528
+
[previews]
; disable if ui & server run on the same computer and exchange uncompressed video frames
enabled=true
diff --git a/voctocore/lib/videomix.py b/voctocore/lib/videomix.py
index d996967..53e1d03 100644
--- a/voctocore/lib/videomix.py
+++ b/voctocore/lib/videomix.py
@@ -8,6 +8,7 @@ from lib.config import Config
class CompositeModes(Enum):
fullscreen = 0
side_by_side_equal = 1
+ side_by_side_preview = 2
class VideoMix(object):
log = logging.getLogger('VideoMix')
@@ -76,9 +77,12 @@ class VideoMix(object):
if self.compositeMode == CompositeModes.fullscreen:
self.updateMixerStateFullscreen()
- if self.compositeMode == CompositeModes.side_by_side_equal:
+ elif self.compositeMode == CompositeModes.side_by_side_equal:
self.updateMixerStateSideBySideEqual()
+ elif self.compositeMode == CompositeModes.side_by_side_preview:
+ self.updateMixerStateSideBySidePreview()
+
def updateMixerStateFullscreen(self):
self.log.info('Updating Mixer-State for Fullscreen-Composition')
@@ -151,6 +155,89 @@ class VideoMix(object):
self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f', idx, 0, 0, 0)
self.log.debug('Resetting Scaler %u to non-scaling', idx)
+ def updateMixerStateSideBySidePreview(self):
+ self.log.info('Updating Mixer-State for Side-by-side-Preview-Composition')
+
+ width, height = self.getInputVideoSize()
+ self.log.debug('Video-Size parsed as %ux%u', width, height)
+
+ try:
+ asize = [int(i) for i in Config.get('side-by-side-preview', 'asize').split('x', 1)]
+ self.log.debug('A-Video-Size configured to %ux%u', asize[0], asize[1])
+ except:
+ asize = [
+ int(width / 1.25), # 80%
+ int(height / 1.25) # 80%
+ ]
+ self.log.debug('A-Video-Size calculated to %ux%u', asize[0], asize[1])
+
+ try:
+ apos = [int(i) for i in Config.get('side-by-side-preview', 'apos').split('/', 1)]
+ self.log.debug('B-Video-Position configured to %u/%u', apos[0], apos[1])
+ except:
+ apos = [
+ int(width / 100), # 1%
+ int(width / 100) # 1%
+ ]
+ self.log.debug('B-Video-Position calculated to %u/%u', apos[0], apos[1])
+
+ try:
+ bsize = [int(i) for i in Config.get('side-by-side-preview', 'bsize').split('x', 1)]
+ self.log.debug('B-Video-Size configured to %ux%u', bsize[0], bsize[1])
+ except:
+ bsize = [
+ int(width / 4), # 25%
+ int(height / 4) # 25%
+ ]
+ self.log.debug('B-Video-Size calculated to %ux%u', bsize[0], bsize[1])
+
+ try:
+ bpos = [int(i) for i in Config.get('side-by-side-preview', 'bpos').split('/', 1)]
+ self.log.debug('B-Video-Position configured to %u/%u', bpos[0], bpos[1])
+ except:
+ bpos = [
+ width - int(width / 100) - bsize[0],
+ height - int(width / 100) - bsize[1] # 1%
+ ]
+ self.log.debug('B-Video-Position calculated to %u/%u', bpos[0], bpos[1])
+
+ aCaps = Gst.Caps.from_string('video/x-raw,width=%u,height=%u' % tuple(asize))
+ bCaps = Gst.Caps.from_string('video/x-raw,width=%u,height=%u' % tuple(bsize))
+ 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)
+
+ 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)
+ 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, 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)
+ 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, 0)
+ self.log.debug('Setting Scaler %u to %u/%u', idx, bsize[0], bsize[1])
+
+ else:
+ mixerpad.set_property('alpha', 0)
+ mixerpad.set_property('xpos', 0)
+ mixerpad.set_property('ypos', 0)
+ capsfilter.set_property('caps', noScaleCaps)
+
+ self.log.debug('Setting Mixerpad %u to x/y=%u/%u and alpha=%0.2f', idx, 0, 0, 0)
+ self.log.debug('Resetting Scaler %u to non-scaling', idx)
+
def setVideoSourceA(self, source):
# swap if required
if self.sourceB == source:
diff --git a/voctocore/scripts/demo-cycle-modes.sh b/voctocore/scripts/demo-cycle-modes.sh
index c0c6736..264bdfa 100755
--- a/voctocore/scripts/demo-cycle-modes.sh
+++ b/voctocore/scripts/demo-cycle-modes.sh
@@ -1,4 +1,7 @@
while true; do
+ ./set-composite-side-by-side-preview.sh
+ sleep 10
+ ./set-video-cam2.sh
sleep 10
./set-composite-side-by-side-equal.sh
sleep 10
diff --git a/voctocore/scripts/set-composite-side-by-side-preview.sh b/voctocore/scripts/set-composite-side-by-side-preview.sh
new file mode 100755
index 0000000..dd8a04b
--- /dev/null
+++ b/voctocore/scripts/set-composite-side-by-side-preview.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+echo set_composite_mode side_by_side_preview | nc -q0 localhost 9999