[gst-devel] hopefully useful gst-python examples

Andy Wingo wingo at pobox.com
Tue Apr 25 02:43:02 CEST 2006


Hi Артём,

On Tue, 2006-04-25 at 11:28 +0700, Артём Попов wrote:
> the first (Segments.py) is a demonstration of seamless
> looping (originally used as showcase for bugs #338290 and #338292)

Excellent! You should file a bug to get them added to gst-python. Just
so we don't forget, also it increases your bug pointage. Which is
absolutely crucial as we all know.

Wrt your looper example, I don't think it is absolutely correct. It has
some race conditions when performing the initial segment seek. The
issues are two: (1) you want to seek before any data has hit the sink;
and (2) you can only seek (in most elements) while data is flowing (i.e.
ready->paused or higher). The only way to reliably catch this transition
is to do the following process:

  (1) block the pads that are linked to the sink via
gst_pad_set_blocked_async;
  (2) when all pads are blocked (or, in your case, just the one pad),
marshal a message to the main thread telling it to do the seek;
  (3) in the main thread, you do a flushing segment seek, ignore any
future asynchronous blocks [a], and unblock the pads.

There is an odd behavior here and a bug you should know about.

First of all, the pad_blocked_async will fire when something tries to
communicate data flow across a connection, which includes
gst_buffer_push and gst_pad_alloc_buffer. It should include synchronized
events as well, i.e. GST_EVENT_NEW_SEGMENT, but atm it does not. This is
a bug. The bug now is that that although you set the pads blocked, the
newsegment gets through, and the sink will receive two newsegments (one
from initial playback, one for the segment), which is a bug. Workaround:
before you block the pads, unlink them, then link again before doing the
flushing seek.

Odd behavior referred to in [a]: When you do the flushing seek, the data
held in the pad_block (the first buffer or bufferalloc) will be flushed,
and at some later point data will hit that pad again and the block
function will be called. Arguably setting a pad blocked should make the
block_async call go through only once, but right now it's every time
until you set it unblocked. The upshot is that you have to be prepared
for pad_blocked to be called again, or not, after a flushing seek. It
would not be called if you manage to unblock the pad before the
streaming thread spins up again.

Tricky, eh ;) There are some examples of proper segment seeking here:

https://core.fluendo.com/flumotion/trac/browser/flumotion/trunk/flumotion/component/producers/looper/looper.py?rev=3132#L139
(lines 139-183)

and

http://webcvs.freedesktop.org/gstreamer/gst-python/examples/remuxer.py?annotate=1.4
line 484 (the RemuxBin class)

Playbin should probably support all of this, and seek-in-ready; it would
obviate the need for all of this blocking. In your case you probably
can't hear it, but I think the audio sink is getting data before you do
your flushing seek, so that you hear the first few milliseconds twice.

Well, just wanted to mention all of this, considering how I had to
implement it twice recently.

Regards,
-- 
Andy Wingo
http://wingolog.org/





More information about the gstreamer-devel mailing list