1
/* libOggFLAC - Free Lossless Audio Codec + Ogg library
2
* Copyright (C) 2002,2003,2004,2005 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)) {
726
/*@@@@@@ we used to do this: */
727
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
728
/* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
730
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
732
else if(*bytes > 0) {
733
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) {
734
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_READ_ERROR;
735
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
738
if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) {
740
/*@@@@@@ we used to do this: */
741
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM;
742
/* but it causes a problem because the Ogg decoding layer reads as much as it can to get pages, so the state will get to end-of-stream before the bitbuffer does */
744
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
747
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
750
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
754
return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */
757
FLAC__StreamDecoderWriteStatus write_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
759
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
762
if(seekable_stream_decoder->protected_->state == OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
763
FLAC__uint64 this_frame_sample = frame->header.number.sample_number;
764
FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize;
765
FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample;
767
FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
769
seekable_stream_decoder->private_->got_a_frame = true;
770
seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */
771
if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
772
unsigned delta = (unsigned)(target_sample - this_frame_sample);
773
/* kick out of seek mode */
774
seekable_stream_decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_OK;
775
/* shift out the samples before target_sample */
778
const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS];
779
for(channel = 0; channel < frame->header.channels; channel++)
780
newbuffer[channel] = buffer[channel] + delta;
781
seekable_stream_decoder->private_->last_frame.header.blocksize -= delta;
782
seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta;
783
/* write the relevant samples */
784
return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data);
787
/* write the relevant samples */
788
return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
792
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
796
if(seekable_stream_decoder->private_->do_md5_checking) {
797
if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
798
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
800
return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data);
804
void metadata_callback_(const OggFLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
806
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
809
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
810
seekable_stream_decoder->private_->stream_info = metadata->data.stream_info;
811
/* save the MD5 signature for comparison later */
812
memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16);
813
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))
814
seekable_stream_decoder->private_->do_md5_checking = false;
816
else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) {
817
seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table;
820
if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING) {
821
FLAC__bool ignore_block = false;
822
if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block)
824
else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block)
827
seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data);
831
void error_callback_(const OggFLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
833
OggFLAC__SeekableStreamDecoder *seekable_stream_decoder = (OggFLAC__SeekableStreamDecoder *)client_data;
836
if(seekable_stream_decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING)
837
seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data);
840
FLAC__bool seek_to_absolute_sample_(OggFLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample)
842
FLAC__uint64 left_pos = 0, right_pos = stream_length;
843
FLAC__uint64 left_sample = 0, right_sample = decoder->private_->stream_info.total_samples;
844
FLAC__uint64 this_frame_sample = 0; /* only initialized to avoid compiler warning */
845
FLAC__uint64 pos = 0; /* only initialized to avoid compiler warning */
846
FLAC__bool did_a_seek;
847
unsigned iteration = 0;
849
/* In the first iterations, we will calculate the target byte position
850
* by the distance from the target sample to left_sample and
851
* right_sample (let's call it "proportional search"). After that, we
852
* will switch to binary search.
854
unsigned BINARY_SEARCH_AFTER_ITERATION = 2;
856
/* We will switch to a linear search once our current sample is less
857
* that this number of samples ahead of the target sample
859
static const FLAC__uint64 LINEAR_SEARCH_WITHIN_SAMPLES = FLAC__MAX_BLOCK_SIZE * 2;
861
/* If the total number of samples is unknown, use a large value and
862
* increase 'iteration' to force binary search immediately.
864
if(right_sample == 0) {
865
right_sample = (FLAC__uint64)(-1);
866
BINARY_SEARCH_AFTER_ITERATION = 0;
869
decoder->private_->target_sample = target_sample;
870
for( ; ; iteration++) {
871
if (iteration == 0 || this_frame_sample > target_sample || target_sample - this_frame_sample > LINEAR_SEARCH_WITHIN_SAMPLES) {
872
if (iteration >= BINARY_SEARCH_AFTER_ITERATION) {
873
pos = (right_pos + left_pos) / 2;
876
#ifndef FLAC__INTEGER_ONLY_LIBRARY
877
#if defined _MSC_VER || defined __MINGW32__
878
/* with MSVC you have to spoon feed it the casting */
879
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));
881
pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos));
884
/* a little less accurate: */
885
if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff))
886
pos = (FLAC__int64)(((target_sample-left_sample) * (right_pos-left_pos)) / (right_sample-left_sample));
887
else /* @@@ WATCHOUT, ~2TB limit */
888
pos = (FLAC__int64)((((target_sample-left_sample)>>8) * ((right_pos-left_pos)>>8)) / ((right_sample-left_sample)>>16));
890
/* @@@ TODO: might want to limit pos to some distance
891
* before EOF, to make sure we land before the last frame,
892
* thereby getting a this_fram_sample and so having a better
893
* estimate. this would also mostly (or totally if we could
894
* be sure to land before the last frame) avoid the
895
* end-of-stream case we have to check later.
900
if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) {
901
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
904
if(!OggFLAC__stream_decoder_flush(decoder->private_->stream_decoder)) {
905
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR;
913
decoder->private_->got_a_frame = false;
914
if(!OggFLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) {
915
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
918
if(!decoder->private_->got_a_frame) {
920
/* this can happen if we seek to a point after the last frame; we drop
921
* to binary search right away in this case to avoid any wasted
922
* iterations of proportional search.
925
BINARY_SEARCH_AFTER_ITERATION = 0;
928
/* this can probably only happen if total_samples is unknown and the
929
* target_sample is past the end of the stream
931
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
935
/* our write callback will change the state when it gets to the target frame */
937
decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_SEEKING &&
938
decoder->protected_->state != OggFLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM
943
this_frame_sample = decoder->private_->last_frame.header.number.sample_number;
944
FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER);
947
if (this_frame_sample <= target_sample) {
948
/* The 'equal' case should not happen, since
949
* OggFLAC__stream_decoder_process_single()
950
* should recognize that it has hit the
951
* target sample and we would exit through
954
FLAC__ASSERT(this_frame_sample != target_sample);
956
left_sample = this_frame_sample;
957
/* sanity check to avoid infinite loop */
958
if (left_pos == pos) {
959
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;
964
else if(this_frame_sample > target_sample) {
965
right_sample = this_frame_sample;
966
/* sanity check to avoid infinite loop */
967
if (right_pos == pos) {
968
decoder->protected_->state = OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR;