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