[Flac-dev] libFLAC header checking
Josh Coalson
xflac at yahoo.com
Tue Jan 6 11:17:46 PST 2009
--- LRN <lrn1986 at gmail.com> wrote:
> On 06.11.2008 22:16, LRN wrote:
> > In stream_decoder.c function find_metadata_() checks whether a file
> is
> > valid or not. There are 4 cases it recognizes:
> > 1) file begins with 'fLaC'
> > 2) file begins with ID3 (skipped), followed by 'fLaC'
> > 3) file may begin with 11111111 111110?? sync code (or
> 11111111111110,
> > depends on endianess i suppose). That is - a raw file with FLAC
> > frames, without header (right?).
> > 4) file begins with ID3 (again - skipped), followed by the same
> sync
> > code as in case 3
> >
> > find_metadata_() accepts all 4 types of files.
> >
> > I don't know what was the intention behind accepting case 3, but
> case
> > 4 ALSO matches mp3 files - they have ID3 at the beginning and
> > FLAC-like two-byte sync code 11111111 11111011 afterwards. Sequence
> is
> > slightly different, but when it is read as two separate bytes and
> the
> > second byte is SHR'ed twice to form 00111110, it matches.
> > Because of this FLAC decoder initially accepts an mp3 file as a
> valid
> > FLAC file. Of course, once decoding starts, decoder throws an error
>
> > and discards the file (at least i think it does, i never reached
> that
> > far myself).
> > Unfortunately, some applications using libFLAC may assume that lack
> of
> > errors after FLAC__stream_decoder_process_until_end_of_metadata()
> > indicates that header is read and stream information (channel
> number,
> > for example) is available.
> >
> > Would you kindly check the find_metadata_() function to make sure
> it
> > only accepts real FLAC sync codes, not the MP3 ones? Or at least
> > mention in the documentation that FLAC__STREAM_DECODER_READ_FRAME
> > status doesn't means that stream info is available.
> Further information:
>
> FLAC header:
> 11111111 111110AB and so on
>
> A =
> 0 - mandatory
> 1 - reserved
> B =
> 0 - fixed-blocksize
> 1 - variable-blocksize
> CCCC =
> 0000 - reserved
> 0001 - 192 samples
> 0010-0101 - 576 * (2^(n-2)) samples
> 0110 - get 8 bit (blocksize-1) from end of header
> 0111 - get 16 bit (blocksize-1) from end of header
> 1000-1111 - 256 * (2^(n-8)) samples
>
> MP3:
> 11111111 111BBCCD and so on
>
> BB =
> 00 - MPEG 2.5
> 01 - reserved
> 10 - MPEG 2
> 11 - MPEG 1
> CC =
> 00 - reserved
> 01 - layer 3
> 10 - layer 2
> 11 - layer 1
> D =
> 0 - with CRC
> 1 - without CRC
>
> The best way to distinguish FLAC header from MP3 header is to look at
>
> "0A" (FLAC) or "CC" (MP3) bit pair.
> In FLAC it must be 00 (first 0 is from magic number second 0 is from
> reserved bit that should always be 0)
> In MP3 it must not be 00 (00 is reserved).
>
> Suggested code change is
> from:
> else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for the last 6
>
> sync bits */
> decoder->private_->header_warmup[1] = (FLAC__byte)x;
> decoder->protected_->state =
> FLAC__STREAM_DECODER_READ_FRAME;
> return true;
> }
> to
> else if(x >> 1 == 0x7c) { /* MAGIC NUMBER for the last 6
>
> sync bits and reserved 7th bit*/
> decoder->private_->header_warmup[1] = (FLAC__byte)x;
> decoder->protected_->state =
> FLAC__STREAM_DECODER_READ_FRAME;
> return true;
> }
I like this. it's kind of a lucky coincidence that the CC bit
patterns are exclusive between the 2 formats. I'll make the fix
and also add a note about the reserved bit to the format docs.
More information about the Flac-dev
mailing list