diff --git a/src/flac/encode.c b/src/flac/encode.c index a9b907fa..85279f2a 100644 --- a/src/flac/encode.c +++ b/src/flac/encode.c @@ -2147,6 +2147,7 @@ FLAC__bool EncoderSession_init_encoder(EncoderSession *e, encode_options_t optio FLAC__stream_encoder_set_apodization(e->encoder, apodizations); FLAC__stream_encoder_set_total_samples_estimate(e->encoder, e->total_samples_to_encode); FLAC__stream_encoder_set_metadata(e->encoder, (num_metadata > 0)? metadata : 0, num_metadata); + FLAC__stream_encoder_set_limit_min_bitrate(e->encoder, options.limit_min_bitrate); FLAC__stream_encoder_disable_constant_subframes(e->encoder, options.debug.disable_constant_subframes); FLAC__stream_encoder_disable_fixed_subframes(e->encoder, options.debug.disable_fixed_subframes); diff --git a/src/flac/encode.h b/src/flac/encode.h index b98bef6b..c0f36296 100644 --- a/src/flac/encode.h +++ b/src/flac/encode.h @@ -85,6 +85,7 @@ typedef struct { FLAC__bool ignore_chunk_sizes; FLAC__bool sector_align; FLAC__bool error_on_compression_fail; + FLAC__bool limit_min_bitrate; FLAC__StreamMetadata *vorbis_comment; FLAC__StreamMetadata *pictures[64]; diff --git a/src/flac/main.c b/src/flac/main.c index 2946168f..360b2fdd 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -168,6 +168,7 @@ static struct share__option long_options_[] = { { "sign" , share__required_argument, 0, 0 }, { "input-size" , share__required_argument, 0, 0 }, { "error-on-compression-fail" , share__no_argument, 0, 0 }, + { "limit-min-bitrate" , share__no_argument, 0, 0 }, /* * analysis options @@ -268,6 +269,7 @@ static struct { FLAC__bool cued_seekpoints; FLAC__bool channel_map_none; /* --channel-map=none specified, eventually will expand to take actual channel map */ FLAC__bool error_on_compression_fail; + FLAC__bool limit_min_bitrate; uint32_t num_files; char **filenames; @@ -597,6 +599,7 @@ FLAC__bool init_options(void) option_values.cued_seekpoints = true; option_values.channel_map_none = false; option_values.error_on_compression_fail = false; + option_values.limit_min_bitrate = false; option_values.num_files = 0; option_values.filenames = 0; @@ -825,6 +828,9 @@ int parse_option(int short_option, const char *long_option, const char *option_a else if(0 == strcmp(long_option, "residual-text")) { option_values.aopts.do_residual_text = true; } + else if(0 == strcmp(long_option, "limit-min-bitrate")) { + option_values.limit_min_bitrate = true; + } /* * negatives */ @@ -1289,6 +1295,7 @@ void show_help(void) printf(" -p, --qlp-coeff-precision-search Exhaustively search LP coeff quantization\n"); printf(" -q, --qlp-coeff-precision=# Specify precision in bits\n"); printf(" -r, --rice-partition-order=[#,]# Set [min,]max residual partition order\n"); + printf(" --limit-min-bitrate Limit minimum bitrate (for streaming)\n"); printf("format options:\n"); printf(" --force-raw-format Treat input or output as raw samples\n"); printf(" --force-aiff-format Force decoding to AIFF format\n"); @@ -1618,6 +1625,11 @@ void show_explain(void) printf(" (# is 0 to 15 inclusive; min defaults to 0;\n"); printf(" the default is -r 0; above 4 does not\n"); printf(" usually help much)\n"); + printf(" --limit-min-bitrate Limit minimum bitrate by not allowing frames\n"); + printf(" consisting of only constant subframes. This\n"); + printf(" ensures a bitrate of at least 1 bit/sample,\n"); + printf(" for example 48kbit/s for 48kHz input. This is\n"); + printf(" mostly beneficial for internet streaming.\n"); printf("format options:\n"); printf(" --force-raw-format Force input (when encoding) or output (when\n"); printf(" decoding) to be treated as raw samples\n"); @@ -1926,6 +1938,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ encode_options.debug.disable_verbatim_subframes = option_values.debug.disable_verbatim_subframes; encode_options.debug.do_md5 = option_values.debug.do_md5; encode_options.error_on_compression_fail = option_values.error_on_compression_fail; + encode_options.limit_min_bitrate = option_values.limit_min_bitrate; /* if infilename and outfilename point to the same file, we need to write to a temporary file */ if(encode_infile != stdin && grabbag__file_are_same(infilename, outfilename)) { diff --git a/test/test_flac.sh b/test/test_flac.sh index 369d23b4..75e995d6 100755 --- a/test/test_flac.sh +++ b/test/test_flac.sh @@ -1249,6 +1249,25 @@ flac2flac input-SCVA.flac case04e "--no-padding -S 5x" # case 04f: on file with SEEKTABLE block and size-changing option specified, drop existing SEEKTABLE, new SEEKTABLE with default points #(already covered by case03c) +############################################################################ +# test limiting minimum bitrate +############################################################################ + +echo $ECHO_N "Testing --limit-min-bitrate" $ECHO_C + +run_flac -f -o out.flac --no-padding --no-seektable --limit-min-bitrate "$testdatadir/input-VA.flac" +size=$(wc -c < out.flac) + +if [ "$size" -lt "1022" ]; then + die "ERROR: filesize of flac file encoded with --limit-min-bitrate is smaller than expected" +fi + +echo OK + +############################################################################ +# test overflow of total samples field in STREAMINFO +############################################################################ + test_total_samples_overflow () { total_samples=$1 @@ -1271,7 +1290,6 @@ if [ "$FLAC__TEST_LEVEL" -gt 1 ] ; then test_total_samples_overflow 68719476737 0 fi - rm -f out.flac out.meta out1.meta #@@@ when metaflac handles ogg flac, duplicate flac2flac tests here