From 4397b2718123140e3ee6b8134f26c8d7b7a82118 Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Fri, 12 Jan 2001 23:52:39 +0000 Subject: [PATCH] add support for MD5 checking and a test mode --- src/flac/decode.c | 175 ++++++++++++++++++++++++++++------------------ src/flac/decode.h | 1 + src/flac/main.c | 39 ++++++----- 3 files changed, 129 insertions(+), 86 deletions(-) diff --git a/src/flac/decode.c b/src/flac/decode.c index d879a628..e54e4607 100644 --- a/src/flac/decode.c +++ b/src/flac/decode.c @@ -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(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(!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; + } + 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 diff --git a/src/flac/decode.h b/src/flac/decode.h index 8c23485f..f09e3cc0 100644 --- a/src/flac/decode.h +++ b/src/flac/decode.h @@ -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); diff --git a/src/flac/main.c b/src/flac/main.c index a232668a..42e0c4fd 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -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);