From 681010d90e9e9f016718431dc74af610aba33bcb Mon Sep 17 00:00:00 2001 From: Martijn van Beurden Date: Wed, 1 Dec 2021 21:34:42 +0100 Subject: [PATCH 1/2] Add API functions to limit minimum bitrate Quite a lot of decoders have trouble streaming or seeking in a file with frames that only consist of constant subframes because of the large difference between the largest and smallest subframe. To remedy this, this commit makes it possible to disable the use of constant subframes for the last subframe in case all others are constant with a new API function. This means the minimum bitrate for a FLAC file encoded with this function used is raised to 1bit/sample (i.e. 48kbit/s for 48kHz material). This commit also adds tests to the test suite --- include/FLAC++/encoder.h | 2 ++ include/FLAC/stream_encoder.h | 28 +++++++++++++++++ src/libFLAC++/stream_encoder.cpp | 12 +++++++ src/libFLAC/fixed.c | 18 ++++++----- src/libFLAC/fixed_intrin_sse2.c | 20 ++++++------ src/libFLAC/fixed_intrin_ssse3.c | 20 ++++++------ .../include/protected/stream_encoder.h | 1 + src/libFLAC/stream_encoder.c | 31 ++++++++++++++++++- src/test_libFLAC++/encoders.cpp | 12 +++++++ src/test_libFLAC/encoders.c | 11 +++++++ 10 files changed, 126 insertions(+), 29 deletions(-) diff --git a/include/FLAC++/encoder.h b/include/FLAC++/encoder.h index ce8d80a463..83ea4c2d06 100644 --- a/include/FLAC++/encoder.h +++ b/include/FLAC++/encoder.h @@ -147,6 +147,7 @@ namespace FLAC { virtual bool set_total_samples_estimate(FLAC__uint64 value); ///< See FLAC__stream_encoder_set_total_samples_estimate() virtual bool set_metadata(::FLAC__StreamMetadata **metadata, uint32_t num_blocks); ///< See FLAC__stream_encoder_set_metadata() virtual bool set_metadata(FLAC::Metadata::Prototype **metadata, uint32_t num_blocks); ///< See FLAC__stream_encoder_set_metadata() + virtual bool set_limit_min_bitrate(bool value); ///< See FLAC__stream_encoder_set_limit_min_bitrate() /* get_state() is not virtual since we want subclasses to be able to return their own state */ State get_state() const; ///< See FLAC__stream_encoder_get_state() @@ -169,6 +170,7 @@ namespace FLAC { virtual uint32_t get_max_residual_partition_order() const; ///< See FLAC__stream_encoder_get_max_residual_partition_order() virtual uint32_t get_rice_parameter_search_dist() const; ///< See FLAC__stream_encoder_get_rice_parameter_search_dist() virtual FLAC__uint64 get_total_samples_estimate() const; ///< See FLAC__stream_encoder_get_total_samples_estimate() + virtual bool get_limit_min_bitrate() const; ///< See FLAC__stream_encoder_get_limit_min_bitrate() virtual ::FLAC__StreamEncoderInitStatus init(); ///< See FLAC__stream_encoder_init_stream() virtual ::FLAC__StreamEncoderInitStatus init_ogg(); ///< See FLAC__stream_encoder_init_ogg_stream() diff --git a/include/FLAC/stream_encoder.h b/include/FLAC/stream_encoder.h index 0c611d0420..03c116aa5f 100644 --- a/include/FLAC/stream_encoder.h +++ b/include/FLAC/stream_encoder.h @@ -1198,6 +1198,24 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_total_samples_estimate(FLAC__Stream */ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, uint32_t num_blocks); +/** Set to \c true to make the encoder not output frames which contain + * only constant subframes. This is beneficial for streaming + * applications: very small frames can cause problems with buffering + * as bitrates can drop as low 1kbit/s for CDDA audio encoded within + * subset. The minimum bitrate for a FLAC file encoded with this + * function used is raised to 1bit/sample (i.e. 48kbit/s for 48kHz + * material). + * + * \default \c false + * \param encoder An encoder instance to set. + * \param value Flag value (see above). + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * \c false if the encoder is already initialized, else \c true. + */ +FLAC_API FLAC__bool FLAC__stream_encoder_set_limit_min_bitrate(FLAC__StreamEncoder *encoder, FLAC__bool value); + /** Get the current encoder state. * * \param encoder An encoder instance to query. @@ -1425,6 +1443,16 @@ FLAC_API uint32_t FLAC__stream_encoder_get_rice_parameter_search_dist(const FLAC */ FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC__StreamEncoder *encoder); +/** Get the "limit_min_bitrate" flag. + * + * \param encoder An encoder instance to query. + * \assert + * \code encoder != NULL \endcode + * \retval FLAC__bool + * See FLAC__stream_encoder_set_limit_min_bitrate(). + */ +FLAC_API FLAC__bool FLAC__stream_encoder_get_limit_min_bitrate(const FLAC__StreamEncoder *encoder); + /** Initialize the encoder instance to encode native FLAC streams. * * This flavor of initialization sets up the encoder to encode to a diff --git a/src/libFLAC++/stream_encoder.cpp b/src/libFLAC++/stream_encoder.cpp index 8230f6095b..e4ae2d6a13 100644 --- a/src/libFLAC++/stream_encoder.cpp +++ b/src/libFLAC++/stream_encoder.cpp @@ -211,6 +211,12 @@ namespace FLAC { return ok; } + bool Stream::set_limit_min_bitrate(bool value) + { + FLAC__ASSERT(is_valid()); + return static_cast(::FLAC__stream_encoder_set_limit_min_bitrate(encoder_, value)); + } + Stream::State Stream::get_state() const { FLAC__ASSERT(is_valid()); @@ -331,6 +337,12 @@ namespace FLAC { return ::FLAC__stream_encoder_get_total_samples_estimate(encoder_); } + bool Stream::get_limit_min_bitrate() const + { + FLAC__ASSERT(is_valid()); + return static_cast(::FLAC__stream_encoder_get_limit_min_bitrate(encoder_)); + } + ::FLAC__StreamEncoderInitStatus Stream::init() { FLAC__ASSERT(is_valid()); diff --git a/src/libFLAC/fixed.c b/src/libFLAC/fixed.c index 166bedd722..f6dc9ac788 100644 --- a/src/libFLAC/fixed.c +++ b/src/libFLAC/fixed.c @@ -235,13 +235,14 @@ uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t d error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; } - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; @@ -297,13 +298,14 @@ uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint3 error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save; } - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; diff --git a/src/libFLAC/fixed_intrin_sse2.c b/src/libFLAC/fixed_intrin_sse2.c index 9a88dcc3b6..fd74b5edf9 100644 --- a/src/libFLAC/fixed_intrin_sse2.c +++ b/src/libFLAC/fixed_intrin_sse2.c @@ -158,14 +158,14 @@ uint32_t FLAC__fixed_compute_best_predictor_intrin_sse2(const FLAC__int32 data[] } } - /* prefer higher order */ - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; @@ -309,14 +309,14 @@ uint32_t FLAC__fixed_compute_best_predictor_wide_intrin_sse2(const FLAC__int32 d } } - /* prefer higher order */ - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; diff --git a/src/libFLAC/fixed_intrin_ssse3.c b/src/libFLAC/fixed_intrin_ssse3.c index 056ef5aaa0..6fad35ca23 100644 --- a/src/libFLAC/fixed_intrin_ssse3.c +++ b/src/libFLAC/fixed_intrin_ssse3.c @@ -143,14 +143,14 @@ uint32_t FLAC__fixed_compute_best_predictor_intrin_ssse3(const FLAC__int32 data[ } } - /* prefer higher order */ - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; @@ -282,14 +282,14 @@ uint32_t FLAC__fixed_compute_best_predictor_wide_intrin_ssse3(const FLAC__int32 } } - /* prefer higher order */ - if(total_error_0 < flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) + /* prefer lower order */ + if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4)) order = 0; - else if(total_error_1 < flac_min(flac_min(total_error_2, total_error_3), total_error_4)) + else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4)) order = 1; - else if(total_error_2 < flac_min(total_error_3, total_error_4)) + else if(total_error_2 <= flac_min(total_error_3, total_error_4)) order = 2; - else if(total_error_3 < total_error_4) + else if(total_error_3 <= total_error_4) order = 3; else order = 4; diff --git a/src/libFLAC/include/protected/stream_encoder.h b/src/libFLAC/include/protected/stream_encoder.h index c290904e72..d422498b02 100644 --- a/src/libFLAC/include/protected/stream_encoder.h +++ b/src/libFLAC/include/protected/stream_encoder.h @@ -107,6 +107,7 @@ typedef struct FLAC__StreamEncoderProtected { uint32_t max_residual_partition_order; uint32_t rice_parameter_search_dist; FLAC__uint64 total_samples_estimate; + FLAC__bool limit_min_bitrate; FLAC__StreamMetadata **metadata; uint32_t num_metadata_blocks; FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset; diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c index 85130659b8..be3b4506f6 100644 --- a/src/libFLAC/stream_encoder.c +++ b/src/libFLAC/stream_encoder.c @@ -1905,6 +1905,17 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_metadata(FLAC__StreamEncoder *encod return true; } +FLAC_API FLAC__bool FLAC__stream_encoder_set_limit_min_bitrate(FLAC__StreamEncoder *encoder, FLAC__bool value) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED) + return false; + encoder->protected_->limit_min_bitrate = value; + return true; +} + /* * These three functions are not static, but not publicly exposed in * include/FLAC/ either. They are used by the test suite. @@ -2135,6 +2146,14 @@ FLAC_API FLAC__uint64 FLAC__stream_encoder_get_total_samples_estimate(const FLAC return encoder->protected_->total_samples_estimate; } +FLAC_API FLAC__bool FLAC__stream_encoder_get_limit_min_bitrate(const FLAC__StreamEncoder *encoder) +{ + FLAC__ASSERT(0 != encoder); + FLAC__ASSERT(0 != encoder->private_); + FLAC__ASSERT(0 != encoder->protected_); + return encoder->protected_->limit_min_bitrate; +} + FLAC_API FLAC__bool FLAC__stream_encoder_process(FLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], uint32_t samples) { uint32_t i, j = 0, k = 0, channel; @@ -2330,6 +2349,7 @@ void set_defaults_(FLAC__StreamEncoder *encoder) encoder->protected_->max_residual_partition_order = 0; encoder->protected_->rice_parameter_search_dist = 0; encoder->protected_->total_samples_estimate = 0; + encoder->protected_->limit_min_bitrate = false; encoder->protected_->metadata = 0; encoder->protected_->num_metadata_blocks = 0; @@ -3127,7 +3147,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder) { FLAC__FrameHeader frame_header; uint32_t channel, min_partition_order = encoder->protected_->min_residual_partition_order, max_partition_order; - FLAC__bool do_independent, do_mid_side; + FLAC__bool do_independent, do_mid_side, backup_disable_constant_subframes = encoder->private_->disable_constant_subframes, all_subframes_constant = true; /* * Calculate the min,max Rice partition orders @@ -3204,6 +3224,12 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder) */ if(do_independent) { for(channel = 0; channel < encoder->protected_->channels; channel++) { + if(encoder->protected_->limit_min_bitrate && all_subframes_constant && (channel + 1) == encoder->protected_->channels){ + /* This frame contains only constant subframes at this point. + * To prevent the frame from becoming too small, make sure + * the last subframe isn't constant */ + encoder->private_->disable_constant_subframes = true; + } if(! process_subframe_( encoder, @@ -3220,6 +3246,8 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder) ) ) return false; + if(encoder->private_->subframe_workspace[channel][encoder->private_->best_subframe[channel]].type != FLAC__SUBFRAME_TYPE_CONSTANT) + all_subframes_constant = false; } } @@ -3365,6 +3393,7 @@ FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder) } encoder->private_->last_channel_assignment = frame_header.channel_assignment; + encoder->private_->disable_constant_subframes = backup_disable_constant_subframes; return true; } diff --git a/src/test_libFLAC++/encoders.cpp b/src/test_libFLAC++/encoders.cpp index 306e323224..694215aca5 100644 --- a/src/test_libFLAC++/encoders.cpp +++ b/src/test_libFLAC++/encoders.cpp @@ -322,6 +322,11 @@ static bool test_stream_encoder(Layer layer, bool is_ogg) return die_s_("returned false", encoder); printf("OK\n"); + printf("testing set_limit_min_bitrate()... "); + if(!encoder->set_limit_min_bitrate(true)) + return die_s_("returned false", encoder); + printf("OK\n"); + if(layer < LAYER_FILENAME) { printf("opening file for FLAC output... "); file = ::flac_fopen(flacfilename(is_ogg), "w+b"); @@ -497,6 +502,13 @@ static bool test_stream_encoder(Layer layer, bool is_ogg) return false; } printf("OK\n"); + + printf("testing get_limit_min_bitrate()... "); + if(encoder->get_limit_min_bitrate() != true) { + printf("FAILED, expected true, got false\n"); + return false; + } + printf("OK\n"); /* init the dummy sample buffer */ for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++) diff --git a/src/test_libFLAC/encoders.c b/src/test_libFLAC/encoders.c index 7aefe79b10..6eaaa67c6e 100644 --- a/src/test_libFLAC/encoders.c +++ b/src/test_libFLAC/encoders.c @@ -275,6 +275,11 @@ static FLAC__bool test_stream_encoder(Layer layer, FLAC__bool is_ogg) return die_s_("returned false", encoder); printf("OK\n"); + printf("testing FLAC__stream_encoder_set_limit_min_bitrate()... "); + if(!FLAC__stream_encoder_set_limit_min_bitrate(encoder, true)) + return die_s_("returned false", encoder); + printf("OK\n"); + if(layer < LAYER_FILENAME) { printf("opening file for FLAC output... "); file = flac_fopen(flacfilename(is_ogg), "w+b"); @@ -455,6 +460,12 @@ static FLAC__bool test_stream_encoder(Layer layer, FLAC__bool is_ogg) return false; } printf("OK\n"); + + printf("testing FLAC__stream_encoder_get_limit_min_bitrate()... "); + if(FLAC__stream_encoder_get_limit_min_bitrate(encoder) != true) { + printf("FAILED, expected true, got false\n"); + return false; + } /* init the dummy sample buffer */ for(i = 0; i < sizeof(samples) / sizeof(FLAC__int32); i++) From 874606979b4a26e5deeea9702a4ebe69601f4438 Mon Sep 17 00:00:00 2001 From: Martijn van Beurden Date: Tue, 11 Jan 2022 09:16:12 +0100 Subject: [PATCH 2/2] Add --limit-min-bitrate to flac and add test for it --- src/flac/encode.c | 1 + src/flac/encode.h | 1 + src/flac/main.c | 13 +++++++++++++ test/test_flac.sh | 20 +++++++++++++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/flac/encode.c b/src/flac/encode.c index a9b907fa67..85279f2a39 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 b98bef6b2d..c0f36296be 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 2946168f47..360b2fdd8f 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 369d23b48b..75e995d66a 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