Identifying duration of audio file

W. Michael Petullo mike at flyn.org
Mon Mar 10 23:46:18 PDT 2014


I use GStreamer in dmapd to identify the duration of media files and to
read the files' metadata. I have recently begun to have trouble with
the former.

What I am finding is that gst_element_query_duration returns false when
called on a MP3 pipeline in the paused state. This is the case even
though the MP3 is not VBR.

The portion of my code in question is below. The first
gst_element_query_duration call fails on MP3s (but succeeds on Ogg
Vorbis files). This means that the code transitions the pipeline into
the playing state (using play_pipeline), which I mean to happen only
for VBR MP3s.

	handler_id = g_signal_connect (gst_reader->priv->src_decoder,
                          "no-more-pads",
                          G_CALLBACK (no_more_pads_cb),
                          gst_reader->priv->loop);
        if (0 == handler_id) {
                g_warning ("Failed to attach no-more-pads signal handler.");
                goto _return;
        }

	g_idle_add ((GSourceFunc) pause_pipeline, gst_reader->priv);
        g_timeout_add_seconds (TRANSITION_TIMEOUT, (GSourceFunc) quit_mainloop, gst_reader->priv->loop);
        g_main_loop_run (gst_reader->priv->loop);

	if (! gst_element_query_duration (gst_reader->priv->sink, fmt, &nanoduration)) {
                g_warning ("Failed to determine duration of %s while paused; trying while playing", uri);

                /* Allow to play for N seconds; do not stop after all pads identified. */
                g_signal_handler_disconnect (gst_reader->priv->src_decoder, handler_id);

                /* Run main loop/play to allow decodebin to create pads. Quit after
                 * three seconds. Should cause one or more GST_MESSAGE_DURATION_CHANGED
                 * messages. Hopefully within three seconds the estimate of a VBR's 
                 * duration will be accurate enough. */
                g_idle_add ((GSourceFunc) play_pipeline, gst_reader->priv);
                g_timeout_add_seconds (TRANSITION_TIMEOUT, (GSourceFunc) quit_mainloop, gst_reader->priv->loop);
                g_main_loop_run (gst_reader->priv->loop);
        }	

	if (! message_loop (GST_ELEMENT (gst_reader->priv->pipeline), &tags)) {
                goto _return;
        }

        if (0 == nanoduration && ! gst_element_query_duration (gst_reader->priv->sink, fmt, &nanoduration)) {
                /* NOTE: Do not change this error message without also updating dmapd-test/test. */
                g_warning ("Failed to determine duration of %s while playing; skipping", uri);
                goto _return;
        }

You can get the actual code with:

	git clone https://www.flyn.org/git/dmapd # (see av-meta-reader-gst.c)

Why might the first gst_element_query_duration fail?

On a related note, is there a recommended way to estimate the duration
of a VBR file without playing through the entire thing?  I want the
duration calculation to be reasonably accurate but not too slow. Right
now I am considering placing my pipeline in the play state for around
3 seconds. Has anyone found a good sweet spot for this, or should I
just experiment?

Thank you,

-- 
Mike

:wq


More information about the gstreamer-devel mailing list