add support for MD5 checking and a test mode
authorJosh Coalson <jcoalson@users.sourceforce.net>
Fri, 12 Jan 2001 23:52:39 +0000 (23:52 +0000)
committerJosh Coalson <jcoalson@users.sourceforce.net>
Fri, 12 Jan 2001 23:52:39 +0000 (23:52 +0000)
src/flac/decode.c
src/flac/decode.h
src/flac/main.c

index d879a62..e54e460 100644 (file)
@@ -30,6 +30,7 @@
 typedef struct {
        FILE *fout;
        bool abort_flag;
+       bool test_only;
        bool is_wave_out;
        bool is_big_endian;
        bool is_unsigned_samples;
@@ -57,23 +58,27 @@ static void print_stats(const stream_info_struct *stream_info);
 
 int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip)
 {
+       bool md5_failure = false;
        stream_info_struct stream_info;
 
        decoder = 0;
        stream_info.abort_flag = false;
+       stream_info.test_only = (outfile == 0);
        stream_info.is_wave_out = true;
        stream_info.verbose = verbose;
        stream_info.skip = skip;
        stream_info.samples_processed = 0;
        stream_info.frame_counter = 0;
 
-       if(0 == strcmp(outfile, "-")) {
-               stream_info.fout = stdout;
-       }
-       else {
-               if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
-                       fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
-                       return false;
+       if(!stream_info.test_only) {
+               if(0 == strcmp(outfile, "-")) {
+                       stream_info.fout = stdout;
+               }
+               else {
+                       if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
+                               fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
+                               return false;
+                       }
                }
        }
 
@@ -82,42 +87,52 @@ int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 ski
 
        if(skip > 0) {
                if(!FLAC__file_decoder_process_metadata(decoder)) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto wav_abort_;
                }
                if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
-                       fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
+                       fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
                        goto wav_abort_;
                }
                if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto wav_abort_;
                }
                if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto wav_abort_;
                }
        }
        else {
                if(!FLAC__file_decoder_process_whole_file(decoder)) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto wav_abort_;
                }
                if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
-                       fprintf(stderr, "ERROR during decoding, state=%d:%s\n", decoder->state, FLAC__FileDecoderStateString[decoder->state]);
+                       fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", infile, decoder->state, FLAC__FileDecoderStateString[decoder->state]);
                        goto wav_abort_;
                }
        }
 
        if(decoder) {
                if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
-                       FLAC__file_decoder_finish(decoder);
+                       md5_failure = !FLAC__file_decoder_finish(decoder);
                print_stats(&stream_info);
                FLAC__file_decoder_free_instance(decoder);
        }
-       fclose(stream_info.fout);
+       if(!stream_info.test_only)
+               fclose(stream_info.fout);
        if(verbose)
                printf("\n");
+       fflush(stdout);
+       if(md5_failure) {
+               fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
+               return 1;
+       }
+       else {
+               if(stream_info.test_only)
+                       printf("%s: ok\n", infile);
+       }
        return 0;
 wav_abort_:
        if(decoder) {
@@ -125,17 +140,21 @@ wav_abort_:
                        FLAC__file_decoder_finish(decoder);
                FLAC__file_decoder_free_instance(decoder);
        }
-       fclose(stream_info.fout);
-       unlink(outfile);
+       if(!stream_info.test_only) {
+               fclose(stream_info.fout);
+               unlink(outfile);
+       }
        return 1;
 }
 
 int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
 {
+       bool md5_failure = false;
        stream_info_struct stream_info;
 
        decoder = 0;
        stream_info.abort_flag = false;
+       stream_info.test_only = (outfile == 0);
        stream_info.is_wave_out = false;
        stream_info.is_big_endian = is_big_endian;
        stream_info.is_unsigned_samples = is_unsigned_samples;
@@ -144,13 +163,15 @@ int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 ski
        stream_info.samples_processed = 0;
        stream_info.frame_counter = 0;
 
-       if(0 == strcmp(outfile, "-")) {
-               stream_info.fout = stdout;
-       }
-       else {
-               if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
-                       fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
-                       return false;
+       if(!stream_info.test_only) {
+               if(0 == strcmp(outfile, "-")) {
+                       stream_info.fout = stdout;
+               }
+               else {
+                       if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
+                               fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
+                               return false;
+                       }
                }
        }
 
@@ -159,42 +180,52 @@ int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 ski
 
        if(skip > 0) {
                if(!FLAC__file_decoder_process_metadata(decoder)) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto raw_abort_;
                }
                if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
-                       fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
+                       fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
                        goto raw_abort_;
                }
                if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto raw_abort_;
                }
                if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto raw_abort_;
                }
        }
        else {
                if(!FLAC__file_decoder_process_whole_file(decoder)) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto raw_abort_;
                }
                if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
