add undocumented option to flac: --ignore-chunk-sizes

This commit is contained in:
Josh Coalson
2007-07-07 05:50:58 +00:00
parent b28c46d2ab
commit 5967f4981e
4 changed files with 97 additions and 18 deletions

View File

@@ -165,6 +165,7 @@
<li>Improved compression with no change to format or decrease in speed.</li> <li>Improved compression with no change to format or decrease in speed.</li>
<li>Encoding and decoding speedups for all modes. Encoding at -8 is twice as fast.</li> <li>Encoding and decoding speedups for all modes. Encoding at -8 is twice as fast.</li>
<li>Added a new option <span class="argument"><a href="documentation_tools_flac.html#flac_options_warnings_as_errors">-w,--warnings-as-errors</a></span> for treating all warnings as errors.</li> <li>Added a new option <span class="argument"><a href="documentation_tools_flac.html#flac_options_warnings_as_errors">-w,--warnings-as-errors</a></span> for treating all warnings as errors.</li>
<li>Added a new undocumented option <span class="argument">--ignore-chunk-sizes</span> for ignoring the size of the 'data' chunk (WAVE) or 'SSND' chunk(AIFF). Can be used to encode files with bogus data sizes. Use with caution, all subsequent data is treated as audio, so the data/SSND chunk must be the last or the following data/tags will be treated as audio and encoded.</li>
<li>Allow <span class="argument"><a href="documentation_tools_flac.html#flac_options_picture">--picture</a></span> option to take only a filename, and have all other attributes extracted from the file itself.</li> <li>Allow <span class="argument"><a href="documentation_tools_flac.html#flac_options_picture">--picture</a></span> option to take only a filename, and have all other attributes extracted from the file itself.</li>
<li>Fixed a bug that caused suboptimal default compression settings in some locales (<a href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=1608883&amp;group_id=13478&amp;atid=113478">SF #1608883</a>).</li> <li>Fixed a bug that caused suboptimal default compression settings in some locales (<a href="https://sourceforge.net/tracker/index.php?func=detail&amp;aid=1608883&amp;group_id=13478&amp;atid=113478">SF #1608883</a>).</li>
<li>Fixed a bug where FLAC-to-FLAC transcoding of a corrupted FLAC file would truncate the transcoded file at the first error (<a href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1615019&amp;group_id=13478&amp;atid=113478">SF #1615019</a>).</li> <li>Fixed a bug where FLAC-to-FLAC transcoding of a corrupted FLAC file would truncate the transcoded file at the first error (<a href="http://sourceforge.net/tracker/index.php?func=detail&amp;aid=1615019&amp;group_id=13478&amp;atid=113478">SF #1615019</a>).</li>

View File

@@ -343,7 +343,7 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con
} }
else if(got_ssnd_chunk==false && !memcmp(chunk_id, "SSND", 4)) { /* sound data chunk */ else if(got_ssnd_chunk==false && !memcmp(chunk_id, "SSND", 4)) { /* sound data chunk */
unsigned int offset= 0U, block_size= 0U, align_remainder= 0U, data_bytes; unsigned int offset= 0U, block_size= 0U, align_remainder= 0U, data_bytes;
size_t bytes_per_frame= channels*(bps>>3); const size_t bytes_per_frame= channels*(bps>>3);
FLAC__uint64 total_samples_in_input, trim = 0; FLAC__uint64 total_samples_in_input, trim = 0;
FLAC__bool pad= false; FLAC__bool pad= false;
@@ -355,9 +355,15 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con
/* SSND chunk size */ /* SSND chunk size */
if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
return EncoderSession_finish_error(&encoder_session); return EncoderSession_finish_error(&encoder_session);
data_bytes= xx; if(options.common.ignore_chunk_sizes) {
FLAC__ASSERT(!options.common.sector_align);
data_bytes = (unsigned)(-(int)bytes_per_frame); /* max out data_bytes; we'll use EOF as signal to stop reading */
}
else {
data_bytes= xx;
data_bytes-= 8U; /* discount the offset and block size fields */
}
pad= (data_bytes & 1U) ? true : false; pad= (data_bytes & 1U) ? true : false;
data_bytes-= 8U; /* discount the offset and block size fields */
/* offset */ /* offset */
if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
@@ -406,7 +412,14 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con
} }
data_bytes-= (unsigned int)encoder_session.skip*bytes_per_frame; /*@@@ WATCHOUT: 4GB limit */ data_bytes-= (unsigned int)encoder_session.skip*bytes_per_frame; /*@@@ WATCHOUT: 4GB limit */
encoder_session.total_samples_to_encode= total_samples_in_input - encoder_session.skip; if(options.common.ignore_chunk_sizes) {
encoder_session.total_samples_to_encode= 0;
flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n");
FLAC__ASSERT(0 == encoder_session.until);
}
else {
encoder_session.total_samples_to_encode= total_samples_in_input - encoder_session.skip;
}
if(encoder_session.until > 0) { if(encoder_session.until > 0) {
trim = total_samples_in_input - encoder_session.until; trim = total_samples_in_input - encoder_session.until;
FLAC__ASSERT(total_samples_in_input > 0); FLAC__ASSERT(total_samples_in_input > 0);
@@ -457,9 +470,14 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con
return EncoderSession_finish_error(&encoder_session); return EncoderSession_finish_error(&encoder_session);
} }
else if(feof(infile)) { else if(feof(infile)) {
flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); if(options.common.ignore_chunk_sizes) {
if(encoder_session.treat_warnings_as_errors) flac__utils_printf(stderr, 1, "%s: INFO: hit EOF with --ignore-chunk-sizes, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.samples_written);
return EncoderSession_finish_error(&encoder_session); }
else {
flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
if(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
}
data_bytes= 0; data_bytes= 0;
} }
} }
@@ -588,7 +606,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con
EncoderSession encoder_session; EncoderSession encoder_session;
FLAC__bool is_unsigned_samples = false; FLAC__bool is_unsigned_samples = false;
unsigned channels = 0, bps = 0, sample_rate = 0, shift = 0; unsigned channels = 0, bps = 0, sample_rate = 0, shift = 0;
size_t bytes_per_wide_sample, bytes_read; size_t bytes_read;
size_t channel_map[FLAC__MAX_CHANNELS]; size_t channel_map[FLAC__MAX_CHANNELS];
FLAC__uint16 x, format; /* format is the wFormatTag word from the 'fmt ' chunk */ FLAC__uint16 x, format; /* format is the wFormatTag word from the 'fmt ' chunk */
FLAC__uint32 xx, channel_mask = 0; FLAC__uint32 xx, channel_mask = 0;
@@ -902,20 +920,25 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con
else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */ else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */
FLAC__uint64 total_samples_in_input, trim = 0; FLAC__uint64 total_samples_in_input, trim = 0;
FLAC__bool pad = false; FLAC__bool pad = false;
const size_t bytes_per_wide_sample = channels * (bps >> 3);
unsigned data_bytes; unsigned data_bytes;
/* data size */ /* data size */
if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
return EncoderSession_finish_error(&encoder_session); return EncoderSession_finish_error(&encoder_session);
data_bytes = xx; if(options.common.ignore_chunk_sizes) {
if(0 == data_bytes) { FLAC__ASSERT(!options.common.sector_align);
flac__utils_printf(stderr, 1, "%s: ERROR: 'data' subchunk has size of 0\n", encoder_session.inbasefilename); data_bytes = (unsigned)(-(int)bytes_per_wide_sample); /* max out data_bytes; we'll use EOF as signal to stop reading */
return EncoderSession_finish_error(&encoder_session); }
else {
data_bytes = xx;
if(0 == data_bytes) {
flac__utils_printf(stderr, 1, "%s: ERROR: 'data' subchunk has size of 0\n", encoder_session.inbasefilename);
return EncoderSession_finish_error(&encoder_session);
}
} }
pad = (data_bytes & 1U) ? true : false; pad = (data_bytes & 1U) ? true : false;
bytes_per_wide_sample = channels * (bps >> 3);
/* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */
FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0);
total_samples_in_input = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples; total_samples_in_input = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples;
@@ -937,7 +960,14 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con
} }
data_bytes -= (unsigned)encoder_session.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */ data_bytes -= (unsigned)encoder_session.skip * bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */
encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; if(options.common.ignore_chunk_sizes) {
encoder_session.total_samples_to_encode = 0;
flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n");
FLAC__ASSERT(0 == encoder_session.until);
}
else {
encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip;
}
if(encoder_session.until > 0) { if(encoder_session.until > 0) {
trim = total_samples_in_input - encoder_session.until; trim = total_samples_in_input - encoder_session.until;
FLAC__ASSERT(total_samples_in_input > 0); FLAC__ASSERT(total_samples_in_input > 0);
@@ -993,9 +1023,14 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con
return EncoderSession_finish_error(&encoder_session); return EncoderSession_finish_error(&encoder_session);
} }
else if(feof(infile)) { else if(feof(infile)) {
flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written); if(options.common.ignore_chunk_sizes) {
if(encoder_session.treat_warnings_as_errors) flac__utils_printf(stderr, 1, "%s: INFO: hit EOF with --ignore-chunk-sizes, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.samples_written);
return EncoderSession_finish_error(&encoder_session); }
else {
flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned)encoder_session.total_samples_to_encode, (unsigned)encoder_session.samples_written);
if(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
}
data_bytes = 0; data_bytes = 0;
} }
} }
@@ -2552,6 +2587,8 @@ void print_stats(const EncoderSession *encoder_session)
const double ratio = (double)encoder_session->bytes_written / ((double)encoder_session->unencoded_size * min(1.0, progress)); const double ratio = (double)encoder_session->bytes_written / ((double)encoder_session->unencoded_size * min(1.0, progress));
#endif #endif
FLAC__ASSERT(encoder_session->total_samples_to_encode > 0);
if(samples_written == encoder_session->total_samples_to_encode) { if(samples_written == encoder_session->total_samples_to_encode) {
flac__utils_printf(stderr, 2, "\r%s:%s wrote %u bytes, ratio=%0.3f", flac__utils_printf(stderr, 2, "\r%s:%s wrote %u bytes, ratio=%0.3f",
encoder_session->inbasefilename, encoder_session->inbasefilename,

View File

@@ -84,6 +84,7 @@ typedef struct {
FLAC__int32 **align_reservoir; FLAC__int32 **align_reservoir;
unsigned *align_reservoir_samples; unsigned *align_reservoir_samples;
FLAC__bool replay_gain; FLAC__bool replay_gain;
FLAC__bool ignore_chunk_sizes;
FLAC__bool sector_align; FLAC__bool sector_align;
FLAC__StreamMetadata *vorbis_comment; FLAC__StreamMetadata *vorbis_comment;

View File

@@ -149,6 +149,7 @@ static struct share__option long_options_[] = {
{ "force-raw-format" , share__no_argument, 0, 0 }, { "force-raw-format" , share__no_argument, 0, 0 },
{ "lax" , share__no_argument, 0, 0 }, { "lax" , share__no_argument, 0, 0 },
{ "replay-gain" , share__no_argument, 0, 0 }, { "replay-gain" , share__no_argument, 0, 0 },
{ "ignore-chunk-sizes" , share__no_argument, 0, 0 },
{ "sector-align" , share__no_argument, 0, 0 }, { "sector-align" , share__no_argument, 0, 0 },
{ "seekpoint" , share__required_argument, 0, 'S' }, { "seekpoint" , share__required_argument, 0, 'S' },
{ "padding" , share__required_argument, 0, 'P' }, { "padding" , share__required_argument, 0, 'P' },
@@ -187,6 +188,7 @@ static struct share__option long_options_[] = {
{ "no-seektable" , share__no_argument, 0, 0 }, { "no-seektable" , share__no_argument, 0, 0 },
{ "no-delete-input-file" , share__no_argument, 0, 0 }, { "no-delete-input-file" , share__no_argument, 0, 0 },
{ "no-replay-gain" , share__no_argument, 0, 0 }, { "no-replay-gain" , share__no_argument, 0, 0 },
{ "no-ignore-chunk-sizes" , share__no_argument, 0, 0 },
{ "no-sector-align" , share__no_argument, 0, 0 }, { "no-sector-align" , share__no_argument, 0, 0 },
{ "no-lax" , share__no_argument, 0, 0 }, { "no-lax" , share__no_argument, 0, 0 },
#if FLAC__HAS_OGG #if FLAC__HAS_OGG
@@ -238,6 +240,7 @@ static struct {
FLAC__bool force_raw_format; FLAC__bool force_raw_format;
FLAC__bool delete_input; FLAC__bool delete_input;
FLAC__bool replay_gain; FLAC__bool replay_gain;
FLAC__bool ignore_chunk_sizes;
FLAC__bool sector_align; FLAC__bool sector_align;
const char *cmdline_forced_outfilename; const char *cmdline_forced_outfilename;
const char *output_prefix; const char *output_prefix;
@@ -385,6 +388,18 @@ int do_it(void)
return usage_error("ERROR: --sample-rate not allowed with --decode\n"); return usage_error("ERROR: --sample-rate not allowed with --decode\n");
} }
if(option_values.ignore_chunk_sizes) {
if(option_values.mode_decode)
return usage_error("ERROR: --ignore-chunk-sizes only allowed for encoding\n");
if(0 != option_values.sector_align)
return usage_error("ERROR: --ignore-chunk-sizes not allowed with --sector-align\n");
if(0 != option_values.until_specification)
return usage_error("ERROR: --ignore-chunk-sizes not allowed with --until\n");
if(0 != option_values.cue_specification)
return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cue\n");
if(0 != option_values.cuesheet_filename)
return usage_error("ERROR: --ignore-chunk-sizes not allowed with --cuesheet\n");
}
if(option_values.sector_align) { if(option_values.sector_align) {
if(option_values.mode_decode) if(option_values.mode_decode)
return usage_error("ERROR: --sector-align only allowed for encoding\n"); return usage_error("ERROR: --sector-align only allowed for encoding\n");
@@ -460,6 +475,9 @@ int do_it(void)
else { /* encode */ else { /* encode */
FLAC__bool first = true; FLAC__bool first = true;
if(option_values.ignore_chunk_sizes)
flac__utils_printf(stderr, 1, "INFO: Make sure you know what you're doing when using --ignore-chunk-sizes.\n Improper use can cause flac to encode non-audio data as audio.\n");
if(option_values.num_files == 0) { if(option_values.num_files == 0) {
retval = encode_file("-", first, true); retval = encode_file("-", first, true);
} }
@@ -525,6 +543,7 @@ FLAC__bool init_options(void)
option_values.force_raw_format = false; option_values.force_raw_format = false;
option_values.delete_input = false; option_values.delete_input = false;
option_values.replay_gain = false; option_values.replay_gain = false;
option_values.ignore_chunk_sizes = false;
option_values.sector_align = false; option_values.sector_align = false;
option_values.cmdline_forced_outfilename = 0; option_values.cmdline_forced_outfilename = 0;
option_values.output_prefix = 0; option_values.output_prefix = 0;
@@ -718,6 +737,9 @@ int parse_option(int short_option, const char *long_option, const char *option_a
else if(0 == strcmp(long_option, "replay-gain")) { else if(0 == strcmp(long_option, "replay-gain")) {
option_values.replay_gain = true; option_values.replay_gain = true;
} }
else if(0 == strcmp(long_option, "ignore-chunk-sizes")) {
option_values.ignore_chunk_sizes = true;
}
else if(0 == strcmp(long_option, "sector-align")) { else if(0 == strcmp(long_option, "sector-align")) {
option_values.sector_align = true; option_values.sector_align = true;
} }
@@ -788,6 +810,9 @@ int parse_option(int short_option, const char *long_option, const char *option_a
else if(0 == strcmp(long_option, "no-replay-gain")) { else if(0 == strcmp(long_option, "no-replay-gain")) {
option_values.replay_gain = false; option_values.replay_gain = false;
} }
else if(0 == strcmp(long_option, "no-ignore-chunk-sizes")) {
option_values.ignore_chunk_sizes = false;
}
else if(0 == strcmp(long_option, "no-sector-align")) { else if(0 == strcmp(long_option, "no-sector-align")) {
option_values.sector_align = false; option_values.sector_align = false;
} }
@@ -1158,6 +1183,9 @@ void show_help(void)
printf("encoding options:\n"); printf("encoding options:\n");
printf(" -V, --verify Verify a correct encoding\n"); printf(" -V, --verify Verify a correct encoding\n");
printf(" --lax Allow encoder to generate non-Subset files\n"); printf(" --lax Allow encoder to generate non-Subset files\n");
#if 0 /*@@@ currently undocumented */
printf(" --ignore-chunk-sizes Ignore data chunk sizes in WAVE/AIFF files\n");
#endif
printf(" --sector-align Align multiple files on sector boundaries\n"); printf(" --sector-align Align multiple files on sector boundaries\n");
printf(" --replay-gain Calculate ReplayGain & store in FLAC tags\n"); printf(" --replay-gain Calculate ReplayGain & store in FLAC tags\n");
printf(" --cuesheet=FILENAME Import cuesheet and store in CUESHEET block\n"); printf(" --cuesheet=FILENAME Import cuesheet and store in CUESHEET block\n");
@@ -1208,6 +1236,9 @@ void show_help(void)
printf(" --no-replay-gain\n"); printf(" --no-replay-gain\n");
printf(" --no-residual-gnuplot\n"); printf(" --no-residual-gnuplot\n");
printf(" --no-residual-text\n"); printf(" --no-residual-text\n");
#if 0 /*@@@ currently undocumented */
printf(" --no-ignore-chunk-sizes\n");
#endif
printf(" --no-sector-align\n"); printf(" --no-sector-align\n");
printf(" --no-seektable\n"); printf(" --no-seektable\n");
printf(" --no-silent\n"); printf(" --no-silent\n");
@@ -1330,6 +1361,11 @@ void show_explain(void)
printf(" output in parallel and comparing to the\n"); printf(" output in parallel and comparing to the\n");
printf(" original\n"); printf(" original\n");
printf(" --lax Allow encoder to generate non-Subset files\n"); printf(" --lax Allow encoder to generate non-Subset files\n");
#if 0 /*@@@ currently undocumented */
printf(" --ignore-chunk-sizes Ignore data chunk sizes in WAVE/AIFF files;\n");
printf(" useful when piping data from programs which\n");
printf(" generate bogus data chunk sizes.\n");
#endif
printf(" --sector-align Align encoding of multiple CD format WAVE files\n"); printf(" --sector-align Align encoding of multiple CD format WAVE files\n");
printf(" on sector boundaries.\n"); printf(" on sector boundaries.\n");
printf(" --replay-gain Calculate ReplayGain values and store them as\n"); printf(" --replay-gain Calculate ReplayGain values and store them as\n");
@@ -1515,6 +1551,9 @@ void show_explain(void)
printf(" --no-qlp-coeff-prec-search\n"); printf(" --no-qlp-coeff-prec-search\n");
printf(" --no-residual-gnuplot\n"); printf(" --no-residual-gnuplot\n");
printf(" --no-residual-text\n"); printf(" --no-residual-text\n");
#if 0 /*@@@ currently undocumented */
printf(" --no-ignore-chunk-sizes\n");
#endif
printf(" --no-sector-align\n"); printf(" --no-sector-align\n");
printf(" --no-seektable\n"); printf(" --no-seektable\n");
printf(" --no-silent\n"); printf(" --no-silent\n");
@@ -1729,6 +1768,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_
common_options.align_reservoir = align_reservoir; common_options.align_reservoir = align_reservoir;
common_options.align_reservoir_samples = &align_reservoir_samples; common_options.align_reservoir_samples = &align_reservoir_samples;
common_options.replay_gain = option_values.replay_gain; common_options.replay_gain = option_values.replay_gain;
common_options.ignore_chunk_sizes = option_values.ignore_chunk_sizes;
common_options.sector_align = option_values.sector_align; common_options.sector_align = option_values.sector_align;
common_options.vorbis_comment = option_values.vorbis_comment; common_options.vorbis_comment = option_values.vorbis_comment;
FLAC__ASSERT(sizeof(common_options.pictures) >= sizeof(option_values.pictures)); FLAC__ASSERT(sizeof(common_options.pictures) >= sizeof(option_values.pictures));