again fix logic around deciphering frame/sample number from frame header
authorJosh Coalson <jcoalson@users.sourceforce.net>
Mon, 24 Jan 2005 00:20:49 +0000 (00:20 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Mon, 24 Jan 2005 00:20:49 +0000 (00:20 +0000)
src/libFLAC/stream_decoder.c

index 5995afe..ce571db 100644 (file)
@@ -121,6 +121,7 @@ typedef struct FLAC__StreamDecoderPrivate {
        FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents[FLAC__MAX_CHANNELS];
        unsigned output_capacity, output_channels;
        FLAC__uint32 last_frame_number;
+       FLAC__uint32 last_block_size;
        FLAC__uint64 samples_decoded;
        FLAC__bool has_stream_info, has_seek_table;
        FLAC__StreamMetadata stream_info;
@@ -284,6 +285,7 @@ FLAC_API FLAC__StreamDecoderState FLAC__stream_decoder_init(FLAC__StreamDecoder
                return decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
 
        decoder->private_->last_frame_number = 0;
+       decoder->private_->last_block_size = 0;
        decoder->private_->samples_decoded = 0;
        decoder->private_->has_stream_info = false;
        decoder->private_->cached = false;
@@ -590,6 +592,8 @@ FLAC_API FLAC__bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder)
                decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR;
                return false;
        }
+       decoder->private_->last_frame_number = 0;
+       decoder->private_->last_block_size = 0;
        decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
 
        return true;
@@ -1702,18 +1706,34 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
                return true;
        }
 
-       if(blocksize_hint && is_known_variable_blocksize_stream) {
-               if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len))
-                       return false; /* the read_callback_ sets the state for us */
-               if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */
-                       decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
-                       decoder->private_->cached = true;
-                       decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
-                       decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
-                       return true;
+       /*
+        * Now we get to the regrettable consequences of not knowing for sure
+        * whether we got a frame number or a sample number.  There are no
+        * encoders that do variable-blocksize encoding so unless we know from
+        * the STREAMINFO that it is variable-blocksize we will assume it is
+        * fixed-blocksize.  The trouble comes when we have no STREAMINFO; again
+        * we will guess that is fixed-blocksize.  Where this can go wrong: 1) a
+        * variable-blocksize stream with no STREAMINFO; 2) a fixed-blocksize
+        * stream that was edited such that one or more frames before or
+        * including this one do not have the same number of samples as the
+        * STREAMINFO's min and max blocksize.
+        */
+       if(is_known_variable_blocksize_stream) {
+               if(blocksize_hint) {
+                       if(!FLAC__bitbuffer_read_utf8_uint64(decoder->private_->input, &xx, read_callback_, decoder, raw_header, &raw_header_len))
+                               return false; /* the read_callback_ sets the state for us */
+                       if(xx == FLAC__U64L(0xffffffffffffffff)) { /* i.e. non-UTF8 code... */
+                               decoder->private_->lookahead = raw_header[raw_header_len-1]; /* back up as much as we can */
+                               decoder->private_->cached = true;
+                               decoder->private_->error_callback(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER, decoder->private_->client_data);
+                               decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
+                               return true;
+                       }
+                       decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER;
+                       decoder->private_->frame.header.number.sample_number = xx;
                }
-               decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER;
-               decoder->private_->frame.header.number.sample_number = xx;
+               else
+                       is_unparseable = true;
        }
        else {
                if(!FLAC__bitbuffer_read_utf8_uint32(decoder->private_->input, &x, read_callback_, decoder, raw_header, &raw_header_len))
@@ -1727,14 +1747,21 @@ FLAC__bool read_frame_header_(FLAC__StreamDecoder *decoder)
                }
                decoder->private_->last_frame_number = x;
                decoder->private_->frame.header.number_type = FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER;
-               if(blocksize_hint) {
-                       if(decoder->private_->has_stream_info)
-                               decoder->private_->frame.header.number.sample_number = (FLAC__int64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__int64)x;
+               if(decoder->private_->has_stream_info) {
+                       FLAC__ASSERT(decoder->private_->stream_info.data.stream_info.min_blocksize == decoder->private_->stream_info.data.stream_info.max_blocksize);
+                       decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->stream_info.data.stream_info.min_blocksize * (FLAC__uint64)x;
+                       decoder->private_->last_block_size = (FLAC__uint64)decoder->private_->frame.header.blocksize;
+               }
+               else if(blocksize_hint) {
+                       if(decoder->private_->last_block_size)
+                               decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->last_block_size * (FLAC__uint64)x;
                        else
                                is_unparseable = true;
                }
-               else    
-                       decoder->private_->frame.header.number.sample_number = (FLAC__int64)decoder->private_->frame.header.blocksize * (FLAC__int64)x;
+               else {
+                       decoder->private_->frame.header.number.sample_number = (FLAC__uint64)decoder->private_->frame.header.blocksize * (FLAC__uint64)x;
+                       decoder->private_->last_block_size = (FLAC__uint64)decoder->private_->frame.header.blocksize;
+               }
        }
 
        if(blocksize_hint) {