GNOME Bugzilla – Bug 750131
mp3: Duration reported on short MP3 file is 0
Last modified: 2015-08-16 13:41:16 UTC
I just notice, to reproduce you need a short mp3: gst-launch-1.0 audiotestsrc num-buffers=10 ! \ lamemp3enc ! filesink location=test.mp3 And to find out the duration is 0 I did: gst-discoverer-1.0 test.mp3 Not sure if it's solvable or not, I'd like to at least understand this surprising result.
Interesting! Looks like the problem is in lamemp3enc. If I crop an mp3 to an extremely short duration of 0.05 seconds, gst-discoverer-1.0 still recognizes it. [example attached file] Properties: Duration: 0:00:00.052244897 Using the above pipeline Nicolas wrote, gst-discoverer-1.0 won't recognize the duration of any generated mp3 file with less than 1 second (or 42 buffers). Even though gst-play-1.0 is happy to reproduce it. Nicolas, I can look into why this is happening if you'd like.
Created attachment 304305 [details] Creative Commons Creative Commons Attribution-ShareAlike License. Title: Siesta Artist: Jahzzar
Created attachment 304306 [details] tiny_duration_example.mp3 Example mp3 file. Duration 0.05 seconds. Creative Commons Attribution-ShareAlike License. Title: Siesta Artist: Jahzzar
Interesting, this is more progress then I made so far. Feel free to have a look.
Cool :) Not sure I will have time today. But for sure on Monday morning, it is intriguing.
In case of the file, tiny_duration_example.mp3 there is a xing header in the file. So in mpegaudioparse, the duration is calculated based on the xing header and updated gst_base_parse_set_duration (GST_BASE_PARSE (mp3parse), GST_FORMAT_TIME, mp3parse->xing_total_time, 0); But in case of mp3 encoded by lame encoder, there will be no xing header. So duration is not being updated. But in case of files having more than 57 frames(1.5 second duration, varies on framerate) here parse->priv->update_interval is calculated to be 57 in baseparse, the duration gets updated else if (parse->priv->update_interval > 0 && (parse->priv->framecount % parse->priv->update_interval) == 0) gst_base_parse_update_duration (parse); So for files with less than 57 frames the duration is never being calculated.
Very interesting Vineeth. Thanks for looking into this. Is this where the update_interval is set to 57? http://cgit.freedesktop.org/gstreamer/gstreamer/tree/libs/gst/base/gstbaseparse.c#n3527 The code you mention is this (for other people to read easily): http://cgit.freedesktop.org/gstreamer/gstreamer/tree/libs/gst/base/gstbaseparse.c#n2221
Created attachment 307115 [details] [review] estimate duration as soon as we have 3 frames. Right now the duration estimation happens after every 1.5 seconds So in case of files which are less than 1.5 seconds, the estimation never happens. But to estimate the duration 3 frames are enough. So instead of waiting till 1.5 seconds, estimate the duration as soon as we get 3 frames and then continue estimating every 1.5 seconds from that time The update interval is calculated as parse->priv->update_interval = fps_num * 3 / (fps_den * 2) for default framerate, it comes out to be 57 frames for 1.5 seconds. Previously the estimation was 57, 114, 171, ...... after the patch it will be 3, 60, 117, 174, ...... Even this case, it needs a minimum of 2 buffers while encoding. As with 1 buffer there is not enough data to estimate.
Interesting fix to switch the modulo by 3 to get an _update_duration() at the 3rd frame, and then every 57 after as normal. I've looked around and this looks like the most elegant solution. +1 from me, but keeping it open in case anybody else wants to comment.
> But to estimate the duration 3 frames are enough. "Citation needed"? :) The problem we have/had is that if you make an estimation too quickly with VBR files you get completely bogus durations, esp. when the beginning of songs are quiet. I think a more conservative fix for this issue would be to force a duration estimation/update at EOS. Would that work
This issue is not only with discoverer.. it happens in gst-play as well... and maybe everywhere if it happens in gst-play In case of small files the duration will not be shown in gst-play.. only for files with more than 57 frames the duration is shown... Yeah the estimated duration in the first iteration if we do for 3 frames might not be exactly proper for some files.. but anyways we would be updating it again after 60th frame :) I felt instead of not showing anything, something can be estimated
I wasn't talking about discoverer. It's a general problem. There's a trade-off between showing bad data and no data. Showing a duration of 22 hours for a 3-minute song is bad as well. For short clips, if you post a duration message on the bus after updating the estimate, gst-play should show it as well.
Vineeth, if we are going to change the modulo to 3 instead of 0. I think it should have a comment explaining why, I'm assuming a lot of puzzled looks when people read that. Tim, that is a good point. Something we have to make sure works well.
The duration is estimated using src_value * duration / bytes where src_value is the bytes queried from pad duration is the cumulative buffer duration bytes is the cumulative size of frames being passed to push frame In case of files encoded using lame encoder with default quality the first frame size is 731, 2nd is 130 and from there it maintains a constant 104 till almost the end of the file.. This explains why i chose 3 frames :).... after 2nd frame the frame size is constant, so the estimations are not changing much because of that... if we change the quality, for example to 9 then first frame size is 365, then next 156 and later almost constant 26 I verified with different set of mp3 files, some of them blank mp3 and with data for all of them, it remains constant from the beginning, and in case of many files, the estimation is also necessary, as the header might contain the actual duration.. The estimation is being done and used for few files... I am thinking, maybe i am wasting time on a not so important issue :P...
I adhere with Tim point. We should do internal estimation, but keep posting at 1.5s. If the file is short, we post at EOS. This should be the same as with your patch, except that it reduce the risk of having a large duration jump between 3rd frame and 1.5s. I don't think you are wasting your time.
Just to make sure i am understanding it ok. . Posting at EOS might solve discoverer able to show the duration. But still it might not help gst-play right? I mean for files smaller than 1.5 second, if we post the duration at EOS and then update the duration msg in bus, that means gst-play would hv completed playing and hence it would not hv shown the duration till it was playing? It's 11 at night(zzzzzz) and i am not infront of system to check the code, so maybe i am wrong and it does get updated properly :)
The parser will get EOS before playing has finished (possibly even before playback has started :)).
Created attachment 307188 [details] [review] Estimate durartion on EOS My bad :).. i didnt realize EOS on parser happens before the actual play... so updating the patch by estimating duration during EOS, when the estimation has not happened already.
Comment on attachment 307188 [details] [review] Estimate durartion on EOS commit 6d78d32d51970003d7bc54fd16cb37922501df91 Author: Vineeth TM <vineeth.tm@samsung.com> Date: Fri Jul 10 09:12:15 2015 +0900 baseparse: estimate duration on EOS For files which are smaller than 1.5 seconds, the duration estimation does not happen. So the duration will always be displayed as 0. Updating the duration on EOS when the estimation has not happened already https://bugzilla.gnome.org/show_bug.cgi?id=750131