From: Antonio Ospite Date: Tue, 5 Mar 2013 15:26:27 +0000 (+0100) Subject: Add a test program where looping in trick mode works seamlessly X-Git-Url: https://git.ao2.it/experiments/gstreamer.git/commitdiff_plain/e1fd500bd67cf3b6136a3f5fb4ce6f6cd698f924 Add a test program where looping in trick mode works seamlessly The secret here is to use SEGMENT seeks instead of normal seeks: http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/gstreamer-GstEvent.html#GstSeekFlags That has been tested with positive playback rates only. --- diff --git a/gst-trick-mode-looping-3.py b/gst-trick-mode-looping-3.py new file mode 100755 index 0000000..94b99af --- /dev/null +++ b/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))