-                       fprintf(stderr, "ERROR during decoding\n");
+                       fprintf(stderr, "%s: ERROR during decoding\n", infile);
                        goto raw_abort_;
                }
        }
 
        if(decoder) {
                if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
-                       FLAC__file_decoder_finish(decoder);
+                       md5_failure = !FLAC__file_decoder_finish(decoder);
                print_stats(&stream_info);
                FLAC__file_decoder_free_instance(decoder);
        }
-       fclose(stream_info.fout);
+       if(!stream_info.test_only)
+               fclose(stream_info.fout);
        if(verbose)
                printf("\n");
+       fflush(stdout);
+       if(md5_failure) {
+               fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
+               return 1;
+       }
+       else {
+               if(stream_info.test_only)
+                       printf("%s: ok\n", infile);
+       }
        return 0;
 raw_abort_:
        if(decoder) {
@@ -202,8 +233,10 @@ raw_abort_:
                        FLAC__file_decoder_finish(decoder);
                FLAC__file_decoder_free_instance(decoder);
        }
-       fclose(stream_info.fout);
-       unlink(outfile);
+       if(!stream_info.test_only) {
+               fclose(stream_info.fout);
+               unlink(outfile);
+       }
        return 1;
 }
 
@@ -218,6 +251,7 @@ bool init(const char *infile, stream_info_struct *stream_info)
                fprintf(stderr, "ERROR creating the decoder instance\n");
                return false;
        }
+       decoder->check_md5 = true;
 
        if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
                fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
@@ -272,41 +306,43 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder,
        if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
                print_stats(stream_info);
 
