diff options
Diffstat (limited to 'apps/codecs/libFLAC/seekable_stream_decoder.c')
-rw-r--r-- | apps/codecs/libFLAC/seekable_stream_decoder.c | 1111 |
1 files changed, 1111 insertions, 0 deletions
diff --git a/apps/codecs/libFLAC/seekable_stream_decoder.c b/apps/codecs/libFLAC/seekable_stream_decoder.c new file mode 100644 index 0000000000..2c899f20b3 --- /dev/null +++ b/apps/codecs/libFLAC/seekable_stream_decoder.c | |||
@@ -0,0 +1,1111 @@ | |||
1 | /* libFLAC - Free Lossless Audio Codec library | ||
2 | * Copyright (C) 2000,2001,2002,2003,2004,2005 Josh Coalson | ||
3 | * | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * | ||
8 | * - Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * | ||
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. | ||
14 | * | ||
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. | ||
18 | * | ||
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. | ||
30 | */ | ||
31 | |||
32 | #include <stdio.h> | ||
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 "private/float.h" /* for FLAC__double */ | ||
39 | #include "private/md5.h" | ||
40 | |||
41 | /* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ | ||
42 | #ifdef _MSC_VER | ||
43 | #define FLAC__U64L(x) x | ||
44 | #else | ||
45 | #define FLAC__U64L(x) x##LLU | ||
46 | #endif | ||
47 | |||
48 | /*********************************************************************** | ||
49 | * | ||
50 | * Private class method prototypes | ||
51 | * | ||
52 | ***********************************************************************/ | ||
53 | |||
54 | static void set_defaults_(FLAC__SeekableStreamDecoder *decoder); | ||
55 | static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data); | ||
56 | static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data); | ||
57 | static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data); | ||
58 | static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data); | ||
59 | static FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample); | ||
60 | |||
61 | /*********************************************************************** | ||
62 | * | ||
63 | * Private class data | ||
64 | * | ||
65 | ***********************************************************************/ | ||
66 | |||
67 | typedef struct FLAC__SeekableStreamDecoderPrivate { | ||
68 | FLAC__SeekableStreamDecoderReadCallback read_callback; | ||
69 | FLAC__SeekableStreamDecoderSeekCallback seek_callback; | ||
70 | FLAC__SeekableStreamDecoderTellCallback tell_callback; | ||
71 | FLAC__SeekableStreamDecoderLengthCallback length_callback; | ||
72 | FLAC__SeekableStreamDecoderEofCallback eof_callback; | ||
73 | FLAC__SeekableStreamDecoderWriteCallback write_callback; | ||
74 | FLAC__SeekableStreamDecoderMetadataCallback metadata_callback; | ||
75 | FLAC__SeekableStreamDecoderErrorCallback error_callback; | ||
76 | void *client_data; | ||
77 | FLAC__StreamDecoder *stream_decoder; | ||
78 | FLAC__bool do_md5_checking; /* initially gets protected_->md5_checking but is turned off after a seek */ | ||
79 | struct FLAC__MD5Context md5context; | ||
80 | FLAC__byte stored_md5sum[16]; /* this is what is stored in the metadata */ | ||
81 | FLAC__byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */ | ||
82 | /* the rest of these are only used for seeking: */ | ||
83 | FLAC__StreamMetadata_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */ | ||
84 | const FLAC__StreamMetadata_SeekTable *seek_table; /* we hold a pointer to the stream decoder's seek table for the same reason */ | ||
85 | /* 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 */ | ||
86 | FLAC__bool ignore_stream_info_block; | ||
87 | FLAC__bool ignore_seek_table_block; | ||
88 | FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */ | ||
89 | FLAC__uint64 target_sample; | ||
90 | } FLAC__SeekableStreamDecoderPrivate; | ||
91 | |||
92 | /*********************************************************************** | ||
93 | * | ||
94 | * Public static class data | ||
95 | * | ||
96 | ***********************************************************************/ | ||
97 | |||
98 | FLAC_API const char * const FLAC__SeekableStreamDecoderStateString[] = { | ||
99 | "FLAC__SEEKABLE_STREAM_DECODER_OK", | ||
100 | "FLAC__SEEKABLE_STREAM_DECODER_SEEKING", | ||
101 | "FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM", | ||
102 | "FLAC__SEEKABLE_STREAM_DECODER_MEMORY_ALLOCATION_ERROR", | ||
103 | "FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR", | ||
104 | "FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR", | ||
105 | "FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR", | ||
106 | "FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED", | ||
107 | "FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK", | ||
108 | "FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED" | ||
109 | }; | ||
110 | |||
111 | FLAC_API const char * const FLAC__SeekableStreamDecoderReadStatusString[] = { | ||
112 | "FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK", | ||
113 | "FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR" | ||
114 | }; | ||
115 | |||
116 | FLAC_API const char * const FLAC__SeekableStreamDecoderSeekStatusString[] = { | ||
117 | "FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK", | ||
118 | "FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR" | ||
119 | }; | ||
120 | |||
121 | FLAC_API const char * const FLAC__SeekableStreamDecoderTellStatusString[] = { | ||
122 | "FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK", | ||
123 | "FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_ERROR" | ||
124 | }; | ||
125 | |||
126 | FLAC_API const char * const FLAC__SeekableStreamDecoderLengthStatusString[] = { | ||
127 | "FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK", | ||
128 | "FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR" | ||
129 | }; | ||
130 | |||
131 | |||
132 | /*********************************************************************** | ||
133 | * | ||
134 | * Class constructor/destructor | ||
135 | * | ||
136 | ***********************************************************************/ | ||
137 | |||
138 | FLAC_API FLAC__SeekableStreamDecoder *FLAC__seekable_stream_decoder_new() | ||
139 | { | ||
140 | FLAC__SeekableStreamDecoder *decoder; | ||
141 | |||
142 | FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */ | ||
143 | |||
144 | decoder = (FLAC__SeekableStreamDecoder*)calloc(1, sizeof(FLAC__SeekableStreamDecoder)); | ||
145 | if(decoder == 0) { | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | decoder->protected_ = (FLAC__SeekableStreamDecoderProtected*)calloc(1, sizeof(FLAC__SeekableStreamDecoderProtected)); | ||
150 | if(decoder->protected_ == 0) { | ||
151 | free(decoder); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | decoder->private_ = (FLAC__SeekableStreamDecoderPrivate*)calloc(1, sizeof(FLAC__SeekableStreamDecoderPrivate)); | ||
156 | if(decoder->private_ == 0) { | ||
157 | free(decoder->protected_); | ||
158 | free(decoder); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | decoder->private_->stream_decoder = FLAC__stream_decoder_new(); | ||
163 | if(0 == decoder->private_->stream_decoder) { | ||
164 | free(decoder->private_); | ||
165 | free(decoder->protected_); | ||
166 | free(decoder); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | set_defaults_(decoder); | ||
171 | |||
172 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED; | ||
173 | |||
174 | return decoder; | ||
175 | } | ||
176 | |||
177 | FLAC_API void FLAC__seekable_stream_decoder_delete(FLAC__SeekableStreamDecoder *decoder) | ||
178 | { | ||
179 | FLAC__ASSERT(0 != decoder); | ||
180 | FLAC__ASSERT(0 != decoder->protected_); | ||
181 | FLAC__ASSERT(0 != decoder->private_); | ||
182 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
183 | |||
184 | (void)FLAC__seekable_stream_decoder_finish(decoder); | ||
185 | |||
186 | FLAC__stream_decoder_delete(decoder->private_->stream_decoder); | ||
187 | |||
188 | free(decoder->private_); | ||
189 | free(decoder->protected_); | ||
190 | free(decoder); | ||
191 | } | ||
192 | |||
193 | /*********************************************************************** | ||
194 | * | ||
195 | * Public class methods | ||
196 | * | ||
197 | ***********************************************************************/ | ||
198 | |||
199 | FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_init(FLAC__SeekableStreamDecoder *decoder) | ||
200 | { | ||
201 | FLAC__ASSERT(0 != decoder); | ||
202 | |||
203 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
204 | return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_ALREADY_INITIALIZED; | ||
205 | |||
206 | 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) | ||
207 | return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK; | ||
208 | |||
209 | if(0 == decoder->private_->write_callback || 0 == decoder->private_->metadata_callback || 0 == decoder->private_->error_callback) | ||
210 | return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_INVALID_CALLBACK; | ||
211 | |||
212 | decoder->private_->seek_table = 0; | ||
213 | |||
214 | decoder->private_->do_md5_checking = decoder->protected_->md5_checking; | ||
215 | |||
216 | /* We initialize the FLAC__MD5Context even though we may never use it. This | ||
217 | * is because md5 checking may be turned on to start and then turned off if | ||
218 | * a seek occurs. So we always init the context here and finalize it in | ||
219 | * FLAC__seekable_stream_decoder_finish() to make sure things are always | ||
220 | * cleaned up properly. | ||
221 | */ | ||
222 | FLAC__MD5Init(&decoder->private_->md5context); | ||
223 | |||
224 | FLAC__stream_decoder_set_read_callback(decoder->private_->stream_decoder, read_callback_); | ||
225 | FLAC__stream_decoder_set_write_callback(decoder->private_->stream_decoder, write_callback_); | ||
226 | FLAC__stream_decoder_set_metadata_callback(decoder->private_->stream_decoder, metadata_callback_); | ||
227 | FLAC__stream_decoder_set_error_callback(decoder->private_->stream_decoder, error_callback_); | ||
228 | FLAC__stream_decoder_set_client_data(decoder->private_->stream_decoder, decoder); | ||
229 | |||
230 | /* We always want to see these blocks. Whether or not we pass them up | ||
231 | * through the metadata callback will be determined by flags set in our | ||
232 | * implementation of ..._set_metadata_respond/ignore...() | ||
233 | */ | ||
234 | FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO); | ||
235 | FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE); | ||
236 | |||
237 | if(FLAC__stream_decoder_init(decoder->private_->stream_decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) | ||
238 | return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
239 | |||
240 | return decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK; | ||
241 | } | ||
242 | |||
243 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_finish(FLAC__SeekableStreamDecoder *decoder) | ||
244 | { | ||
245 | FLAC__bool md5_failed = false; | ||
246 | |||
247 | FLAC__ASSERT(0 != decoder); | ||
248 | FLAC__ASSERT(0 != decoder->private_); | ||
249 | FLAC__ASSERT(0 != decoder->protected_); | ||
250 | |||
251 | if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
252 | return true; | ||
253 | |||
254 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
255 | |||
256 | /* see the comment in FLAC__seekable_stream_decoder_init() as to why we | ||
257 | * always call FLAC__MD5Final() | ||
258 | */ | ||
259 | FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); | ||
260 | |||
261 | FLAC__stream_decoder_finish(decoder->private_->stream_decoder); | ||
262 | |||
263 | if(decoder->private_->do_md5_checking) { | ||
264 | if(memcmp(decoder->private_->stored_md5sum, decoder->private_->computed_md5sum, 16)) | ||
265 | md5_failed = true; | ||
266 | } | ||
267 | |||
268 | set_defaults_(decoder); | ||
269 | |||
270 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED; | ||
271 | |||
272 | return !md5_failed; | ||
273 | } | ||
274 | |||
275 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_md5_checking(FLAC__SeekableStreamDecoder *decoder, FLAC__bool value) | ||
276 | { | ||
277 | FLAC__ASSERT(0 != decoder); | ||
278 | FLAC__ASSERT(0 != decoder->protected_); | ||
279 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
280 | return false; | ||
281 | decoder->protected_->md5_checking = value; | ||
282 | return true; | ||
283 | } | ||
284 | |||
285 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_read_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderReadCallback value) | ||
286 | { | ||
287 | FLAC__ASSERT(0 != decoder); | ||
288 | FLAC__ASSERT(0 != decoder->private_); | ||
289 | FLAC__ASSERT(0 != decoder->protected_); | ||
290 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
291 | return false; | ||
292 | decoder->private_->read_callback = value; | ||
293 | return true; | ||
294 | } | ||
295 | |||
296 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_seek_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderSeekCallback value) | ||
297 | { | ||
298 | FLAC__ASSERT(0 != decoder); | ||
299 | FLAC__ASSERT(0 != decoder->private_); | ||
300 | FLAC__ASSERT(0 != decoder->protected_); | ||
301 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
302 | return false; | ||
303 | decoder->private_->seek_callback = value; | ||
304 | return true; | ||
305 | } | ||
306 | |||
307 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_tell_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderTellCallback value) | ||
308 | { | ||
309 | FLAC__ASSERT(0 != decoder); | ||
310 | FLAC__ASSERT(0 != decoder->private_); | ||
311 | FLAC__ASSERT(0 != decoder->protected_); | ||
312 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
313 | return false; | ||
314 | decoder->private_->tell_callback = value; | ||
315 | return true; | ||
316 | } | ||
317 | |||
318 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_length_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderLengthCallback value) | ||
319 | { | ||
320 | FLAC__ASSERT(0 != decoder); | ||
321 | FLAC__ASSERT(0 != decoder->private_); | ||
322 | FLAC__ASSERT(0 != decoder->protected_); | ||
323 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
324 | return false; | ||
325 | decoder->private_->length_callback = value; | ||
326 | return true; | ||
327 | } | ||
328 | |||
329 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_eof_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderEofCallback value) | ||
330 | { | ||
331 | FLAC__ASSERT(0 != decoder); | ||
332 | FLAC__ASSERT(0 != decoder->private_); | ||
333 | FLAC__ASSERT(0 != decoder->protected_); | ||
334 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
335 | return false; | ||
336 | decoder->private_->eof_callback = value; | ||
337 | return true; | ||
338 | } | ||
339 | |||
340 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_write_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderWriteCallback value) | ||
341 | { | ||
342 | FLAC__ASSERT(0 != decoder); | ||
343 | FLAC__ASSERT(0 != decoder->private_); | ||
344 | FLAC__ASSERT(0 != decoder->protected_); | ||
345 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
346 | return false; | ||
347 | decoder->private_->write_callback = value; | ||
348 | return true; | ||
349 | } | ||
350 | |||
351 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderMetadataCallback value) | ||
352 | { | ||
353 | FLAC__ASSERT(0 != decoder); | ||
354 | FLAC__ASSERT(0 != decoder->private_); | ||
355 | FLAC__ASSERT(0 != decoder->protected_); | ||
356 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
357 | return false; | ||
358 | decoder->private_->metadata_callback = value; | ||
359 | return true; | ||
360 | } | ||
361 | |||
362 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_error_callback(FLAC__SeekableStreamDecoder *decoder, FLAC__SeekableStreamDecoderErrorCallback value) | ||
363 | { | ||
364 | FLAC__ASSERT(0 != decoder); | ||
365 | FLAC__ASSERT(0 != decoder->private_); | ||
366 | FLAC__ASSERT(0 != decoder->protected_); | ||
367 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
368 | return false; | ||
369 | decoder->private_->error_callback = value; | ||
370 | return true; | ||
371 | } | ||
372 | |||
373 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_client_data(FLAC__SeekableStreamDecoder *decoder, void *value) | ||
374 | { | ||
375 | FLAC__ASSERT(0 != decoder); | ||
376 | FLAC__ASSERT(0 != decoder->private_); | ||
377 | FLAC__ASSERT(0 != decoder->protected_); | ||
378 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
379 | return false; | ||
380 | decoder->private_->client_data = value; | ||
381 | return true; | ||
382 | } | ||
383 | |||
384 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type) | ||
385 | { | ||
386 | FLAC__ASSERT(0 != decoder); | ||
387 | FLAC__ASSERT(0 != decoder->private_); | ||
388 | FLAC__ASSERT(0 != decoder->protected_); | ||
389 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
390 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
391 | return false; | ||
392 | if(type == FLAC__METADATA_TYPE_STREAMINFO) | ||
393 | decoder->private_->ignore_stream_info_block = false; | ||
394 | else if(type == FLAC__METADATA_TYPE_SEEKTABLE) | ||
395 | decoder->private_->ignore_seek_table_block = false; | ||
396 | return FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, type); | ||
397 | } | ||
398 | |||
399 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]) | ||
400 | { | ||
401 | FLAC__ASSERT(0 != decoder); | ||
402 | FLAC__ASSERT(0 != decoder->private_); | ||
403 | FLAC__ASSERT(0 != decoder->protected_); | ||
404 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
405 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
406 | return false; | ||
407 | return FLAC__stream_decoder_set_metadata_respond_application(decoder->private_->stream_decoder, id); | ||
408 | } | ||
409 | |||
410 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_respond_all(FLAC__SeekableStreamDecoder *decoder) | ||
411 | { | ||
412 | FLAC__ASSERT(0 != decoder); | ||
413 | FLAC__ASSERT(0 != decoder->private_); | ||
414 | FLAC__ASSERT(0 != decoder->protected_); | ||
415 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
416 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
417 | return false; | ||
418 | decoder->private_->ignore_stream_info_block = false; | ||
419 | decoder->private_->ignore_seek_table_block = false; | ||
420 | return FLAC__stream_decoder_set_metadata_respond_all(decoder->private_->stream_decoder); | ||
421 | } | ||
422 | |||
423 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore(FLAC__SeekableStreamDecoder *decoder, FLAC__MetadataType type) | ||
424 | { | ||
425 | FLAC__ASSERT(0 != decoder); | ||
426 | FLAC__ASSERT(0 != decoder->private_); | ||
427 | FLAC__ASSERT(0 != decoder->protected_); | ||
428 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
429 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
430 | return false; | ||
431 | if(type == FLAC__METADATA_TYPE_STREAMINFO) { | ||
432 | decoder->private_->ignore_stream_info_block = true; | ||
433 | return true; | ||
434 | } | ||
435 | else if(type == FLAC__METADATA_TYPE_SEEKTABLE) { | ||
436 | decoder->private_->ignore_seek_table_block = true; | ||
437 | return true; | ||
438 | } | ||
439 | else | ||
440 | return FLAC__stream_decoder_set_metadata_ignore(decoder->private_->stream_decoder, type); | ||
441 | } | ||
442 | |||
443 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore_application(FLAC__SeekableStreamDecoder *decoder, const FLAC__byte id[4]) | ||
444 | { | ||
445 | FLAC__ASSERT(0 != decoder); | ||
446 | FLAC__ASSERT(0 != decoder->private_); | ||
447 | FLAC__ASSERT(0 != decoder->protected_); | ||
448 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
449 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
450 | return false; | ||
451 | return FLAC__stream_decoder_set_metadata_ignore_application(decoder->private_->stream_decoder, id); | ||
452 | } | ||
453 | |||
454 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_set_metadata_ignore_all(FLAC__SeekableStreamDecoder *decoder) | ||
455 | { | ||
456 | FLAC__ASSERT(0 != decoder); | ||
457 | FLAC__ASSERT(0 != decoder->private_); | ||
458 | FLAC__ASSERT(0 != decoder->protected_); | ||
459 | FLAC__ASSERT(0 != decoder->private_->stream_decoder); | ||
460 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_UNINITIALIZED) | ||
461 | return false; | ||
462 | decoder->private_->ignore_stream_info_block = true; | ||
463 | decoder->private_->ignore_seek_table_block = true; | ||
464 | return | ||
465 | FLAC__stream_decoder_set_metadata_ignore_all(decoder->private_->stream_decoder) && | ||
466 | FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_STREAMINFO) && | ||
467 | FLAC__stream_decoder_set_metadata_respond(decoder->private_->stream_decoder, FLAC__METADATA_TYPE_SEEKTABLE); | ||
468 | } | ||
469 | |||
470 | FLAC_API FLAC__SeekableStreamDecoderState FLAC__seekable_stream_decoder_get_state(const FLAC__SeekableStreamDecoder *decoder) | ||
471 | { | ||
472 | FLAC__ASSERT(0 != decoder); | ||
473 | FLAC__ASSERT(0 != decoder->protected_); | ||
474 | return decoder->protected_->state; | ||
475 | } | ||
476 | |||
477 | FLAC_API FLAC__StreamDecoderState FLAC__seekable_stream_decoder_get_stream_decoder_state(const FLAC__SeekableStreamDecoder *decoder) | ||
478 | { | ||
479 | FLAC__ASSERT(0 != decoder); | ||
480 | FLAC__ASSERT(0 != decoder->private_); | ||
481 | return FLAC__stream_decoder_get_state(decoder->private_->stream_decoder); | ||
482 | } | ||
483 | |||
484 | FLAC_API const char *FLAC__seekable_stream_decoder_get_resolved_state_string(const FLAC__SeekableStreamDecoder *decoder) | ||
485 | { | ||
486 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) | ||
487 | return FLAC__SeekableStreamDecoderStateString[decoder->protected_->state]; | ||
488 | else | ||
489 | return FLAC__stream_decoder_get_resolved_state_string(decoder->private_->stream_decoder); | ||
490 | } | ||
491 | |||
492 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_get_md5_checking(const FLAC__SeekableStreamDecoder *decoder) | ||
493 | { | ||
494 | FLAC__ASSERT(0 != decoder); | ||
495 | FLAC__ASSERT(0 != decoder->protected_); | ||
496 | return decoder->protected_->md5_checking; | ||
497 | } | ||
498 | |||
499 | FLAC_API unsigned FLAC__seekable_stream_decoder_get_channels(const FLAC__SeekableStreamDecoder *decoder) | ||
500 | { | ||
501 | FLAC__ASSERT(0 != decoder); | ||
502 | FLAC__ASSERT(0 != decoder->private_); | ||
503 | return FLAC__stream_decoder_get_channels(decoder->private_->stream_decoder); | ||
504 | } | ||
505 | |||
506 | FLAC_API FLAC__ChannelAssignment FLAC__seekable_stream_decoder_get_channel_assignment(const FLAC__SeekableStreamDecoder *decoder) | ||
507 | { | ||
508 | FLAC__ASSERT(0 != decoder); | ||
509 | FLAC__ASSERT(0 != decoder->private_); | ||
510 | return FLAC__stream_decoder_get_channel_assignment(decoder->private_->stream_decoder); | ||
511 | } | ||
512 | |||
513 | FLAC_API unsigned FLAC__seekable_stream_decoder_get_bits_per_sample(const FLAC__SeekableStreamDecoder *decoder) | ||
514 | { | ||
515 | FLAC__ASSERT(0 != decoder); | ||
516 | FLAC__ASSERT(0 != decoder->private_); | ||
517 | return FLAC__stream_decoder_get_bits_per_sample(decoder->private_->stream_decoder); | ||
518 | } | ||
519 | |||
520 | FLAC_API unsigned FLAC__seekable_stream_decoder_get_sample_rate(const FLAC__SeekableStreamDecoder *decoder) | ||
521 | { | ||
522 | FLAC__ASSERT(0 != decoder); | ||
523 | FLAC__ASSERT(0 != decoder->private_); | ||
524 | return FLAC__stream_decoder_get_sample_rate(decoder->private_->stream_decoder); | ||
525 | } | ||
526 | |||
527 | FLAC_API unsigned FLAC__seekable_stream_decoder_get_blocksize(const FLAC__SeekableStreamDecoder *decoder) | ||
528 | { | ||
529 | FLAC__ASSERT(0 != decoder); | ||
530 | FLAC__ASSERT(0 != decoder->private_); | ||
531 | return FLAC__stream_decoder_get_blocksize(decoder->private_->stream_decoder); | ||
532 | } | ||
533 | |||
534 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_get_decode_position(const FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 *position) | ||
535 | { | ||
536 | FLAC__ASSERT(0 != decoder); | ||
537 | FLAC__ASSERT(0 != decoder->private_); | ||
538 | FLAC__ASSERT(0 != position); | ||
539 | |||
540 | if(decoder->private_->tell_callback(decoder, position, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) | ||
541 | return false; | ||
542 | FLAC__ASSERT(*position >= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder)); | ||
543 | *position -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder); | ||
544 | return true; | ||
545 | } | ||
546 | |||
547 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_flush(FLAC__SeekableStreamDecoder *decoder) | ||
548 | { | ||
549 | FLAC__ASSERT(0 != decoder); | ||
550 | FLAC__ASSERT(0 != decoder->private_); | ||
551 | FLAC__ASSERT(0 != decoder->protected_); | ||
552 | |||
553 | decoder->private_->do_md5_checking = false; | ||
554 | |||
555 | if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) { | ||
556 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
557 | return false; | ||
558 | } | ||
559 | |||
560 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK; | ||
561 | |||
562 | return true; | ||
563 | } | ||
564 | |||
565 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_reset(FLAC__SeekableStreamDecoder *decoder) | ||
566 | { | ||
567 | FLAC__ASSERT(0 != decoder); | ||
568 | FLAC__ASSERT(0 != decoder->private_); | ||
569 | FLAC__ASSERT(0 != decoder->protected_); | ||
570 | |||
571 | if(!FLAC__seekable_stream_decoder_flush(decoder)) { | ||
572 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
573 | return false; | ||
574 | } | ||
575 | |||
576 | if(!FLAC__stream_decoder_reset(decoder->private_->stream_decoder)) { | ||
577 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
578 | return false; | ||
579 | } | ||
580 | |||
581 | decoder->private_->seek_table = 0; | ||
582 | |||
583 | decoder->private_->do_md5_checking = decoder->protected_->md5_checking; | ||
584 | |||
585 | /* We initialize the FLAC__MD5Context even though we may never use it. This | ||
586 | * is because md5 checking may be turned on to start and then turned off if | ||
587 | * a seek occurs. So we always init the context here and finalize it in | ||
588 | * FLAC__seekable_stream_decoder_finish() to make sure things are always | ||
589 | * cleaned up properly. | ||
590 | */ | ||
591 | FLAC__MD5Init(&decoder->private_->md5context); | ||
592 | |||
593 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK; | ||
594 | |||
595 | return true; | ||
596 | } | ||
597 | |||
598 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_single(FLAC__SeekableStreamDecoder *decoder) | ||
599 | { | ||
600 | FLAC__bool ret; | ||
601 | FLAC__ASSERT(0 != decoder); | ||
602 | |||
603 | if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) | ||
604 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; | ||
605 | |||
606 | if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) | ||
607 | return true; | ||
608 | |||
609 | FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK); | ||
610 | |||
611 | ret = FLAC__stream_decoder_process_single(decoder->private_->stream_decoder); | ||
612 | if(!ret) | ||
613 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
614 | |||
615 | return ret; | ||
616 | } | ||
617 | |||
618 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_metadata(FLAC__SeekableStreamDecoder *decoder) | ||
619 | { | ||
620 | FLAC__bool ret; | ||
621 | FLAC__ASSERT(0 != decoder); | ||
622 | |||
623 | if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) | ||
624 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; | ||
625 | |||
626 | if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) | ||
627 | return true; | ||
628 | |||
629 | FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK); | ||
630 | |||
631 | ret = FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder); | ||
632 | if(!ret) | ||
633 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
634 | |||
635 | return ret; | ||
636 | } | ||
637 | |||
638 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_process_until_end_of_stream(FLAC__SeekableStreamDecoder *decoder) | ||
639 | { | ||
640 | FLAC__bool ret; | ||
641 | FLAC__ASSERT(0 != decoder); | ||
642 | |||
643 | if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) | ||
644 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; | ||
645 | |||
646 | if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) | ||
647 | return true; | ||
648 | |||
649 | FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK); | ||
650 | |||
651 | ret = FLAC__stream_decoder_process_until_end_of_stream(decoder->private_->stream_decoder); | ||
652 | if(!ret) | ||
653 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
654 | |||
655 | return ret; | ||
656 | } | ||
657 | |||
658 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_skip_single_frame(FLAC__SeekableStreamDecoder *decoder) | ||
659 | { | ||
660 | FLAC__bool ret; | ||
661 | FLAC__ASSERT(0 != decoder); | ||
662 | |||
663 | if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_END_OF_STREAM) | ||
664 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; | ||
665 | |||
666 | if(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) | ||
667 | return true; | ||
668 | |||
669 | FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK); | ||
670 | |||
671 | ret = FLAC__stream_decoder_skip_single_frame(decoder->private_->stream_decoder); | ||
672 | if(!ret) | ||
673 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
674 | |||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | FLAC_API FLAC__bool FLAC__seekable_stream_decoder_seek_absolute(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 sample) | ||
679 | { | ||
680 | FLAC__uint64 length; | ||
681 | |||
682 | FLAC__ASSERT(0 != decoder); | ||
683 | FLAC__ASSERT(decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_OK || decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM); | ||
684 | |||
685 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEKING; | ||
686 | |||
687 | /* turn off md5 checking if a seek is attempted */ | ||
688 | decoder->private_->do_md5_checking = false; | ||
689 | |||
690 | if(!FLAC__stream_decoder_reset(decoder->private_->stream_decoder)) { | ||
691 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
692 | return false; | ||
693 | } | ||
694 | /* get the file length */ | ||
695 | if(decoder->private_->length_callback(decoder, &length, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK) { | ||
696 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
697 | return false; | ||
698 | } | ||
699 | /* rewind */ | ||
700 | if(decoder->private_->seek_callback(decoder, 0, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) { | ||
701 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
702 | return false; | ||
703 | } | ||
704 | if(!FLAC__stream_decoder_process_until_end_of_metadata(decoder->private_->stream_decoder)) { | ||
705 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
706 | return false; | ||
707 | } | ||
708 | if(decoder->private_->stream_info.total_samples > 0 && sample >= decoder->private_->stream_info.total_samples) { | ||
709 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
710 | return false; | ||
711 | } | ||
712 | |||
713 | return seek_to_absolute_sample_(decoder, length, sample); | ||
714 | } | ||
715 | |||
716 | /*********************************************************************** | ||
717 | * | ||
718 | * Private class methods | ||
719 | * | ||
720 | ***********************************************************************/ | ||
721 | |||
722 | void set_defaults_(FLAC__SeekableStreamDecoder *decoder) | ||
723 | { | ||
724 | decoder->private_->read_callback = 0; | ||
725 | decoder->private_->seek_callback = 0; | ||
726 | decoder->private_->tell_callback = 0; | ||
727 | decoder->private_->length_callback = 0; | ||
728 | decoder->private_->eof_callback = 0; | ||
729 | decoder->private_->write_callback = 0; | ||
730 | decoder->private_->metadata_callback = 0; | ||
731 | decoder->private_->error_callback = 0; | ||
732 | decoder->private_->client_data = 0; | ||
733 | /* WATCHOUT: these should match the default behavior of FLAC__StreamDecoder */ | ||
734 | decoder->private_->ignore_stream_info_block = false; | ||
735 | decoder->private_->ignore_seek_table_block = true; | ||
736 | |||
737 | decoder->protected_->md5_checking = false; | ||
738 | } | ||
739 | |||
740 | FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) | ||
741 | { | ||
742 | FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data; | ||
743 | (void)decoder; | ||
744 | if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) { | ||
745 | *bytes = 0; | ||
746 | #if 0 | ||
747 | /*@@@@@@ verify that this is not needed */ | ||
748 | seekable_stream_decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; | ||
749 | #endif | ||
750 | return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; | ||
751 | } | ||
752 | else if(*bytes > 0) { | ||
753 | if(seekable_stream_decoder->private_->read_callback(seekable_stream_decoder, buffer, bytes, seekable_stream_decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK) { | ||
754 | seekable_stream_decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_READ_ERROR; | ||
755 | return FLAC__STREAM_DECODER_READ_STATUS_ABORT; | ||
756 | } | ||
757 | if(*bytes == 0) { | ||
758 | if(seekable_stream_decoder->private_->eof_callback(seekable_stream_decoder, seekable_stream_decoder->private_->client_data)) { | ||
759 | #if 0 | ||
760 | /*@@@@@@ verify that this is not needed */ | ||
761 | seekable_stream_decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM; | ||
762 | #endif | ||
763 | return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; | ||
764 | } | ||
765 | else | ||
766 | return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; | ||
767 | } | ||
768 | else { | ||
769 | return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; | ||
770 | } | ||
771 | } | ||
772 | else | ||
773 | return FLAC__STREAM_DECODER_READ_STATUS_ABORT; /* abort to avoid a deadlock */ | ||
774 | } | ||
775 | |||
776 | FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) | ||
777 | { | ||
778 | FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data; | ||
779 | (void)decoder; | ||
780 | |||
781 | if(seekable_stream_decoder->protected_->state == FLAC__SEEKABLE_STREAM_DECODER_SEEKING) { | ||
782 | FLAC__uint64 this_frame_sample = frame->header.number.sample_number; | ||
783 | FLAC__uint64 next_frame_sample = this_frame_sample + (FLAC__uint64)frame->header.blocksize; | ||
784 | FLAC__uint64 target_sample = seekable_stream_decoder->private_->target_sample; | ||
785 | |||
786 | FLAC__ASSERT(frame->header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); | ||
787 | |||
788 | seekable_stream_decoder->private_->last_frame = *frame; /* save the frame */ | ||
789 | if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */ | ||
790 | unsigned delta = (unsigned)(target_sample - this_frame_sample); | ||
791 | /* kick out of seek mode */ | ||
792 | seekable_stream_decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_OK; | ||
793 | /* shift out the samples before target_sample */ | ||
794 | if(delta > 0) { | ||
795 | unsigned channel; | ||
796 | const FLAC__int32 *newbuffer[FLAC__MAX_CHANNELS]; | ||
797 | for(channel = 0; channel < frame->header.channels; channel++) | ||
798 | newbuffer[channel] = buffer[channel] + delta; | ||
799 | seekable_stream_decoder->private_->last_frame.header.blocksize -= delta; | ||
800 | seekable_stream_decoder->private_->last_frame.header.number.sample_number += (FLAC__uint64)delta; | ||
801 | /* write the relevant samples */ | ||
802 | return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, &seekable_stream_decoder->private_->last_frame, newbuffer, seekable_stream_decoder->private_->client_data); | ||
803 | } | ||
804 | else { | ||
805 | /* write the relevant samples */ | ||
806 | return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data); | ||
807 | } | ||
808 | } | ||
809 | else { | ||
810 | return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; | ||
811 | } | ||
812 | } | ||
813 | else { | ||
814 | if(seekable_stream_decoder->private_->do_md5_checking) { | ||
815 | if(!FLAC__MD5Accumulate(&seekable_stream_decoder->private_->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8)) | ||
816 | return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; | ||
817 | } | ||
818 | return seekable_stream_decoder->private_->write_callback(seekable_stream_decoder, frame, buffer, seekable_stream_decoder->private_->client_data); | ||
819 | } | ||
820 | } | ||
821 | |||
822 | void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) | ||
823 | { | ||
824 | FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data; | ||
825 | (void)decoder; | ||
826 | |||
827 | if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { | ||
828 | seekable_stream_decoder->private_->stream_info = metadata->data.stream_info; | ||
829 | /* save the MD5 signature for comparison later */ | ||
830 | memcpy(seekable_stream_decoder->private_->stored_md5sum, metadata->data.stream_info.md5sum, 16); | ||
831 | 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)) | ||
832 | seekable_stream_decoder->private_->do_md5_checking = false; | ||
833 | } | ||
834 | else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE) { | ||
835 | seekable_stream_decoder->private_->seek_table = &metadata->data.seek_table; | ||
836 | } | ||
837 | |||
838 | if(seekable_stream_decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING) { | ||
839 | FLAC__bool ignore_block = false; | ||
840 | if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO && seekable_stream_decoder->private_->ignore_stream_info_block) | ||
841 | ignore_block = true; | ||
842 | else if(metadata->type == FLAC__METADATA_TYPE_SEEKTABLE && seekable_stream_decoder->private_->ignore_seek_table_block) | ||
843 | ignore_block = true; | ||
844 | if(!ignore_block) | ||
845 | seekable_stream_decoder->private_->metadata_callback(seekable_stream_decoder, metadata, seekable_stream_decoder->private_->client_data); | ||
846 | } | ||
847 | } | ||
848 | |||
849 | void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) | ||
850 | { | ||
851 | FLAC__SeekableStreamDecoder *seekable_stream_decoder = (FLAC__SeekableStreamDecoder *)client_data; | ||
852 | (void)decoder; | ||
853 | |||
854 | if(seekable_stream_decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING) | ||
855 | seekable_stream_decoder->private_->error_callback(seekable_stream_decoder, status, seekable_stream_decoder->private_->client_data); | ||
856 | } | ||
857 | |||
858 | FLAC__bool seek_to_absolute_sample_(FLAC__SeekableStreamDecoder *decoder, FLAC__uint64 stream_length, FLAC__uint64 target_sample) | ||
859 | { | ||
860 | FLAC__uint64 first_frame_offset, lower_bound, upper_bound; | ||
861 | FLAC__int64 pos = -1, last_pos = -1; | ||
862 | int i, lower_seek_point = -1, upper_seek_point = -1; | ||
863 | unsigned approx_bytes_per_frame; | ||
864 | FLAC__uint64 last_frame_sample = FLAC__U64L(0xffffffffffffffff); | ||
865 | FLAC__bool needs_seek; | ||
866 | const FLAC__uint64 total_samples = decoder->private_->stream_info.total_samples; | ||
867 | const unsigned min_blocksize = decoder->private_->stream_info.min_blocksize; | ||
868 | const unsigned max_blocksize = decoder->private_->stream_info.max_blocksize; | ||
869 | const unsigned max_framesize = decoder->private_->stream_info.max_framesize; | ||
870 | const unsigned channels = FLAC__seekable_stream_decoder_get_channels(decoder); | ||
871 | const unsigned bps = FLAC__seekable_stream_decoder_get_bits_per_sample(decoder); | ||
872 | |||
873 | /* we are just guessing here, but we want to guess high, not low */ | ||
874 | if(max_framesize > 0) { | ||
875 | approx_bytes_per_frame = max_framesize; | ||
876 | } | ||
877 | /* | ||
878 | * Check if it's a known fixed-blocksize stream. Note that though | ||
879 | * the spec doesn't allow zeroes in the STREAMINFO block, we may | ||
880 | * never get a STREAMINFO block when decoding so the value of | ||
881 | * min_blocksize might be zero. | ||
882 | */ | ||
883 | else if(min_blocksize == max_blocksize && min_blocksize > 0) { | ||
884 | /* note there are no () around 'bps/8' to keep precision up since it's an integer calulation */ | ||
885 | approx_bytes_per_frame = min_blocksize * channels * bps/8 + 64; | ||
886 | } | ||
887 | else | ||
888 | approx_bytes_per_frame = 4608 * channels * bps/8 + 64; | ||
889 | |||
890 | /* | ||
891 | * The decode position is currently at the first frame since we | ||
892 | * rewound and processed metadata. | ||
893 | */ | ||
894 | if(!FLAC__seekable_stream_decoder_get_decode_position(decoder, &first_frame_offset)) { | ||
895 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
896 | return false; | ||
897 | } | ||
898 | |||
899 | /* | ||
900 | * First, we set an upper and lower bound on where in the | ||
901 | * stream we will search. For now we assume the worst case | ||
902 | * scenario, which is our best guess at the beginning of | ||
903 | * the first and last frames. | ||
904 | */ | ||
905 | lower_bound = first_frame_offset; | ||
906 | |||
907 | /* calc the upper_bound, beyond which we never want to seek */ | ||
908 | if(max_framesize > 0) | ||
909 | upper_bound = stream_length - (max_framesize + 128 + 2); /* 128 for a possible ID3V1 tag, 2 for indexing differences */ | ||
910 | else | ||
911 | upper_bound = stream_length - ((channels * bps * FLAC__MAX_BLOCK_SIZE) / 8 + 128 + 2); | ||
912 | |||
913 | /* | ||
914 | * Now we refine the bounds if we have a seektable with | ||
915 | * suitable points. Note that according to the spec they | ||
916 | * must be ordered by ascending sample number. | ||
917 | */ | ||
918 | if(0 != decoder->private_->seek_table) { | ||
919 | /* find the closest seek point <= target_sample, if it exists */ | ||
920 | for(i = (int)decoder->private_->seek_table->num_points - 1; i >= 0; i--) { | ||
921 | if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number <= target_sample) | ||
922 | break; | ||
923 | } | ||
924 | if(i >= 0) { /* i.e. we found a suitable seek point... */ | ||
925 | lower_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset; | ||
926 | lower_seek_point = i; | ||
927 | } | ||
928 | |||
929 | /* find the closest seek point > target_sample, if it exists */ | ||
930 | for(i = 0; i < (int)decoder->private_->seek_table->num_points; i++) { | ||
931 | if(decoder->private_->seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER && decoder->private_->seek_table->points[i].sample_number > target_sample) | ||
932 | break; | ||
933 | } | ||
934 | if(i < (int)decoder->private_->seek_table->num_points) { /* i.e. we found a suitable seek point... */ | ||
935 | upper_bound = first_frame_offset + decoder->private_->seek_table->points[i].stream_offset; | ||
936 | upper_seek_point = i; | ||
937 | } | ||
938 | } | ||
939 | |||
940 | /* | ||
941 | * Now guess at where within those bounds our target | ||
942 | * sample will be. | ||
943 | */ | ||
944 | if(lower_seek_point >= 0) { | ||
945 | /* first see if our sample is within a few frames of the lower seekpoint */ | ||
946 | if(decoder->private_->seek_table->points[lower_seek_point].sample_number <= target_sample && target_sample < decoder->private_->seek_table->points[lower_seek_point].sample_number + (decoder->private_->seek_table->points[lower_seek_point].frame_samples * 4)) { | ||
947 | pos = (FLAC__int64)lower_bound; | ||
948 | } | ||
949 | else if(upper_seek_point >= 0) { | ||
950 | const FLAC__uint64 target_offset = target_sample - decoder->private_->seek_table->points[lower_seek_point].sample_number; | ||
951 | const FLAC__uint64 range_samples = decoder->private_->seek_table->points[upper_seek_point].sample_number - decoder->private_->seek_table->points[lower_seek_point].sample_number; | ||
952 | const FLAC__uint64 range_bytes = (upper_bound>lower_bound? upper_bound - lower_bound - 1 : 0); | ||
953 | #ifndef FLAC__INTEGER_ONLY_LIBRARY | ||
954 | #if defined _MSC_VER || defined __MINGW32__ | ||
955 | /* with MSVC you have to spoon feed it the casting */ | ||
956 | pos = (FLAC__int64)lower_bound + (FLAC__int64)(((FLAC__double)(FLAC__int64)target_offset / (FLAC__double)(FLAC__int64)range_samples) * (FLAC__double)(FLAC__int64)(range_bytes-1)) - approx_bytes_per_frame; | ||
957 | #else | ||
958 | pos = (FLAC__int64)lower_bound + (FLAC__int64)(((FLAC__double)target_offset / (FLAC__double)range_samples) * (FLAC__double)range_bytes) - approx_bytes_per_frame; | ||
959 | #endif | ||
960 | #else | ||
961 | /* a little less accurate: */ | ||
962 | if (range_bytes <= 0xffffffff) | ||
963 | pos = (FLAC__int64)lower_bound + (FLAC__int64)((target_offset * range_bytes) / range_samples) - approx_bytes_per_frame; | ||
964 | else /* @@@ WATCHOUT, ~2TB limit */ | ||
965 | pos = (FLAC__int64)lower_bound + (FLAC__int64)(((target_offset>>8) * (range_bytes>>8)) / (range_samples>>16)) - approx_bytes_per_frame; | ||
966 | #endif | ||
967 | } | ||
968 | } | ||
969 | |||
970 | /* | ||
971 | * If there's no seek table, we need to use the metadata (if we | ||
972 | * have it) and the filelength to estimate the position of the | ||
973 | * frame with the correct sample. | ||
974 | */ | ||
975 | if(pos < 0 && total_samples > 0) { | ||
976 | /* | ||
977 | * For max accuracy we should be using | ||
978 | * (stream_length-first_frame_offset-1) in the divisor, but the | ||
979 | * difference is trivial and (stream_length-first_frame_offset) | ||
980 | * has no chance of underflow. | ||
981 | */ | ||
982 | #ifndef FLAC__INTEGER_ONLY_LIBRARY | ||
983 | #if defined _MSC_VER || defined __MINGW32__ | ||
984 | /* with VC++ you have to spoon feed it the casting */ | ||
985 | pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((FLAC__double)(FLAC__int64)target_sample / (FLAC__double)(FLAC__int64)total_samples) * (FLAC__double)(FLAC__int64)(stream_length-first_frame_offset)) - approx_bytes_per_frame; | ||
986 | #else | ||
987 | pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((FLAC__double)target_sample / (FLAC__double)total_samples) * (FLAC__double)(stream_length-first_frame_offset)) - approx_bytes_per_frame; | ||
988 | #endif | ||
989 | #else | ||
990 | /* a little less accurate: */ | ||
991 | if (stream_length < 0xffffffff) | ||
992 | pos = (FLAC__int64)first_frame_offset + (FLAC__int64)((target_sample * (stream_length-first_frame_offset)) / total_samples) - approx_bytes_per_frame; | ||
993 | else /* @@@ WATCHOUT, ~2TB limit */ | ||
994 | pos = (FLAC__int64)first_frame_offset + (FLAC__int64)(((target_sample>>8) * ((stream_length-first_frame_offset)>>8)) / (total_samples>>16)) - approx_bytes_per_frame; | ||
995 | #endif | ||
996 | } | ||
997 | |||
998 | /* | ||
999 | * If there's no seek table and total_samples is unknown, we | ||
1000 | * don't even bother trying to figure out a target, we just use | ||
1001 | * our current position. | ||
1002 | */ | ||
1003 | if(pos < 0) { | ||
1004 | FLAC__uint64 upos; | ||
1005 | if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) { | ||
1006 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
1007 | return false; | ||
1008 | } | ||
1009 | pos = (FLAC__int64)upos; | ||
1010 | needs_seek = false; | ||
1011 | } | ||
1012 | else | ||
1013 | needs_seek = true; | ||
1014 | |||
1015 | /* clip the position to the bounds, lower bound takes precedence */ | ||
1016 | if(pos >= (FLAC__int64)upper_bound) { | ||
1017 | pos = (FLAC__int64)upper_bound-1; | ||
1018 | needs_seek = true; | ||
1019 | } | ||
1020 | if(pos < (FLAC__int64)lower_bound) { | ||
1021 | pos = (FLAC__int64)lower_bound; | ||
1022 | needs_seek = true; | ||
1023 | } | ||
1024 | |||
1025 | decoder->private_->target_sample = target_sample; | ||
1026 | while(1) { | ||
1027 | if(needs_seek) { | ||
1028 | if(decoder->private_->seek_callback(decoder, (FLAC__uint64)pos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK) { | ||
1029 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
1030 | return false; | ||
1031 | } | ||
1032 | if(!FLAC__stream_decoder_flush(decoder->private_->stream_decoder)) { | ||
1033 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR; | ||
1034 | return false; | ||
1035 | } | ||
1036 | } | ||
1037 | /* Now we need to get a frame. It is possible for our seek | ||
1038 | * to land in the middle of audio data that looks exactly like | ||
1039 | * a frame header from a future version of an encoder. When | ||
1040 | * that happens, FLAC__stream_decoder_process_single() will | ||
1041 | * return false and the state will be | ||
1042 | * FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. But there is a | ||
1043 | * remote possibility that it is properly synced at such a | ||
1044 | * "future-codec frame", so to make sure, we wait to see | ||
1045 | * several "unparseable" errors in a row before bailing out. | ||
1046 | */ | ||
1047 | { | ||
1048 | unsigned unparseable_count; | ||
1049 | FLAC__bool got_a_frame = false; | ||
1050 | for (unparseable_count = 0; !got_a_frame && unparseable_count < 10; unparseable_count++) { | ||
1051 | if(FLAC__stream_decoder_process_single(decoder->private_->stream_decoder)) | ||
1052 | got_a_frame = true; | ||
1053 | else if(decoder->private_->stream_decoder->protected_->state == FLAC__STREAM_DECODER_UNPARSEABLE_STREAM) | ||
1054 | /* try again. we don't want to flush the decoder since that clears the bitbuffer */ | ||
1055 | decoder->private_->stream_decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; | ||
1056 | else /* it's a real error */ | ||
1057 | break; | ||
1058 | } | ||
1059 | if (!got_a_frame) { | ||
1060 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
1061 | return false; | ||
1062 | } | ||
1063 | } | ||
1064 | /* our write callback will change the state when it gets to the target frame */ | ||
1065 | /* actually, we could have got_a_frame if our decoder is at FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM so we need to check for that also */ | ||
1066 | if(decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_SEEKING && decoder->protected_->state != FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM) { | ||
1067 | break; | ||
1068 | } | ||
1069 | else { /* we need to narrow the search */ | ||
1070 | const FLAC__uint64 this_frame_sample = decoder->private_->last_frame.header.number.sample_number; | ||
1071 | FLAC__ASSERT(decoder->private_->last_frame.header.number_type == FLAC__FRAME_NUMBER_TYPE_SAMPLE_NUMBER); | ||
1072 | if(this_frame_sample == last_frame_sample && pos < last_pos) { | ||
1073 | /* our last move backwards wasn't big enough, double it */ | ||
1074 | pos -= (last_pos - pos); | ||
1075 | needs_seek = true; | ||
1076 | } | ||
1077 | else { | ||
1078 | if(target_sample < this_frame_sample) { | ||
1079 | last_pos = pos; | ||
1080 | approx_bytes_per_frame = decoder->private_->last_frame.header.blocksize * channels * bps/8 + 64; | ||
1081 | pos -= approx_bytes_per_frame; | ||
1082 | needs_seek = true; | ||
1083 | } | ||
1084 | else { /* target_sample >= this_frame_sample + this frame's blocksize */ | ||
1085 | FLAC__uint64 upos; | ||
1086 | if(decoder->private_->tell_callback(decoder, &upos, decoder->private_->client_data) != FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK) { | ||
1087 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
1088 | return false; | ||
1089 | } | ||
1090 | last_pos = pos; | ||
1091 | pos = (FLAC__int64)upos; | ||
1092 | pos -= FLAC__stream_decoder_get_input_bytes_unconsumed(decoder->private_->stream_decoder); | ||
1093 | needs_seek = false; | ||
1094 | /* | ||
1095 | * if we haven't hit the target frame yet and our position hasn't changed, | ||
1096 | * it means we're at the end of the stream and the seek target does not exist. | ||
1097 | */ | ||
1098 | if(last_pos == pos) { | ||
1099 | decoder->protected_->state = FLAC__SEEKABLE_STREAM_DECODER_SEEK_ERROR; | ||
1100 | return false; | ||
1101 | } | ||
1102 | } | ||
1103 | } | ||
1104 | if(pos < (FLAC__int64)lower_bound) | ||
1105 | pos = (FLAC__int64)lower_bound; | ||
1106 | last_frame_sample = this_frame_sample; | ||
1107 | } | ||
1108 | } | ||
1109 | |||
1110 | return true; | ||
1111 | } | ||