summaryrefslogtreecommitdiff
path: root/libavcodec/flacdec.c
diff options
context:
space:
mode:
authorCarl Eugen Hoyos <cehoyos@ag.or.at>2015-05-12 13:00:29 +0200
committerCarl Eugen Hoyos <cehoyos@ag.or.at>2015-05-17 02:08:58 +0200
commite609cfd697f8eed7325591f767585041719807d1 (patch)
treede8a4644b6f5192633100b191d58a10bdcba1327 /libavcodec/flacdec.c
parent38f5a266eed1160e87da8e832a0a07818d7673cb (diff)
lavc/flac: Fix encoding and decoding with high lpc.
Based on an analysis by trac user lvqcl. Fixes ticket #4421, reported by Chase Walker.
Diffstat (limited to 'libavcodec/flacdec.c')
-rw-r--r--libavcodec/flacdec.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index 00b4726875..36d2928137 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -35,6 +35,7 @@
#include "libavutil/avassert.h"
#include "libavutil/crc.h"
+#include "libavutil/opt.h"
#include "avcodec.h"
#include "internal.h"
#include "get_bits.h"
@@ -48,6 +49,7 @@
typedef struct FLACContext {
+ AVClass *class;
struct FLACStreaminfo flac_stream_info;
AVCodecContext *avctx; ///< parent AVCodecContext
@@ -61,6 +63,7 @@ typedef struct FLACContext {
int32_t *decoded[FLAC_MAX_CHANNELS]; ///< decoded samples
uint8_t *decoded_buffer;
unsigned int decoded_buffer_size;
+ int buggy_lpc; ///< use workaround for old lavc encoded files
FLACDSPContext dsp;
} FLACContext;
@@ -343,7 +346,13 @@ static int decode_subframe_lpc(FLACContext *s, int32_t *decoded, int pred_order,
if ((ret = decode_residuals(s, decoded, pred_order)) < 0)
return ret;
- s->dsp.lpc(decoded, coeffs, pred_order, qlevel, s->blocksize);
+ if ( ( s->buggy_lpc && s->flac_stream_info.bps <= 16)
+ || ( !s->buggy_lpc && bps <= 16
+ && bps + coeff_prec + av_log2(pred_order) <= 32)) {
+ s->dsp.lpc16(decoded, coeffs, pred_order, qlevel, s->blocksize);
+ } else {
+ s->dsp.lpc32(decoded, coeffs, pred_order, qlevel, s->blocksize);
+ }
return 0;
}
@@ -605,6 +614,18 @@ static av_cold int flac_decode_close(AVCodecContext *avctx)
return 0;
}
+static const AVOption options[] = {
+{ "use_buggy_lpc", "emulate old buggy lavc behavior", offsetof(FLACContext, buggy_lpc), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM },
+{ NULL },
+};
+
+static const AVClass flac_decoder_class = {
+ "FLAC decoder",
+ av_default_item_name,
+ options,
+ LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_flac_decoder = {
.name = "flac",
.long_name = NULL_IF_CONFIG_SMALL("FLAC (Free Lossless Audio Codec)"),
@@ -621,4 +642,5 @@ AVCodec ff_flac_decoder = {
AV_SAMPLE_FMT_S32,
AV_SAMPLE_FMT_S32P,
AV_SAMPLE_FMT_NONE },
+ .priv_class = &flac_decoder_class,
};