GNOME Bugzilla – Bug 729625
Problem playing a 1 frame mp3 (encoded as a data: URL or from file)
Last modified: 2018-11-03 12:20:29 UTC
I believe (from speaking to Sebastian) that this is actually two bugs, but I'll explain below. Background: The nuvolaplayer (https://nuvolaplayer.fenryxo.cz) uses GStreamer to provide HTML5 support for Google Music. This avoids the need for using the Flash plugin to play the audio content, and we'd all like to see less use of Flash I'm sure! The problem comes when the Google side does a test to see if the HTML5 support is functional. It does this by playing a silent, one-frame mp3 encoded as a data: url in base64. With GStreamer, this fails and thus HTML5 support is not enabled and Google Music thus falls back to Flash (ugg). Here is a test pipleline: gst-launch-1.0 playbin uri="data:audio/mpeg;base64,//vgZAAACZ2B1FVl4ACUEFrIoJgAagonULndgAK2RKx7FtAAAAC4AABKIwQSyZbdAOkWy+AgQUbTx98nvic7ZnhsfTkLYFxFcD/Q801XIhhoE4NAnZO0eTAOAA0AFARhOg2AVAuBoIYrFYyPL+jx5ElP8nYmgagHIEgEMLgyUgP37Gr0PQ80y3k7HoHoHoIQTg6FAyRLsZzlvJ2TsuZpqNDEMUCsZHkSkNWQS/i3ibi5mW+OQesXMhZczTQ9D1e/iU1ljT6jfEoBzhIyXu2BDEMQxDDTOtD0PV6vfx8J9R2PwWwHIDkFgcS2EILgaBoHQhiseR77gKw5DQUEFgVjJEyxoeW8uY9A9BCCcE4JwXA0DoOtD0PQ85zTJ2XM61ArFYyPKe7948pSlKfNNXhv7+A8V6vV6vV6vV6fUaGIYhiGIYrEMQxDDTNM0zrQ9D1ezv3jx48eRKAGAAAAxjGMb3AAAFHEREREZv//92QIRH/////92QjO99ou7u7smmQIEIiIMIAMBhZMmTu7iIiIiIu73xERd3e////xEZ4iIiP/////+0RH////e7uIiIiIi7JkyZMmTuIiIiP4//7QQAYDJkyZMmTJkCBAghERBNO98REXd3d3dxEGECCGOQQiIiCBAmTJkyZMmns4AwAIABg6IximJldpt0cA4xxL4z2OorDYw8rYFBiZEuAGTMYJAaYXiIkqapA4CgXMBEjCwKrh/tPQaMVJN/M/ugNtwzOgZQZnRnnEZ2A/5mPGBnTvtxLcmFDYFbjVgv88QauGkjf3fMBCg1nQ8QmlpU6aBNt/tf+4KSb//m09DIgQyQHfQuclSg6oKIHoBKbrc1/mEoAtPUfP/5aZofFmqthwn1dkQCFYzM5v///ocLKplR9j//uYFSAyUKQ2fqtTRqYCosHFta2CiCK9//jIFGygZ/yaEkPf/4JGDtnf8aS4S7lTmNg5eFTWVS54X2S3EAIwFYv/pPQx4C5///XBGkCV//+lWYyC5f//mjoHFNXrXcqGDR0HRySGaSxGBePSletpQIustFFVCT///////3cFqEwXh//+hIUbH///////////yYYFFrb///IWEnK6AAAAABAAAAAAChLqAAkbf5sLM9YLgmjtHGW4DOAB96S2/F4xpBxGWHCY6JiXUxMOYCjxcHqPYxLprt6vw2Aph7DiJEeo9SWE6+FGXG9YBvHq0VGQW+C2t6y7CdN8Ygna0dahPzBE1Ft9YmqeS35IEPRU5mNJeJIxHqPUyNw4przUT5/kV282GFf5FHo9SKKI7BuSzJFEQ5ID2HsYl01//YXDb6x8Pf//mxA/JEopiCmopmXHJyXGoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" It produces: Setting pipeline to PAUSED ... Pipeline is PREROLLING ... ERROR: from element /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind: Could not determine type of stream. Additional debug info: gsttypefindelement.c(1067): gst_type_find_element_loop (): /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind ERROR: pipeline doesn't want to preroll. Setting pipeline to NULL ... Freeing pipeline ... Enabling debugging I can make a few observations: The dataurisrc seems to correctly extract the mime type from the URL and properly decode the payload. Good start. When the type find system kicks in, it does not see that some caps are set and still tries to determine the type of the stream by parsing an extension out of the URL. With data: URLs this is really not a nice idea. I tried a hideous hack >:) to make dataurisrc "fake" the URL provided to the rest of the system (i.e. I replaced it with "file:///fake-uri.mp3"). This allowed things to get further, but type find still failed to detect the type of the stream. I presume this is because it was simply too short. To confirm this last theory, I took the base64 data, passed it through base64 -d and piped it to a file mp3.mp3 and tried a simple playbin pipeline, avoiding the dataurisrc completely. It still failed with the same error as above: gst-launch-1.0 playbin uri=file://`pwd`/mp3.mp3 Setting pipeline to PAUSED ... Pipeline is PREROLLING ... ERROR: from element /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind: Could not determine type of stream. Additional debug info: gsttypefindelement.c(1067): gst_type_find_element_loop (): /GstPlayBin:playbin0/GstURIDecodeBin:uridecodebin0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind ERROR: pipeline doesn't want to preroll. Setting pipeline to NULL ... Freeing pipeline ... However, specifying the pipeline manually (to avoid typefind) works fine: gst-launch-1.0 filesrc location=mp3.mp3 ! mpeg2dec ! autoaudiosink Setting pipeline to PAUSED ... Pipeline is PREROLLING ... Pipeline is PREROLLED ... Setting pipeline to PLAYING ... New clock: GstSystemClock Got EOS from element "pipeline0". Execution ended after 0:00:00.000087481 Setting pipeline to PAUSED ... Setting pipeline to READY ... Setting pipeline to NULL ... Freeing pipeline ... For reference, vlc (I think), mplayer and mpg123 play the file fine, although mpg123 does print out an amusing: [parse.c:1007] warning: Cannot read next header, a one-frame stream? Duh... :) I spoke privately to Sebastian about this before reporting the bug. I had hoped that it was just that the dataurisrc's caps were not being trusted by the core when in pull mode and thus the typefind kicked in, but he corrected me saying that the mime type was not sufficient on it's own anyway. The fact that I could make it fail without the dataurisrc makes me confident he's correct, but I'm fairly certainly that you would want to avoid trying to extract a file extension from a data: uri anyway (hence why I think this is actually two bugs). This was reported a long time ago in Launchpad for Ubuntu but I see no progress and no actual upstream report which is pretty weird (why did no one report this upstream yet? That said, I did find a potential duplicate... from 2006, but Tim says it's fixed ;) bug #153004 this fix may have been lost over the years I guess) Anyway, Launchpad bug: https://bugs.launchpad.net/ubuntu/+source/gstreamer1.0/+bug/1204672
Created attachment 275947 [details] The base64 data (just in case the paste into the bug doesn't work too well)
Created attachment 275948 [details] The one-frame mp3 for convenience
Oh, just as a small reference point, a manual pipeline which uses the dataurisrc ! mpeg2dec ! autoaudiosrc also works fine too.
> Oh, just as a small reference point, a manual pipeline which uses the > dataurisrc ! mpeg2dec ! autoaudiosrc also works fine too. That's a bit surprising, seeing that mpeg2dec is a video decoder.. (and I guess you mean autoaudiosink)
(In reply to comment #4) > > Oh, just as a small reference point, a manual pipeline which uses the > > dataurisrc ! mpeg2dec ! autoaudiosrc also works fine too. > > That's a bit surprising, seeing that mpeg2dec is a video decoder.. :p Well, it seems to work! Using "mad" also works fine (I forget the names of the other mp3 decoders!) > (and I guess you mean autoaudiosink) Oops, yeah, fingers faster than brain!
And for more reference points, it seems that playing a slightly longer dataurisrc works fine. gst-launch-1.0 playbin uri="data:audio/mpeg;base64,SUQzAwAAAAABBFRJVDIAAAAZAAAAU2lsZW50IE1QMyAxMHRoLW9mLWEtc2VjVFBFMQAAAA8AAAB3d3cueGFtdWVsLmNvbUNPTU0AAAArAAAAWFhYAEZyb20gaHR0cDovL3d3dy54YW11ZWwuY29tL2JsYW5rLW1wM3MvVENPTgAAAAkAAABTeW50aHBvcP/6kMBfqwAAAAABpBgAAAAAADSDgAAATEFNRTMuOTNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy45M1VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/6ksDmn8UDwAABpAAAAAAAADSAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMuOTNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/+pLA+t7/g8AAAaQAAAAAAAA0gAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUxBTUUzLjkzVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//qSwPre/4PAAAGkAAAAAAAANIAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy45M1VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/6ksD63v+DwAABpAAAAAAAADSAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVTEFNRTMuOTNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVX/+pLA+t7/g8AAAaQAAAAAAAA0gAAAAFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" Setting pipeline to PAUSED ... Pipeline is PREROLLING ... Pipeline is PREROLLED ... Setting pipeline to PLAYING ... New clock: GstPulseSinkClock Got EOS from element "playbin0". Execution ended after 0:00:00.158479363 Setting pipeline to PAUSED ... Setting pipeline to READY ... Setting pipeline to NULL ... Freeing pipeline ... This is the smallest file on http://www.xamuel.com/blank-mp3s/ I'll cook up a test hack in dataurisrc that will replace the test data with this data to see if it fools Google Music into working (because I can do that without needing to understand GST!), but this will obviously be a horrible hack!
Nuvola Player developer here :-) The original Launchpad bug report was for GST 1.0.x. I didn't bother to report it upstream, because the issue was not reproducible with GST 1.1.x, thus problem solved. I could create a bug report to ask GST developers to backport the fix to Gst 1.0.x, but I doubt anybody would update the GST 1.0.x Ubuntu package to make Nuvola Player users happy, so I usually give up such efforts. I don't think the GST 1.2.x bug is same as the GST 1.0.x bug: the both bugs cause GST not to be able to play datauri streams, but there is one significant difference: GST 1.0.x gst-launch-1.0 test command hangs and must be interrupted by Ctrl+C, GST 1.2.4 doesn't hang, just fails.
Created attachment 276143 [details] [review] Hack to make the test case pass via gst-launch. Hi Jiří and thanks for your response! I have to admit I didn't notice the difference between the bug initially reported under gst 1.0 and this one in gst 1.2! Thanks for clarifying that there was a window of success in 1.1! :) I added a hideous hack to gst to make it play the test data fine, and gst-launch will now play it fine, but sadly using it in a real example (i.e. for Google Music via nuvola) it seems to trigger more code paths in GST that cause it not to be detected as working. I think one of the code paths is returning the duration of the track (I'm only guessing, but perhaps the Google Music side double checks that the HTML5 media support returns the proper track duration?). Anyway, attached is my (horrible, horrible) hack to make it play the test case! Please don't judge me Tim (I've already pre-marked it as rejected!!) :p
Created attachment 276157 [details] [review] typefind: Deal with single-frame MP3s better For tiny files It makes sense to be a little less demanding about the minimum number of valid headers we need to successfully determine the presence of MP3 data. For a single frame, we still report a fairly low probability (60% for exactly 1 frame), so if some other typefinder detects another type more reliably, we don't lose anything. (this doesn't quite fix the bug - there seems to be some issue getting mad to decode this frame, but that should be unrelated)
Comment on attachment 276157 [details] [review] typefind: Deal with single-frame MP3s better 60% is not a low probability in the grand scheme of things. I'm not in favour of this patch, I think it compromises robustness in the general case for an exotic cornercase. We used to have a fallback in the mp3 typefinder that gave a low probability for everything that started with the frame marker, but removed that (for good reasons imho, but then I would say that, wouldn't I). I don't mind adding back a special case fallback, but it needs to take into account the size of the media as well then.
(In reply to comment #10) > (From update of attachment 276157 [details] [review]) > 60% is not a low probability in the grand scheme of things. I'm not in favour > of this patch, I think it compromises robustness in the general case for an > exotic cornercase. We'll only end up using GST_MP3_TYPEFIND_MIN_HEADERS if we read less than GST_MP3_TYPEFIND_TRY_HEADERS, and even then, there's a penalty for skipped bytes. That said, we could increase the penalty for finding _any_ bad data, if we find less than the 5 headers we are currently looking for (like halve the probability if skipped > 0). Do you think that would allow us to continue being robust enough for the general case?
Looks like libmad doesn't support decoding single frame MP3s. Works with avdec_mp3, though. Don't really see a way around this other than possibly fixing mad's mad_header_decode() itself.
Parenthetically, I seem to remember having to twiddle probabilities around because the typefinder would confuse MP3 and other things. This part was pretty fiddly IIRC. You may want to look for closed bugs matching "typefinding mp3" in the comments and check the files there still typefind correctly with any patch.
I removed that in commit ef5c6d351f04ff5d711912971d77c4be75963800. If you want to add it back, only with the condition that the file/data size matches one or two frames exactly. But what's the point anyway if our default decoder doesn't decoder it anyway?
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/gstreamer/gstreamer/issues/56.