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