Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demuxer expects whole file to be available when probing #12

Closed
Pheo-Player opened this issue Sep 30, 2014 · 2 comments
Closed

Demuxer expects whole file to be available when probing #12

Pheo-Player opened this issue Sep 30, 2014 · 2 comments

Comments

@Pheo-Player
Copy link

See fabslab/aurora-websocket#1

I investigated and found the UnderflowError's cause to be in MP3Demuxer.probe (l. 138), where the stream tries to advance and can't due to the data not having been streamed yet.

FLAC.js meanwhile works, because all its probe function does is peek a string at the beginning of the file. So I googled around for a bit checking if I can find similar logic for MP3s, and found this answer:
http://stackoverflow.com/a/7302482/3090225
and replaced the probe function with the following code:

const sigID3 = 0x494433;
const sigNoID3 = 0xfffb;
this.probe = function(stream) {
    var off = stream.offset; // Not entirely sure if this needs to be here, but it already was

    return stream.peekUInt16(off) == sigNoID3 ||
        stream.peekUInt24(off) == sigID3;
};

which got my MP3 file to play, even though I have 9 errors being thrown now:

screen shot 2014-09-30 at 09 06 56

But the file still played from start to end without further errors or audible glitches.

@devongovett
Copy link
Member

The test above won't work reliably since ID3 data can be used in other file formats, and even if it wasn't there, MP3s can have all sorts of padding and whatnot at the beginning of the file and we're supposed to still work fine. Most other audio formats we deal with have a container format (e.g. MP4 for AAC audio) that has a nice way (usually the first four bytes) to determine what format it is and all kinds of metadata (what ID3 provides, sinktables, etc.).

MP3 is weird because it really has no container format, and it's designed for streaming, so in order to find and decode a frame requires a complex syncing algorithm to skip over the padding and junk that can be there. MP3 was really not a very well designed file format: it's a fine codec, but as a file format, it sucks.

So, to determine if a file is an MP3, we basically need to skip over any ID3 data, find the first frame (which may not be immediately after the ID3 data), decode it, jump to where the next frame is supposed to be and try decoding that. If two frames decode, we can be pretty sure it's an MP3. Unfortunately, that might require a lot of data.

The problem you described here where there are underflows is more of a problem with the way Aurora.js does probing than with mp3.js in particular, mp3 just happens to be the only format that causes the issue so far. We need quite a bit of data, and this can be more than the first chunk Aurora provides us. Probing should really be an asynchronous process, just like everything else in Aurora so that probes like the one in MP3.js can load more data as needed until it has enough to determine if the file is an MP3.

I've opened an issue on Aurora.js for this: audiocogs/aurora.js#97.

@Pheo-Player
Copy link
Author

I feared as much. The example was not meant to be anything but a test what happens if probe succeeds for an example MP3 :)

That makes a lot of sense, MP3 + all the ID3 versions have been hurting my brain and heart for some time as well. There's not even a lot of good information around that gives 100% reliable results. We can close this here then and continue over in aurora.js...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants