aboutsummaryrefslogtreecommitdiff
path: root/example-scripts/gstreamer
diff options
context:
space:
mode:
Diffstat (limited to 'example-scripts/gstreamer')
-rwxr-xr-xexample-scripts/gstreamer/ingest.py230
-rwxr-xr-xexample-scripts/gstreamer/source-background-loop.py118
-rwxr-xr-xexample-scripts/gstreamer/source-nostream-music-from-folder.py363
-rwxr-xr-xexample-scripts/gstreamer/source-remote-desktop-as-cam1.py163
-rwxr-xr-xexample-scripts/gstreamer/source-remote-videotestsrc-as-cam1.py149
5 files changed, 538 insertions, 485 deletions
diff --git a/example-scripts/gstreamer/ingest.py b/example-scripts/gstreamer/ingest.py
index a9e06c4..efb7be2 100755
--- a/example-scripts/gstreamer/ingest.py
+++ b/example-scripts/gstreamer/ingest.py
@@ -9,7 +9,6 @@ Features:
Mix and match audio and video sources muxed into one streem.
Can display video locally, including frame count and fps.
Defaults to test audio and video sent to local core.
-
"""
import argparse
@@ -27,8 +26,8 @@ GObject.threads_init()
Gst.init([])
# this is to use the same code tha gui uses to get config from core
-sys.path.insert(0, '../..' )
-sys.path.insert(0, '.' )
+sys.path.insert(0, '../..')
+sys.path.insert(0, '.')
import voctogui.lib.connection as Connection
@@ -39,142 +38,143 @@ def mk_video_src(args, videocaps):
video_device = "device={}".format(args.video_dev) \
if args.video_dev else ""
- monitor = """tee name=t ! queue !
- videoconvert ! fpsdisplaysink sync=false
- t. ! queue !""" \
- if args.monitor else ""
+ monitor = """
+ tee name=t !
+ queue !
+ videoconvert !
+ fpsdisplaysink sync=false
+ t. ! queue !
+ """ if args.monitor else ""
if args.video_source == 'dv':
video_src = """
- dv1394src name=videosrc {video_device}!
- dvdemux name=demux !
- queue !
- dvdec !
- {monitor}
- deinterlace mode=1 !
- videoconvert !
- videorate !
- videoscale !
- """
-
+ dv1394src name=videosrc {video_device} !
+ dvdemux name=demux !
+ queue !
+ dvdec !
+ {monitor}
+ deinterlace mode=1 !
+ videoconvert !
+ videorate !
+ videoscale !
+ """
+
elif args.video_source == 'hdv':
video_src = """
hdv1394src {video_device} do-timestamp=true name=videosrc !
- tsdemux name=demux!
- queue !
- decodebin !
- {monitor}
- deinterlace mode=1 !
- videorate !
- videoscale !
- videoconvert !
- """
+ tsdemux name=demux!
+ queue !
+ decodebin !
+ {monitor}
+ deinterlace mode=1 !
+ videorate !
+ videoscale !
+ videoconvert !
+ """
elif args.video_source == 'hdmi2usb':
# https://hdmi2usb.tv
# Note: this code works with 720p
video_src = """
v4l2src {video_device} name=videosrc !
- queue !
- image/jpeg,width=1280,height=720 !
- jpegdec !
- {monitor}
- videoconvert !
- videorate !
- """
+ queue !
+ image/jpeg,width=1280,height=720 !
+ jpegdec !
+ {monitor}
+ videoconvert !
+ videorate !
+ """
elif args.video_source == 'ximage':
video_src = """
- ximagesrc name=videosrc
- use-damage=false !
- {monitor}
- videoconvert !
- videorate !
- videoscale !
- """
- # startx=0 starty=0 endx=1919 endy=1079 !
+ ximagesrc name=videosrc
+ use-damage=false !
+ {monitor}
+ videoconvert !
+ videorate !
+ videoscale !
+ """
+ # startx=0 starty=0 endx=1919 endy=1079 !
elif args.video_source == 'blackmagichdmi':
video_src = """
decklinkvideosrc mode=17 connection=2 !
- {monitor}
- videoconvert !
- videorate !
- videoscale !
- """
+ {monitor}
+ videoconvert !
+ videorate !
+ videoscale !
+ """
elif args.video_source == 'test':
video_src = """
- videotestsrc name=videosrc
- pattern=ball
+ videotestsrc name=videosrc
+ pattern=ball
foreground-color=0x00ff0000 background-color=0x00440000 !
- {monitor}
- """
+ {monitor}
+ """
- video_src = video_src.format(
- video_device=video_device,
- monitor=monitor)
+ video_src = video_src.format(video_device=video_device, monitor=monitor)
video_src += videocaps + "!\n"
return video_src
-def mk_audio_src(args, audiocaps):
+def mk_audio_src(args, audiocaps):
audio_device = "device={}".format(args.audio_dev) \
if args.audio_dev else ""
- if args.audio_source in [ 'dv', 'hdv' ]:
+ if args.audio_source in ['dv', 'hdv']:
# this only works if video is from DV also.
# or some gst source that gets demux ed
audio_src = """
demux. !
- audioconvert !
- """
+ audioconvert !
+ """
elif args.audio_source == 'pulse':
audio_src = """
- pulsesrc {audio_device} name=audiosrc !
- """.format(audio_device=audio_device)
+ pulsesrc {audio_device} name=audiosrc !
+ """.format(audio_device=audio_device)
elif args.audio_source == 'alsa':
audio_src = """
- alsasrc {audio_device} name=audiosrc !
- """.format(audio_device=audio_device)
+ alsasrc {audio_device} name=audiosrc !
+ """.format(audio_device=audio_device)
elif args.audio_source == 'blackmagichdmi':
audio_src = """
decklinkaudiosrc !
- """
+ """
elif args.audio_source == 'test':
audio_src = """
audiotestsrc name=audiosrc freq=330 !
- """
+ """
audio_src += audiocaps + "!\n"
return audio_src
-def mk_mux(args):
+def mk_mux(args):
mux = """
- mux.
- matroskamux name=mux !
- """
+ mux.
+ matroskamux name=mux !
+ """
return mux
+
def mk_client(args):
core_ip = socket.gethostbyname(args.host)
- client = """
- tcpclientsink host={host} port={port}
- """.format(host=core_ip, port=args.port)
+ client = """
+ tcpclientsink host={host} port={port}
+ """.format(host=core_ip, port=args.port)
return client
def mk_pipeline(args, server_caps):
-
video_src = mk_video_src(args, server_caps['videocaps'])
audio_src = mk_audio_src(args, server_caps['audiocaps'])
mux = mk_mux(args)
@@ -183,22 +183,21 @@ def mk_pipeline(args, server_caps):
pipeline = video_src + "mux.\n" + audio_src + mux + client
# remove blank lines to make it more human readable
- pipeline = pipeline.replace("\n\n","\n")
+ pipeline = pipeline.replace("\n\n", "\n")
return pipeline
-def get_server_caps():
-
+def get_server_caps():
# fetch config from server
server_config = Connection.fetchServerConfig()
server_caps = {'videocaps': server_config['mix']['videocaps'],
- 'audiocaps': server_config['mix']['audiocaps']}
+ 'audiocaps': server_config['mix']['audiocaps']}
return server_caps
-def run_pipeline(pipeline, args):
+def run_pipeline(pipeline, args):
core_ip = socket.gethostbyname(args.host)
clock = GstNet.NetClientClock.new('voctocore', core_ip, 9998, 0)
@@ -212,17 +211,16 @@ def run_pipeline(pipeline, args):
senderPipeline.use_clock(clock)
src = senderPipeline.get_by_name('src')
- def on_eos(self, bus, message):
+ def on_eos(bus, message):
print('Received EOS-Signal')
sys.exit(1)
- def on_error(self, bus, message):
+ def on_error(bus, message):
print('Received Error-Signal')
(error, debug) = message.parse_error()
print('Error-Details: #%u: %s' % (error.code, debug))
sys.exit(1)
-
# Binding End-of-Stream-Signal on Source-Pipeline
senderPipeline.bus.add_signal_watch()
senderPipeline.bus.connect("message::eos", on_eos)
@@ -230,7 +228,7 @@ def run_pipeline(pipeline, args):
print("playing")
senderPipeline.set_state(Gst.State.PLAYING)
-
+
mainloop = GObject.MainLoop()
try:
mainloop.run()
@@ -243,65 +241,64 @@ def run_pipeline(pipeline, args):
return
-def get_args():
+def get_args():
parser = argparse.ArgumentParser(
- description='''Vocto-ingest Client with Net-time support.
+ description='''Vocto-ingest Client with Net-time support.
Gst caps are retrieved from the server.
Run without parameters: send test av to localhost:10000
- ''')
-
+ '''
+ )
+
parser.add_argument('-v', '--verbose', action='count', default=0,
- help="Also print INFO and DEBUG messages.")
+ help="Also print INFO and DEBUG messages.")
- parser.add_argument( '--video-source', action='store',
- choices=[
- 'dv', 'hdv', 'hdmi2usb', 'blackmagichdmi',
- 'ximage',
- 'test', ],
- default='test',
- help="Where to get video from")
+ parser.add_argument('--video-source', action='store',
+ choices=['dv', 'hdv', 'hdmi2usb',
+ 'blackmagichdmi', 'ximage', 'test'],
+ default='test',
+ help="Where to get video from")
- parser.add_argument( '--video-dev', action='store',
- help="video device")
+ parser.add_argument('--video-dev', action='store',
+ help="video device")
- parser.add_argument( '--audio-source', action='store',
- choices=['dv', 'alsa', 'pulse', 'blackmagichdmi', 'test'],
- default='test',
- help="Where to get audio from")
+ parser.add_argument('--audio-source', action='store',
+ choices=['dv', 'alsa', 'pulse',
+ 'blackmagichdmi', 'test'],
+ default='test',
+ help="Where to get audio from")
- parser.add_argument( '--audio-dev', action='store',
- default='hw:CARD=CODEC',
- help="for alsa/pulse, audio device")
- # maybe hw:1,0
+ # maybe hw:1,0
+ parser.add_argument('--audio-dev', action='store',
+ default='hw:CARD=CODEC',
+ help="for alsa/pulse, audio device")
- parser.add_argument( '--audio-delay', action='store',
- default='10',
- help="ms to delay audio")
+ parser.add_argument('--audio-delay', action='store',
+ default='10',
+ help="ms to delay audio")
parser.add_argument('-m', '--monitor', action='store_true',
- help="fps display sink")
+ help="fps display sink")
- parser.add_argument( '--host', action='store',
- default='localhost',
- help="hostname of vocto core")
+ parser.add_argument('--host', action='store',
+ default='localhost',
+ help="hostname of vocto core")
- parser.add_argument( '--port', action='store',
- default='10000',
- help="port of vocto core")
+ parser.add_argument('--port', action='store',
+ default='10000',
+ help="port of vocto core")
args = parser.parse_args()
return args
-
+
def main():
-
args = get_args()
core_ip = socket.gethostbyname(args.host)
# establish a synchronus connection to server
- Connection.establish(core_ip)
+ Connection.establish(core_ip)
server_caps = get_server_caps()
@@ -310,6 +307,5 @@ def main():
run_pipeline(pipeline, args)
-
if __name__ == '__main__':
main()
diff --git a/example-scripts/gstreamer/source-background-loop.py b/example-scripts/gstreamer/source-background-loop.py
index 2f13edf..4d1dae1 100755
--- a/example-scripts/gstreamer/source-background-loop.py
+++ b/example-scripts/gstreamer/source-background-loop.py
@@ -1,5 +1,8 @@
#!/usr/bin/env python3
-import os, sys, gi, signal
+import os
+import sys
+import gi
+import signal
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject
@@ -8,66 +11,71 @@ from gi.repository import Gst, GObject
GObject.threads_init()
Gst.init([])
+
class LoopSource(object):
- def __init__(self, settings):
- # it works much better with a local file
- pipeline = """
- uridecodebin name=src uri=http://c3voc.mazdermind.de/testfiles/bg.ts !
- videoscale !
- videoconvert !
- video/x-raw,format=I420,width={WIDTH},height={HEIGHT},framerate={FRAMERATE}/1,pixel-aspect-ratio=1/1 !
- matroskamux !
- tcpclientsink host=localhost port=16000
- """.format_map(settings)
-
- print('starting pipeline '+pipeline)
- self.senderPipeline = Gst.parse_launch(pipeline)
- self.src = self.senderPipeline.get_by_name('src')
-
- # Binding End-of-Stream-Signal on Source-Pipeline
- self.senderPipeline.bus.add_signal_watch()
- self.senderPipeline.bus.connect("message::eos", self.on_eos)
- self.senderPipeline.bus.connect("message::error", self.on_error)
-
- print("playing")
- self.senderPipeline.set_state(Gst.State.PLAYING)
-
-
- def on_eos(self, bus, message):
- print('Received EOS-Signal, Seeking to start')
- self.src.seek(
- 1.0, # rate (float)
- Gst.Format.TIME, # format (Gst.Format)
- Gst.SeekFlags.FLUSH, # flags (Gst.SeekFlags)
- Gst.SeekType.SET, # start_type (Gst.SeekType)
- 0, # start (int)
- Gst.SeekType.NONE, # stop_type (Gst.SeekType)
- 0 # stop (int)
- )
-
- def on_error(self, bus, message):
- print('Received Error-Signal')
- (error, debug) = message.parse_error()
- print('Error-Details: #%u: %s' % (error.code, debug))
- sys.exit(1)
+
+ def __init__(self, settings):
+ # it works much better with a local file
+ pipeline = """
+ uridecodebin name=src
+ uri=http://c3voc.mazdermind.de/testfiles/bg.ts !
+ videoscale !
+ videoconvert !
+ video/x-raw,format=I420,width={WIDTH},height={HEIGHT},
+ framerate={FRAMERATE}/1,pixel-aspect-ratio=1/1 !
+ matroskamux !
+ tcpclientsink host=localhost port=16000
+ """.format_map(settings)
+
+ print('starting pipeline ' + pipeline)
+ self.senderPipeline = Gst.parse_launch(pipeline)
+ self.src = self.senderPipeline.get_by_name('src')
+
+ # Binding End-of-Stream-Signal on Source-Pipeline
+ self.senderPipeline.bus.add_signal_watch()
+ self.senderPipeline.bus.connect("message::eos", self.on_eos)
+ self.senderPipeline.bus.connect("message::error", self.on_error)
+
+ print("playing")
+ self.senderPipeline.set_state(Gst.State.PLAYING)
+
+ def on_eos(self, bus, message):
+ print('Received EOS-Signal, Seeking to start')
+ self.src.seek(
+ 1.0, # rate (float)
+ Gst.Format.TIME, # format (Gst.Format)
+ Gst.SeekFlags.FLUSH, # flags (Gst.SeekFlags)
+ Gst.SeekType.SET, # start_type (Gst.SeekType)
+ 0, # start (int)
+ Gst.SeekType.NONE, # stop_type (Gst.SeekType)
+ 0 # stop (int)
+ )
+
+ def on_error(self, bus, message):
+ print('Received Error-Signal')
+ (error, debug) = message.parse_error()
+ print('Error-Details: #%u: %s' % (error.code, debug))
+ sys.exit(1)
+
def main():
- signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
- config = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../config.sh')
- with open(config, 'r') as config:
- lines = [ line.strip() for line in config if line[0] != '#' ]
- pairs = [ line.split('=', 1) for line in lines ]
- settings = { pair[0]: pair[1] for pair in pairs }
+ config = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ '../config.sh')
+ with open(config, 'r') as config:
+ lines = [line.strip() for line in config if line[0] != '#']
+ pairs = [line.split('=', 1) for line in lines]
+ settings = {pair[0]: pair[1] for pair in pairs}
- src = LoopSource(settings)
+ src = LoopSource(settings)
- mainloop = GObject.MainLoop()
- try:
- mainloop.run()
- except KeyboardInterrupt:
- print('Terminated via Ctrl-C')
+ mainloop = GObject.MainLoop()
+ try:
+ mainloop.run()
+ except KeyboardInterrupt:
+ print('Terminated via Ctrl-C')
if __name__ == '__main__':
- main()
+ main()
diff --git a/example-scripts/gstreamer/source-nostream-music-from-folder.py b/example-scripts/gstreamer/source-nostream-music-from-folder.py
index a176a7d..c804182 100755
--- a/example-scripts/gstreamer/source-nostream-music-from-folder.py
+++ b/example-scripts/gstreamer/source-nostream-music-from-folder.py
@@ -1,6 +1,12 @@
#!/usr/bin/env python3
-import os, sys, gi, signal, random
-import argparse, logging, pyinotify
+import os
+import sys
+import gi
+import signal
+import random
+import argparse
+import logging
+import pyinotify
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GLib
@@ -9,189 +15,206 @@ from gi.repository import Gst, GObject, GLib
GObject.threads_init()
Gst.init([])
-class Directory(object):
- def __init__(self, path):
- self.log = logging.getLogger('Directory')
- self.path = path
- self.scheduled = False
- self.rescan()
-
- self.log.debug('setting up inotify watch for %s', self.path)
- wm = pyinotify.WatchManager()
- notifier = pyinotify.Notifier(wm,
- timeout=10,
- default_proc_fun=self.inotify_callback)
-
- wm.add_watch(
- self.path,
- #pyinotify.ALL_EVENTS,
- pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MODIFY,
- rec=True)
-
- GLib.io_add_watch(
- notifier._fd,
- GLib.IO_IN,
- self.io_callback,
- notifier)
-
- def inotify_callback(self, notifier):
- self.log.info('inotify callback %s: %s', notifier.maskname, notifier.pathname)
- if not self.scheduled:
- self.scheduled = True
- GLib.timeout_add(100, self.rescan)
- return True
-
- def io_callback(self, source, condition, notifier):
- notifier.process_events()
- while notifier.check_events():
- notifier.read_events()
- notifier.process_events()
-
- return True
- def is_playable_file(self, filepath):
- root, ext = os.path.splitext(filepath)
- return ext in ['.mp3', '.ogg', '.oga', '.wav', '.m4a', '.flac', 'self.opus']
-
- def rescan(self):
- self.log.info('scanning directory %s', self.path)
- self.scheduled = False
-
- all_files = []
-
- for root, dirs, files in os.walk(self.path):
- files = filter(self.is_playable_file, files)
- files = map(lambda f: os.path.join(root, f), files)
- files = list(files)
-
- self.log.debug('found directory %s: %u playable file(s)', root, len(files))
- all_files.extend(files)
+class Directory(object):
- self.log.info('found %u playable files', len(all_files))
- self.files = all_files
+ def __init__(self, path):
+ self.log = logging.getLogger('Directory')
+ self.path = path
+ self.scheduled = False
+ self.rescan()
+
+ self.log.debug('setting up inotify watch for %s', self.path)
+ wm = pyinotify.WatchManager()
+ notifier = pyinotify.Notifier(
+ wm,
+ timeout=10,
+ default_proc_fun=self.inotify_callback
+ )
+
+ wm.add_watch(
+ self.path,
+ # pyinotify.ALL_EVENTS,
+ pyinotify.IN_DELETE | pyinotify.IN_CREATE | pyinotify.IN_MODIFY,
+ rec=True
+ )
+
+ GLib.io_add_watch(
+ notifier._fd,
+ GLib.IO_IN,
+ self.io_callback,
+ notifier
+ )
+
+ def inotify_callback(self, notifier):
+ self.log.info('inotify callback %s: %s',
+ notifier.maskname, notifier.pathname)
+ if not self.scheduled:
+ self.scheduled = True
+ GLib.timeout_add(100, self.rescan)
+ return True
+
+ def io_callback(self, source, condition, notifier):
+ notifier.process_events()
+ while notifier.check_events():
+ notifier.read_events()
+ notifier.process_events()
+
+ return True
+
+ def is_playable_file(self, filepath):
+ root, ext = os.path.splitext(filepath)
+ return ext in ['.mp3', '.ogg', '.oga', '.wav', '.m4a',
+ '.flac', 'self.opus']
+
+ def rescan(self):
+ self.log.info('scanning directory %s', self.path)
+ self.scheduled = False
+
+ all_files = []
+
+ for root, dirs, files in os.walk(self.path):
+ files = filter(self.is_playable_file, files)
+ files = map(lambda f: os.path.join(root, f), files)
+ files = list(files)
+
+ self.log.debug('found directory %s: %u playable file(s)',
+ root, len(files))
+ all_files.extend(files)
+
+ self.log.info('found %u playable files', len(all_files))
+ self.files = all_files
+
+ def get_random_file(self):
+ return random.choice(self.files)
+
+ def get_random_uri(self):
+ return 'file://' + self.get_random_file()
- def get_random_file(self):
- return random.choice(self.files)
- def get_random_uri(self):
- return 'file://'+self.get_random_file()
+class LoopSource(object):
+ def __init__(self, directory):
+ self.log = logging.getLogger('LoopSource')
+ self.directory = directory
+
+ pipeline = """
+ audioresample name=join !
+ audioconvert !
+ audio/x-raw,format=S16LE,channels=2,rate=48000,
+ layout=interleaved !
+ matroskamux !
+ tcpclientsink host=localhost port=18000
+ """
+
+ # Parsing Pipeline
+ self.log.debug('creating pipeline\n%s', pipeline)
+ self.pipeline = Gst.parse_launch(pipeline)
+
+ # Selecting inital URI
+ inital_uri = self.directory.get_random_uri()
+ self.log.info('initial track %s', inital_uri)
+
+ # Create decoder-element
+ self.src = Gst.ElementFactory.make('uridecodebin', None)
+ self.src.set_property('uri', inital_uri)
+ self.src.connect('pad-added', self.on_pad_added)
+ self.pipeline.add(self.src)
+
+ # Save pad on the Join-Element
+ self.joinpad = self.pipeline.get_by_name('join').get_static_pad('sink')
+
+ # Binding End-of-Stream-Signal on Source-Pipeline
+ self.pipeline.bus.add_signal_watch()
+ self.pipeline.bus.connect("message::eos", self.on_eos)
+ self.pipeline.bus.connect("message::error", self.on_error)
+
+ self.log.debug('setting pipeline to playing')
+ self.pipeline.set_state(Gst.State.PLAYING)
+
+ def on_pad_added(self, src, pad):
+ self.log.debug('new pad on decoder, setting pad-probe')
+ pad.add_probe(
+ Gst.PadProbeType.EVENT_DOWNSTREAM | Gst.PadProbeType.BLOCK,
+ self.on_pad_event
+ )
+ if self.joinpad.is_linked():
+ self.log.debug('unlinking with joinpad')
+ self.joinpad.unlink(self.joinpad.get_peer())
+
+ clock = self.pipeline.get_clock()
+ if clock:
+ runtime = clock.get_time() - self.pipeline.get_base_time()
+ self.log.debug('setting pad offset to pipeline runtime: %sns',
+ runtime)
+ pad.set_offset(runtime)
+
+ self.log.debug('linking with joinpad')
+ pad.link(self.joinpad)
+
+ def on_pad_event(self, pad, info):
+ event = info.get_event()
+ self.log.debug('event %s on pad %s', event.type, pad)
+
+ if event.type == Gst.EventType.EOS:
+ self.log.debug('scheduling next track and dropping EOS-Event')
+ GObject.idle_add(self.next_track)
+ return Gst.PadProbeReturn.DROP
+
+ return Gst.PadProbeReturn.PASS
+
+ def next_track(self):
+ next_uri = self.directory.get_random_uri()
+ self.log.info('next track %s', next_uri)
+
+ self.src.set_state(Gst.State.READY)
+ self.src.set_property('uri', next_uri)
+ self.src.set_state(Gst.State.PLAYING)
+ return False
+
+ def on_eos(self, bus, message):
+ self.log.info('received EOS-Event on bus, exiting')
+ sys.exit(1)
+
+ def on_error(self, bus, message):
+ self.log.warning('received Error-Event on bus, exiting')
+ (error, debug) = message.parse_error()
+ self.log.warning('Error-Details: #%u: %s', error.code, debug)
+ sys.exit(1)
-class LoopSource(object):
- def __init__(self, directory):
- self.log = logging.getLogger('LoopSource')
- self.directory = directory
-
- pipeline = """
- audioresample name=join !
- audioconvert !
- audio/x-raw,format=S16LE,channels=2,layout=interleaved,rate=48000 !
- matroskamux !
- tcpclientsink host=localhost port=18000
- """
-
- # Parsing Pipeline
- self.log.debug('creating pipeline\n%s', pipeline)
- self.pipeline = Gst.parse_launch(pipeline)
-
- # Selecting inital URI
- inital_uri = self.directory.get_random_uri()
- self.log.info('initial track %s', inital_uri)
-
- # Create decoder-element
- self.src = Gst.ElementFactory.make('uridecodebin', None)
- self.src.set_property('uri', inital_uri);
- self.src.connect('pad-added', self.on_pad_added)
- self.pipeline.add(self.src)
-
- # Save pad on the Join-Element
- self.joinpad = self.pipeline.get_by_name('join').get_static_pad('sink')
-
- # Binding End-of-Stream-Signal on Source-Pipeline
- self.pipeline.bus.add_signal_watch()
- self.pipeline.bus.connect("message::eos", self.on_eos)
- self.pipeline.bus.connect("message::error", self.on_error)
-
- self.log.debug('setting pipeline to playing')
- self.pipeline.set_state(Gst.State.PLAYING)
-
- def on_pad_added(self, src, pad):
- self.log.debug('new pad on decoder, setting pad-probe')
- pad.add_probe(Gst.PadProbeType.EVENT_DOWNSTREAM | Gst.PadProbeType.BLOCK, self.on_pad_event)
- if self.joinpad.is_linked():
- self.log.debug('unlinking with joinpad')
- self.joinpad.unlink(self.joinpad.get_peer())
-
- clock = self.pipeline.get_clock()
- if clock:
- runtime = clock.get_time() - self.pipeline.get_base_time()
- self.log.debug('setting pad offset to pipeline runtime: %sns', runtime)
- pad.set_offset(runtime)
-
- self.log.debug('linking with joinpad')
- pad.link(self.joinpad)
-
- def on_pad_event(self, pad, info):
- event = info.get_event()
- self.log.debug('event %s on pad %s', event.type, pad)
-
- if event.type == Gst.EventType.EOS:
- self.log.debug('scheduling next track and dropping EOS-Event')
- GObject.idle_add(self.next_track)
- return Gst.PadProbeReturn.DROP
-
- return Gst.PadProbeReturn.PASS
-
- def next_track(self):
- next_uri = self.directory.get_random_uri()
- self.log.info('next track %s', next_uri)
-
- self.src.set_state(Gst.State.READY)
- self.src.set_property('uri', next_uri);
- self.src.set_state(Gst.State.PLAYING)
- return False
-
- def on_eos(self, bus, message):
- self.log.info('received EOS-Event on bus, exiting')
- sys.exit(1)
-
- def on_error(self, bus, message):
- self.log.warning('received Error-Event on bus, exiting')
- (error, debug) = message.parse_error()
- self.log.warning('Error-Details: #%u: %s', error.code, debug)
- sys.exit(1)
def main():
- signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
- parser = argparse.ArgumentParser(description='Voctocore Music-Source')
- parser.add_argument('directory')
+ parser = argparse.ArgumentParser(description='Voctocore Music-Source')
+ parser.add_argument('directory')
- parser.add_argument('-v|-vv', '--verbose', action='count', default=0,
- help="Also print INFO and DEBUG messages.")
+ parser.add_argument('-v|-vv', '--verbose', action='count', default=0,
+ help="Also print INFO and DEBUG messages.")
- args = parser.parse_args()
+ args = parser.parse_args()
- if args.verbose >= 2:
- level = logging.DEBUG
- elif args.verbose == 1:
- level = logging.INFO
- else:
- level = logging.WARNING
+ if args.verbose >= 2:
+ level = logging.DEBUG
+ elif args.verbose == 1:
+ level = logging.INFO
+ else:
+ level = logging.WARNING
- logging.basicConfig(
- level=level,
- format='%(levelname)8s %(name)s: %(message)s')
+ logging.basicConfig(
+ level=level,
+ format='%(levelname)8s %(name)s: %(message)s'
+ )
- directory = Directory(args.directory)
- src = LoopSource(directory)
+ directory = Directory(args.directory)
+ src = LoopSource(directory)
- mainloop = GObject.MainLoop()
- try:
- mainloop.run()
- except KeyboardInterrupt:
- print('Terminated via Ctrl-C')
+ mainloop = GObject.MainLoop()
+ try:
+ mainloop.run()
+ except KeyboardInterrupt:
+ print('Terminated via Ctrl-C')
if __name__ == '__main__':
- main()
+ main()
diff --git a/example-scripts/gstreamer/source-remote-desktop-as-cam1.py b/example-scripts/gstreamer/source-remote-desktop-as-cam1.py
index 7d1c7f2..4788554 100755
--- a/example-scripts/gstreamer/source-remote-desktop-as-cam1.py
+++ b/example-scripts/gstreamer/source-remote-desktop-as-cam1.py
@@ -1,6 +1,10 @@
#!/usr/bin/python3
-import os, sys, gi, signal
-import argparse, socket
+import os
+import sys
+import gi
+import signal
+import argparse
+import socket
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GstNet, GObject
@@ -9,88 +13,97 @@ from gi.repository import Gst, GstNet, GObject
GObject.threads_init()
Gst.init([])
+
class Source(object):
- def __init__(self, settings):
- pipeline = """
- ximagesrc use-damage=0 startx=0 starty=0 endx=1919 endy=1079 !
- queue !
- videoscale !
- videorate !
- timeoverlay !
- videoconvert !
- video/x-raw,format=I420,width={WIDTH},height={HEIGHT},framerate={FRAMERATE}/1,pixel-aspect-ratio=1/1 !
- queue !
- mux.
-
- pulsesrc !
- audio/x-raw,format=S16LE,channels=2,layout=interleaved,rate={AUDIORATE} !
- queue !
- mux.
-
- matroskamux name=mux !
- tcpclientsink host={IP} port=10000
- """.format_map(settings)
-
- self.clock = GstNet.NetClientClock.new('voctocore', settings['IP'], 9998, 0)
- print('obtained NetClientClock from host', self.clock)
-
- print('waiting for NetClientClock to sync…')
- self.clock.wait_for_sync(Gst.CLOCK_TIME_NONE)
-
- print('starting pipeline '+pipeline)
- self.senderPipeline = Gst.parse_launch(pipeline)
- self.senderPipeline.use_clock(self.clock)
- self.src = self.senderPipeline.get_by_name('src')
-
- # Binding End-of-Stream-Signal on Source-Pipeline
- self.senderPipeline.bus.add_signal_watch()
- self.senderPipeline.bus.connect("message::eos", self.on_eos)
- self.senderPipeline.bus.connect("message::error", self.on_error)
-
- print("playing")
- self.senderPipeline.set_state(Gst.State.PLAYING)
-
-
- def on_eos(self, bus, message):
- print('Received EOS-Signal')
- sys.exit(1)
-
- def on_error(self, bus, message):
- print('Received Error-Signal')
- (error, debug) = message.parse_error()
- print('Error-Details: #%u: %s' % (error.code, debug))
- sys.exit(1)
+
+ def __init__(self, settings):
+ pipeline = """
+ ximagesrc
+ use-damage=0
+ startx=0 starty=0 endx=1919 endy=1079 !
+ queue !
+ videoscale !
+ videorate !
+ timeoverlay !
+ videoconvert !
+ video/x-raw,format=I420,width={WIDTH},height={HEIGHT},
+ framerate={FRAMERATE}/1,pixel-aspect-ratio=1/1 !
+ queue !
+ mux.
+
+ pulsesrc !
+ audio/x-raw,format=S16LE,channels=2,rate={AUDIORATE},
+ layout=interleaved !
+ queue !
+ mux.
+
+ matroskamux name=mux !
+ tcpclientsink host={IP} port=10000
+ """.format_map(settings)
+
+ self.clock = GstNet.NetClientClock.new('voctocore',
+ settings['IP'], 9998,
+ 0)
+ print('obtained NetClientClock from host', self.clock)
+
+ print('waiting for NetClientClock to sync…')
+ self.clock.wait_for_sync(Gst.CLOCK_TIME_NONE)
+
+ print('starting pipeline ' + pipeline)
+ self.senderPipeline = Gst.parse_launch(pipeline)
+ self.senderPipeline.use_clock(self.clock)
+ self.src = self.senderPipeline.get_by_name('src')
+
+ # Binding End-of-Stream-Signal on Source-Pipeline
+ self.senderPipeline.bus.add_signal_watch()
+ self.senderPipeline.bus.connect("message::eos", self.on_eos)
+ self.senderPipeline.bus.connect("message::error", self.on_error)
+
+ print("playing")
+ self.senderPipeline.set_state(Gst.State.PLAYING)
+
+ def on_eos(self, bus, message):
+ print('Received EOS-Signal')
+ sys.exit(1)
+
+ def on_error(self, bus, message):
+ print('Received Error-Signal')
+ (error, debug) = message.parse_error()
+ print('Error-Details: #%u: %s' % (error.code, debug))
+ sys.exit(1)
+
def main():
- signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
- parser = argparse.ArgumentParser(description='Voctocore Remote-Source')
- parser.add_argument('host')
+ parser = argparse.ArgumentParser(description='Voctocore Remote-Source')
+ parser.add_argument('host')
- args = parser.parse_args()
- print('Resolving hostname '+args.host)
- addrs = [ str(i[4][0]) for i in socket.getaddrinfo(args.host, None) ]
- if len(addrs) == 0:
- print('Found no IPs')
- sys.exit(1)
+ args = parser.parse_args()
+ print('Resolving hostname ' + args.host)
+ addrs = [str(i[4][0]) for i in socket.getaddrinfo(args.host, None)]
+ if len(addrs) == 0:
+ print('Found no IPs')
+ sys.exit(1)
- print('Using IP '+addrs[0])
+ print('Using IP ' + addrs[0])
- config = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../config.sh')
- with open(config) as config:
- lines = [ line.strip() for line in config if line[0] != '#' ]
- pairs = [ line.split('=', 1) for line in lines ]
- settings = { pair[0]: pair[1] for pair in pairs }
+ config = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ '../config.sh')
+ with open(config) as config:
+ lines = [line.strip() for line in config if line[0] != '#']
+ pairs = [line.split('=', 1) for line in lines]
+ settings = {pair[0]: pair[1] for pair in pairs}
- settings['IP'] = addrs[0]
+ settings['IP'] = addrs[0]
- src = Source(settings)
- mainloop = GObject.MainLoop()
- try:
- mainloop.run()
- except KeyboardInterrupt:
- print('Terminated via Ctrl-C')
+ src = Source(settings)
+ mainloop = GObject.MainLoop()
+ try:
+ mainloop.run()
+ except KeyboardInterrupt:
+ print('Terminated via Ctrl-C')
if __name__ == '__main__':
- main()
+ main()
diff --git a/example-scripts/gstreamer/source-remote-videotestsrc-as-cam1.py b/example-scripts/gstreamer/source-remote-videotestsrc-as-cam1.py
index 5404add..e09f0ec 100755
--- a/example-scripts/gstreamer/source-remote-videotestsrc-as-cam1.py
+++ b/example-scripts/gstreamer/source-remote-videotestsrc-as-cam1.py
@@ -1,6 +1,10 @@
#!/usr/bin/python3
-import os, sys, gi, signal
-import argparse, socket
+import os
+import sys
+import gi
+import signal
+import argparse
+import socket
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GstNet, GObject
@@ -9,83 +13,92 @@ from gi.repository import Gst, GstNet, GObject
GObject.threads_init()
Gst.init([])
-class Source(object):
- def __init__(self, settings):
- # it works much better with a local file
- pipeline = """
- videotestsrc pattern=ball foreground-color=0x00ff0000 background-color=0x00440000 !
- timeoverlay !
- video/x-raw,format=I420,width=1280,height=720,framerate=25/1,pixel-aspect-ratio=1/1 !
- mux.
-
- audiotestsrc freq=330 !
- audio/x-raw,format=S16LE,channels=2,layout=interleaved,rate=48000 !
- mux.
-
- matroskamux name=mux !
- tcpclientsink host={IP} port=10000
- """.format_map(settings)
-
- self.clock = GstNet.NetClientClock.new('voctocore', settings['IP'], 9998, 0)
- print('obtained NetClientClock from host', self.clock)
-
- print('waiting for NetClientClock to sync…')
- self.clock.wait_for_sync(Gst.CLOCK_TIME_NONE)
-
- print('starting pipeline '+pipeline)
- self.senderPipeline = Gst.parse_launch(pipeline)
- self.senderPipeline.use_clock(self.clock)
- self.src = self.senderPipeline.get_by_name('src')
-
- # Binding End-of-Stream-Signal on Source-Pipeline
- self.senderPipeline.bus.add_signal_watch()
- self.senderPipeline.bus.connect("message::eos", self.on_eos)
- self.senderPipeline.bus.connect("message::error", self.on_error)
-
- print("playing")
- self.senderPipeline.set_state(Gst.State.PLAYING)
+class Source(object):
- def on_eos(self, bus, message):
- print('Received EOS-Signal')
- sys.exit(1)
+ def __init__(self, settings):
+ # it works much better with a local file
+ pipeline = """
+ videotestsrc
+ pattern=ball
+ foreground-color=0x00ff0000 background-color=0x00440000 !
+ timeoverlay !
+ video/x-raw,format=I420,width=1280,height=720,
+ framerate=25/1,pixel-aspect-ratio=1/1 !
+ mux.
+
+ audiotestsrc freq=330 !
+ audio/x-raw,format=S16LE,channels=2,rate=48000,
+ layout=interleaved !
+ mux.
+
+ matroskamux name=mux !
+ tcpclientsink host={IP} port=10000
+ """.format_map(settings)
+
+ self.clock = GstNet.NetClientClock.new('voctocore',
+ settings['IP'], 9998,
+ 0)
+ print('obtained NetClientClock from host', self.clock)
+
+ print('waiting for NetClientClock to sync…')
+ self.clock.wait_for_sync(Gst.CLOCK_TIME_NONE)
+
+ print('starting pipeline ' + pipeline)
+ self.senderPipeline = Gst.parse_launch(pipeline)
+ self.senderPipeline.use_clock(self.clock)
+ self.src = self.senderPipeline.get_by_name('src')
+
+ # Binding End-of-Stream-Signal on Source-Pipeline
+ self.senderPipeline.bus.add_signal_watch()
+ self.senderPipeline.bus.connect("message::eos", self.on_eos)
+ self.senderPipeline.bus.connect("message::error", self.on_error)
+
+ print("playing")
+ self.senderPipeline.set_state(Gst.State.PLAYING)
+
+ def on_eos(self, bus, message):
+ print('Received EOS-Signal')
+ sys.exit(1)
+
+ def on_error(self, bus, message):
+ print('Received Error-Signal')
+ (error, debug) = message.parse_error()
+ print('Error-Details: #%u: %s' % (error.code, debug))
+ sys.exit(1)
- def on_error(self, bus, message):
- print('Received Error-Signal')
- (error, debug) = message.parse_error()
- print('Error-Details: #%u: %s' % (error.code, debug))
- sys.exit(1)
def main():
- signal.signal(signal.SIGINT, signal.SIG_DFL)
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
- parser = argparse.ArgumentParser(description='Voctocore Remote-Source')
- parser.add_argument('host')
+ parser = argparse.ArgumentParser(description='Voctocore Remote-Source')
+ parser.add_argument('host')
- args = parser.parse_args()
- print('Resolving hostname '+args.host)
- addrs = [ str(i[4][0]) for i in socket.getaddrinfo(args.host, None) ]
- if len(addrs) == 0:
- print('Found no IPs')
- sys.exit(1)
+ args = parser.parse_args()
+ print('Resolving hostname ' + args.host)
+ addrs = [str(i[4][0]) for i in socket.getaddrinfo(args.host, None)]
+ if len(addrs) == 0:
+ print('Found no IPs')
+ sys.exit(1)
- print('Using IP '+addrs[0])
+ print('Using IP ' + addrs[0])
- config = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../config.sh')
- with open(config) as config:
- lines = [ line.strip() for line in config if line[0] != '#' ]
- pairs = [ line.split('=', 1) for line in lines ]
- settings = { pair[0]: pair[1] for pair in pairs }
+ config = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+ '../config.sh')
+ with open(config) as config:
+ lines = [line.strip() for line in config if line[0] != '#']
+ pairs = [line.split('=', 1) for line in lines]
+ settings = {pair[0]: pair[1] for pair in pairs}
- settings['IP'] = addrs[0]
+ settings['IP'] = addrs[0]
- src = Source(settings)
- mainloop = GObject.MainLoop()
- try:
- mainloop.run()
- except KeyboardInterrupt:
- print('Terminated via Ctrl-C')
+ src = Source(settings)
+ mainloop = GObject.MainLoop()
+ try:
+ mainloop.run()
+ except KeyboardInterrupt:
+ print('Terminated via Ctrl-C')
if __name__ == '__main__':
- main()
+ main()