diff options
-rwxr-xr-x | example-scripts/control-server/demo-cycle-modes.sh | 3 | ||||
-rw-r--r-- | voctocore/README.md | 9 | ||||
-rw-r--r-- | voctocore/lib/avpreviewoutput.py | 7 | ||||
-rw-r--r-- | voctocore/lib/config.py | 7 | ||||
-rw-r--r-- | voctogui/README.md | 17 | ||||
-rw-r--r-- | voctogui/lib/config.py | 1 |
6 files changed, 34 insertions, 10 deletions
diff --git a/example-scripts/control-server/demo-cycle-modes.sh b/example-scripts/control-server/demo-cycle-modes.sh index b626b28..7440cf1 100755 --- a/example-scripts/control-server/demo-cycle-modes.sh +++ b/example-scripts/control-server/demo-cycle-modes.sh @@ -1,3 +1,6 @@ +#!/bin/bash +cd "$(dirname ${BASH_SOURCE[0]})" + while true; do sleep 10 echo "composite-picture-in-picture" diff --git a/voctocore/README.md b/voctocore/README.md index e3e62f4..b7b5242 100644 --- a/voctocore/README.md +++ b/voctocore/README.md @@ -3,7 +3,7 @@ ## Design goals Our Design is heavily influenced by gst-switch. We wanted a small videomixer core-process, whose sourcecode can be read and understand in about a weekend. All Sources (Cameras, Slide-Grabbers) and Sinks (Streaming, Recording) should be separate Processes. As far as possible we wanted to reuse our existing and well-tested ffmpeg Commandlines for streaming and recording. It should be possible to connect additional Sinks at any time while the number of Sources is predefined in our Setup. All sources and sinks should be able to die and get restarted without taking the core process down. -While Sources ans Sinks all run on the same Machine, Control- or Monitoring-Clients, for example a GUI, should be able to run on a different machine and connect to the core-process via Gigabit Ethernet. The core-process should be controllable by a very simple protocol which can easily be scripted or spoken with usual networking tools. +While Sources and Sinks all run on the same Machine, Control- or Monitoring-Clients, for example a GUI, should be able to run on a different machine and connect to the core-process via Gigabit Ethernet. The core-process should be controllable by a very simple protocol which can easily be scripted or spoken with usual networking tools. ## Design decisions To meet our goal of "read and understand in about a weekend" python was chosen as language for the high-level parts, with [GStreamer](http://gstreamer.freedesktop.org/) for the low-level media handling. GStreamer can be controlled via the [PyGI](https://wiki.gnome.org/action/show/Projects/PyGObject) bindings from Python. @@ -11,7 +11,7 @@ As an Idea borrowed from gst-switch, all Video- and Audio-Streams to and from th The ubiquitous Input/Output-Format into the core-process is therefore Raw UYVY Frames and Raw S16LE Audio in a Matroska container for Timestamping via TCP over localhost. Network handling is done in python, because it allows for greater flexibility. After the TCP connection is ready, its file descriptor is passed to GStreamer which handles the low-level read/write operations. To be able to attach/detach sinks, the `multifdsink`-Element can be used. For the Sources it's more complicated: -When a source is not connected, its video and audio stream must be substituted with black frames ans silence, to that the remaining parts of the pipeline can keep on running. To achive this, a separate GStreamer-Pipeline is launched for an incoming Source-Connection and destroyed in case of a disconnect or an error. To pass Video -and Audio-Buffers between the Source-Pipelines and the other parts of the Mixer, we make use of the `inter(audio/video)(sink/source)`-Elements. `intervideosrc` and `interaudiosrc` implement the creation of black frames and silence, in case no source is connected or the source broke down somehow. +When a source is not connected, its video and audio stream must be substituted with black frames and silence, to that the remaining parts of the pipeline can keep on running. To achive this, a separate GStreamer-Pipeline is launched for an incoming Source-Connection and destroyed in case of a disconnect or an error. To pass Video -and Audio-Buffers between the Source-Pipelines and the other parts of the Mixer, we make use of the `inter(audio/video)(sink/source)`-Elements. `intervideosrc` and `interaudiosrc` implement the creation of black frames and silence, in case no source is connected or the source broke down somehow. If enabled in Config, the core process offers two formats for most outputs: Raw-Frames in mkv as described above, which should be used to feed recording or streaming processes running on the same machine. For the GUI which usually runs on a different computer, they are not suited because of the bandwidth requirements (1920×1080 UYVY @25fps = 791 MBit/s). For this reason the Servers offers Preview-Ports for each Input and the Main-Mix, which serves the same content, but the video frames there are jpeg compressed, combined with uncompressed S16LE audio and encapsulated in mkv. @@ -147,8 +147,9 @@ They can be used to Implement Features like a "Cut-Button" in the GUI. When Clic On Startup the Video-Mixer reads the following Configuration-Files: - `<install-dir>/default-config.ini` - `<install-dir>/config.ini` - - `/etc/voctomix.ini` - - `<homedir>/.voctomix.ini` + - `/etc/voctomix/voctocore.ini` + - `/etc/voctocore.ini` + - `<homedir>/.voctocore.ini` - `<File specified on Command-Line via --ini-file>` From top to bottom the individual Settings override previous Settings. `default-config.ini` should not be edited, because a missing Setting will result in an Exception. diff --git a/voctocore/lib/avpreviewoutput.py b/voctocore/lib/avpreviewoutput.py index ac5fd0a..a0bb951 100644 --- a/voctocore/lib/avpreviewoutput.py +++ b/voctocore/lib/avpreviewoutput.py @@ -20,10 +20,13 @@ class AVPreviewOutput(TCPMultiConnection): pipeline = """ intervideosrc channel=video_{channel} ! {vcaps_in} ! + capssetter caps="video/x-raw,interlace-mode=interlaced" ! + deinterlace ! + video/x-raw,interlace-mode=progressive ! + videoscale ! videorate ! - videoscale method=nearest-neighbour ! {vcaps_out} ! - jpegenc ! + jpegenc quality=90 ! queue ! mux. diff --git a/voctocore/lib/config.py b/voctocore/lib/config.py index ebb9e1e..3075f61 100644 --- a/voctocore/lib/config.py +++ b/voctocore/lib/config.py @@ -12,8 +12,11 @@ SafeConfigParser.getlist = getlist files = [ os.path.join(os.path.dirname(os.path.realpath(__file__)), '../default-config.ini'), os.path.join(os.path.dirname(os.path.realpath(__file__)), '../config.ini'), - '/etc/voctomix.ini', - os.path.expanduser('~/.voctomix.ini'), + '/etc/voctomix/voctocore.ini', + '/etc/voctomix.ini', # deprecated + '/etc/voctocore.ini', + os.path.expanduser('~/.voctomix.ini'), # deprecated + os.path.expanduser('~/.voctocore.ini'), ] if Args.ini_file is not None: diff --git a/voctogui/README.md b/voctogui/README.md index 156a086..6c5fd84 100644 --- a/voctogui/README.md +++ b/voctogui/README.md @@ -1,4 +1,4 @@ -# Voctocore - The gui-frontend for voctocore +# Voctogui - The GUI frontend for Voctocore ![Screenshot of voctogui in action](voctomix.png) @@ -23,4 +23,17 @@ - `t` Cut ### Select an Audio-Source -Click twice on the Selection Combobox, the select your Source within 5 Seconds (It will auto-lock again after 5 Seconds) +Click twice on the selection combobox, then select your source within 5 Seconds. (It will auto-lock again after 5 seconds.) + +## Configuration +On startup the GUI reads the following configuration files: + - `<install-dir>/default-config.ini` + - `<install-dir>/config.ini` + - `/etc/voctomix/voctogui.ini` + - `/etc/voctogui.ini` + - `<homedir>/.voctogui.ini` + - `<File specified on Command-Line via --ini-file>` + +From top to bottom the individual settings override previous settings. `default-config.ini` should not be edited, because a missing setting will result in a Python exception. + +On startup the GUI fetches all configuration settings from the core and merges them into the GUI config. diff --git a/voctogui/lib/config.py b/voctogui/lib/config.py index 4120092..d4630bf 100644 --- a/voctogui/lib/config.py +++ b/voctogui/lib/config.py @@ -25,6 +25,7 @@ SafeConfigParser.fetchServerConfig = fetchServerConfig files = [ os.path.join(os.path.dirname(os.path.realpath(__file__)), '../default-config.ini'), os.path.join(os.path.dirname(os.path.realpath(__file__)), '../config.ini'), + '/etc/voctomix/voctogui.ini', '/etc/voctogui.ini', os.path.expanduser('~/.voctogui.ini'), ] |