fix decode buffer size
[platform/upstream/flac.git] / src / flac / decode.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000,2001  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #if defined _WIN32 && !defined __CYGWIN__
20 /* where MSVC puts unlink() */
21 # include <io.h>
22 #else
23 # include <unistd.h>
24 #endif
25 #include <assert.h> /* for FILE */
26 #include <stdio.h> /* for FILE */
27 #include <string.h> /* for strcmp() */
28 #include "FLAC/all.h"
29 #include "decode.h"
30
31 typedef struct {
32         FILE *fout;
33         bool abort_flag;
34         bool analysis_mode;
35         bool test_only;
36         bool is_wave_out;
37         bool is_big_endian;
38         bool is_unsigned_samples;
39         uint64 total_samples;
40         unsigned bps;
41         unsigned channels;
42         unsigned sample_rate;
43         bool verbose;
44         uint64 skip;
45         uint64 samples_processed;
46         unsigned frame_counter;
47 } stream_info_struct;
48
49 static FLAC__FileDecoder *decoder;
50 static bool is_big_endian_host;
51
52 /* local routines */
53 static bool init(const char *infile, stream_info_struct *stream_info);
54 static bool write_little_endian_uint16(FILE *f, uint16 val);
55 static bool write_little_endian_uint32(FILE *f, uint32 val);
56 static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data);
57 static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
58 static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
59 static void print_stats(const stream_info_struct *stream_info);
60
61 int decode_wav(const char *infile, const char *outfile, bool analysis_mode, bool verbose, uint64 skip)
62 {
63         bool md5_failure = false;
64         stream_info_struct stream_info;
65
66         decoder = 0;
67         stream_info.abort_flag = false;
68         stream_info.analysis_mode = analysis_mode;
69         stream_info.test_only = (outfile == 0);
70         stream_info.is_wave_out = true;
71         stream_info.verbose = verbose;
72         stream_info.skip = skip;
73         stream_info.samples_processed = 0;
74         stream_info.frame_counter = 0;
75
76         assert(!(stream_info.test_only && stream_info.analysis_mode));
77
78         if(!stream_info.test_only) {
79                 if(0 == strcmp(outfile, "-")) {
80                         stream_info.fout = stdout;
81                 }
82                 else {
83                         if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
84                                 fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
85                                 return false;
86                         }
87                 }
88         }
89
90         if(!init(infile, &stream_info))
91                 goto wav_abort_;
92
93         if(skip > 0) {
94                 if(!FLAC__file_decoder_process_metadata(decoder)) {
95                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
96                         goto wav_abort_;
97                 }
98                 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
99                         fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
100                         goto wav_abort_;
101                 }
102                 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
103                         if(verbose) { printf("\n"); fflush(stdout); }
104                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
105                         goto wav_abort_;
106                 }
107                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
108                         if(verbose) { printf("\n"); fflush(stdout); }
109                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
110                         goto wav_abort_;
111                 }
112         }
113         else {
114                 if(!FLAC__file_decoder_process_whole_file(decoder)) {
115                         if(verbose) { printf("\n"); fflush(stdout); }
116                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
117                         goto wav_abort_;
118                 }
119                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
120                         if(verbose) { printf("\n"); fflush(stdout); }
121                         fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", infile, decoder->state, FLAC__FileDecoderStateString[decoder->state]);
122                         goto wav_abort_;
123                 }
124         }
125
126         if(decoder) {
127                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
128                         md5_failure = !FLAC__file_decoder_finish(decoder);
129                 print_stats(&stream_info);
130                 FLAC__file_decoder_free_instance(decoder);
131         }
132         if(!stream_info.test_only)
133                 fclose(stream_info.fout);
134         if(verbose)
135                 printf("\n");
136         fflush(stdout);
137         if(md5_failure) {
138                 fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
139                 return 1;
140         }
141         else {
142                 if(stream_info.test_only)
143                         printf("%s: ok\n", infile);
144         }
145         return 0;
146 wav_abort_:
147         if(decoder) {
148                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
149                         FLAC__file_decoder_finish(decoder);
150                 FLAC__file_decoder_free_instance(decoder);
151         }
152         if(!stream_info.test_only) {
153                 fclose(stream_info.fout);
154                 unlink(outfile);
155         }
156         return 1;
157 }
158
159 int decode_raw(const char *infile, const char *outfile, bool analysis_mode, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
160 {
161         bool md5_failure = false;
162         stream_info_struct stream_info;
163
164         decoder = 0;
165         stream_info.abort_flag = false;
166         stream_info.analysis_mode = analysis_mode;
167         stream_info.test_only = (outfile == 0);
168         stream_info.is_wave_out = false;
169         stream_info.is_big_endian = is_big_endian;
170         stream_info.is_unsigned_samples = is_unsigned_samples;
171         stream_info.verbose = verbose;
172         stream_info.skip = skip;
173         stream_info.samples_processed = 0;
174         stream_info.frame_counter = 0;
175
176         assert(!(stream_info.test_only && stream_info.analysis_mode));
177
178         if(!stream_info.test_only) {
179                 if(0 == strcmp(outfile, "-")) {
180                         stream_info.fout = stdout;
181                 }
182                 else {
183                         if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
184                                 fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
185                                 return false;
186                         }
187                 }
188         }
189
190         if(!init(infile, &stream_info))
191                 goto raw_abort_;
192
193         if(skip > 0) {
194                 if(!FLAC__file_decoder_process_metadata(decoder)) {
195                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
196                         goto raw_abort_;
197                 }
198                 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
199                         fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
200                         goto raw_abort_;
201                 }
202                 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
203                         if(verbose) { printf("\n"); fflush(stdout); }
204                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
205                         goto raw_abort_;
206                 }
207                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
208                         if(verbose) { printf("\n"); fflush(stdout); }
209                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
210                         goto raw_abort_;
211                 }
212         }
213         else {
214                 if(!FLAC__file_decoder_process_whole_file(decoder)) {
215                         if(verbose) { printf("\n"); fflush(stdout); }
216                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
217                         goto raw_abort_;
218                 }
219                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
220                         if(verbose) { printf("\n"); fflush(stdout); }
221                         fprintf(stderr, "%s: ERROR during decoding\n", infile);
222                         goto raw_abort_;
223                 }
224         }
225
226         if(decoder) {
227                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
228                         md5_failure = !FLAC__file_decoder_finish(decoder);
229                 print_stats(&stream_info);
230                 FLAC__file_decoder_free_instance(decoder);
231         }
232         if(!stream_info.test_only)
233                 fclose(stream_info.fout);
234         if(verbose)
235                 printf("\n");
236         fflush(stdout);
237         if(md5_failure) {
238                 fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
239                 return 1;
240         }
241         else {
242                 if(stream_info.test_only)
243                         printf("%s: ok\n", infile);
244         }
245         return 0;
246 raw_abort_:
247         if(decoder) {
248                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
249                         FLAC__file_decoder_finish(decoder);
250                 FLAC__file_decoder_free_instance(decoder);
251         }
252         if(!stream_info.test_only) {
253                 fclose(stream_info.fout);
254                 unlink(outfile);
255         }
256         return 1;
257 }
258
259 bool init(const char *infile, stream_info_struct *stream_info)
260 {
261         uint32 test = 1;
262
263         is_big_endian_host = (*((byte*)(&test)))? false : true;
264
265         decoder = FLAC__file_decoder_get_new_instance();
266         if(0 == decoder) {
267                 fprintf(stderr, "ERROR creating the decoder instance\n");
268                 return false;
269         }
270         decoder->check_md5 = true;
271
272         if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
273                 fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
274                 return false;
275         }
276
277         return true;
278 }
279
280 bool write_little_endian_uint16(FILE *f, uint16 val)
281 {
282         byte *b = (byte*)(&val);
283         if(is_big_endian_host) {
284                 byte tmp;
285                 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
286         }
287         return fwrite(b, 1, 2, f) == 2;
288 }
289
290 bool write_little_endian_uint32(FILE *f, uint32 val)
291 {
292         byte *b = (byte*)(&val);
293         if(is_big_endian_host) {
294                 byte tmp;
295                 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
296                 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
297         }
298         return fwrite(b, 1, 4, f) == 4;
299 }
300
301 FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data)
302 {
303         stream_info_struct *stream_info = (stream_info_struct *)client_data;
304         FILE *fout = stream_info->fout;
305         unsigned bps = stream_info->bps, channels = stream_info->channels;
306         bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
307         bool is_unsigned_samples = (stream_info->is_wave_out? bps<=8 : stream_info->is_unsigned_samples);
308         unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte;
309         static int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(int32)]; /* WATCHOUT: can be up to 2 megs */
310         /* WATCHOUT: we say 'sizeof(int32)' above instead of '(FLAC__MAX_BITS_PER_SAMPLE+7)/8' because we have to use an array int32 even for 24 bps */
311         uint8  *u8buffer  = (uint8  *)s8buffer;
312         int16  *s16buffer = (int16  *)s8buffer;
313         uint16 *u16buffer = (uint16 *)s8buffer;
314         int32  *s32buffer = (int32  *)s8buffer;
315         uint32 *u32buffer = (uint32 *)s8buffer;
316
317         (void)decoder;
318
319         if(stream_info->abort_flag)
320                 return FLAC__STREAM_DECODER_WRITE_ABORT;
321
322         stream_info->samples_processed += wide_samples;
323         stream_info->frame_counter++;
324
325         if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
326                 print_stats(stream_info);
327
328         if(stream_info->analysis_mode) {
329                 unsigned i;
330                 fprintf(fout, "frame=%u\tblocksize=%u\tsample_rate=%u\tchannels=%u\tchannel_assignment=%s\n", stream_info->frame_counter-1, frame->header.blocksize, frame->header.sample_rate, frame->header.channels, FLAC__ChannelAssignmentString[frame->header.channel_assignment]);
331                 for(channel = 0; channel < channels; channel++) {
332                         const FLAC__Subframe *subframe = frame->subframes+channel;
333                         fprintf(fout, "\tsubframe=%u\ttype=%s", channel, FLAC__SubframeTypeString[subframe->type]);
334                         switch(subframe->type) {
335                                 case FLAC__SUBFRAME_TYPE_CONSTANT:
336                                         fprintf(fout, "\tvalue=%d\n", subframe->data.constant.value);
337                                         break;
338                                 case FLAC__SUBFRAME_TYPE_FIXED:
339                                         fprintf(fout, "\torder=%u\tpartition_order=%u\n", subframe->data.fixed.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order); /*@@@ assumes method is partitioned-rice */
340                                         for(i = 0; i < subframe->data.fixed.order; i++)
341                                                 fprintf(fout, "\twarmup[%u]=%d\n", i, subframe->data.fixed.warmup[i]);
342                                         break;
343                                 case FLAC__SUBFRAME_TYPE_LPC:
344                                         fprintf(fout, "\torder=%u\tpartition_order=%u\tqlp_coeff_precision=%u\tquantization_level=%d\n", subframe->data.lpc.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.qlp_coeff_precision, subframe->data.lpc.quantization_level); /*@@@ assumes method is partitioned-rice */
345                                         for(i = 0; i < subframe->data.lpc.order; i++)
346                                                 fprintf(fout, "\twarmup[%u]=%d\n", i, subframe->data.lpc.warmup[i]);
347                                         break;
348                                 case FLAC__SUBFRAME_TYPE_VERBATIM:
349                                         fprintf(fout, "\n");
350                                         break;
351                         }
352                 }
353         }
354         else if(!stream_info->test_only) {
355                 if(bps == 8) {
356                         if(is_unsigned_samples) {
357                                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
358                                         for(channel = 0; channel < channels; channel++, sample++)
359                                                 u8buffer[sample] = buffer[channel][wide_sample] + 0x80;
360                         }
361                         else {
362                                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
363                                         for(channel = 0; channel < channels; channel++, sample++)
364                                                 s8buffer[sample] = buffer[channel][wide_sample];
365                         }
366                         if(fwrite(u8buffer, 1, sample, fout) != sample)
367                                 return FLAC__STREAM_DECODER_WRITE_ABORT;
368                 }
369                 else if(bps == 16) {
370                         if(is_unsigned_samples) {
371                                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
372                                         for(channel = 0; channel < channels; channel++, sample++)
373                                                 u16buffer[sample] = buffer[channel][wide_sample] + 0x8000;
374                         }
375                         else {
376                                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
377                                         for(channel = 0; channel < channels; channel++, sample++)
378                                                 s16buffer[sample] = buffer[channel][wide_sample];
379                         }
380                         if(is_big_endian != is_big_endian_host) {
381                                 unsigned char tmp;
382                                 const unsigned bytes = sample * 2;
383                                 for(byte = 0; byte < bytes; byte += 2) {
384                                         tmp = u8buffer[byte];
385                                         u8buffer[byte] = u8buffer[byte+1];
386                                         u8buffer[byte+1] = tmp;
387                                 }
388                         }
389                         if(fwrite(u16buffer, 2, sample, fout) != sample)
390                                 return FLAC__STREAM_DECODER_WRITE_ABORT;
391                 }
392                 else if(bps == 24) {
393                         if(is_unsigned_samples) {
394                                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
395                                         for(channel = 0; channel < channels; channel++, sample++)
396                                                 u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
397                         }
398                         else {
399                                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
400                                         for(channel = 0; channel < channels; channel++, sample++)
401                                                 s32buffer[sample] = buffer[channel][wide_sample];
402                         }
403                         if(is_big_endian != is_big_endian_host) {
404                                 unsigned char tmp;
405                                 const unsigned bytes = sample * 4;
406                                 for(byte = 0; byte < bytes; byte += 4) {
407                                         tmp = u8buffer[byte];
408                                         u8buffer[byte] = u8buffer[byte+3];
409                                         u8buffer[byte+3] = tmp;
410                                         tmp = u8buffer[byte+1];
411                                         u8buffer[byte+1] = u8buffer[byte+2];
412                                         u8buffer[byte+2] = tmp;
413                                 }
414                         }
415                         if(is_big_endian) {
416                                 unsigned lbyte;
417                                 const unsigned bytes = sample * 4;
418                                 for(lbyte = byte = 0; byte < bytes; ) {
419                                         byte++;
420                                         u8buffer[lbyte++] = u8buffer[byte++];
421                                         u8buffer[lbyte++] = u8buffer[byte++];
422                                         u8buffer[lbyte++] = u8buffer[byte++];
423                                 }
424                         }
425                         else {
426                                 unsigned lbyte;
427                                 const unsigned bytes = sample * 4;
428                                 for(lbyte = byte = 0; byte < bytes; ) {
429                                         u8buffer[lbyte++] = u8buffer[byte++];
430                                         u8buffer[lbyte++] = u8buffer[byte++];
431                                         u8buffer[lbyte++] = u8buffer[byte++];
432                                         byte++;
433                                 }
434                         }
435                         if(fwrite(u8buffer, 3, sample, fout) != sample)
436                                 return FLAC__STREAM_DECODER_WRITE_ABORT;
437                 }
438                 else {
439                         assert(0);
440                 }
441         }
442         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
443 }
444
445 void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
446 {
447         stream_info_struct *stream_info = (stream_info_struct *)client_data;
448         (void)decoder;
449         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
450                 stream_info->total_samples = metadata->data.stream_info.total_samples - stream_info->skip;
451                 stream_info->bps = metadata->data.stream_info.bits_per_sample;
452                 stream_info->channels = metadata->data.stream_info.channels;
453                 stream_info->sample_rate = metadata->data.stream_info.sample_rate;
454
455                 if(stream_info->bps != 8 && stream_info->bps != 16 && stream_info->bps != 24) {
456                         fprintf(stderr, "ERROR: bits per sample is not 8/16/24\n");
457                         stream_info->abort_flag = true;
458                         return;
459                 }
460
461                 /* write the WAVE headers if necessary */
462                 if(!stream_info->analysis_mode && !stream_info->test_only && stream_info->is_wave_out) {
463                         uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
464                         if(data_size >= 0xFFFFFFDC) {
465                                 fprintf(stderr, "ERROR: stream is too big for a wave file\n");
466                                 stream_info->abort_flag = true;
467                                 return;
468                         }
469                         if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
470                         if(!write_little_endian_uint32(stream_info->fout, (uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
471                         if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
472                         if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
473                         if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
474                         if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels))) stream_info->abort_flag = true;
475                         if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
476                         if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate * stream_info->channels * ((stream_info->bps+7) / 8))) stream_info->abort_flag = true; /* @@@ or is it (sample_rate*channels*bps) / 8 ??? */
477                         if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
478                         if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
479                         if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
480                         if(!write_little_endian_uint32(stream_info->fout, (uint32)data_size)) stream_info->abort_flag = true; /* data size */
481                 }
482         }
483 }
484
485 void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
486 {
487         stream_info_struct *stream_info = (stream_info_struct *)client_data;
488         (void)decoder;
489         fprintf(stderr, "*** Got error code %d\n", status);
490         stream_info->abort_flag = true;
491 }
492
493 void print_stats(const stream_info_struct *stream_info)
494 {
495         if(stream_info->verbose) {
496                 printf("\r%s %u of %u samples, %6.2f%% complete",
497                         stream_info->test_only? "tested" : stream_info->analysis_mode? "analyzed" : "wrote",
498                         (unsigned)stream_info->samples_processed,
499                         (unsigned)stream_info->total_samples,
500 #ifdef _MSC_VER
501                         /* with VC++ you have to spoon feed it the casting */
502                         (double)(int64)stream_info->samples_processed / (double)(int64)stream_info->total_samples * 100.0
503 #else
504                         (double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0
505 #endif
506                 );
507                 fflush(stdout);
508         }
509 }