From 0e270e13f80d9df99df90a4c2af06b9347e54678 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 24 Oct 2013 13:27:42 +0200 Subject: [PATCH] Move python experiments to a python/ subdir --- gst-custom-player.py | 209 ------------------------------------- gst-looping-video-1.py | 51 --------- gst-looping-video-2.py | 48 --------- gst-trick-mode-looping-1.py | 96 ----------------- gst-trick-mode-looping-2.py | 104 ------------------ gst-trick-mode-looping-3.py | 77 -------------- gst-trick-mode.py | 85 --------------- python/gst-custom-player.py | 209 +++++++++++++++++++++++++++++++++++++ python/gst-looping-video-1.py | 51 +++++++++ python/gst-looping-video-2.py | 48 +++++++++ python/gst-trick-mode-looping-1.py | 96 +++++++++++++++++ python/gst-trick-mode-looping-2.py | 104 ++++++++++++++++++ python/gst-trick-mode-looping-3.py | 77 ++++++++++++++ python/gst-trick-mode.py | 85 +++++++++++++++ 14 files changed, 670 insertions(+), 670 deletions(-) delete mode 100755 gst-custom-player.py delete mode 100755 gst-looping-video-1.py delete mode 100755 gst-looping-video-2.py delete mode 100755 gst-trick-mode-looping-1.py delete mode 100755 gst-trick-mode-looping-2.py delete mode 100755 gst-trick-mode-looping-3.py delete mode 100755 gst-trick-mode.py create mode 100755 python/gst-custom-player.py create mode 100755 python/gst-looping-video-1.py create mode 100755 python/gst-looping-video-2.py create mode 100755 python/gst-trick-mode-looping-1.py create mode 100755 python/gst-trick-mode-looping-2.py create mode 100755 python/gst-trick-mode-looping-3.py create mode 100755 python/gst-trick-mode.py diff --git a/gst-custom-player.py b/gst-custom-player.py deleted file mode 100755 index cbeace2..0000000 --- a/gst-custom-player.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python - -# Simple media player with GStreamer -# -# Copyright (C) 2013 Antonio Ospite -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# References: -# http://pygstdocs.berlios.de/pygst-reference -# https://core.fluendo.com/gstreamer/svn/trunk/gst-fluendo-gdlsink/test/ismdplay.py - -import sys -import os - -import gobject -gobject.threads_init() - -import gst - -# The player window will have a fixed width and height. -# This is just to demonstrate the use of capabilities. -WIDTH = 640 -HEIGHT = 300 - - -class CustomVideoBin(gst.Bin): - def __init__(self): - gst.Bin.__init__(self, 'CustomVideoBin') - - queue = gst.element_factory_make('queue', 'vqueue') - self.add(queue) - - rescale = gst.element_factory_make("videoscale", "rescale") - self.add(rescale) - - caps = gst.Caps("video/x-raw-yuv,format=(fourcc)AYUV,width=%d,height=%d,pixel-aspect-ratio=1/1" % (WIDTH, HEIGHT)) - capsfilter = gst.element_factory_make("capsfilter", "filter") - capsfilter.set_property("caps", caps) - self.add(capsfilter) - - colorspace = gst.element_factory_make("colorspace", "colorspace") - self.add(colorspace) - - videosink = gst.element_factory_make("autovideosink", "vidoesink") - self.add(videosink) - - gst.element_link_many(queue, rescale, capsfilter, colorspace, videosink) - sink = queue.get_pad('sink') - self.add_pad(gst.GhostPad('sink', sink)) - - -class CustomAudioBin(gst.Bin): - def __init__(self): - gst.Bin.__init__(self, 'CustomAudioBin') - - queue = gst.element_factory_make('queue', 'aqueue') - self.add(queue) - - audioconvert = gst.element_factory_make("audioconvert", "audioconverter") - self.add(audioconvert) - - audiosink = gst.element_factory_make("autoaudiosink", "audiosink") - self.add(audiosink) - - gst.element_link_many(queue, audioconvert, audiosink) - sink = queue.get_pad('sink') - self.add_pad(gst.GhostPad('sink', sink)) - - -class CustomPlayBin(gst.Pipeline): - __gproperties__ = { - 'source': (gst.Element, "source", "Source element", gobject.PARAM_READABLE) - } - - def __init__(self, uri=None): - gst.Pipeline.__init__(self, 'CustomPlayBin') - - self._uri = uri - - self._playbin = gst.element_factory_make("playbin2", "playbin") - self.add(self._playbin) - - self._playbin.set_property("uri", self._uri) - self._playbin.set_property("video-sink", CustomVideoBin()) - self._playbin.set_property("audio-sink", CustomAudioBin()) - - def set_uri(self, uri): - self._uri = uri - self._playbin.set_property("uri", self._uri) - - -class GstPlayer: - def __init__(self): - - # The user can require some action at End Of Stream - self.eos_cb = None - - self.pipeline = CustomPlayBin() - - bus = self.pipeline.get_bus() - bus.add_signal_watch() - bus.connect('message::eos', self.on_eos) - bus.connect('message::tag', self.on_tag) - bus.connect('message::error', self.on_error) - bus.connect('message::state-changed', self.on_state_changed) - - def on_eos(self, bus, msg): - print 'on_eos' - self.stop() - if self.eos_cb: - self.eos_cb() - - def on_tag(self, bus, msg): - print 'on_tag:' - taglist = msg.parse_tag() - for key in taglist.keys(): - print '\t%s = %s' % (key, taglist[key]) - - def on_error(self, bus, msg): - print 'on_error' - error, debug = msg.parse_error() - print "Error: %s" % error, debug - self.stop() - - def on_state_changed(self, bus, msg): - print 'on_state_changed' - if msg.src != self.pipeline: - return - - old_state, new_state, pending = msg.parse_state_changed() - - def set_location(self, location): - self.pipeline.set_uri(location) - - def play(self): - self.pipeline.set_state(gst.STATE_PLAYING) - - def pause(self): - self.pipeline.set_state(gst.STATE_PAUSED) - - def stop(self): - self.pipeline.set_state(gst.STATE_NULL) - - -class PlayerTUI(): - def __init__(self, location): - - self.player = GstPlayer() - self.player.eos_cb = self.quit - - self.mainloop = gobject.MainLoop() - - self.player.set_location(location) - self.player.play() - - gobject.io_add_watch(sys.stdin, gobject.IO_IN, self.on_stdin) - - try: - self.mainloop.run() - except KeyboardInterrupt: - self.quit() - - def on_stdin(self, fd, event): - # The user has to send a newline fo this to go on - c = os.read(fd.fileno(), 1) - - if c == "q": - self.quit() - elif c == "s": - self.player.pause() - elif c == "r": - self.player.play() - - return True - - def quit(self): - self.player.stop() - self.player = None - self.mainloop.quit() - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - tui = PlayerTUI(args[1]) - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/gst-looping-video-1.py b/gst-looping-video-1.py deleted file mode 100755 index 9886abe..0000000 --- a/gst-looping-video-1.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -# Get a test sample with: -# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y - -import sys - -import gobject -gobject.threads_init() - -import gst - - -class Player: - def __init__(self, filename): - self._filename = filename - - self._player = gst.element_factory_make("playbin2", "player") - self._player.set_property("uri", filename) - - bus = self._player.get_bus() - bus.add_signal_watch() - bus.connect('message::eos', self.on_eos) - - def run(self): - self._player.set_state(gst.STATE_PLAYING) - loop = gobject.MainLoop() - loop.run() - - def on_eos(self, bus, msg): - sys.stderr.write(".") - self._player.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, 0) - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - player = Player(args[1]) - player.run() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/gst-looping-video-2.py b/gst-looping-video-2.py deleted file mode 100755 index eabb7a4..0000000 --- a/gst-looping-video-2.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# Get a test sample with: -# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y - -import sys - -import gobject -gobject.threads_init() - -import gst - - -class Player: - def __init__(self, filename): - self._filename = filename - - self._player = gst.element_factory_make("playbin2", "player") - self._player.set_property("uri", filename) - self._player.connect("about-to-finish", self.on_about_to_finish) - - def run(self): - self._player.set_state(gst.STATE_PLAYING) - loop = gobject.MainLoop() - loop.run() - - def on_about_to_finish(self, player): - sys.stderr.write(".") - player.set_property("uri", self._filename) - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - player = Player(args[1]) - player.run() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/gst-trick-mode-looping-1.py b/gst-trick-mode-looping-1.py deleted file mode 100755 index fe00556..0000000 --- a/gst-trick-mode-looping-1.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -# Get a test sample with: -# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y - -import sys - -import gobject -gobject.threads_init() - -import gst - - -class Player: - def __init__(self, filename, rate): - self._filename = filename - self._rate = rate - - self._player = gst.element_factory_make("playbin2", "player") - self._player.set_property("uri", filename) - - bus = self._player.get_bus() - bus.add_signal_watch() - bus.connect('message::eos', self.on_eos) - bus.connect('message::state-changed', self.on_state_changed) - - def run(self): - self._player.set_state(gst.STATE_PLAYING) - loop = gobject.MainLoop() - loop.run() - - def on_eos(self, bus, msg): - sys.stderr.write(".") - self._player.set_state(gst.STATE_PLAYING) - seek_event = gst.event_new_seek(self._rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, 0, - gst.SEEK_TYPE_NONE, 0) - self._player.send_event(seek_event) - - def on_state_changed(self, bus, msg): - if msg.src != self._player: - return - - print 'on_state_changed' - old_state, new_state, pending = msg.parse_state_changed() - print "%s -> %s" % (old_state, new_state) - if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: - self.set_rate(self._rate) - - def set_rate(self, rate): - self._rate = rate - try: - position, format = self._player.query_position(gst.FORMAT_TIME) - except: - position = 0 - - # Create the seek event - if rate > 0: - seek_event = gst.event_new_seek(rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, position, - gst.SEEK_TYPE_NONE, 0) - else: - seek_event = gst.event_new_seek(rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, 0, - gst.SEEK_TYPE_SET, position) - - if seek_event: - self._player.send_event(seek_event) - gst.info("rate set to %s" % rate) - else: - gst.warining("change rate failed") - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - player = Player(args[1], 3.0) - player.run() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/gst-trick-mode-looping-2.py b/gst-trick-mode-looping-2.py deleted file mode 100755 index 920677d..0000000 --- a/gst-trick-mode-looping-2.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python - -# Get a test sample with: -# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y - -import sys - -import gobject -gobject.threads_init() - -import gst - - -class Player: - def __init__(self, filename, rate): - self._filename = filename - self._rate = rate - - self._player = gst.element_factory_make("playbin2", "player") - self._player.set_property("uri", filename) - self._player.connect("about-to-finish", self.on_about_to_finish) - - bus = self._player.get_bus() - bus.add_signal_watch() - bus.connect('message::state-changed', self.on_state_changed) - - def run(self): - self._player.set_state(gst.STATE_PLAYING) - loop = gobject.MainLoop() - loop.run() - - def on_about_to_finish(self, player): - sys.stderr.write(".") - player.set_property("uri", self._filename) - - # XXX Ater the first iteration of the loop the playback rate is - # reset to normal. Do I need to re-set the rate here? - - # If I uncomment the following line, the player hangs: - #self.set_rate(self._date) - - # And it hangs also if I set the seek_event manually using position=0: - #seek_event = gst.event_new_seek(self._rate, - # gst.FORMAT_TIME, - # gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - # gst.SEEK_TYPE_SET, 0, - # gst.SEEK_TYPE_NONE, 0) - #self._player.send_event(seek_event) - - def on_state_changed(self, bus, msg): - if msg.src != self._player: - return - - print 'on_state_changed' - old_state, new_state, pending = msg.parse_state_changed() - print "%s -> %s" % (old_state, new_state) - if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: - self.set_rate(self._rate) - - def set_rate(self, rate): - self._rate = rate - try: - position, format = self._player.query_position(gst.FORMAT_TIME) - except: - position = 0 - - # Create the seek event - if rate > 0: - seek_event = gst.event_new_seek(rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, position, - gst.SEEK_TYPE_NONE, 0) - else: - seek_event = gst.event_new_seek(rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, 0, - gst.SEEK_TYPE_SET, position) - - if seek_event: - self._player.send_event(seek_event) - gst.info("rate set to %s" % rate) - else: - gst.warining("change rate failed") - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - player = Player(args[1], 3.0) - player.run() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/gst-trick-mode-looping-3.py b/gst-trick-mode-looping-3.py deleted file mode 100755 index 94b99af..0000000 --- a/gst-trick-mode-looping-3.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python - -# Get a test sample with: -# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y - -import sys - -import gobject -gobject.threads_init() - -import gst - - -class Player: - def __init__(self, filename, rate): - self._filename = filename - self._rate = rate - - self._player = gst.element_factory_make("playbin2", "player") - self._player.set_property("uri", filename) - - bus = self._player.get_bus() - bus.add_signal_watch() - bus.connect('message::state-changed', self.on_state_changed) - bus.connect('message::segment-done', self.on_segment_done) - - def run(self): - self._player.set_state(gst.STATE_PLAYING) - loop = gobject.MainLoop() - loop.run() - - def on_segment_done(self, bus, msg): - self._player.seek(self._rate, gst.FORMAT_TIME, - gst.SEEK_FLAG_SEGMENT | gst.SEEK_FLAG_SKIP | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, 0, - gst.SEEK_TYPE_END, 0) - - def on_state_changed(self, bus, msg): - if msg.src != self._player: - return - - print 'on_state_changed' - old_state, new_state, pending = msg.parse_state_changed() - print "%s -> %s" % (old_state, new_state) - if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: - self.set_rate(self._rate) - - def set_rate(self, rate): - self._rate = rate - - if rate == 0: - self._player.set_state(gst.STATE_PAUSED) - else: - self._player.set_state(gst.STATE_PLAYING) - self._player.seek(self._rate, gst.FORMAT_TIME, - gst.SEEK_FLAG_SEGMENT | gst.SEEK_FLAG_SKIP | gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, 0, - gst.SEEK_TYPE_END, 0) - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - player = Player(args[1], 3.0) - player.run() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/gst-trick-mode.py b/gst-trick-mode.py deleted file mode 100755 index a4e063f..0000000 --- a/gst-trick-mode.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python - -# Get a test sample with: -# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y - -import sys - -import gobject -gobject.threads_init() - -import gst - - -class Player: - def __init__(self, filename, rate): - self._filename = filename - self._rate = rate - - self._player = gst.element_factory_make("playbin2", "player") - self._player.set_property("uri", filename) - - bus = self._player.get_bus() - bus.add_signal_watch() - bus.connect('message::state-changed', self.on_state_changed) - - def run(self): - self._player.set_state(gst.STATE_PLAYING) - loop = gobject.MainLoop() - loop.run() - - def on_state_changed(self, bus, msg): - if msg.src != self._player: - return - - print 'on_state_changed' - old_state, new_state, pending = msg.parse_state_changed() - print "%s -> %s" % (old_state, new_state) - if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: - self.set_rate(self._rate) - - def set_rate(self, rate): - self._rate = rate - try: - position, format = self._player.query_position(gst.FORMAT_TIME) - except: - position = 0 - - # Create the seek event - if rate > 0: - seek_event = gst.event_new_seek(rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, position, - gst.SEEK_TYPE_NONE, 0) - else: - seek_event = gst.event_new_seek(rate, - gst.FORMAT_TIME, - gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, - gst.SEEK_TYPE_SET, 0, - gst.SEEK_TYPE_SET, position) - - if seek_event: - self._player.send_event(seek_event) - gst.info("rate set to %s" % rate) - else: - gst.warining("change rate failed") - - -def main(args): - def usage(): - sys.stdout.write("usage: %s \n" % args[0]) - - if len(args) != 2: - usage() - sys.exit(1) - - if not gst.uri_is_valid(args[1]): - sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) - sys.exit(1) - - player = Player(args[1], 3.0) - player.run() - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/python/gst-custom-player.py b/python/gst-custom-player.py new file mode 100755 index 0000000..cbeace2 --- /dev/null +++ b/python/gst-custom-player.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python + +# Simple media player with GStreamer +# +# Copyright (C) 2013 Antonio Ospite +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# References: +# http://pygstdocs.berlios.de/pygst-reference +# https://core.fluendo.com/gstreamer/svn/trunk/gst-fluendo-gdlsink/test/ismdplay.py + +import sys +import os + +import gobject +gobject.threads_init() + +import gst + +# The player window will have a fixed width and height. +# This is just to demonstrate the use of capabilities. +WIDTH = 640 +HEIGHT = 300 + + +class CustomVideoBin(gst.Bin): + def __init__(self): + gst.Bin.__init__(self, 'CustomVideoBin') + + queue = gst.element_factory_make('queue', 'vqueue') + self.add(queue) + + rescale = gst.element_factory_make("videoscale", "rescale") + self.add(rescale) + + caps = gst.Caps("video/x-raw-yuv,format=(fourcc)AYUV,width=%d,height=%d,pixel-aspect-ratio=1/1" % (WIDTH, HEIGHT)) + capsfilter = gst.element_factory_make("capsfilter", "filter") + capsfilter.set_property("caps", caps) + self.add(capsfilter) + + colorspace = gst.element_factory_make("colorspace", "colorspace") + self.add(colorspace) + + videosink = gst.element_factory_make("autovideosink", "vidoesink") + self.add(videosink) + + gst.element_link_many(queue, rescale, capsfilter, colorspace, videosink) + sink = queue.get_pad('sink') + self.add_pad(gst.GhostPad('sink', sink)) + + +class CustomAudioBin(gst.Bin): + def __init__(self): + gst.Bin.__init__(self, 'CustomAudioBin') + + queue = gst.element_factory_make('queue', 'aqueue') + self.add(queue) + + audioconvert = gst.element_factory_make("audioconvert", "audioconverter") + self.add(audioconvert) + + audiosink = gst.element_factory_make("autoaudiosink", "audiosink") + self.add(audiosink) + + gst.element_link_many(queue, audioconvert, audiosink) + sink = queue.get_pad('sink') + self.add_pad(gst.GhostPad('sink', sink)) + + +class CustomPlayBin(gst.Pipeline): + __gproperties__ = { + 'source': (gst.Element, "source", "Source element", gobject.PARAM_READABLE) + } + + def __init__(self, uri=None): + gst.Pipeline.__init__(self, 'CustomPlayBin') + + self._uri = uri + + self._playbin = gst.element_factory_make("playbin2", "playbin") + self.add(self._playbin) + + self._playbin.set_property("uri", self._uri) + self._playbin.set_property("video-sink", CustomVideoBin()) + self._playbin.set_property("audio-sink", CustomAudioBin()) + + def set_uri(self, uri): + self._uri = uri + self._playbin.set_property("uri", self._uri) + + +class GstPlayer: + def __init__(self): + + # The user can require some action at End Of Stream + self.eos_cb = None + + self.pipeline = CustomPlayBin() + + bus = self.pipeline.get_bus() + bus.add_signal_watch() + bus.connect('message::eos', self.on_eos) + bus.connect('message::tag', self.on_tag) + bus.connect('message::error', self.on_error) + bus.connect('message::state-changed', self.on_state_changed) + + def on_eos(self, bus, msg): + print 'on_eos' + self.stop() + if self.eos_cb: + self.eos_cb() + + def on_tag(self, bus, msg): + print 'on_tag:' + taglist = msg.parse_tag() + for key in taglist.keys(): + print '\t%s = %s' % (key, taglist[key]) + + def on_error(self, bus, msg): + print 'on_error' + error, debug = msg.parse_error() + print "Error: %s" % error, debug + self.stop() + + def on_state_changed(self, bus, msg): + print 'on_state_changed' + if msg.src != self.pipeline: + return + + old_state, new_state, pending = msg.parse_state_changed() + + def set_location(self, location): + self.pipeline.set_uri(location) + + def play(self): + self.pipeline.set_state(gst.STATE_PLAYING) + + def pause(self): + self.pipeline.set_state(gst.STATE_PAUSED) + + def stop(self): + self.pipeline.set_state(gst.STATE_NULL) + + +class PlayerTUI(): + def __init__(self, location): + + self.player = GstPlayer() + self.player.eos_cb = self.quit + + self.mainloop = gobject.MainLoop() + + self.player.set_location(location) + self.player.play() + + gobject.io_add_watch(sys.stdin, gobject.IO_IN, self.on_stdin) + + try: + self.mainloop.run() + except KeyboardInterrupt: + self.quit() + + def on_stdin(self, fd, event): + # The user has to send a newline fo this to go on + c = os.read(fd.fileno(), 1) + + if c == "q": + self.quit() + elif c == "s": + self.player.pause() + elif c == "r": + self.player.play() + + return True + + def quit(self): + self.player.stop() + self.player = None + self.mainloop.quit() + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + tui = PlayerTUI(args[1]) + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/python/gst-looping-video-1.py b/python/gst-looping-video-1.py new file mode 100755 index 0000000..9886abe --- /dev/null +++ b/python/gst-looping-video-1.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +# Get a test sample with: +# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y + +import sys + +import gobject +gobject.threads_init() + +import gst + + +class Player: + def __init__(self, filename): + self._filename = filename + + self._player = gst.element_factory_make("playbin2", "player") + self._player.set_property("uri", filename) + + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect('message::eos', self.on_eos) + + def run(self): + self._player.set_state(gst.STATE_PLAYING) + loop = gobject.MainLoop() + loop.run() + + def on_eos(self, bus, msg): + sys.stderr.write(".") + self._player.seek_simple(gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH, 0) + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + player = Player(args[1]) + player.run() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/python/gst-looping-video-2.py b/python/gst-looping-video-2.py new file mode 100755 index 0000000..eabb7a4 --- /dev/null +++ b/python/gst-looping-video-2.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# Get a test sample with: +# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y + +import sys + +import gobject +gobject.threads_init() + +import gst + + +class Player: + def __init__(self, filename): + self._filename = filename + + self._player = gst.element_factory_make("playbin2", "player") + self._player.set_property("uri", filename) + self._player.connect("about-to-finish", self.on_about_to_finish) + + def run(self): + self._player.set_state(gst.STATE_PLAYING) + loop = gobject.MainLoop() + loop.run() + + def on_about_to_finish(self, player): + sys.stderr.write(".") + player.set_property("uri", self._filename) + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + player = Player(args[1]) + player.run() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/python/gst-trick-mode-looping-1.py b/python/gst-trick-mode-looping-1.py new file mode 100755 index 0000000..fe00556 --- /dev/null +++ b/python/gst-trick-mode-looping-1.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +# Get a test sample with: +# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y + +import sys + +import gobject +gobject.threads_init() + +import gst + + +class Player: + def __init__(self, filename, rate): + self._filename = filename + self._rate = rate + + self._player = gst.element_factory_make("playbin2", "player") + self._player.set_property("uri", filename) + + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect('message::eos', self.on_eos) + bus.connect('message::state-changed', self.on_state_changed) + + def run(self): + self._player.set_state(gst.STATE_PLAYING) + loop = gobject.MainLoop() + loop.run() + + def on_eos(self, bus, msg): + sys.stderr.write(".") + self._player.set_state(gst.STATE_PLAYING) + seek_event = gst.event_new_seek(self._rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, 0, + gst.SEEK_TYPE_NONE, 0) + self._player.send_event(seek_event) + + def on_state_changed(self, bus, msg): + if msg.src != self._player: + return + + print 'on_state_changed' + old_state, new_state, pending = msg.parse_state_changed() + print "%s -> %s" % (old_state, new_state) + if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: + self.set_rate(self._rate) + + def set_rate(self, rate): + self._rate = rate + try: + position, format = self._player.query_position(gst.FORMAT_TIME) + except: + position = 0 + + # Create the seek event + if rate > 0: + seek_event = gst.event_new_seek(rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, position, + gst.SEEK_TYPE_NONE, 0) + else: + seek_event = gst.event_new_seek(rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, 0, + gst.SEEK_TYPE_SET, position) + + if seek_event: + self._player.send_event(seek_event) + gst.info("rate set to %s" % rate) + else: + gst.warining("change rate failed") + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + player = Player(args[1], 3.0) + player.run() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/python/gst-trick-mode-looping-2.py b/python/gst-trick-mode-looping-2.py new file mode 100755 index 0000000..920677d --- /dev/null +++ b/python/gst-trick-mode-looping-2.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +# Get a test sample with: +# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y + +import sys + +import gobject +gobject.threads_init() + +import gst + + +class Player: + def __init__(self, filename, rate): + self._filename = filename + self._rate = rate + + self._player = gst.element_factory_make("playbin2", "player") + self._player.set_property("uri", filename) + self._player.connect("about-to-finish", self.on_about_to_finish) + + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect('message::state-changed', self.on_state_changed) + + def run(self): + self._player.set_state(gst.STATE_PLAYING) + loop = gobject.MainLoop() + loop.run() + + def on_about_to_finish(self, player): + sys.stderr.write(".") + player.set_property("uri", self._filename) + + # XXX Ater the first iteration of the loop the playback rate is + # reset to normal. Do I need to re-set the rate here? + + # If I uncomment the following line, the player hangs: + #self.set_rate(self._date) + + # And it hangs also if I set the seek_event manually using position=0: + #seek_event = gst.event_new_seek(self._rate, + # gst.FORMAT_TIME, + # gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + # gst.SEEK_TYPE_SET, 0, + # gst.SEEK_TYPE_NONE, 0) + #self._player.send_event(seek_event) + + def on_state_changed(self, bus, msg): + if msg.src != self._player: + return + + print 'on_state_changed' + old_state, new_state, pending = msg.parse_state_changed() + print "%s -> %s" % (old_state, new_state) + if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: + self.set_rate(self._rate) + + def set_rate(self, rate): + self._rate = rate + try: + position, format = self._player.query_position(gst.FORMAT_TIME) + except: + position = 0 + + # Create the seek event + if rate > 0: + seek_event = gst.event_new_seek(rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, position, + gst.SEEK_TYPE_NONE, 0) + else: + seek_event = gst.event_new_seek(rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, 0, + gst.SEEK_TYPE_SET, position) + + if seek_event: + self._player.send_event(seek_event) + gst.info("rate set to %s" % rate) + else: + gst.warining("change rate failed") + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + player = Player(args[1], 3.0) + player.run() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/python/gst-trick-mode-looping-3.py b/python/gst-trick-mode-looping-3.py new file mode 100755 index 0000000..94b99af --- /dev/null +++ b/python/gst-trick-mode-looping-3.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +# Get a test sample with: +# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y + +import sys + +import gobject +gobject.threads_init() + +import gst + + +class Player: + def __init__(self, filename, rate): + self._filename = filename + self._rate = rate + + self._player = gst.element_factory_make("playbin2", "player") + self._player.set_property("uri", filename) + + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect('message::state-changed', self.on_state_changed) + bus.connect('message::segment-done', self.on_segment_done) + + def run(self): + self._player.set_state(gst.STATE_PLAYING) + loop = gobject.MainLoop() + loop.run() + + def on_segment_done(self, bus, msg): + self._player.seek(self._rate, gst.FORMAT_TIME, + gst.SEEK_FLAG_SEGMENT | gst.SEEK_FLAG_SKIP | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, 0, + gst.SEEK_TYPE_END, 0) + + def on_state_changed(self, bus, msg): + if msg.src != self._player: + return + + print 'on_state_changed' + old_state, new_state, pending = msg.parse_state_changed() + print "%s -> %s" % (old_state, new_state) + if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: + self.set_rate(self._rate) + + def set_rate(self, rate): + self._rate = rate + + if rate == 0: + self._player.set_state(gst.STATE_PAUSED) + else: + self._player.set_state(gst.STATE_PLAYING) + self._player.seek(self._rate, gst.FORMAT_TIME, + gst.SEEK_FLAG_SEGMENT | gst.SEEK_FLAG_SKIP | gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, 0, + gst.SEEK_TYPE_END, 0) + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + player = Player(args[1], 3.0) + player.run() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/python/gst-trick-mode.py b/python/gst-trick-mode.py new file mode 100755 index 0000000..a4e063f --- /dev/null +++ b/python/gst-trick-mode.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +# Get a test sample with: +# youtube-dl -t http://www.youtube.com/watch?v=yWa-YXiSk2Y + +import sys + +import gobject +gobject.threads_init() + +import gst + + +class Player: + def __init__(self, filename, rate): + self._filename = filename + self._rate = rate + + self._player = gst.element_factory_make("playbin2", "player") + self._player.set_property("uri", filename) + + bus = self._player.get_bus() + bus.add_signal_watch() + bus.connect('message::state-changed', self.on_state_changed) + + def run(self): + self._player.set_state(gst.STATE_PLAYING) + loop = gobject.MainLoop() + loop.run() + + def on_state_changed(self, bus, msg): + if msg.src != self._player: + return + + print 'on_state_changed' + old_state, new_state, pending = msg.parse_state_changed() + print "%s -> %s" % (old_state, new_state) + if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED: + self.set_rate(self._rate) + + def set_rate(self, rate): + self._rate = rate + try: + position, format = self._player.query_position(gst.FORMAT_TIME) + except: + position = 0 + + # Create the seek event + if rate > 0: + seek_event = gst.event_new_seek(rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, position, + gst.SEEK_TYPE_NONE, 0) + else: + seek_event = gst.event_new_seek(rate, + gst.FORMAT_TIME, + gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, + gst.SEEK_TYPE_SET, 0, + gst.SEEK_TYPE_SET, position) + + if seek_event: + self._player.send_event(seek_event) + gst.info("rate set to %s" % rate) + else: + gst.warining("change rate failed") + + +def main(args): + def usage(): + sys.stdout.write("usage: %s \n" % args[0]) + + if len(args) != 2: + usage() + sys.exit(1) + + if not gst.uri_is_valid(args[1]): + sys.stderr.write("Error: Invalid URI: %s\n" % args[1]) + sys.exit(1) + + player = Player(args[1], 3.0) + player.run() + +if __name__ == '__main__': + sys.exit(main(sys.argv)) -- 2.1.4