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/md5.h" /* @@@@@@ ugly hack, but how else to do? we need to reuse the md5 code but don't want to expose it */
40 /***********************************************************************
42 * Private class method prototypes
44 ***********************************************************************/
46 static void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder);
47 static FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
48 static FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
49 static void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
50 static void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
51 static FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample);
53 /***********************************************************************
57 ***********************************************************************/
59 typedef struct OggFLAC__SeekableStreamDecoderPrivate {
60 OggFLAC__SeekableStreamDecoderReadCallback read_callback;
61 OggFLAC__SeekableStreamDecoderSeekCallback seek_callback;
62 OggFLAC__SeekableStreamDecoderTellCallback tell_callback;
63 OggFLAC__SeekableStreamDecoderLengthCallback length_callback;
64 OggFLAC__SeekableStreamDecoderEofCallback eof_callback;
65 OggFLAC__SeekableStreamDecoderWriteCallback write_callback;
66 OggFLAC__SeekableStreamDecoderMetadataCallback metadata_callback;
67 OggFLAC__SeekableStreamDecoderErrorCallback error_callback;
69 OggFLAC__StreamDecoder *stream_decoder;
70 FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */
71 struct FLAC__MD5Context md5context;
72 FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */
73 FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
74 /* the rest of these are only used for seeking: */
75 FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
76 const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */
77 /* 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 */
78 FLAC__bool ignore_stream_info_block;
79 FLAC__bool ignore_seek_table_block;
80 FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
81 FLAC__uint64 target_sample;
82 } OggFLAC__SeekableStreamDecoderPrivate;
84 /***********************************************************************
86 * Public static class data
88 ***********************************************************************/
90 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderStateString[] = {
91 "OggFLAC__SEEKABLE_STREAM_DECODER_OK",
92 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING",
93 "OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM",
94 "OggFLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR",
95 "OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR",
96 "OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR",
97 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR",
98 "OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED",
99 "OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK",
100 "OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED"
103 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderReadStatusString[] = {
104 "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK",
105 "OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR"
108 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderSeekStatusString[] = {
109 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK",
110 "OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR"
113 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderTellStatusString[] = {
114 "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK",
115 "OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR"
118 OggFLAC_API const char * const OggFLAC__SeekableStreamDecoderLengthStatusString[] = {
119 "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK",
120 "OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR"
124 /***********************************************************************
126 * Class constructor/destructor
128 ***********************************************************************/
130 OggFLAC_API OggFLAC__SeekableStreamDecoder *OggFLAC__seekable_stream_decoder_new()
132 OggFLAC__SeekableStreamDecoder *decoder;
134 FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
136 decoder = (OggFLAC__SeekableStreamDecoder*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoder));
141 decoder->protected_ = (OggFLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderProtected));
142 if(decoder->protected_ == 0) {
147 decoder->private_ = (OggFLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamDecoderPrivate));
148 if(decoder->private_ == 0) {
149 free(decoder->protected_);
154 decoder->private_->stream_decoder = OggFLAC__stream_decoder_new();
155 if(0 == decoder->private_->stream_decoder) {
156 free(decoder->private_);
157 free(decoder->protected_);
162 set_defaults_(decoder);
164 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
169 OggFLAC_API void OggFLAC__seekable_stream_decoder_delete(OggFLAC__SeekableStreamDecoder *decoder)
171 FLAC__ASSERT(0 != decoder);
172 FLAC__ASSERT(0 != decoder->protected_);
173 FLAC__ASSERT(0 != decoder->private_);
174 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
176 (void)OggFLAC__seekable_stream_decoder_finish(decoder);
178 OggFLAC__stream_decoder_delete(decoder->private_->stream_decoder);
180 free(decoder->private_);
181 free(decoder->protected_);
185 /***********************************************************************
187 * Public class methods
189 ***********************************************************************/
191 OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_init(OggFLAC__SeekableStreamDecoder *decoder)
193 FLAC__ASSERT(0 != decoder);
195 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
196 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED;
198 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)
199 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
201 if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback)
202 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK;
204 decoder->private_->seek_table = 0;
206 decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
208 /* We initialize the FLAC__MD5Context even though we may never use it. This
209 * is because md5 checking may be turned on to start and then turned off if
210 * a seek occurs. So we always init the context here and finalize it in
211 * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
212 * cleaned up properly.
214 FLAC__MD5Init(&decoder->private_->md5context);
216 OggFLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_);
217 OggFLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_);
218 OggFLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_);
219 OggFLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_);
220 OggFLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder);
222 /* We always want to see these blocks. Whether or not we pass them up
223 * through the metadata callback will be determined by flags set in our
224 * implementation of ..._set_metadata_respond/ignore...()
226 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO);
227 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
229 if(OggFLAC__stream_decoder_init(decoder->private_->stream_decoder) != OggFLAC__STREAM_DECODER_OK)
230 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
232 return decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
235 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_finish(OggFLAC__SeekableStreamDecoder *decoder)
237 FLAC__bool md5_failed = false;
239 FLAC__ASSERT(0 != decoder);
240 FLAC__ASSERT(0 != decoder->private_);
241 FLAC__ASSERT(0 != decoder->protected_);
243 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
246 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
248 /* see the comment in OggFLAC__seekable_stream_decoder_init() as to why we
249 * always call FLAC__MD5Final()
251 FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context);
253 OggFLAC__stream_decoder_finish(decoder->private_->stream_decoder);
255 if(decoder->private_->do_md5_checking) {
256 if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16))
260 set_defaults_(decoder);
262 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED;
267 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_md5_checking(OggFLAC__SeekableStreamDecoder *decoder, FLAC__bool value)
269 FLAC__ASSERT(0 != decoder);
270 FLAC__ASSERT(0 != decoder->protected_);
271 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
273 decoder->protected_->md5_checking = value;
277 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_read_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderReadCallback value)
279 FLAC__ASSERT(0 != decoder);
280 FLAC__ASSERT(0 != decoder->private_);
281 FLAC__ASSERT(0 != decoder->protected_);
282 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
284 decoder->private_->read_callback = value;
288 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_seek_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderSeekCallback value)
290 FLAC__ASSERT(0 != decoder);
291 FLAC__ASSERT(0 != decoder->private_);
292 FLAC__ASSERT(0 != decoder->protected_);
293 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
295 decoder->private_->seek_callback = value;
299 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_tell_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderTellCallback value)
301 FLAC__ASSERT(0 != decoder);
302 FLAC__ASSERT(0 != decoder->private_);
303 FLAC__ASSERT(0 != decoder->protected_);
304 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
306 decoder->private_->tell_callback = value;
310 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_length_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderLengthCallback value)
312 FLAC__ASSERT(0 != decoder);
313 FLAC__ASSERT(0 != decoder->private_);
314 FLAC__ASSERT(0 != decoder->protected_);
315 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
317 decoder->private_->length_callback = value;
321 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_eof_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderEofCallback value)
323 FLAC__ASSERT(0 != decoder);
324 FLAC__ASSERT(0 != decoder->private_);
325 FLAC__ASSERT(0 != decoder->protected_);
326 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
328 decoder->private_->eof_callback = value;
332 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_write_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderWriteCallback value)
334 FLAC__ASSERT(0 != decoder);
335 FLAC__ASSERT(0 != decoder->private_);
336 FLAC__ASSERT(0 != decoder->protected_);
337 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
339 decoder->private_->write_callback = value;
343 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderMetadataCallback value)
345 FLAC__ASSERT(0 != decoder);
346 FLAC__ASSERT(0 != decoder->private_);
347 FLAC__ASSERT(0 != decoder->protected_);
348 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
350 decoder->private_->metadata_callback = value;
354 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_error_callback(OggFLAC__SeekableStreamDecoder *decoder, OggFLAC__SeekableStreamDecoderErrorCallback value)
356 FLAC__ASSERT(0 != decoder);
357 FLAC__ASSERT(0 != decoder->private_);
358 FLAC__ASSERT(0 != decoder->protected_);
359 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
361 decoder->private_->error_callback = value;
365 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_client_data(OggFLAC__SeekableStreamDecoder *decoder, void *value)
367 FLAC__ASSERT(0 != decoder);
368 FLAC__ASSERT(0 != decoder->private_);
369 FLAC__ASSERT(0 != decoder->protected_);
370 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
372 decoder->private_->client_data = value;
376 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_serial_number(OggFLAC__SeekableStreamDecoder *decoder, long value)
378 FLAC__ASSERT(0 != decoder);
379 FLAC__ASSERT(0 != decoder->private_);
380 FLAC__ASSERT(0 != decoder->protected_);
381 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
383 OggFLAC__ogg_decoder_aspect_set_serial_number(&decoder->protected_->ogg_decoder_aspect, value);
387 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
389 FLAC__ASSERT(0 != decoder);
390 FLAC__ASSERT(0 != decoder->private_);
391 FLAC__ASSERT(0 != decoder->protected_);
392 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
393 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
395 if(type == FLAC__METADATA_TYPE_STREAMINFO)
396 decoder->private_->ignore_stream_info_block = false;
397 else if(type == FLAC__METADATA_TYPE_SEEKTABLE)
398 decoder->private_->ignore_seek_table_block = false;
399 return OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type);
402 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
404 FLAC__ASSERT(0 != decoder);
405 FLAC__ASSERT(0 != decoder->private_);
406 FLAC__ASSERT(0 != decoder->protected_);
407 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
408 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
410 return OggFLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id);
413 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_respond_all(OggFLAC__SeekableStreamDecoder *decoder)
415 FLAC__ASSERT(0 != decoder);
416 FLAC__ASSERT(0 != decoder->private_);
417 FLAC__ASSERT(0 != decoder->protected_);
418 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
419 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
421 decoder->private_->ignore_stream_info_block = false;
422 decoder->private_->ignore_seek_table_block = false;
423 return OggFLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder);
426 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore(OggFLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type)
428 FLAC__ASSERT(0 != decoder);
429 FLAC__ASSERT(0 != decoder->private_);
430 FLAC__ASSERT(0 != decoder->protected_);
431 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
432 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
434 if(type == FLAC__METADATA_TYPE_STREAMINFO) {
435 decoder->private_->ignore_stream_info_block = true;
438 else if(type == FLAC__METADATA_TYPE_SEEKTABLE) {
439 decoder->private_->ignore_seek_table_block = true;
443 return OggFLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type);
446 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_application(OggFLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4])
448 FLAC__ASSERT(0 != decoder);
449 FLAC__ASSERT(0 != decoder->private_);
450 FLAC__ASSERT(0 != decoder->protected_);
451 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
452 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
454 return OggFLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id);
457 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_set_metadata_ignore_all(OggFLAC__SeekableStreamDecoder *decoder)
459 FLAC__ASSERT(0 != decoder);
460 FLAC__ASSERT(0 != decoder->private_);
461 FLAC__ASSERT(0 != decoder->protected_);
462 FLAC__ASSERT(0 != decoder->private_->stream_decoder);
463 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED)
465 decoder->private_->ignore_stream_info_block = true;
466 decoder->private_->ignore_seek_table_block = true;
468 OggFLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) &&
469 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) &&
470 OggFLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE);
473 OggFLAC_API OggFLAC__SeekableStreamDecoderState OggFLAC__seekable_stream_decoder_get_state(const OggFLAC__SeekableStreamDecoder *decoder)
475 FLAC__ASSERT(0 != decoder);
476 FLAC__ASSERT(0 != decoder->protected_);
477 return decoder->protected_->state;
480 OggFLAC_API OggFLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
482 FLAC__ASSERT(0 != decoder);
483 FLAC__ASSERT(0 != decoder->private_);
484 return OggFLAC__stream_decoder_get_state(decoder->private_->stream_decoder);
487 OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_decoder_get_FLAC_stream_decoder_state(const OggFLAC__SeekableStreamDecoder *decoder)
489 FLAC__ASSERT(0 != decoder);
490 FLAC__ASSERT(0 != decoder->private_);
491 return OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(decoder->private_->stream_decoder);
494 OggFLAC_API const char *OggFLAC__seekable_stream_decoder_get_resolved_state_string(const OggFLAC__SeekableStreamDecoder *decoder)
496 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR)
497 return OggFLAC__SeekableStreamDecoderStateString[decoder->protected_->state];
499 return OggFLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder);
502 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_get_md5_checking(const OggFLAC__SeekableStreamDecoder *decoder)
504 FLAC__ASSERT(0 != decoder);
505 FLAC__ASSERT(0 != decoder->protected_);
506 return decoder->protected_->md5_checking;
509 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_channels(const OggFLAC__SeekableStreamDecoder *decoder)
511 FLAC__ASSERT(0 != decoder);
512 FLAC__ASSERT(0 != decoder->private_);
513 return OggFLAC__stream_decoder_get_channels(decoder->private_->stream_decoder);
516 OggFLAC_API FLAC__ChannelAssignment OggFLAC__seekable_stream_decoder_get_channel_assignment(const OggFLAC__SeekableStreamDecoder *decoder)
518 FLAC__ASSERT(0 != decoder);
519 FLAC__ASSERT(0 != decoder->private_);
520 return OggFLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder);
523 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_bits_per_sample(const OggFLAC__SeekableStreamDecoder *decoder)
525 FLAC__ASSERT(0 != decoder);
526 FLAC__ASSERT(0 != decoder->private_);
527 return OggFLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder);
530 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_sample_rate(const OggFLAC__SeekableStreamDecoder *decoder)
532 FLAC__ASSERT(0 != decoder);
533 FLAC__ASSERT(0 != decoder->private_);
534 return OggFLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder);
537 OggFLAC_API unsigned OggFLAC__seekable_stream_decoder_get_blocksize(const OggFLAC__SeekableStreamDecoder *decoder)
539 FLAC__ASSERT(0 != decoder);
540 FLAC__ASSERT(0 != decoder->private_);
541 return OggFLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder);
544 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_flush(OggFLAC__SeekableStreamDecoder *decoder)
546 FLAC__ASSERT(0 != decoder);
547 FLAC__ASSERT(0 != decoder->private_);
548 FLAC__ASSERT(0 != decoder->protected_);
550 decoder->private_->do_md5_checking = false;
552 if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
553 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
557 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
562 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_reset(OggFLAC__SeekableStreamDecoder *decoder)
564 FLAC__ASSERT(0 != decoder);
565 FLAC__ASSERT(0 != decoder->private_);
566 FLAC__ASSERT(0 != decoder->protected_);
568 if(!OggFLAC__seekable_stream_decoder_flush(decoder)) {
569 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
573 if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
574 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
578 decoder->private_->seek_table = 0;
580 decoder->private_->do_md5_checking = decoder->protected_->md5_checking;
582 /* We initialize the FLAC__MD5Context even though we may never use it. This
583 * is because md5 checking may be turned on to start and then turned off if
584 * a seek occurs. So we always init the context here and finalize it in
585 * OggFLAC__seekable_stream_decoder_finish() to make sure things are always
586 * cleaned up properly.
588 FLAC__MD5Init(&decoder->private_->md5context);
590 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
595 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_single(OggFLAC__SeekableStreamDecoder *decoder)
598 FLAC__ASSERT(0 != decoder);
600 if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
601 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
603 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
606 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
608 ret = OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder);
610 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
615 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_metadata(OggFLAC__SeekableStreamDecoder *decoder)
618 FLAC__ASSERT(0 != decoder);
620 if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
621 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
623 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
626 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
628 ret = OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder);
630 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
635 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_process_until_end_of_stream(OggFLAC__SeekableStreamDecoder *decoder)
638 FLAC__ASSERT(0 != decoder);
640 if(decoder->private_->stream_decoder->protected_->state == OggFLAC__STREAM_DECODER_END_OF_STREAM)
641 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
643 if(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM)
646 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK);
648 ret = OggFLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder);
650 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
655 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_decoder_seek_absolute(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample)
659 FLAC__ASSERT(0 != decoder);
660 FLAC__ASSERT(decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM);
662 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING;
664 /* turn off md5 checking if a seek is attempted */
665 decoder->private_->do_md5_checking = false;
667 if(!OggFLAC__stream_decoder_reset(decoder->private_->stream_decoder)) {
668 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
671 /* get the file length */
672 if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) {
673 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
677 if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
678 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
681 if(!OggFLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) {
682 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
685 if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) {
686 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
690 return seek_to_absolute_sample_(decoder, length, sample);
693 /***********************************************************************
695 * Private class methods
697 ***********************************************************************/
699 void set_defaults_(OggFLAC__SeekableStreamDecoder *decoder)
701 decoder->private_->read_callback = 0;
702 decoder->private_->seek_callback = 0;
703 decoder->private_->tell_callback = 0;
704 decoder->private_->length_callback = 0;
705 decoder->private_->eof_callback = 0;
706 decoder->private_->write_callback = 0;
707 decoder->private_->metadata_callback = 0;
708 decoder->private_->error_callback = 0;
709 decoder->private_->client_data = 0;
710 /* WATCHOUT: these should match the default behavior of OggFLAC__StreamDecoder */
711 decoder->private_->ignore_stream_info_block = false;
712 decoder->private_->ignore_seek_table_block = true;
714 decoder->protected_->md5_checking = false;
717 FLAC__StreamDecoderReadStatus read_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
719 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
721 if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
724 @@@@@@ verify that this is not needed:
725 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
727 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
729 else if(*bytes > 0) {
730 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) {
731 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
732 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
735 if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
737 @@@@@@ verify that this is not needed:
738 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
740 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
743 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
746 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
750 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
753 FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
755 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
758 if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
759 FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
760 FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
761 FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
763 FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
765 seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
766 if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
767 unsigned delta = (unsigned)(target_sample - this_frame_sample);
768 /* kick out of seek mode */
769 seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
770 /* shift out the samples before target_sample */
773 const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
774 for(channel = 0; channel < frame->header.channels; channel++)
775 newbuffer[channel] = buffer[channel] + delta;
776 seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
777 seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
778 /* write the relevant samples */
779 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
782 /* write the relevant samples */
783 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
787 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
791 if(seekable_stream_decoder->private_->do_md5_checking) {
792 if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
793 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
795 return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
799 void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
801 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
804 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
805 seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
806 /* save the MD5 signature for comparison later */
807 memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
808 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))
809 seekable_stream_decoder->private_->do_md5_checking = false;
811 else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
812 seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
815 if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
816 FLAC__bool ignore_block = false;
817 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
819 else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
822 seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
826 void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
828 OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
831 if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
832 seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
835 FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
837 FLAC__uint64 left_pos = 0, right_pos = stream_length;
838 FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
839 unsigned iteration = 0;
841 /* In the first iterations, we will calculate the target byte position
842 * by the distance from the target sample to left_sample and
843 * right_sample. After that, we will switch to binary search.
845 static const unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
847 /* We will switch to a linear search once our current sample is less
848 * that this number of samples ahead of the target sample
850 static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
852 /* If the total number of samples is unknown, use a large value and
853 * increase 'iteration' to force binary search immediately.
855 if(right_sample == 0) {
856 right_sample = (FLAC__uint64)(-1);
857 iteration = BINARY_SEARCH_AFTER_ITERATION;
860 decoder->private_->target_sample = target_sample;
861 for( ; ; iteration++) {
862 if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
863 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
866 /* our write callback will change the state when it gets to the target frame */
867 if(decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
871 const FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
872 FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
874 if (this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
877 if (iteration >= BINARY_SEARCH_AFTER_ITERATION)
878 pos = (right_pos + left_pos) / 2;
880 #if defined _MSC_VER || defined __MINGW32__
881 /* with VC++ you have to spoon feed it the casting */
882 pos = (FLAC__uint64)((double)(FLAC__int64)(target_sample - left_sample) / (double)(FLAC__int64)(right_pos - left_pos));
884 pos = (FLAC__uint64)((double)(target_sample - left_sample) / (double)(right_pos - left_pos));
887 if (this_frame_sample <= target_sample) {
888 /* The 'equal' case should not happen, since
889 * OggFLAC__stream_decoder_process_single()
890 * should recognize that it has hit the
891 * target sample and we would exit through
894 FLAC__ASSERT(this_frame_sample != target_sample);
896 left_sample = this_frame_sample;
899 else if(this_frame_sample > target_sample) {
900 right_sample = this_frame_sample;
905 if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
906 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
909 if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
910 decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;