make some improvements to the seek algo
[flac.git] / src / libFLAC / file_decoder.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2000,2001  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <assert.h>
21 #include <stdio.h>
22 #include <stdlib.h> /* for malloc() */
23 #include <string.h> /* for strcmp() */
24 #include <sys/stat.h> /* for stat() */
25 #include "FLAC/file_decoder.h"
26 #include "protected/stream_decoder.h"
27 #include "private/md5.h"
28
29 typedef struct FLAC__FileDecoderPrivate {
30         FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data);
31         void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
32         void (*error_callback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
33         void *client_data;
34         FILE *file;
35         char *filename; /* == NULL if stdin */
36         FLAC__StreamDecoder *stream;
37         struct MD5Context md5context;
38         byte stored_md5sum[16]; /* this is what is stored in the metadata */
39         byte computed_md5sum[16]; /* this is the sum we computed from the decoded data */
40         /* the rest of these are only used for seeking: */
41         FLAC__StreamMetaData_StreamInfo stream_info; /* we keep this around so we can figure out how to seek quickly */
42         FLAC__Frame last_frame; /* holds the info of the last frame we seeked to */
43         uint64 target_sample;
44 } FLAC__FileDecoderPrivate;
45
46 static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data);
47 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data);
48 static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
49 static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
50 static bool seek_to_absolute_sample_(FLAC__FileDecoder *decoder, long filesize, uint64 target_sample);
51
52 const char *FLAC__FileDecoderStateString[] = {
53         "FLAC__FILE_DECODER_OK",
54         "FLAC__FILE_DECODER_SEEKING",
55         "FLAC__FILE_DECODER_END_OF_FILE",
56         "FLAC__FILE_DECODER_ERROR_OPENING_FILE",
57         "FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR",
58         "FLAC__FILE_DECODER_SEEK_ERROR",
59         "FLAC__FILE_DECODER_STREAM_ERROR",
60         "FLAC__FILE_DECODER_UNINITIALIZED"
61 };
62
63 FLAC__FileDecoder *FLAC__file_decoder_get_new_instance()
64 {
65         FLAC__FileDecoder *decoder = (FLAC__FileDecoder*)malloc(sizeof(FLAC__FileDecoder));
66         if(decoder != 0) {
67                 decoder->state = FLAC__FILE_DECODER_UNINITIALIZED;
68                 decoder->guts = 0;
69         }
70         return decoder;
71 }
72
73 void FLAC__file_decoder_free_instance(FLAC__FileDecoder *decoder)
74 {
75         free(decoder);
76 }
77
78 FLAC__FileDecoderState FLAC__file_decoder_init(
79         FLAC__FileDecoder *decoder,
80         const char *filename,
81         FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data),
82         void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data),
83         void (*error_callback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data),
84         void *client_data
85 )
86 {
87         assert(sizeof(int) >= 4); /* we want to die right away if this is not true */
88         assert(decoder != 0);
89         assert(write_callback != 0);
90         assert(metadata_callback != 0);
91         assert(error_callback != 0);
92         assert(decoder->state == FLAC__FILE_DECODER_UNINITIALIZED);
93         assert(decoder->guts == 0);
94
95         decoder->state = FLAC__FILE_DECODER_OK;
96
97         decoder->guts = (FLAC__FileDecoderPrivate*)malloc(sizeof(FLAC__FileDecoderPrivate));
98         if(decoder->guts == 0)
99                 return decoder->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
100
101         decoder->guts->write_callback = write_callback;
102         decoder->guts->metadata_callback = metadata_callback;
103         decoder->guts->error_callback = error_callback;
104         decoder->guts->client_data = client_data;
105         decoder->guts->stream = 0;
106         decoder->guts->file = 0;
107         decoder->guts->filename = 0;
108
109         if(0 == strcmp(filename, "-")) {
110                 decoder->guts->file = stdin;
111         }
112         else {
113                 if(0 == (decoder->guts->filename = (char*)malloc(strlen(filename)+1)))
114                         return decoder->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
115                 strcpy(decoder->guts->filename, filename);
116                 decoder->guts->file = fopen(filename, "rb");
117         }
118
119         if(decoder->guts->file == 0)
120                 return decoder->state = FLAC__FILE_DECODER_ERROR_OPENING_FILE;
121
122         /* We initialize the MD5Context even though we may never use it.  This is
123          * because check_md5 may be turned on to start and then turned off if a
124          * seek occurs.  So we always init the context here and finalize it in
125          * FLAC__file_decoder_finish() to make sure things are always cleaned up
126          * properly.
127          */
128         MD5Init(&decoder->guts->md5context);
129
130         decoder->guts->stream = FLAC__stream_decoder_get_new_instance();
131         if(FLAC__stream_decoder_init(decoder->guts->stream, read_callback_, write_callback_, metadata_callback_, error_callback_, decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
132                 return decoder->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR; /* this is based on internal knowledge of FLAC__stream_decoder_init() */
133
134         return decoder->state;
135 }
136
137 bool FLAC__file_decoder_finish(FLAC__FileDecoder *decoder)
138 {
139         bool md5_failed = false;
140
141         assert(decoder != 0);
142         if(decoder->state == FLAC__FILE_DECODER_UNINITIALIZED)
143                 return true;
144         if(decoder->guts != 0) {
145                 if(decoder->guts->file != 0 && decoder->guts->file != stdin)
146                         fclose(decoder->guts->file);
147                 if(0 != decoder->guts->filename)
148                         free(decoder->guts->filename);
149                 /* see the comment in FLAC__file_decoder_init() as to why we always
150                  * call MD5Final()
151                  */
152                 MD5Final(decoder->guts->computed_md5sum, &decoder->guts->md5context);
153                 if(decoder->guts->stream != 0) {
154                         FLAC__stream_decoder_finish(decoder->guts->stream);
155                         FLAC__stream_decoder_free_instance(decoder->guts->stream);
156                 }
157                 if(decoder->check_md5) {
158                         if(memcmp(decoder->guts->stored_md5sum, decoder->guts->computed_md5sum, 16))
159                                 md5_failed = true;
160                 }
161                 free(decoder->guts);
162                 decoder->guts = 0;
163         }
164         decoder->state = FLAC__FILE_DECODER_UNINITIALIZED;
165         return !md5_failed;
166 }
167
168 bool FLAC__file_decoder_process_whole_file(FLAC__FileDecoder *decoder)
169 {
170         bool ret;
171         assert(decoder != 0);
172
173         if(decoder->guts->stream->state == FLAC__STREAM_DECODER_END_OF_STREAM)
174                 decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
175
176         if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
177                 return true;
178
179         assert(decoder->state == FLAC__FILE_DECODER_OK);
180
181         ret = FLAC__stream_decoder_process_whole_stream(decoder->guts->stream);
182         if(!ret)
183                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
184
185         return ret;
186 }
187
188 bool FLAC__file_decoder_process_metadata(FLAC__FileDecoder *decoder)
189 {
190         bool ret;
191         assert(decoder != 0);
192
193         if(decoder->guts->stream->state == FLAC__STREAM_DECODER_END_OF_STREAM)
194                 decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
195
196         if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
197                 return true;
198
199         assert(decoder->state == FLAC__FILE_DECODER_OK);
200
201         ret = FLAC__stream_decoder_process_metadata(decoder->guts->stream);
202         if(!ret)
203                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
204
205         return ret;
206 }
207
208 bool FLAC__file_decoder_process_one_frame(FLAC__FileDecoder *decoder)
209 {
210         bool ret;
211         assert(decoder != 0);
212
213         if(decoder->guts->stream->state == FLAC__STREAM_DECODER_END_OF_STREAM)
214                 decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
215
216         if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
217                 return true;
218
219         assert(decoder->state == FLAC__FILE_DECODER_OK);
220
221         ret = FLAC__stream_decoder_process_one_frame(decoder->guts->stream);
222         if(!ret)
223                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
224
225         return ret;
226 }
227
228 bool FLAC__file_decoder_process_remaining_frames(FLAC__FileDecoder *decoder)
229 {
230         bool ret;
231         assert(decoder != 0);
232
233         if(decoder->guts->stream->state == FLAC__STREAM_DECODER_END_OF_STREAM)
234                 decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
235
236         if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
237                 return true;
238
239         assert(decoder->state == FLAC__FILE_DECODER_OK);
240
241         ret = FLAC__stream_decoder_process_remaining_frames(decoder->guts->stream);
242         if(!ret)
243                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
244
245         return ret;
246 }
247
248 bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, uint64 sample)
249 {
250         long filesize;
251         struct stat filestats;
252
253         assert(decoder != 0);
254         assert(decoder->state == FLAC__FILE_DECODER_OK);
255
256         if(decoder->guts->filename == 0) { /* means the file is stdin... */
257                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
258                 return false;
259         }
260
261         decoder->state = FLAC__FILE_DECODER_SEEKING;
262
263         /* turn off md5 checking if a seek is attempted */
264         decoder->check_md5 = false;
265
266         if(!FLAC__stream_decoder_reset(decoder->guts->stream)) {
267                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
268                 return false;
269         }
270         /* get the file length */
271         if(stat(decoder->guts->filename, &filestats) != 0) {
272                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
273                 return false;
274         }
275         filesize = filestats.st_size;
276         /* rewind */
277         if(0 != fseek(decoder->guts->file, 0, SEEK_SET)) {
278                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
279                 return false;
280         }
281         if(!FLAC__stream_decoder_process_metadata(decoder->guts->stream)) {
282                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
283                 return false;
284         }
285         if(sample > decoder->guts->stream_info.total_samples) {
286                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
287                 return false;
288         }
289
290         return seek_to_absolute_sample_(decoder, filesize, sample);
291 }
292
293 FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data)
294 {
295         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
296         (void)decoder;
297         if(feof(file_decoder->guts->file)) {
298                 file_decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
299                 return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
300         }
301         else if(*bytes > 0) {
302                 size_t bytes_read = fread(buffer, sizeof(byte), *bytes, file_decoder->guts->file);
303                 if(bytes_read == 0) {
304                         if(feof(file_decoder->guts->file)) {
305                                 file_decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
306                                 return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
307                         }
308                         else
309                                 return FLAC__STREAM_DECODER_READ_ABORT;
310                 }
311                 else {
312                         *bytes = (unsigned)bytes_read;
313                         return FLAC__STREAM_DECODER_READ_CONTINUE;
314                 }
315         }
316         else
317                 return FLAC__STREAM_DECODER_READ_ABORT; /* abort to avoid a deadlock */
318 }
319
320 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data)
321 {
322         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
323         (void)decoder;
324
325         if(file_decoder->state == FLAC__FILE_DECODER_SEEKING) {
326                 uint64 this_frame_sample = frame->header.number.sample_number;
327                 uint64 next_frame_sample = this_frame_sample + (uint64)frame->header.blocksize;
328                 uint64 target_sample = file_decoder->guts->target_sample;
329
330                 file_decoder->guts->last_frame = *frame; /* save the frame in the guts */
331                 if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
332                         unsigned delta = (unsigned)(target_sample - this_frame_sample);
333                         /* kick out of seek mode */
334                         file_decoder->state = FLAC__FILE_DECODER_OK;
335                         /* shift out the samples before target_sample */
336                         if(delta > 0) {
337                                 unsigned channel;
338                                 const int32 *newbuffer[FLAC__MAX_CHANNELS];
339                                 for(channel = 0; channel < frame->header.channels; channel++)
340                                         newbuffer[channel] = buffer[channel] + delta;
341                                 file_decoder->guts->last_frame.header.blocksize -= delta;
342                                 file_decoder->guts->last_frame.header.number.sample_number += (uint64)delta;
343                                 /* write the relevant samples */
344                                 return file_decoder->guts->write_callback(file_decoder, &file_decoder->guts->last_frame, newbuffer, file_decoder->guts->client_data);
345                         }
346                         else {
347                                 /* write the relevant samples */
348                                 return file_decoder->guts->write_callback(file_decoder, frame, buffer, file_decoder->guts->client_data);
349                         }
350                 }
351                 else {
352                         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
353                 }
354         }
355         else {
356                 if(file_decoder->check_md5) {
357                         if(!FLAC__MD5Accumulate(&file_decoder->guts->md5context, buffer, frame->header.channels, frame->header.blocksize, (frame->header.bits_per_sample+7) / 8))
358                                 return FLAC__STREAM_DECODER_WRITE_ABORT;
359                 }
360                 return file_decoder->guts->write_callback(file_decoder, frame, buffer, file_decoder->guts->client_data);
361         }
362 }
363
364 void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
365 {
366         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
367         (void)decoder;
368
369         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
370                 file_decoder->guts->stream_info = metadata->data.stream_info;
371                 /* save the MD5 signature for comparison later */
372                 memcpy(file_decoder->guts->stored_md5sum, metadata->data.stream_info.md5sum, 16);
373                 if(0 == memcmp(file_decoder->guts->stored_md5sum, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16))
374                         file_decoder->check_md5 = false;
375         }
376         if(file_decoder->state != FLAC__FILE_DECODER_SEEKING)
377                 file_decoder->guts->metadata_callback(file_decoder, metadata, file_decoder->guts->client_data);
378 }
379
380 void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
381 {
382         FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
383         (void)decoder;
384
385         if(file_decoder->state != FLAC__FILE_DECODER_SEEKING)
386                 file_decoder->guts->error_callback(file_decoder, status, file_decoder->guts->client_data);
387 }
388
389 bool seek_to_absolute_sample_(FLAC__FileDecoder *decoder, long filesize, uint64 target_sample)
390 {
391         long l, r, pos, last_pos = -1;
392         unsigned approx_bytes_per_frame;
393         uint64 last_frame_sample = 0xffffffffffffffff;
394         bool needs_seek;
395         const bool is_variable_blocksize_stream = (decoder->guts->stream_info.min_blocksize != decoder->guts->stream_info.max_blocksize);
396
397         /* we are just guessing here, but we want to guess high, not low */
398         if(decoder->guts->stream_info.max_framesize > 0) {
399                 approx_bytes_per_frame = decoder->guts->stream_info.max_framesize + 64;
400         }
401         else if(!is_variable_blocksize_stream) {
402                 /* note there are no () around 'decoder->guts->stream_info.bits_per_sample/8' to keep precision up since it's an integer calulation */
403                 approx_bytes_per_frame = decoder->guts->stream_info.min_blocksize * decoder->guts->stream_info.channels * decoder->guts->stream_info.bits_per_sample/8 + 64;
404         }
405         else
406                 approx_bytes_per_frame = 1152 * decoder->guts->stream_info.channels * decoder->guts->stream_info.bits_per_sample/8 + 64;
407
408         /* The file pointer is currently at the first frame plus any read
409            ahead data, so first we get the file pointer, then subtract
410            uncomsumed bytes to get the position (l) of the first frame
411            in the file */
412         if(-1 == (l = ftell(decoder->guts->file))) {
413                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
414                 return false;
415         }
416         l -= FLAC__stream_decoder_input_bytes_unconsumed(decoder->guts->stream) + 1;
417         if(l < 0)
418                 l = 0;
419
420         /* Now we need to use the metadata and the filelength to search to the frame with the correct sample */
421 #ifdef _MSC_VER
422         /* with VC++ you have to spoon feed it the casting */
423         pos = l + (long)((double)(int64)target_sample / (double)(int64)decoder->guts->stream_info.total_samples * (double)(filesize-l+1)) - approx_bytes_per_frame;
424 #else
425         pos = l + (long)((double)target_sample / (double)decoder->guts->stream_info.total_samples * (double)(filesize-l+1)) - approx_bytes_per_frame;
426 #endif
427         if(decoder->guts->stream_info.max_framesize > 0)
428                 r = filesize - decoder->guts->stream_info.max_framesize - 2;
429         else
430                 r = filesize - ((decoder->guts->stream_info.channels * decoder->guts->stream_info.bits_per_sample * FLAC__MAX_BLOCK_SIZE) / 8 + 64);
431         if(pos >= r)
432                 pos = r-1;
433         if(pos < l)
434                 pos = l;
435         needs_seek = true;
436
437         decoder->guts->target_sample = target_sample;
438         while(1) {
439                 if(needs_seek) {
440                         if(-1 == fseek(decoder->guts->file, pos, SEEK_SET)) {
441                                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
442                                 return false;
443                         }
444                         if(!FLAC__stream_decoder_flush(decoder->guts->stream)) {
445                                 decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
446                                 return false;
447                         }
448                 }
449                 if(!FLAC__stream_decoder_process_one_frame(decoder->guts->stream)) {
450                         decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
451                         return false;
452                 }
453                 /* our write callback will change the state when it gets to the target frame */
454                 if(decoder->state != FLAC__FILE_DECODER_SEEKING) {
455                         break;
456                 }
457                 else { /* we need to narrow the search */
458                         uint64 this_frame_sample = decoder->guts->last_frame.header.number.sample_number;
459                         if(this_frame_sample == last_frame_sample) {
460                                 /* our last move backwards wasn't big enough */
461                                 pos -= (last_pos - pos);
462                                 needs_seek = true;
463                         }
464                         else {
465                                 if(target_sample < this_frame_sample) {
466                                         last_pos = pos;
467                                         approx_bytes_per_frame = decoder->guts->last_frame.header.blocksize * decoder->guts->last_frame.header.channels * decoder->guts->last_frame.header.bits_per_sample/8 + 64;
468                                         pos -= approx_bytes_per_frame;
469                                         needs_seek = true;
470                                 }
471                                 else {
472                                         last_pos = pos;
473                                         if(-1 == (pos = ftell(decoder->guts->file))) {
474                                                 decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
475                                                 return false;
476                                         }
477                                         pos -= FLAC__stream_decoder_input_bytes_unconsumed(decoder->guts->stream);
478                                         needs_seek = false;
479                                 }
480                         }
481                         if(pos < l)
482                                 pos = l;
483                         last_frame_sample = this_frame_sample;
484                 }
485         }
486
487         return true;
488 }