fix some bugs with seeking; the libogg ogg_stream_pagein() bug with large packets...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 21 Sep 2004 05:40:23 +0000 (05:40 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 21 Sep 2004 05:40:23 +0000 (05:40 +0000)
src/libOggFLAC/seekable_stream_decoder.c

index a6973e0..7bb2111 100644 (file)
@@ -380,7 +380,7 @@ OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLA
        FLAC__ASSERT(0 != decoder->protected_);
        if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
                return false;
-       OggFLAC__ogg_decoder_aspect_set_serial_number(&decoder->protected_->ogg_decoder_aspect, value);
+       OggFLAC__stream_decoder_set_serial_number(decoder->private_->stream_decoder, value);
        return true;
 }
 
@@ -836,13 +836,16 @@ FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLA
 {
        FLAC__uint64 left_pos = 0, right_pos = stream_length;
        FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
+       FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
+       FLAC__uint64 pos; /* only initialized to avoid compiler warning */
+       FLAC__bool did_a_seek;
        unsigned iteration = 0;
 
        /* In the first iterations, we will calculate the target byte position 
         * by the distance from the target sample to left_sample and
         * right_sample.  After that, we will switch to binary search.
         */
-       static const unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
+       unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
 
        /* We will switch to a linear search once our current sample is less
         * that this number of samples ahead of the target sample
@@ -854,11 +857,43 @@ FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLA
         */
        if(right_sample == 0) {
                right_sample = (FLAC__uint64)(-1);
-               iteration = BINARY_SEARCH_AFTER_ITERATION;
+               BINARY_SEARCH_AFTER_ITERATION = 0;
        }
 
        decoder->private_->target_sample = target_sample;
        for( ; ; iteration++) {
+               if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
+                       if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
+                               /* sanity check to avoid infinite loop */
+                               if (left_pos == right_pos) {
+                                       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
+                                       return false;
+                               }
+                               pos = (right_pos + left_pos) / 2;
+                       }
+                       else {
+#if defined _MSC_VER || defined __MINGW32__
+                               /* with MSVC you have to spoon feed it the casting */
+                               pos = (FLAC__uint64)((double)(FLAC__int64)(target_sample - left_sample) / (double)(FLAC__int64)(right_sample - left_sample) * (double)(FLAC__int64)(right_pos - left_pos));
+#else
+                               pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_sample - left_sample) * (double)(right_pos - left_pos));
+#endif
+                       }
+
+                       /* physical seek */
+                       if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
+                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
+                               return false;
+                       }
+                       if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
+                               decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
+                               return false;
+                       }
+                       did_a_seek = true;
+               }
+               else
+                       did_a_seek = false;
+
                if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
                        decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
                        return false;
@@ -868,22 +903,10 @@ FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLA
                        break;
                }
                else {
-                       const FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
+                       this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
                        FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
 
-                       if (this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
-                               FLAC__uint64 pos;
-
-                               if (iteration >= BINARY_SEARCH_AFTER_ITERATION)
-                                       pos = (right_pos + left_pos) / 2;
-                               else
-#if defined _MSC_VER || defined __MINGW32__
-                                       /* with VC++ you have to spoon feed it the casting */
-                                       pos = (FLAC__uint64)((double)(FLAC__int64)(target_sample - left_sample) / (double)(FLAC__int64)(right_pos - left_pos));
-#else
-                                       pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_pos - left_pos));
-#endif
-
+                       if (did_a_seek) {
                                if (this_frame_sample <= target_sample) {
                                        /* The 'equal' case should not happen, since
                                         * OggFLAC__stream_decoder_process_single()
@@ -900,16 +923,6 @@ FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLA
                                        right_sample = this_frame_sample;
                                        right_pos = pos;
                                }
-
-                               /* physical seek */
-                               if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
-                                       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                                       return false;
-                               }
-                               if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
-                                       decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
-                                       return false;
-                               }
                        }
                }
        }