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