GNOME Bugzilla – Bug 726144
gst_element_query_duration returns false while pipeline paused, even if MP3 has duration tag
Last modified: 2014-03-14 02:46:09 UTC
Created attachment 271567 [details] Simple program that illustrates problem I have some code in dmapd that determines the duration of an MP3, first by calling gst_element_query_duration on a paused pipeline and then calling gst_element_query_duration after having played the pipeline. It looks like gst_element_query_duration does not identify the duration while paused, even when the MP3 contains a duration tag. Only when I call gst_element_query_duration again after playing the stream for a few seconds, does the function identify the stream's duration. I stripped down my code (attached). When I run it, I see: ./a.out /var/db/BigDisk/Storage/Music/Dire\ Straits/Dire\ Straits\ -\ On\ The\ Night\ -\ 04\ -\ Romeo\ And\ Juliet.mp3 found duration 604 ** (a.out:20808): WARNING **: Failed to determine duration of file:///var/db/BigDisk/Storage/Music/Dire%20Straits/Dire%20Straits%20-%20On%20The%20Night%20-%2004%20-%20Romeo%20And%20Juliet.mp3 while paused; trying while playing
I meant to also report that gst-launch also finds the duration tag in this file: $ gst-launch -t uridecodebin uri=file:///var/db/BigDisk/Storage/Music/Dire\ Straits/Dire\ Straits\ -\ On\ The\ Night\ -\ 04\ -\ Romeo\ And\ Juliet.mp3 Setting pipeline to PAUSED ... Pipeline is PREROLLING ... FOUND TAG : found by element "id3demux0". title: Romeo And Juliet artist: Dire Straits album: On The Night track number: 4 genre: Rock container format: ID3 tag track count: 10 duration: 604000000000 Pipeline is PREROLLED ... FOUND TAG : found by element "mpegaudioparse0". audio codec: MPEG 1 Audio, Layer 3 (MP3) nominal bitrate: 128000 FOUND TAG : found by element "mpegaudioparse0". has crc: FALSE channel mode: stereo Setting pipeline to PLAYING ... FOUND TAG : found by element "mad0". layer: 3 mode: stereo emphasis: none bitrate: 128000 New clock: GstSystemClock ERROR: from element /GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin2:decodebin20/GstMpegAudioParse:mpegaudioparse0: GStreamer encountered a general stream error. Additional debug info: gstbaseparse.c(2890): gst_base_parse_loop (): /GstPipeline:pipeline0/GstURIDecodeBin:uridecodebin0/GstDecodeBin2:decodebin20/GstMpegAudioParse:mpegaudioparse0: streaming stopped, reason not-linked Execution ended after 244905 ns. Setting pipeline to PAUSED ... Setting pipeline to READY ... Setting pipeline to NULL ... Freeing pipeline ...
We tend not to trust duration tags. If you want to fallback to taking the duration from the tags if querying the duration fails, or in general, that's a decision you can make in your application. Usually querying the duration in paused state should work (this is assuming you wait for preroll, which you do), but the audio parsers will sometimes only try and estimate a duration when they've seen a couple of frames pass through, in order not to give a completely bogus duration for VBR files. That's probably why you don't get a duration here.
I do not want to turn this bug report into a support request, but perhaps it could be an RFE. Is there a way to identify whether an MP3 stream is VBR while in the paused state? If this is the case, could the audio parser provide a duration before playing, and only require a few frames in the case of VBR? What does Ogg/Vorbis do? (I get a duration while paused from this format.) My problem is that I want to catalog a large number of media files, so I want to assess their duration as quickly as possible (while maintaining a reasonable accuracy). I am not actually playing the files at this point, and I only do so (for some short period of time) when required to assess the duration.
With Ogg you get that information because there's a container where oggdemux can get that information from the container bitstream. If you put mp3 into matroska or mp4 or whatever you also get that information reliably every time. You might be interested in using GstDiscoverer to collect that information (although it is not immune to this of course, but it will try harder to extract it and take more time if required). You can't know if it's VBR without reading the entire file, or at least quite a few frames. I
GstDiscoverer is great---thank you for bringing my attention to it. I am going to close this bug as NOTABUG. Sorry this turned out to be a support request.