mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
parent
9f4a73d282
commit
b921832369
1 changed files with 198 additions and 0 deletions
198
examples/segments.py
Executable file
198
examples/segments.py
Executable file
|
@ -0,0 +1,198 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Segments.py
|
||||
# Copyright (C) 2006 Artem Popov <artfwo@gmail.com>
|
||||
#
|
||||
# This example demonstrates segment seeking
|
||||
# and seamless looping within playbin.
|
||||
|
||||
import pygst
|
||||
pygst.require ("0.10")
|
||||
import gst
|
||||
|
||||
import pygtk
|
||||
pygtk.require ("2.0")
|
||||
import gobject
|
||||
|
||||
class Looper (gobject.GObject):
|
||||
__gproperties__ = {
|
||||
"loop": (gobject.TYPE_BOOLEAN,
|
||||
"loop",
|
||||
"Whether to loop the segment",
|
||||
False,
|
||||
gobject.PARAM_READWRITE),
|
||||
"start-pos": (gobject.TYPE_UINT64,
|
||||
"start position",
|
||||
"The segment start marker",
|
||||
0,
|
||||
0xfffffffffffffff, # max long possible
|
||||
0,
|
||||
gobject.PARAM_READWRITE),
|
||||
"stop-pos": (gobject.TYPE_UINT64,
|
||||
"stop position",
|
||||
"The segment stop marker",
|
||||
0,
|
||||
0xfffffffffffffff, # max long possible
|
||||
0,
|
||||
gobject.PARAM_READWRITE),
|
||||
} # __gproperties__
|
||||
|
||||
__gsignals__ = {
|
||||
"stopped": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
|
||||
"position-updated": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_FLOAT,)),
|
||||
"error": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
|
||||
} # __gsignals__
|
||||
|
||||
def __init__ (self, location = None):
|
||||
gobject.GObject.__init__ (self)
|
||||
|
||||
self.__playbin = gst.element_factory_make ("playbin")
|
||||
self.__playbin.props.video_sink = gst.element_factory_make ("fakesink")
|
||||
|
||||
bus = self.__playbin.get_bus ()
|
||||
bus.add_watch (self.__on_bus_message)
|
||||
|
||||
self.__loop = False
|
||||
self.__start_pos = 0
|
||||
self.__stop_pos = 0
|
||||
|
||||
self.__timeout_id = 0
|
||||
|
||||
if location:
|
||||
self.load (location)
|
||||
|
||||
def load (self, location):
|
||||
self.__playbin.props.uri = location
|
||||
self.__start_position = 0
|
||||
self.__stop_position = 0
|
||||
|
||||
def set_segment (self, start, stop):
|
||||
self.props.start_pos = start
|
||||
self.props.stop_pos = stop
|
||||
|
||||
def play (self):
|
||||
if not (self.__start_pos or self.__stop_pos):
|
||||
raise RuntimeError, "Cannot start playback, segment was not set!"
|
||||
|
||||
self.__playbin.set_state (gst.STATE_PLAYING)
|
||||
|
||||
def stop (self, silent = False):
|
||||
self.__playbin.set_state (gst.STATE_NULL)
|
||||
if not silent:
|
||||
self.emit ("stopped")
|
||||
|
||||
def do_get_property (self, property):
|
||||
if property.name == "loop":
|
||||
return self.__loop
|
||||
elif property.name == "start-pos":
|
||||
return self.__start_pos
|
||||
elif property.name == "stop-pos":
|
||||
return self.__stop_pos
|
||||
else:
|
||||
raise AttributeError, "Unknown property %s" % property.name
|
||||
|
||||
def do_set_property (self, property, value):
|
||||
if property.name == "loop":
|
||||
self.__loop = value
|
||||
elif property.name == "start-pos":
|
||||
self.__start_pos = value
|
||||
elif property.name == "stop-pos":
|
||||
self.__stop_pos = value
|
||||
else:
|
||||
raise AttributeError, "Unknown property %s" % property.name
|
||||
|
||||
def do_stopped (self):
|
||||
if self.__timeout_id:
|
||||
gobject.source_remove (self.__timeout_id)
|
||||
self.__timeout_id = 0
|
||||
|
||||
def __seek (self, start, stop, flush):
|
||||
flags = gst.SEEK_FLAG_SEGMENT | gst.SEEK_FLAG_ACCURATE
|
||||
if flush:
|
||||
flags = flags | gst.SEEK_FLAG_FLUSH
|
||||
self.__playbin.seek (1.0, gst.FORMAT_TIME, flags,
|
||||
gst.SEEK_TYPE_SET, start,
|
||||
gst.SEEK_TYPE_SET, stop)
|
||||
|
||||
def __on_timeout (self):
|
||||
position = self.__playbin.query_position (gst.FORMAT_TIME) [0]
|
||||
self.emit ("position-updated", float (position))
|
||||
return True
|
||||
|
||||
def __on_bus_message (self, bus, message):
|
||||
if message.type == gst.MESSAGE_ERROR:
|
||||
error, debug = message.parse_error ()
|
||||
self.stop () # this looks neccessary here
|
||||
self.emit ("error", (error, debug))
|
||||
|
||||
elif message.type == gst.MESSAGE_NEW_CLOCK:
|
||||
# we connect the timeout handler here to be sure that further queries succeed
|
||||
interval = int ((self.__stop_position - self.__start_position) / (2 * gst.SECOND) + 50)
|
||||
self.__timeout_id = gobject.timeout_add (interval, self.__on_timeout)
|
||||
|
||||
elif message.type == gst.MESSAGE_STATE_CHANGED:
|
||||
old_state, new_state, pending = message.parse_state_changed ()
|
||||
if old_state == gst.STATE_READY and new_state == gst.STATE_PAUSED and message.src == self.__playbin:
|
||||
self.__seek (self.__start_pos, self.__stop_pos, True)
|
||||
|
||||
elif message.type == gst.MESSAGE_SEGMENT_DONE:
|
||||
if self.__loop:
|
||||
self.__seek (self.__start_pos, self.__stop_pos, False)
|
||||
else:
|
||||
src = self.__playbin.get_property ("source")
|
||||
pad = src.get_pad ('src')
|
||||
pad.push_event (gst.event_new_eos ())
|
||||
|
||||
# this is the good old way:
|
||||
#
|
||||
# pads = src.src_pads ()
|
||||
# while True:
|
||||
# try:
|
||||
# pad = pads.next ()
|
||||
# pad.push_event (gst.event_new_eos ())
|
||||
# except:
|
||||
# break
|
||||
|
||||
elif message.type == gst.MESSAGE_EOS:
|
||||
self.stop ()
|
||||
|
||||
return True
|
||||
|
||||
mainloop = gobject.MainLoop ()
|
||||
|
||||
def on_looper_stopped (looper):
|
||||
mainloop.quit ()
|
||||
|
||||
def on_looper_pos_updated (looper, position):
|
||||
print round (position / gst.SECOND, 2)
|
||||
|
||||
def on_looper_error (looper, error_tuple):
|
||||
error, debug = error_tuple
|
||||
print "\n\n%s\n\n%s\n\n" % (error, debug)
|
||||
mainloop.quit ()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len (sys.argv) != 5:
|
||||
print "Usage: %s <filename|uri> <start_seconds> <stop_seconds> <loop = 0|1>" % sys.argv [0]
|
||||
sys.exit (1)
|
||||
|
||||
if "://" in sys.argv [1]:
|
||||
uri = sys.argv [1]
|
||||
else:
|
||||
import os.path
|
||||
uri = "file://" + os.path.abspath (sys.argv [1])
|
||||
|
||||
looper = Looper (uri)
|
||||
|
||||
looper.props.start_pos = long (sys.argv [2]) * gst.SECOND
|
||||
looper.props.stop_pos = long (sys.argv [3]) * gst.SECOND
|
||||
looper.props.loop = int (sys.argv [4])
|
||||
|
||||
looper.connect ("stopped", on_looper_stopped)
|
||||
looper.connect ("position-updated", on_looper_pos_updated)
|
||||
looper.connect ("error", on_looper_error)
|
||||
|
||||
looper.play ()
|
||||
mainloop.run ()
|
Loading…
Reference in a new issue