Commit 5967f498 authored by Josh Coalson's avatar Josh Coalson
Browse files

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

parent b28c46d2
......@@ -165,6 +165,7 @@
<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>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>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>
......
......@@ -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 */
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__bool pad= false;
......@@ -355,9 +355,15 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con
/* SSND chunk size */
if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
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;
data_bytes-= 8U; /* discount the offset and block size fields */
/* offset */
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 */
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) {
trim = total_samples_in_input - encoder_session.until;
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);
}
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(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
if(options.common.ignore_chunk_sizes) {
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);
}
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;
}
}
......@@ -588,7 +606,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con
EncoderSession encoder_session;
FLAC__bool is_unsigned_samples = false;
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];
FLAC__uint16 x, format; /* format is the wFormatTag word from the 'fmt ' chunk */
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" */
FLAC__uint64 total_samples_in_input, trim = 0;
FLAC__bool pad = false;
const size_t bytes_per_wide_sample = channels * (bps >> 3);
unsigned data_bytes;
/* data size */
if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename))
return EncoderSession_finish_error(&encoder_session);
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);
if(options.common.ignore_chunk_sizes) {
FLAC__ASSERT(!options.common.sector_align);
data_bytes = (unsigned)(-(int)bytes_per_wide_sample); /* max out data_bytes; we'll use EOF as signal to stop reading */
}
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;
bytes_per_wide_sample = channels * (bps >> 3);
/* *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);
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 */
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) {
trim = total_samples_in_input - encoder_session.until;
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);
}
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(encoder_session.treat_warnings_as_errors)
return EncoderSession_finish_error(&encoder_session);
if(options.common.ignore_chunk_sizes) {
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);
}
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;
}
}
......@@ -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));
#endif
FLAC__ASSERT(encoder_session->total_samples_to_encode > 0);
if(samples_written == encoder_session->total_samples_to_encode) {
flac__utils_printf(stderr, 2, "\r%s:%s wrote %u bytes, ratio=%0.3f",
encoder_session->inbasefilename,
......
......@@ -84,6 +84,7 @@ typedef struct {
FLAC__int32 **align_reservoir;
unsigned *align_reservoir_samples;
FLAC__bool replay_gain;
FLAC__bool ignore_chunk_sizes;
FLAC__bool sector_align;
FLAC__StreamMetadata *vorbis_comment;
......
......@@ -149,6 +149,7 @@ static struct share__option long_options_[] = {
{ "force-raw-format" , share__no_argument, 0, 0 },
{ "lax" , 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 },
{ "seekpoint" , share__required_argument, 0, 'S' },
{ "padding" , share__required_argument, 0, 'P' },
......@@ -187,6 +188,7 @@ static struct share__option long_options_[] = {
{ "no-seektable" , share__no_argument, 0, 0 },
{ "no-delete-input-file" , 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-lax" , share__no_argument, 0, 0 },
#if FLAC__HAS_OGG
......@@ -238,6 +240,7 @@ static struct {
FLAC__bool force_raw_format;
FLAC__bool delete_input;
FLAC__bool replay_gain;
FLAC__bool ignore_chunk_sizes;
FLAC__bool sector_align;
const char *cmdline_forced_outfilename;
const char *output_prefix;
......@@ -385,6 +388,18 @@ int do_it(void)
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.mode_decode)
return usage_error("ERROR: --sector-align only allowed for encoding\n");
......@@ -460,6 +475,9 @@ int do_it(void)
else { /* encode */
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) {
retval = encode_file("-", first, true);
}
......@@ -525,6 +543,7 @@ FLAC__bool init_options(void)
option_values.force_raw_format = false;
option_values.delete_input = false;
option_values.replay_gain = false;
option_values.ignore_chunk_sizes = false;
option_values.sector_align = false;
option_values.cmdline_forced_outfilename = 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")) {
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")) {
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")) {
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")) {
option_values.sector_align = false;
}
......@@ -1158,6 +1183,9 @@ void show_help(void)
printf("encoding options:\n");
printf(" -V, --verify Verify a correct encoding\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(" --replay-gain Calculate ReplayGain & store in FLAC tags\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-residual-gnuplot\n");
printf(" --no-residual-text\n");
#if 0 /*@@@ currently undocumented */
printf(" --no-ignore-chunk-sizes\n");
#endif
printf(" --no-sector-align\n");
printf(" --no-seektable\n");
printf(" --no-silent\n");
......@@ -1330,6 +1361,11 @@ void show_explain(void)
printf(" output in parallel and comparing to the\n");
printf(" original\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(" on sector boundaries.\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-residual-gnuplot\n");
printf(" --no-residual-text\n");
#if 0 /*@@@ currently undocumented */
printf(" --no-ignore-chunk-sizes\n");
#endif
printf(" --no-sector-align\n");
printf(" --no-seektable\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_samples = &align_reservoir_samples;
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.vorbis_comment = option_values.vorbis_comment;
FLAC__ASSERT(sizeof(common_options.pictures) >= sizeof(option_values.pictures));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment