about summary refs log tree commit
path: root/src/libFLAC/stream_decoder.c
diff options
context:
space:
mode:
authorjcoalson <jcoalson>2005-01-24 00:20:49 +0000
committerjcoalson <jcoalson>2005-01-24 00:20:49 +0000
commitb7016f20c88d3463299b812d8f69d46e98ba7494 (patch)
treed7e987f46e2af9a57b06e020ba34f9e8b8af19f5 /src/libFLAC/stream_decoder.c
parent233f5a34615526231e781eeb74236fc0538aaf20 (diff)
downloadflac-arm-1.1.3-b7016f20c88d3463299b812d8f69d46e98ba7494.tar.gz
again fix logic around deciphering frame/sample number from frame header
Diffstat (limited to 'src/libFLAC/stream_decoder.c')
-rw-r--r--src/libFLAC/stream_decoder.c59
1 files changed, 43 insertions, 16 deletions
diff --git a/src/libFLAC/stream_decoder.c b/src/libFLAC/stream_decoder.c
index 5995afeb..ce571dba 100644
--- a/src/libFLAC/stream_decoder.c
+++ b/src/libFLAC/stream_decoder.c
@@ -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) {