-       if(bps == 8) {
-               if(is_unsigned_samples) {
-                       for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
-                               for(channel = 0; channel < channels; channel++, sample++)
-                                       ucbuffer[sample] = buffer[channel][wide_sample] + 128;
-               }
-               else {
-                       for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
-                               for(channel = 0; channel < channels; channel++, sample++)
-                                       scbuffer[sample] = buffer[channel][wide_sample];
-               }
-               if(fwrite(ucbuffer, 1, sample, fout) != sample)
-                       return FLAC__STREAM_DECODER_WRITE_ABORT;
-       }
-       else { /* bps == 16 */
-               if(is_unsigned_samples) {
-                       for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
-                               for(channel = 0; channel < channels; channel++, sample++)
-                                       usbuffer[sample] = buffer[channel][wide_sample] + 32768;
-               }
-               else {
-                       for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
-                               for(channel = 0; channel < channels; channel++, sample++)
-                                       ssbuffer[sample] = buffer[channel][wide_sample];
+       if(!stream_info->test_only) {
+               if(bps == 8) {
+                       if(is_unsigned_samples) {
+                               for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
+                                       for(channel = 0; channel < channels; channel++, sample++)
+                                               ucbuffer[sample] = buffer[channel][wide_sample] + 128;
+                       }
+                       else {
+                               for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
+                                       for(channel = 0; channel < channels; channel++, sample++)
+                                               scbuffer[sample] = buffer[channel][wide_sample];
+                       }
+                       if(fwrite(ucbuffer, 1, sample, fout) != sample)
+                               return FLAC__STREAM_DECODER_WRITE_ABORT;
                }
-               if(is_big_endian != is_big_endian_host) {
-                       unsigned char tmp;
-                       for(byte = 0; byte < sample<<1; byte += 2) {
-                               tmp = ucbuffer[byte];
-                               ucbuffer[byte] = ucbuffer[byte+1];
-                               ucbuffer[byte+1] = tmp;
+               else { /* bps == 16 */
+                       if(is_unsigned_samples) {
+                               for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
+                                       for(channel = 0; channel < channels; channel++, sample++)
+                                               usbuffer[sample] = buffer[channel][wide_sample] + 32768;
+                       }
+                       else {
+                               for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
+                                       for(channel = 0; channel < channels; channel++, sample++)
+                                               ssbuffer[sample] = buffer[channel][wide_sample];
+                       }
+                       if(is_big_endian != is_big_endian_host) {
+                               unsigned char tmp;
+                               for(byte = 0; byte < sample<<1; byte += 2) {
+                                       tmp = ucbuffer[byte];
+                                       ucbuffer[byte] = ucbuffer[byte+1];
+                                       ucbuffer[byte+1] = tmp;
+                               }
                        }
+                       if(fwrite(usbuffer, 2, sample, fout) != sample)
+                               return FLAC__STREAM_DECODER_WRITE_ABORT;
                }
-               if(fwrite(usbuffer, 2, sample, fout) != sample)
-                       return FLAC__STREAM_DECODER_WRITE_ABORT;
        }
        return FLAC__STREAM_DECODER_WRITE_CONTINUE;
 }
@@ -328,7 +364,7 @@ void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaD
                }
 
                /* write the WAVE headers if necessary */
-               if(stream_info->is_wave_out) {
+               if(!stream_info->test_only && stream_info->is_wave_out) {
                        uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
                        if(data_size >= 0xFFFFFFDC) {
                                fprintf(stderr, "ERROR: stream is too big for a wave file\n");
@@ -362,7 +398,8 @@ void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorSt
 void print_stats(const stream_info_struct *stream_info)
 {
        if(stream_info->verbose) {
-               printf("\rwrote %u of %u samples, %6.2f%% complete",
+               printf("\r%s %u of %u samples, %6.2f%% complete",
+                       stream_info->test_only? "tested" : "wrote",
                        (unsigned)stream_info->samples_processed,
                        (unsigned)stream_info->total_samples,
 #ifdef _MSC_VER
index 8c23485..f09e3cc 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef flac__decode_h
 #define flac__decode_h
 
+/* outfile == 0 => test only */
 int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip);
 int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples);
 
index a232668..42e0c4f 100644 (file)
@@ -31,7 +31,8 @@ static int usage(const char *message, ...);
 int main(int argc, char *argv[])
 {
        int i;
-       bool verify = false, verbose = true, lax = false, mode_decode = false, do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
+       bool verify = false, verbose = true, lax = false, mode_decode = false, test_only = false;
+       bool do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
        unsigned max_lpc_order = 8;
        unsigned qlp_coeff_precision = 0;
        uint64 skip = 0;
@@ -48,6 +49,10 @@ int main(int argc, char *argv[])
                        break;
                if(0 == strcmp(argv[i], "-d"))
                        mode_decode = true;
+               else if(0 == strcmp(argv[i], "-t")) {
+                       mode_decode = true;
+                       test_only = true;
+               }
                else if(0 == strcmp(argv[i], "-s"))
                        verbose = false;
                else if(0 == strcmp(argv[i], "-s-"))
@@ -158,8 +163,8 @@ int main(int argc, char *argv[])
                        return usage("ERROR: invalid option '%s'\n", argv[i]);
                }
        }
-       if(i + 2 != argc)
-               return usage("ERROR: invalid arguments (more/less than 2 filenames?)\n");
+       if(i + (test_only? 1:2) != argc)
+               return usage("ERROR: invalid arguments (more/less than %d filename%s?)\n", (test_only? 1:2), (test_only? "":"s"));
 
        /* tweak options based on the filenames; validate the values */
        if(!mode_decode) {
@@ -191,15 +196,17 @@ int main(int argc, char *argv[])
                }
        }
        else {
-               if(format_is_wave < 0) {
-                       if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
-                               format_is_wave = true;
-                       else
-                               format_is_wave = false;
-               }
-               if(!format_is_wave) {
-                       if(format_is_big_endian < 0)
-                               return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
+               if(!test_only) {
+                       if(format_is_wave < 0) {
+                               if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
+                                       format_is_wave = true;
+                               else
+                                       format_is_wave = false;
+                       }
+                       if(!format_is_wave) {
+                               if(format_is_big_endian < 0)
+                                       return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
+                       }
                }
        }
 
@@ -225,7 +232,7 @@ int main(int argc, char *argv[])
        }
 
        /* turn off verbosity if the output stream is going to stdout */
-       if(0 == strcmp(argv[i+1], "-"))
+       if(!test_only && 0 == strcmp(argv[i+1], "-"))
                verbose = false;
 
        if(verbose) {
@@ -246,9 +253,9 @@ int main(int argc, char *argv[])
 
        if(mode_decode)
                if(format_is_wave)
-                       return decode_wav(argv[i], argv[i+1], verbose, skip);
+                       return decode_wav(argv[i], test_only? 0 : argv[i+1], verbose, skip);
                else
-                       return decode_raw(argv[i], argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
+                       return decode_raw(argv[i], test_only? 0 : argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
        else
                if(format_is_wave)
                        return encode_wav(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision);
@@ -263,8 +270,6 @@ int usage(const char *message, ...)
        va_list args;
 
        if(message) {
-               fprintf(stderr, message);
-               fprintf(stderr, "\n");
                va_start(args, message);
 
                (void) vfprintf(stderr, message, args);