mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
lavc/flac: Fix encoding and decoding with high lpc.
Based on an analysis by trac user lvqcl. Fixes ticket #4421, reported by Chase Walker.
This commit is contained in:
parent
38f5a266ee
commit
e609cfd697
@ -83,6 +83,23 @@ Loud sounds are fully compressed. Soft sounds are enhanced.
|
||||
|
||||
@end table
|
||||
|
||||
@section flac
|
||||
|
||||
FLAC audio decoder.
|
||||
|
||||
This decoder aims to implement the complete FLAC specification from Xiph.
|
||||
|
||||
@subsection FLAC Decoder options
|
||||
|
||||
@table @option
|
||||
|
||||
@item -use_buggy_lpc
|
||||
The lavc FLAC encoder used to produce buggy streams with high lpc values
|
||||
(like the default value). This option allows to decode such streams
|
||||
correctly by using lavc's old buggy lpc logic for decoding.
|
||||
|
||||
@end table
|
||||
|
||||
@section ffwavesynth
|
||||
|
||||
Internal wave synthetizer.
|
||||
|
@ -27,6 +27,6 @@ void ff_flac_lpc_16_arm(int32_t *samples, const int coeffs[32], int order,
|
||||
av_cold void ff_flacdsp_init_arm(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
|
||||
int bps)
|
||||
{
|
||||
if (CONFIG_FLAC_DECODER && bps <= 16)
|
||||
c->lpc = ff_flac_lpc_16_arm;
|
||||
if (CONFIG_FLAC_DECODER)
|
||||
c->lpc16 = ff_flac_lpc_16_arm;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -88,13 +88,10 @@ static void flac_lpc_32_c(int32_t *decoded, const int coeffs[32],
|
||||
av_cold void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int channels,
|
||||
int bps)
|
||||
{
|
||||
if (bps > 16) {
|
||||
c->lpc = flac_lpc_32_c;
|
||||
c->lpc_encode = flac_lpc_encode_c_32;
|
||||
} else {
|
||||
c->lpc = flac_lpc_16_c;
|
||||
c->lpc_encode = flac_lpc_encode_c_16;
|
||||
}
|
||||
c->lpc16 = flac_lpc_16_c;
|
||||
c->lpc32 = flac_lpc_32_c;
|
||||
c->lpc16_encode = flac_lpc_encode_c_16;
|
||||
c->lpc32_encode = flac_lpc_encode_c_32;
|
||||
|
||||
switch (fmt) {
|
||||
case AV_SAMPLE_FMT_S32:
|
||||
|
@ -25,10 +25,14 @@
|
||||
typedef struct FLACDSPContext {
|
||||
void (*decorrelate[4])(uint8_t **out, int32_t **in, int channels,
|
||||
int len, int shift);
|
||||
void (*lpc)(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
void (*lpc_encode)(int32_t *res, const int32_t *smp, int len, int order,
|
||||
const int32_t coefs[32], int shift);
|
||||
void (*lpc16)(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
void (*lpc32)(int32_t *samples, const int coeffs[32], int order,
|
||||
int qlevel, int len);
|
||||
void (*lpc16_encode)(int32_t *res, const int32_t *smp, int len, int order,
|
||||
const int32_t coefs[32], int shift);
|
||||
void (*lpc32_encode)(int32_t *res, const int32_t *smp, int len, int order,
|
||||
const int32_t coefs[32], int shift);
|
||||
} FLACDSPContext;
|
||||
|
||||
void ff_flacdsp_init(FLACDSPContext *c, enum AVSampleFormat fmt, int channels, int bps);
|
||||
|
@ -838,8 +838,13 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch)
|
||||
order = av_clip(order, min_order - 1, max_order - 1);
|
||||
if (order == last_order)
|
||||
continue;
|
||||
s->flac_dsp.lpc_encode(res, smp, n, order+1, coefs[order],
|
||||
shift[order]);
|
||||
if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(order) <= 32) {
|
||||
s->flac_dsp.lpc16_encode(res, smp, n, order+1, coefs[order],
|
||||
shift[order]);
|
||||
} else {
|
||||
s->flac_dsp.lpc32_encode(res, smp, n, order+1, coefs[order],
|
||||
shift[order]);
|
||||
}
|
||||
bits[i] = find_subframe_rice_params(s, sub, order+1);
|
||||
if (bits[i] < bits[opt_index]) {
|
||||
opt_index = i;
|
||||
@ -853,7 +858,11 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch)
|
||||
opt_order = 0;
|
||||
bits[0] = UINT32_MAX;
|
||||
for (i = min_order-1; i < max_order; i++) {
|
||||
s->flac_dsp.lpc_encode(res, smp, n, i+1, coefs[i], shift[i]);
|
||||
if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(i) <= 32) {
|
||||
s->flac_dsp.lpc16_encode(res, smp, n, i+1, coefs[i], shift[i]);
|
||||
} else {
|
||||
s->flac_dsp.lpc32_encode(res, smp, n, i+1, coefs[i], shift[i]);
|
||||
}
|
||||
bits[i] = find_subframe_rice_params(s, sub, i+1);
|
||||
if (bits[i] < bits[opt_order])
|
||||
opt_order = i;
|
||||
@ -871,7 +880,11 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch)
|
||||
for (i = last-step; i <= last+step; i += step) {
|
||||
if (i < min_order-1 || i >= max_order || bits[i] < UINT32_MAX)
|
||||
continue;
|
||||
s->flac_dsp.lpc_encode(res, smp, n, i+1, coefs[i], shift[i]);
|
||||
if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(i) <= 32) {
|
||||
s->flac_dsp.lpc32_encode(res, smp, n, i+1, coefs[i], shift[i]);
|
||||
} else {
|
||||
s->flac_dsp.lpc16_encode(res, smp, n, i+1, coefs[i], shift[i]);
|
||||
}
|
||||
bits[i] = find_subframe_rice_params(s, sub, i+1);
|
||||
if (bits[i] < bits[opt_order])
|
||||
opt_order = i;
|
||||
@ -886,7 +899,11 @@ static int encode_residual_ch(FlacEncodeContext *s, int ch)
|
||||
for (i = 0; i < sub->order; i++)
|
||||
sub->coefs[i] = coefs[sub->order-1][i];
|
||||
|
||||
s->flac_dsp.lpc_encode(res, smp, n, sub->order, sub->coefs, sub->shift);
|
||||
if (s->bps_code * 4 + s->options.lpc_coeff_precision + av_log2(opt_order) <= 32) {
|
||||
s->flac_dsp.lpc16_encode(res, smp, n, sub->order, sub->coefs, sub->shift);
|
||||
} else {
|
||||
s->flac_dsp.lpc32_encode(res, smp, n, sub->order, sub->coefs, sub->shift);
|
||||
}
|
||||
|
||||
find_subframe_rice_params(s, sub, sub->order);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 56
|
||||
#define LIBAVCODEC_VERSION_MINOR 39
|
||||
#define LIBAVCODEC_VERSION_MICRO 100
|
||||
#define LIBAVCODEC_VERSION_MICRO 101
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
LIBAVCODEC_VERSION_MINOR, \
|
||||
|
@ -85,8 +85,7 @@ av_cold void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int
|
||||
}
|
||||
}
|
||||
if (EXTERNAL_SSE4(cpu_flags)) {
|
||||
if (bps > 16)
|
||||
c->lpc = ff_flac_lpc_32_sse4;
|
||||
c->lpc32 = ff_flac_lpc_32_sse4;
|
||||
}
|
||||
if (EXTERNAL_AVX(cpu_flags)) {
|
||||
if (fmt == AV_SAMPLE_FMT_S16) {
|
||||
@ -102,15 +101,14 @@ av_cold void ff_flacdsp_init_x86(FLACDSPContext *c, enum AVSampleFormat fmt, int
|
||||
}
|
||||
}
|
||||
if (EXTERNAL_XOP(cpu_flags)) {
|
||||
if (bps > 16)
|
||||
c->lpc = ff_flac_lpc_32_xop;
|
||||
c->lpc32 = ff_flac_lpc_32_xop;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_FLAC_ENCODER
|
||||
if (EXTERNAL_SSE4(cpu_flags)) {
|
||||
if (CONFIG_GPL && bps == 16)
|
||||
c->lpc_encode = ff_flac_enc_lpc_16_sse4;
|
||||
if (CONFIG_GPL)
|
||||
c->lpc16_encode = ff_flac_enc_lpc_16_sse4;
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_YASM */
|
||||
|
Loading…
Reference in New Issue
Block a user