mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-08-12 13:23:48 +00:00
avcodec/ac3dec_fixed: fix dither at exponent 24
the fixed decoder discarded fractional coefficient data before the imdct, causing low-level coefficients to be truncated at large exponents. dithered bap 0 coefficients at exponent 24 were consequently quantized with a negative bias. keep ac-3 coefficients in q2, compensate during windowing, and round the affected dither symmetrically. keep the forced e-ac-3 path in q0. add a synthetic fate test covering the corrected output.
This commit is contained in:
+62
-7
@@ -390,6 +390,26 @@ typedef struct mant_groups {
|
||||
int b4;
|
||||
} mant_groups;
|
||||
|
||||
static av_always_inline int dequantize_coeff(int mantissa, int exponent,
|
||||
int coeff_bits)
|
||||
{
|
||||
#if USE_FIXED
|
||||
return (mantissa * (1 << coeff_bits)) >> exponent;
|
||||
#else
|
||||
return mantissa >> exponent;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_FIXED
|
||||
static av_always_inline int dequantize_dexp24_dither(int mantissa)
|
||||
{
|
||||
int scaled = mantissa * (1 << AC3_FIXED_COEFF_BITS);
|
||||
int round = 1 << (AC3_FIXED_EXPONENT_MAX - 1);
|
||||
|
||||
return (scaled + round - (scaled < 0)) >> AC3_FIXED_EXPONENT_MAX;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Decode the transform coefficients for a particular channel
|
||||
* reference: Section 7.3 Quantization and Decoding of Mantissas
|
||||
@@ -402,6 +422,11 @@ static void ac3_decode_transform_coeffs_ch(AC3DecodeContext *s, int ch_index, ma
|
||||
int8_t *exps = s->dexps[ch_index];
|
||||
int32_t *coeffs = s->fixed_coeffs[ch_index];
|
||||
int dither = (ch_index == CPL_CH) || s->dither_flag[ch_index];
|
||||
#if USE_FIXED
|
||||
int coeff_bits = fixed_coeff_bits(s);
|
||||
#else
|
||||
int coeff_bits = 0;
|
||||
#endif
|
||||
GetBitContext *gbc = &s->gbc;
|
||||
int freq;
|
||||
|
||||
@@ -411,10 +436,19 @@ static void ac3_decode_transform_coeffs_ch(AC3DecodeContext *s, int ch_index, ma
|
||||
switch (bap) {
|
||||
case 0:
|
||||
/* random noise with approximate range of -0.707 to 0.707 */
|
||||
if (dither)
|
||||
if (dither) {
|
||||
mantissa = (((av_lfg_get(&s->dith_state)>>8)*181)>>8) - 5931008;
|
||||
else
|
||||
#if USE_FIXED
|
||||
/* At dexp 24 the dither is below half a Q0 step. Keep two
|
||||
* fractional bits so it is not truncated to -1 or 0. */
|
||||
if (coeff_bits && exps[freq] == AC3_FIXED_EXPONENT_MAX) {
|
||||
coeffs[freq] = dequantize_dexp24_dither(mantissa);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
mantissa = 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (m->b1) {
|
||||
@@ -466,7 +500,7 @@ static void ac3_decode_transform_coeffs_ch(AC3DecodeContext *s, int ch_index, ma
|
||||
mantissa = (unsigned)get_sbits(gbc, ff_ac3_quantization_tab[bap]) << (24 - ff_ac3_quantization_tab[bap]);
|
||||
break;
|
||||
}
|
||||
coeffs[freq] = mantissa >> exps[freq];
|
||||
coeffs[freq] = dequantize_coeff(mantissa, exps[freq], coeff_bits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +534,8 @@ static inline void decode_transform_coeffs_ch(AC3DecodeContext *s, int blk,
|
||||
if (CONFIG_EAC3_DECODER && !blk)
|
||||
ff_eac3_decode_transform_coeffs_aht_ch(s, ch);
|
||||
for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) {
|
||||
s->fixed_coeffs[ch][bin] = s->pre_mantissa[ch][bin][blk] >> s->dexps[ch][bin];
|
||||
s->fixed_coeffs[ch][bin] = dequantize_coeff(
|
||||
s->pre_mantissa[ch][bin][blk], s->dexps[ch][bin], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -571,6 +606,9 @@ static void do_rematrixing(AC3DecodeContext *s)
|
||||
static inline void do_imdct(AC3DecodeContext *s, int channels, int offset)
|
||||
{
|
||||
int ch;
|
||||
#if USE_FIXED
|
||||
int window_bits = 8 + fixed_coeff_bits(s);
|
||||
#endif
|
||||
|
||||
for (ch = 1; ch <= channels; ch++) {
|
||||
if (s->block_switch[ch]) {
|
||||
@@ -581,7 +619,7 @@ static inline void do_imdct(AC3DecodeContext *s, int channels, int offset)
|
||||
s->tx_fn_128(s->tx_128, s->tmp_output, x, sizeof(INTFLOAT));
|
||||
#if USE_FIXED
|
||||
s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset],
|
||||
s->tmp_output, s->window, 128, 8);
|
||||
s->tmp_output, s->window, 128, window_bits);
|
||||
#else
|
||||
s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset],
|
||||
s->tmp_output, s->window, 128);
|
||||
@@ -593,7 +631,7 @@ static inline void do_imdct(AC3DecodeContext *s, int channels, int offset)
|
||||
s->tx_fn_256(s->tx_256, s->tmp_output, s->transform_coeffs[ch], sizeof(INTFLOAT));
|
||||
#if USE_FIXED
|
||||
s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1 + offset],
|
||||
s->tmp_output, s->window, 128, 8);
|
||||
s->tmp_output, s->window, 128, window_bits);
|
||||
#else
|
||||
s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1 + offset],
|
||||
s->tmp_output, s->window, 128);
|
||||
@@ -1287,7 +1325,11 @@ static int decode_audio_block(AC3DecodeContext *s, int blk, int offset)
|
||||
gain = s->dynamic_range[audio_channel];
|
||||
|
||||
#if USE_FIXED
|
||||
scale_coefs(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain, 256);
|
||||
if (fixed_coeff_bits(s))
|
||||
scale_coefs_q2(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain,
|
||||
256);
|
||||
else
|
||||
scale_coefs(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain, 256);
|
||||
#else
|
||||
if (s->target_level != 0)
|
||||
gain = gain * s->level_gain[audio_channel];
|
||||
@@ -1356,6 +1398,9 @@ static int ac3_decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
||||
AC3DecodeContext *s = avctx->priv_data;
|
||||
int blk, ch, err, offset, ret;
|
||||
int i;
|
||||
#if USE_FIXED
|
||||
int previous_coeff_bits;
|
||||
#endif
|
||||
int skip = 0, got_independent_frame = 0;
|
||||
const uint8_t *channel_map;
|
||||
uint8_t extended_channel_map[EAC3_MAX_CHANNELS];
|
||||
@@ -1390,6 +1435,9 @@ static int ac3_decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
||||
|
||||
buf = s->input_buffer;
|
||||
dependent_frame:
|
||||
#if USE_FIXED
|
||||
previous_coeff_bits = fixed_coeff_bits(s);
|
||||
#endif
|
||||
/* initialize the GetBitContext with the start of valid AC-3 Frame */
|
||||
if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0)
|
||||
return ret;
|
||||
@@ -1397,6 +1445,13 @@ dependent_frame:
|
||||
/* parse the syncinfo */
|
||||
err = parse_frame_header(s);
|
||||
|
||||
#if USE_FIXED
|
||||
/* Do not mix Q0 and Q2 overlap samples if a malformed or explicitly
|
||||
* forced stream switches between E-AC-3 and AC-3. */
|
||||
if (!err && previous_coeff_bits != fixed_coeff_bits(s))
|
||||
memset(s->delay, 0, sizeof(s->delay));
|
||||
#endif
|
||||
|
||||
if (err) {
|
||||
switch (err) {
|
||||
case AC3_PARSE_ERROR_SYNC:
|
||||
|
||||
@@ -55,6 +55,17 @@
|
||||
|
||||
#include "ac3dec.h"
|
||||
|
||||
/* Keep two fractional bits in fixed-point transform coefficients. */
|
||||
#define AC3_FIXED_COEFF_BITS 2
|
||||
#define AC3_FIXED_EXPONENT_MAX 24
|
||||
|
||||
static av_always_inline int fixed_coeff_bits(const AC3DecodeContext *s)
|
||||
{
|
||||
/* ac3_fixed normally decodes AC-3. Keep Q0 when it is explicitly forced
|
||||
* to decode E-AC-3, whose AHT coefficient bounds are different. */
|
||||
return s->eac3 ? 0 : AC3_FIXED_COEFF_BITS;
|
||||
}
|
||||
|
||||
static const int end_freq_inv_tab[8] =
|
||||
{
|
||||
50529027, 44278013, 39403370, 32292987, 27356480, 23729101, 20951060, 18755316
|
||||
@@ -124,6 +135,49 @@ static void scale_coefs (
|
||||
}
|
||||
}
|
||||
|
||||
static void scale_coefs_q2(int32_t *dst, const int32_t *src, int dynrng,
|
||||
int len)
|
||||
{
|
||||
int i, shift;
|
||||
int mul;
|
||||
|
||||
mul = (dynrng & 0x1f) + 0x20;
|
||||
shift = 4 - (sign_extend(dynrng, 9) >> 5);
|
||||
|
||||
/* AC-3 mantissas have magnitude at most 2^23, hence Q2 coefficients
|
||||
* have magnitude at most 2^25. Coupling uses MULH(coeff * 2^4, coord)
|
||||
* with coord < 2^31, so coupled coefficients are below 2^28.
|
||||
* Rematrixing can at most double them, keeping src below 2^29. */
|
||||
if (dynrng == 32) {
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = src[i] * 4;
|
||||
return;
|
||||
}
|
||||
|
||||
if (shift >= 4) {
|
||||
const int round = 1 << (shift - 1);
|
||||
const int unit = 1 << shift;
|
||||
|
||||
/* With shift >= 4, quotient * mul is below 2^25 * 63. Splitting
|
||||
* quotient and remainder therefore keeps both products in int32_t. */
|
||||
for (i = 0; i < len; i++) {
|
||||
int quotient = src[i] >> shift;
|
||||
int remainder = src[i] - quotient * unit;
|
||||
|
||||
dst[i] = quotient * mul + ((remainder * mul + round) >> shift);
|
||||
}
|
||||
} else if (shift > 0) {
|
||||
const int round = 1 << (shift - 1);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = av_clipl_int32(((int64_t)src[i] * mul + round) >> shift);
|
||||
} else {
|
||||
mul <<= -shift;
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = av_clipl_int32((int64_t)src[i] * mul);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downmix samples from original signal to stereo or mono (this is for 16-bit samples
|
||||
* and fixed point decoder - original (for 32-bit samples) is in ac3dsp.c).
|
||||
|
||||
+24
-1
@@ -102,11 +102,34 @@ fate-ac3-fixed-encode-3: tests/data/asynth-44100-6.wav
|
||||
fate-ac3-fixed-encode-3: SRC = $(TARGET_PATH)/tests/data/asynth-44100-6.wav
|
||||
fate-ac3-fixed-encode-3: CMD = framecrc -i $(SRC) -c:a ac3_fixed -flags2 +fixed_frame_size -ab 256k -af aresample,atrim=start_sample=0:end_sample=12096
|
||||
|
||||
# With coupling and rematrixing disabled, this produces bap=0, dexp=24 bins
|
||||
# whose dither affects the decoded output.
|
||||
tests/data/fate/ac3-fixed-dexp24.ac3: TAG = GEN
|
||||
tests/data/fate/ac3-fixed-dexp24.ac3: tests/data/asynth-44100-2.wav
|
||||
tests/data/fate/ac3-fixed-dexp24.ac3: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data/fate
|
||||
$(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \
|
||||
-hide_banner -loglevel error -nostdin \
|
||||
-i $(TARGET_PATH)/tests/data/asynth-44100-2.wav \
|
||||
-c:a ac3_fixed -b:a 192k \
|
||||
-channel_coupling 0 -stereo_rematrixing 0 -flags +bitexact \
|
||||
-frames:a 173 -f ac3 -y $(TARGET_PATH)/$@
|
||||
|
||||
FATE_AC3_FIXED_DEXP24-$(call ALLYES, FFMPEG WAV_DEMUXER ARESAMPLE_FILTER ATRIM_FILTER \
|
||||
AC3_FIXED_ENCODER FRAMECRC_MUXER \
|
||||
AC3_MUXER AC3_DEMUXER AC3_FIXED_DECODER \
|
||||
PCM_S16LE_DECODER PCM_S16LE_ENCODER \
|
||||
FILE_PROTOCOL) += fate-ac3-fixed-dexp24
|
||||
fate-ac3-fixed-dexp24: tests/data/fate/ac3-fixed-dexp24.ac3
|
||||
fate-ac3-fixed-dexp24: CMD = framecrc -auto_conversion_filters -c ac3_fixed \
|
||||
-i $(TARGET_PATH)/tests/data/fate/ac3-fixed-dexp24.ac3 \
|
||||
-af atrim=start_sample=264192
|
||||
|
||||
FATE_EAC3-$(call ALLYES, EAC3_DEMUXER EAC3_MUXER EAC3_CORE_BSF) += fate-eac3-core-bsf
|
||||
fate-eac3-core-bsf: CMD = md5pipe -i $(TARGET_SAMPLES)/eac3/the_great_wall_7.1.eac3 -c:a copy -bsf:a eac3_core -fflags +bitexact -f eac3
|
||||
fate-eac3-core-bsf: CMP = oneline
|
||||
fate-eac3-core-bsf: REF = b704bf851e99b7442e9bed368b60e6ca
|
||||
|
||||
FATE_SAMPLES_AVCONV += $(FATE_AC3-yes) $(FATE_EAC3-yes)
|
||||
FATE_FFMPEG += $(FATE_AC3_FIXED_DEXP24-yes)
|
||||
|
||||
fate-ac3: $(FATE_AC3-yes) $(FATE_EAC3-yes)
|
||||
fate-ac3: $(FATE_AC3-yes) $(FATE_EAC3-yes) $(FATE_AC3_FIXED_DEXP24-yes)
|
||||
@@ -0,0 +1,6 @@
|
||||
#tb 0: 1/44100
|
||||
#media_type 0: audio
|
||||
#codec_id 0: pcm_s16le
|
||||
#sample_rate 0: 44100
|
||||
#channel_layout_name 0: stereo
|
||||
0, 264134, 264134, 1536, 6144, 0xff5a9359
|
||||
Reference in New Issue
Block a user