Isolating elements in a pipeline for seeking
Axel Poulain
ax.poulain at free.fr
Fri Aug 27 13:37:58 UTC 2021
Hi,
I’m pretty new to GStreamer and I’m encountering some difficulties…
I’m trying to build an audio player that should read an audio file by looping
from a point A to a point B. First, I tried a simple approach using seek events
on a simple pipeline (uridecodebin -> audioconvert -> audioresample -> autoaudiosink),
by listening to “segment-done” messages on the bus and invoking callbacks which
should then call gst_element_seek() on the whole pipeline, which worked correctly.
However, I’d like to play multiple files simultaneously, with different lengths
and different loop points. To achieve this isolation between different files,
I wanted to create a special GstBin, individually playing and looping through
a single audio file, which I could then connect to the rest of the player’s
pipeline by using an adder element.
My GstBin looks like (uridecodebin -> audioconvert -> audioresample), and I
connect it to the main pipeline (adder -> autoaudiosink) using a ghostpad.
Here comes my problem…
When I tried to connect a single GstBin to the main pipeline, everything worked
fine while I was still using my callbacks listening for “message::segment-done”
on the whole pipeline. However, to be able to use multiple GstBin simultaneously,
I need them to be able to loop themselves on their file. That’s why instead of
listening for “message::segment-done” on the whole pipeline, I added a probe on
the bin's audioresample which should listen for downstream events.
I added my probe like this :
/* out is the src pad of the audioresample element, the last one of my bin */
gst_pad_add_probe(out, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, myapp_tail_segment_done_cb, tail, NULL);
and, in my callback, I’m seeking back to the start of my loop, which looks like this
static GstPadProbeReturn myapp_tail_segment_done_cb(GstPad *pad, GstPadProbeInfo *info, gpointer data) {
Tail *tail = data; /* My custom struct containing the bin, as well as other informations for the loop */
GstEvent *event;
GstEventType type;
event = gst_pad_probe_info_get_event(info);
/* Checking the event type */
type = GST_EVENT_TYPE(event);
if (type != GST_EVENT_SEGMENT_DONE) {
return GST_PAD_PROBE_OK;
}
/* And then, code using…
gst_element_seek(tail->bin, 1.0, myfavoriteformat, GST_SEEK_FLAG_SEGMENT,
GST_SEEK_TYPE_SET, tail->start,
GST_SEEK_TYPE_SET, tail->end);
/*…under different conditions (start and end values changing)
return GST_PAD_PROBE_OK;
}
…but when I launch my application, as soon as the first loop is read and the
first “segment-done” event is catched, the playback suddenly doesn’t output
any sound, and I’m getting flooded by “segment-done” events followed by “segment”
events (which call my probe's callback endlessly).
I realized that using GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH flags instead
of a single GST_SEEK_FLAG_SEGMENT in my callback when seeking made my problem
disappear, but unfortunately that’s not the expected behavior, because my player
then drops the last pieces of the loop, and the seek doesn’t happen seamlessly.
I don’t really understand why is this happening… Could someone help me understand
what's going on with all these "segment-done" events, and how to avoid them ?
And if I’m not doing things right, is there a better, recommended way to isolate
different elements, allowing them to handle themselves the seeking ?
Thanks if you can help me !
Best regards.
More information about the gstreamer-devel
mailing list