Query duration of many sound files in a loop

Jiergir Ogoerg f35f22fan at gmail.com
Mon Aug 19 12:25:44 PDT 2013


Thanks,
I'm using Ubuntu 13.04 amd64 with ppa with gstreamer 1.0.8, using the ppa
to avoid bugs.

I gave up on the bus solution since it only over-complicates things and I
can achieve the same thing with get_state() which apparently blocks if the
previous set_state() returned an async result.
This is the best I came up with, but it still randomly displays wrong
duration about a few (mp3) files and I don't know why.

//SOURCE CODE START, the relevant part

for (int i=0; i<vec_size; i++) {
        mtl::io::QtFile *file = (*vec)[i];

        if (file->IsDir()) { // not a sound file
            delete file;
            continue;
        }

        QString uri = "file://" + file->full_path();
        QByteArray arr = uri.toLocal8Bit();
        const char *c_uri = arr.data();

        if (gst_element_set_state(ref, GST_STATE_NULL) != 1) {
            MTL_WARN("set_state() failed");
            break;
        }

        g_object_set(G_OBJECT(ref), "uri", c_uri, NULL);
//EXTRA PREPARATION START
        state = gst_element_set_state(ref, GST_STATE_PLAYING);
        if (state != GST_STATE_CHANGE_ASYNC) {
            MTL_WARN("Not a GST_STATE_CHANGE_ASYNC");
            break;
        }

        // wait for set_state to finish
        state = gst_element_get_state(ref, &ret1, &ret2,
GST_CLOCK_TIME_NONE);
        if (state != GST_STATE_CHANGE_SUCCESS) {
            MTL_WARN("get_state() failed");
            break;
        }

        state = gst_element_set_state(ref, GST_STATE_PAUSED);
        // wait for set_state to finish
        if (state == GST_STATE_CHANGE_ASYNC) {
            state = gst_element_get_state(ref, &ret1, &ret2,
GST_CLOCK_TIME_NONE);
            if (state != GST_STATE_CHANGE_SUCCESS) {
                MTL_WARN("get_state() failed");
                break;
            }
        }
//EXTRA PREPARATION END
        gst_element_query_duration(ref, GST_FORMAT_TIME, &duration);
        file->duration_set(duration);
        song_tree->AddSong(file);
    }
//SOURCE CODE END

What frustrates me is that apparently I have to know about these "extra
preparation" steps for such a simple task as querying for duration, worse
yet,
if you don't do them gstreamer reports arbitrary durations.

As one can see I set two states: to "playing", then to "paused" because if
"playing" is skipped I get even more arbitrary duration results.

What am I doing wrong, can't the API be more intuitive?




On Sat, Aug 17, 2013 at 8:40 PM, Tim-Philipp Müller <t.i.m at zen.co.uk> wrote:

> On Sat, 2013-08-17 at 04:52 +0300, Jiergir Ogoerg wrote:
>
> Hi,
>
> > I wanna query a lot of sound files duration in a loop efficiently, so
> > instead of waiting in a sub-loop with a sleep method until the query
> > succeeds for each given file - I wanna go for the second approach by
> > processing the GST_MESSAGE_ASYNC_DONE message on the bus, thus
> > bypassing the potential need to do (several) sleep(s) for each sound
> > file.
> >
> >
> > How do I do it properly?
> >
> > The only thing I can think about is launching the files query loop in
> > a different thread, from there for each file block on a condition
> > variable until I get the async event on the bus on the main thread
> > which would fire pthread_cond_signal() to unblock the querying thread
> > to query the corresponding file and move on to the next sound file in
> > the loop.
> >
> >
> > Is there a better way to implement this non-sleep approach?
>
> If you're happy to block, you could simply do:
>
>  msg = gst_bus_timed_pop_filtered (bus, -1,
>      GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR);
>
> which will block until you get an error message or async_done.
>
>
> > How do I know that GST_MESSAGE_ASYNC_DONE isn't fired by some other
> > source since gstreamer is multi-threaded and can work with many sound
> > sources in parallel so the events on the bus might be rather random,
> > right?
>
> Not sure if I understand this question right. What's your setup exactly?
> Do you have multiple pipelines? Or are you trying to process multiple
> files in parallel within the same pipeline?
>
> ASYNC_DONE is part of the preroll mechanism in GStreamer. It is usually
> posted by sinks, and aggregated by bins/the pipeline to only be
> forwarded once all sinks/children are finished prerolling.
>
> Cheers
>  -Tim
>
>
> _______________________________________________
> gstreamer-devel mailing list
> gstreamer-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/gstreamer-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20130819/a8269789/attachment.html>


More information about the gstreamer-devel mailing list