fix seeking bug where I/O seek to "unparseable" frame header caused a seek error...
authorJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 23 Mar 2004 04:27:47 +0000 (04:27 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Tue, 23 Mar 2004 04:27:47 +0000 (04:27 +0000)
src/libFLAC/seekable_stream_decoder.c

index 92eef70..94b6f58 100644 (file)
@@ -970,9 +970,32 @@ FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__
                                return false;
                        }
                }
-               if(!FLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
-                       decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
-                       return false;
+               /* Now we need to get a frame.  It is possible for our seek
+                * to land in the middle of audio data that looks exactly like
+                * a frame header from a future version of an encoder.  When
+                * that happens, FLAC__stream_decoder_process_single() will
+                * return false and the state will be
+                * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM.  But there is a
+                * remote possibility that it is properly synced at such a
+                * "future-codec frame", so to make sure, we wait to see
+                * several "unparseable" errors in a row before bailing out.
+                */
+               {
+                       unsigned unparseable_count;
+                       FLAC__bool got_a_frame = false;
+                       for (unparseable_count = 0; !got_a_frame && unparseable_count < 10; unparseable_count++) {
+                               if(FLAC__stream_decoder_process_single(decoder->private_->stream_decoder))
+                                       got_a_frame = true;
+                               else if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_UNPARSEABLE_STREAM)
+                                       /* try again.  we don't want to flush the decoder since that clears the bitbuffer */
+                                       decoder->private_->stream_decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC;
+                               else /* it's a real error */
+                                       break;
+                       }
+                       if (!got_a_frame) {
+                               decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
+                               return false;
+                       }
                }
                /* our write callback will change the state when it gets to the target frame */
                if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING) {