1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2 * Copyright (C) 2002,2003,2004 Josh Coalson
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <stdlib.h> /* for calloc() */
34 #include <string.h> /* for memcpy()/memcmp() */
35 #include "FLAC/assert.h"
36 #include "protected/seekable_stream_decoder.h"
37 #include "protected/stream_decoder.h"
38 #include "../libFLAC/include/private/float.h" /* @@@ ugly hack, but how else to do? we need to reuse the float formats but don't want to expose it */
39 #include "../libFLAC/include/private/md5.h" /* @@@ ugly hack, but how else to do? we need to reuse the md5 code but don't want to expose it */
41 /***********************************************************************
43 * Private class method prototypes
45 ***********************************************************************/
47 static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder);
48 static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
49 static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
50 static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
51 static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
52 static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
54 /***********************************************************************
58 ***********************************************************************/
60 typedef struct OggFLAC__SeekableStreamDecoderPrivate {
61 OggFLAC__SeekableStreamDecoderReadCallback read_callback;
62 OggFLAC__SeekableStreamDecoderSeekCallback seek_callback;
63 OggFLAC__SeekableStreamDecoderTellCallback tell_callback;
64 OggFLAC__SeekableStreamDecoderLengthCallback length_callback;
65 OggFLAC__SeekableStreamDecoderEofCallback eof_callback;
66 OggFLAC__SeekableStreamDecoderWriteCallback write_callback;
67 OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
68 OggFLAC__SeekableStreamDecoderErrorCallback error_callback;
70 OggFLAC__StreamDecoder *stream_decoder;
71 FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */
72 struct FLAC__MD5Context md5context;
73 FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
74 FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
75 /* the rest of these are only used for seeking: */
76 FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
77 const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
78 /* Since we always want to see the STREAMINFO and SEEK_TABLE blocks at this level, we need some extra flags to keep track of whether they should be passed on up through the metadata_callback */
79 FLAC__bool ignore_stream_info_block;
80 FLAC__bool ignore_seek_table_block;
81 FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
82 FLAC__uint64 target_sample;
83 FLAC__bool got_a_frame; /* hack needed in seek routine to check when process_single() actually writes a frame */
84 } OggFLAC__SeekableStreamDecoderPrivate;
86 /***********************************************************************
88 * Public static class data
90 ***********************************************************************/
92 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[] = {
93 "OggFLAC__SEEKABLE_STREAM_DECODER_OK",
94 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING",
95 "OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
96 "OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
97 "OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
98 "OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
99 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
100 "OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
101 "OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
102 "OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
105 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[] = {
106 "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
107 "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
110 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[] = {
111 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
112 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
115 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[] = {
116 "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
117 "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
120 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[] = {
121 "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
122 "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
126 /***********************************************************************
128 * Class constructor/destructor
130 ***********************************************************************/
132 OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new()
134 OggFLAC__SeekableStreamDecoder *decoder;
136 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
138 decoder = (OggFLAC__SeekableStreamDecoder*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoder));
143 decoder->protected_ = (OggFLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderProtected));
144 if(decoder->protected_ == 0) {
149 decoder->private_ = (OggFLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderPrivate));
150 if(decoder->private_ == 0) {
151 free(decoder->protected_);
156 decoder->private_->stream_decoder = OggFLAC__stream_decoder_new();
157 if(0 == decoder->private_->stream_decoder) {
158 free(decoder->private_);
159 free(decoder->protected_);
164 set_defaults_(decoder);
166 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
171 OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStreamDecoder *decoder)
173 FLAC__ASSERT(0 != decoder);
174 FLAC__ASSERT(0 != decoder->protected_);
175 FLAC__ASSERT(0 != decoder->private_);
176 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
178 (void)OggFLAC__seekable_stream_decoder_finish(decoder);
180 OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder);
182 free(decoder->private_);
183 free(decoder->protected_);
187 /***********************************************************************
189 * Public class methods
191 ***********************************************************************/
193 OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_init(OggFLAC__SeekableStreamDecoder *decoder)
195 FLAC__ASSERT(0 != decoder);
197 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
198 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
200 if(0 == decoder->private_->read_callback || 0 == decoder->private_->seek_callback || 0 == decoder->private_->tell_callback || 0 == decoder->private_->length_callback || 0 == decoder->private_->eof_callback)
201 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
203 if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
204 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
206 decoder->private_->seek_table = 0;
208 decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
210 /* We initialize the FLAC__MD5Context even though we may never use it. This
211 * is because md5 checking may be turned on to start and then turned off if
212 * a seek occurs. So we always init the context here and finalize it in
213 * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
214 * cleaned up properly.
216 FLAC__MD5Init(&decoder->private_->md5context);
218 OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
219 OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
220 OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
221 OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
222 OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
224 /* We always want to see these blocks. Whether or not we pass them up
225 * through the metadata callback will be determined by flags set in our
226 * implementation of ..._set_metadata_respond/ignore...()
228 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
229 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
231 if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK)
232 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
234 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
237 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder)
239 FLAC__bool md5_failed = false;
241 FLAC__ASSERT(0 != decoder);
242 FLAC__ASSERT(0 != decoder->private_);
243 FLAC__ASSERT(0 != decoder->protected_);
245 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
248 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
250 /* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we
251 * always call FLAC__MD5Final()
253 FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
255 OggFLAC__stream_decoder_finish(decoder->private_->stream_decoder);
257 if(decoder->private_->do_md5_checking) {
258 if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
262 set_defaults_(decoder);
264 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
269 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
271 FLAC__ASSERT(0 != decoder);
272 FLAC__ASSERT(0 != decoder->protected_);
273 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
275 decoder->protected_->md5_checking = value;
279 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value)
281 FLAC__ASSERT(0 != decoder);
282 FLAC__ASSERT(0 != decoder->private_);
283 FLAC__ASSERT(0 != decoder->protected_);
284 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
286 decoder->private_->read_callback = value;
290 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_seek_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderSeekCallback value)
292 FLAC__ASSERT(0 != decoder);
293 FLAC__ASSERT(0 != decoder->private_);
294 FLAC__ASSERT(0 != decoder->protected_);
295 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
297 decoder->private_->seek_callback = value;
301 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_tell_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderTellCallback value)
303 FLAC__ASSERT(0 != decoder);
304 FLAC__ASSERT(0 != decoder->private_);
305 FLAC__ASSERT(0 != decoder->protected_);
306 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
308 decoder->private_->tell_callback = value;
312 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_length_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderLengthCallback value)
314 FLAC__ASSERT(0 != decoder);
315 FLAC__ASSERT(0 != decoder->private_);
316 FLAC__ASSERT(0 != decoder->protected_);
317 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
319 decoder->private_->length_callback = value;
323 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_eof_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderEofCallback value)
325 FLAC__ASSERT(0 != decoder);
326 FLAC__ASSERT(0 != decoder->private_);
327 FLAC__ASSERT(0 != decoder->protected_);
328 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
330 decoder->private_->eof_callback = value;
334 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_write_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderWriteCallback value)
336 FLAC__ASSERT(0 != decoder);
337 FLAC__ASSERT(0 != decoder->private_);
338 FLAC__ASSERT(0 != decoder->protected_);
339 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
341 decoder->private_->write_callback = value;
345 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderMetadataCallback value)
347 FLAC__ASSERT(0 != decoder);
348 FLAC__ASSERT(0 != decoder->private_);
349 FLAC__ASSERT(0 != decoder->protected_);
350 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
352 decoder->private_->metadata_callback = value;
356 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_error_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderErrorCallback value)
358 FLAC__ASSERT(0 != decoder);
359 FLAC__ASSERT(0 != decoder->private_);
360 FLAC__ASSERT(0 != decoder->protected_);
361 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
363 decoder->private_->error_callback = value;
367 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_client_data(OggFLAC__SeekableStreamDecoder *decoder, void *value)
369 FLAC__ASSERT(0 != decoder);
370 FLAC__ASSERT(0 != decoder->private_);
371 FLAC__ASSERT(0 != decoder->protected_);
372 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
374 decoder->private_->client_data = value;
378 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLAC__SeekableStreamDecoder *decoder, long value)
380 FLAC__ASSERT(0 != decoder);
381 FLAC__ASSERT(0 != decoder->private_);
382 FLAC__ASSERT(0 != decoder->protected_);
383 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
385 OggFLAC__stream_decoder_set_serial_number(decoder->private_->stream_decoder, value);
389 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
391 FLAC__ASSERT(0 != decoder);
392 FLAC__ASSERT(0 != decoder->private_);
393 FLAC__ASSERT(0 != decoder->protected_);
394 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
395 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
397 if(type == FLAC__METADATA_TYPE_STREAMINFO)
398 decoder->private_->ignore_stream_info_block = false;
399 else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
400 decoder->private_->ignore_seek_table_block = false;
401 return OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
404 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
406 FLAC__ASSERT(0 != decoder);
407 FLAC__ASSERT(0 != decoder->private_);
408 FLAC__ASSERT(0 != decoder->protected_);
409 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
410 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
412 return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
415 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder)
417 FLAC__ASSERT(0 != decoder);
418 FLAC__ASSERT(0 != decoder->private_);
419 FLAC__ASSERT(0 != decoder->protected_);
420 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
421 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
423 decoder->private_->ignore_stream_info_block = false;
424 decoder->private_->ignore_seek_table_block = false;
425 return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
428 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
430 FLAC__ASSERT(0 != decoder);
431 FLAC__ASSERT(0 != decoder->private_);
432 FLAC__ASSERT(0 != decoder->protected_);
433 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
434 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
436 if(type == FLAC__METADATA_TYPE_STREAMINFO) {
437 decoder->private_->ignore_stream_info_block = true;
440 else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
441 decoder->private_->ignore_seek_table_block = true;
445 return OggFLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type);
448 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
450 FLAC__ASSERT(0 != decoder);
451 FLAC__ASSERT(0 != decoder->private_);
452 FLAC__ASSERT(0 != decoder->protected_);
453 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
454 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
456 return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id);
459 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder)
461 FLAC__ASSERT(0 != decoder);
462 FLAC__ASSERT(0 != decoder->private_);
463 FLAC__ASSERT(0 != decoder->protected_);
464 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
465 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
467 decoder->private_->ignore_stream_info_block = true;
468 decoder->private_->ignore_seek_table_block = true;
470 OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) &&
471 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) &&
472 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
475 OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder)
477 FLAC__ASSERT(0 != decoder);
478 FLAC__ASSERT(0 != decoder->protected_);
479 return decoder->protected_->state;
482 OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
484 FLAC__ASSERT(0 != decoder);
485 FLAC__ASSERT(0 != decoder->private_);
486 return OggFLAC__stream_decoder_get_state(decoder->private_->stream_decoder);
489 OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
491 FLAC__ASSERT(0 != decoder);
492 FLAC__ASSERT(0 != decoder->private_);
493 return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->stream_decoder);
496 OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder)
498 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR)
499 return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state];
501 return OggFLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder);
504 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder)
506 FLAC__ASSERT(0 != decoder);
507 FLAC__ASSERT(0 != decoder->protected_);
508 return decoder->protected_->md5_checking;
511 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder)
513 FLAC__ASSERT(0 != decoder);
514 FLAC__ASSERT(0 != decoder->private_);
515 return OggFLAC__stream_decoder_get_channels(decoder->private_->stream_decoder);
518 OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder)
520 FLAC__ASSERT(0 != decoder);
521 FLAC__ASSERT(0 != decoder->private_);
522 return OggFLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder);
525 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder)
527 FLAC__ASSERT(0 != decoder);
528 FLAC__ASSERT(0 != decoder->private_);
529 return OggFLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder);
532 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder)
534 FLAC__ASSERT(0 != decoder);
535 FLAC__ASSERT(0 != decoder->private_);
536 return OggFLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder);
539 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder)
541 FLAC__ASSERT(0 != decoder);
542 FLAC__ASSERT(0 != decoder->private_);
543 return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder);
546 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder)
548 FLAC__ASSERT(0 != decoder);
549 FLAC__ASSERT(0 != decoder->private_);
550 FLAC__ASSERT(0 != decoder->protected_);
552 decoder->private_->do_md5_checking = false;
554 if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
555 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
559 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
564 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableStreamDecoder *decoder)
566 FLAC__ASSERT(0 != decoder);
567 FLAC__ASSERT(0 != decoder->private_);
568 FLAC__ASSERT(0 != decoder->protected_);
570 if(!OggFLAC__seekable_stream_decoder_flush(decoder)) {
571 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
575 if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
576 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
580 decoder->private_->seek_table = 0;
582 decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
584 /* We initialize the FLAC__MD5Context even though we may never use it. This
585 * is because md5 checking may be turned on to start and then turned off if
586 * a seek occurs. So we always init the context here and finalize it in
587 * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
588 * cleaned up properly.
590 FLAC__MD5Init(&decoder->private_->md5context);
592 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
597 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__SeekableStreamDecoder *decoder)
600 FLAC__ASSERT(0 != decoder);
602 if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
603 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
605 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
608 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
610 ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder);
612 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
617 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(OggFLAC__SeekableStreamDecoder *decoder)
620 FLAC__ASSERT(0 != decoder);
622 if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
623 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
625 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
628 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
630 ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder);
632 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
637 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_stream(OggFLAC__SeekableStreamDecoder *decoder)
640 FLAC__ASSERT(0 != decoder);
642 if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
643 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
645 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
648 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
650 ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder);
652 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
657 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
661 FLAC__ASSERT(0 != decoder);
662 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);
664 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING;
666 /* turn off md5 checking if a seek is attempted */
667 decoder->private_->do_md5_checking = false;
669 if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
670 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
673 /* get the file length */
674 if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {
675 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
679 if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
680 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
683 if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {
684 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
687 if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) {
688 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
692 return seek_to_absolute_sample_(decoder, length, sample);
695 /***********************************************************************
697 * Private class methods
699 ***********************************************************************/
701 void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder)
703 decoder->private_->read_callback = 0;
704 decoder->private_->seek_callback = 0;
705 decoder->private_->tell_callback = 0;
706 decoder->private_->length_callback = 0;
707 decoder->private_->eof_callback = 0;
708 decoder->private_->write_callback = 0;
709 decoder->private_->metadata_callback = 0;
710 decoder->private_->error_callback = 0;
711 decoder->private_->client_data = 0;
712 /* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
713 decoder->private_->ignore_stream_info_block = false;
714 decoder->private_->ignore_seek_table_block = true;
716 decoder->protected_->md5_checking = false;
719 FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
721 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
723 if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
725 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
727 else if(*bytes > 0) {
728 if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) {
729 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
730 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
733 if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
734 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
737 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
740 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
744 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
747 FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
749 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
752 if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
753 FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
754 FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
755 FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
757 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
759 seekable_stream_decoder->private_->got_a_frame = true;
760 seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
761 if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
762 unsigned delta = (unsigned)(target_sample - this_frame_sample);
763 /* kick out of seek mode */
764 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
765 /* shift out the samples before target_sample */
768 const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
769 for(channel = 0; channel < frame->header.channels; channel++)
770 newbuffer[channel] = buffer[channel] + delta;
771 seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
772 seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
773 /* write the relevant samples */
774 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
777 /* write the relevant samples */
778 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
782 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
786 if(seekable_stream_decoder->private_->do_md5_checking) {
787 if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
788 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
790 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
794 void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
796 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
799 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
800 seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
801 /* save the MD5 signature for comparison later */
802 memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
803 if(0 == memcmp(seekable_stream_decoder->private_->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
804 seekable_stream_decoder->private_->do_md5_checking = false;
806 else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
807 seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
810 if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
811 FLAC__bool ignore_block = false;
812 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
814 else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
817 seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
821 void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
823 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
826 if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
827 seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
830 FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
832 FLAC__uint64 left_pos = 0, right_pos = stream_length;
833 FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
834 FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
835 FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
836 FLAC__bool did_a_seek;
837 unsigned iteration = 0;
839 /* In the first iterations, we will calculate the target byte position
840 * by the distance from the target sample to left_sample and
841 * right_sample (let's call it "proportional search"). After that, we
842 * will switch to binary search.
844 unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
846 /* We will switch to a linear search once our current sample is less
847 * that this number of samples ahead of the target sample
849 static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
851 /* If the total number of samples is unknown, use a large value and
852 * increase 'iteration' to force binary search immediately.
854 if(right_sample == 0) {
855 right_sample = (FLAC__uint64)(-1);
856 BINARY_SEARCH_AFTER_ITERATION = 0;
859 decoder->private_->target_sample = target_sample;
860 for( ; ; iteration++) {
861 if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
862 if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
863 pos = (right_pos + left_pos) / 2;
866 #ifndef FLAC__INTEGER_ONLY_LIBRARY
867 #if defined _MSC_VER || defined __MINGW32__
868 /* with MSVC you have to spoon feed it the casting */
869 pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos));
871 pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
874 /* a little less accurate: */
875 if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
876 pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
877 else /* @@@ WATCHOUT, ~2TB limit */
878 pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
880 /* @@@ TODO: might want to limit pos to some distance
881 * before EOF, to make sure we land before the last frame,
882 * thereby getting a this_fram_sample and so having a better
883 * estimate. this would also mostly (or totally if we could
884 * be sure to land before the last frame) avoid the
885 * end-of-stream case we have to check later.
890 if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
891 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
894 if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
895 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
903 decoder->private_->got_a_frame = false;
904 if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
905 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
908 if(!decoder->private_->got_a_frame) {
910 /* this can happen if we seek to a point after the last frame; we drop
911 * to binary search right away in this case to avoid any wasted
912 * iterations of proportional search.
915 BINARY_SEARCH_AFTER_ITERATION = 0;
918 /* this can probably only happen if total_samples is unknown and the
919 * target_sample is past the end of the stream
921 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
925 /* our write callback will change the state when it gets to the target frame */
927 decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING &&
928 decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
933 this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
934 FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
937 if (this_frame_sample <= target_sample) {
938 /* The 'equal' case should not happen, since
939 * OggFLAC__stream_decoder_process_single()
940 * should recognize that it has hit the
941 * target sample and we would exit through
944 FLAC__ASSERT(this_frame_sample != target_sample);
946 left_sample = this_frame_sample;
947 /* sanity check to avoid infinite loop */
948 if (left_pos == pos) {
949 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
954 else if(this_frame_sample > target_sample) {
955 right_sample = this_frame_sample;
956 /* sanity check to avoid infinite loop */
957 if (right_pos == pos) {
958 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;