diff options
author | MaZderMind <git@mazdermind.de> | 2016-09-26 20:42:07 +0200 |
---|---|---|
committer | MaZderMind <git@mazdermind.de> | 2016-09-26 20:42:07 +0200 |
commit | 6e846c7081e242213cd70ceacfcff319e221942c (patch) | |
tree | 9d037e9272e65aea06c74775b2af1eae2f50a46e /example-scripts/gstreamer | |
parent | fbcbc3743e9179738244a96be54aa588e44314cb (diff) | |
parent | 1972da7f6aa60d3cb3b68808d0381e37898665f3 (diff) |
Merge branch 'pep8'
Diffstat (limited to 'example-scripts/gstreamer')
-rwxr-xr-x | example-scripts/gstreamer/ingest.py | 230 | ||||
-rwxr-xr-x | example-scripts/gstreamer/source-background-loop.py | 118 | ||||
-rwxr-xr-x | example-scripts/gstreamer/source-nostream-music-from-folder.py | 363 | ||||
-rwxr-xr-x | example-scripts/gstreamer/source-remote-desktop-as-cam1.py | 163 | ||||
-rwxr-xr-x | example-scripts/gstreamer/source-remote-videotestsrc-as-cam1.py | 149 |
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() |