mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
libavcodec: Implementation of AC3 fixedpoint decoder
Signed-off-by: Nedeljko Babic <nbabic@mips.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
d506deaeaa
commit
696e34a6e1
@ -2,6 +2,7 @@ Entries are sorted chronologically from oldest to youngest within each release,
|
||||
releases are sorted from youngest to oldest.
|
||||
|
||||
version <next>:
|
||||
- added AC3 fixed-point decoding
|
||||
- shuffleplanes filter
|
||||
- subfile protocol
|
||||
- Phantom Cine demuxer
|
||||
|
1
configure
vendored
1
configure
vendored
@ -1951,6 +1951,7 @@ aac_decoder_select="mdct sinewin"
|
||||
aac_encoder_select="audio_frame_queue mdct sinewin"
|
||||
aac_latm_decoder_select="aac_decoder aac_latm_parser"
|
||||
ac3_decoder_select="mdct ac3dsp ac3_parser dsputil"
|
||||
ac3_fixed_decoder_select="mdct ac3dsp ac3_parser dsputil"
|
||||
ac3_encoder_select="mdct ac3dsp dsputil"
|
||||
ac3_fixed_encoder_select="mdct ac3dsp dsputil"
|
||||
aic_decoder_select="dsputil golomb"
|
||||
|
@ -820,7 +820,7 @@ following image formats are supported:
|
||||
@tab encoding supported through external library libaacplus
|
||||
@item AAC @tab E @tab X
|
||||
@tab encoding supported through external library libfaac and libvo-aacenc
|
||||
@item AC-3 @tab IX @tab X
|
||||
@item AC-3 @tab IX @tab IX
|
||||
@item ADPCM 4X Movie @tab @tab X
|
||||
@item ADPCM CDROM XA @tab @tab X
|
||||
@item ADPCM Creative Technology @tab @tab X
|
||||
|
@ -94,7 +94,8 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o \
|
||||
psymodel.o iirfilter.o \
|
||||
mpeg4audio.o kbdwin.o
|
||||
OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o
|
||||
OBJS-$(CONFIG_AC3_DECODER) += ac3dec.o ac3dec_data.o ac3.o kbdwin.o
|
||||
OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o
|
||||
OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o
|
||||
OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \
|
||||
ac3.o kbdwin.o
|
||||
OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o
|
||||
|
@ -51,6 +51,52 @@
|
||||
#define EXP_D25 2
|
||||
#define EXP_D45 3
|
||||
|
||||
#ifndef CONFIG_AC3_FIXED
|
||||
#define CONFIG_AC3_FIXED 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_AC3_FIXED
|
||||
|
||||
#define FFT_FLOAT 0
|
||||
|
||||
#define FIXR(a) ((int)((a) * 0 + 0.5))
|
||||
#define FIXR12(a) ((int)((a) * 4096 + 0.5))
|
||||
#define FIXR15(a) ((int)((a) * 32768 + 0.5))
|
||||
#define ROUND15(x) ((x) + 16384) >> 15
|
||||
|
||||
#define AC3_RENAME(x) x ## _fixed
|
||||
#define AC3_NORM(norm) (1<<24)/(norm)
|
||||
#define AC3_MUL(a,b) ((((int64_t) (a)) * (b))>>12)
|
||||
#define AC3_RANGE(x) (x)
|
||||
#define AC3_DYNAMIC_RANGE(x) (x)
|
||||
#define AC3_SPX_BLEND(x) (x)
|
||||
#define AC3_DYNAMIC_RANGE1 0
|
||||
|
||||
#define INTFLOAT int
|
||||
#define SHORTFLOAT int16_t
|
||||
|
||||
#else /* CONFIG_AC3_FIXED */
|
||||
|
||||
#define FIXR(x) ((float)(x))
|
||||
#define FIXR12(x) ((float)(x))
|
||||
#define FIXR15(x) ((float)(x))
|
||||
#define ROUND15(x) (x)
|
||||
|
||||
#define AC3_RENAME(x) x
|
||||
#define AC3_NORM(norm) (1.0f/(norm))
|
||||
#define AC3_MUL(a,b) ((a) * (b))
|
||||
#define AC3_RANGE(x) (dynamic_range_tab[(x)])
|
||||
#define AC3_DYNAMIC_RANGE(x) (powf(x, s->drc_scale))
|
||||
#define AC3_SPX_BLEND(x) (x)* (1.0f/32)
|
||||
#define AC3_DYNAMIC_RANGE1 1.0f
|
||||
|
||||
#define INTFLOAT float
|
||||
#define SHORTFLOAT float
|
||||
|
||||
#endif /* CONFIG_AC3_FIXED */
|
||||
|
||||
#define AC3_LEVEL(x) ROUND15((x) * FIXR15(0.7071067811865476))
|
||||
|
||||
/* pre-defined gain values */
|
||||
#define LEVEL_PLUS_3DB 1.4142135623730950
|
||||
#define LEVEL_PLUS_1POINT5DB 1.1892071150027209
|
||||
|
@ -179,14 +179,23 @@ static av_cold int ac3_decode_init(AVCodecContext *avctx)
|
||||
ac3_tables_init();
|
||||
ff_mdct_init(&s->imdct_256, 8, 1, 1.0);
|
||||
ff_mdct_init(&s->imdct_512, 9, 1, 1.0);
|
||||
ff_kbd_window_init(s->window, 5.0, 256);
|
||||
AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256);
|
||||
ff_dsputil_init(&s->dsp, avctx);
|
||||
|
||||
#if (CONFIG_AC3_FIXED)
|
||||
s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & CODEC_FLAG_BITEXACT);
|
||||
#else
|
||||
avpriv_float_dsp_init(&s->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
|
||||
#endif
|
||||
|
||||
ff_ac3dsp_init(&s->ac3dsp, avctx->flags & CODEC_FLAG_BITEXACT);
|
||||
ff_fmt_convert_init(&s->fmt_conv, avctx);
|
||||
av_lfg_init(&s->dith_state, 0);
|
||||
|
||||
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||
if (CONFIG_AC3_FIXED)
|
||||
avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
|
||||
else
|
||||
avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
||||
|
||||
/* allow downmixing to stereo or mono */
|
||||
#if FF_API_REQUEST_CHANNELS
|
||||
@ -345,40 +354,45 @@ static void set_downmix_coeffs(AC3DecodeContext *s)
|
||||
float cmix = gain_levels[s-> center_mix_level];
|
||||
float smix = gain_levels[s->surround_mix_level];
|
||||
float norm0, norm1;
|
||||
float downmix_coeffs[AC3_MAX_CHANNELS][2];
|
||||
|
||||
for (i = 0; i < s->fbw_channels; i++) {
|
||||
s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]];
|
||||
s->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]];
|
||||
downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]];
|
||||
downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]];
|
||||
}
|
||||
if (s->channel_mode > 1 && s->channel_mode & 1) {
|
||||
s->downmix_coeffs[1][0] = s->downmix_coeffs[1][1] = cmix;
|
||||
downmix_coeffs[1][0] = downmix_coeffs[1][1] = cmix;
|
||||
}
|
||||
if (s->channel_mode == AC3_CHMODE_2F1R || s->channel_mode == AC3_CHMODE_3F1R) {
|
||||
int nf = s->channel_mode - 2;
|
||||
s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB;
|
||||
downmix_coeffs[nf][0] = downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB;
|
||||
}
|
||||
if (s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) {
|
||||
int nf = s->channel_mode - 4;
|
||||
s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix;
|
||||
downmix_coeffs[nf][0] = downmix_coeffs[nf+1][1] = smix;
|
||||
}
|
||||
|
||||
/* renormalize */
|
||||
norm0 = norm1 = 0.0;
|
||||
for (i = 0; i < s->fbw_channels; i++) {
|
||||
norm0 += s->downmix_coeffs[i][0];
|
||||
norm1 += s->downmix_coeffs[i][1];
|
||||
norm0 += downmix_coeffs[i][0];
|
||||
norm1 += downmix_coeffs[i][1];
|
||||
}
|
||||
norm0 = 1.0f / norm0;
|
||||
norm1 = 1.0f / norm1;
|
||||
for (i = 0; i < s->fbw_channels; i++) {
|
||||
s->downmix_coeffs[i][0] *= norm0;
|
||||
s->downmix_coeffs[i][1] *= norm1;
|
||||
downmix_coeffs[i][0] *= norm0;
|
||||
downmix_coeffs[i][1] *= norm1;
|
||||
}
|
||||
|
||||
if (s->output_mode == AC3_CHMODE_MONO) {
|
||||
for (i = 0; i < s->fbw_channels; i++)
|
||||
s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] +
|
||||
s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB;
|
||||
downmix_coeffs[i][0] = (downmix_coeffs[i][0] +
|
||||
downmix_coeffs[i][1]) * LEVEL_MINUS_3DB;
|
||||
}
|
||||
for (i = 0; i < s->fbw_channels; i++) {
|
||||
s->downmix_coeffs[i][0] = FIXR12(downmix_coeffs[i][0]);
|
||||
s->downmix_coeffs[i][1] = FIXR12(downmix_coeffs[i][1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -646,20 +660,30 @@ static inline void do_imdct(AC3DecodeContext *s, int channels)
|
||||
for (ch = 1; ch <= channels; ch++) {
|
||||
if (s->block_switch[ch]) {
|
||||
int i;
|
||||
float *x = s->tmp_output + 128;
|
||||
FFTSample *x = s->tmp_output + 128;
|
||||
for (i = 0; i < 128; i++)
|
||||
x[i] = s->transform_coeffs[ch][2 * i];
|
||||
s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x);
|
||||
#if CONFIG_AC3_FIXED
|
||||
s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
|
||||
s->tmp_output, s->window, 128, 8);
|
||||
#else
|
||||
s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
|
||||
s->tmp_output, s->window, 128);
|
||||
#endif
|
||||
for (i = 0; i < 128; i++)
|
||||
x[i] = s->transform_coeffs[ch][2 * i + 1];
|
||||
s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x);
|
||||
} else {
|
||||
s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]);
|
||||
#if CONFIG_AC3_FIXED
|
||||
s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
|
||||
s->tmp_output, s->window, 128, 8);
|
||||
#else
|
||||
s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
|
||||
s->tmp_output, s->window, 128);
|
||||
memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(float));
|
||||
#endif
|
||||
memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -794,13 +818,13 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
if (get_bits1(gbc)) {
|
||||
/* Allow asymmetric application of DRC when drc_scale > 1.
|
||||
Amplification of quiet sounds is enhanced */
|
||||
float range = dynamic_range_tab[get_bits(gbc, 8)];
|
||||
INTFLOAT range = AC3_RANGE(get_bits(gbc, 8));
|
||||
if (range > 1.0 || s->drc_scale <= 1.0)
|
||||
s->dynamic_range[i] = powf(range, s->drc_scale);
|
||||
s->dynamic_range[i] = AC3_DYNAMIC_RANGE(range);
|
||||
else
|
||||
s->dynamic_range[i] = range;
|
||||
} else if (blk == 0) {
|
||||
s->dynamic_range[i] = 1.0f;
|
||||
s->dynamic_range[i] = AC3_DYNAMIC_RANGE1;
|
||||
}
|
||||
} while (i--);
|
||||
|
||||
@ -826,6 +850,9 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
if (start_subband > 7)
|
||||
start_subband += start_subband - 7;
|
||||
end_subband = get_bits(gbc, 3) + 5;
|
||||
#if CONFIG_AC3_FIXED
|
||||
s->spx_dst_end_freq = end_freq_inv_tab[end_subband];
|
||||
#endif
|
||||
if (end_subband > 7)
|
||||
end_subband += end_subband - 7;
|
||||
dst_start_freq = dst_start_freq * 12 + 25;
|
||||
@ -846,7 +873,9 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
|
||||
s->spx_dst_start_freq = dst_start_freq;
|
||||
s->spx_src_start_freq = src_start_freq;
|
||||
#if !CONFIG_AC3_FIXED
|
||||
s->spx_dst_end_freq = dst_end_freq;
|
||||
#endif
|
||||
|
||||
decode_band_structure(gbc, blk, s->eac3, 0,
|
||||
start_subband, end_subband,
|
||||
@ -866,18 +895,40 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
for (ch = 1; ch <= fbw_channels; ch++) {
|
||||
if (s->channel_uses_spx[ch]) {
|
||||
if (s->first_spx_coords[ch] || get_bits1(gbc)) {
|
||||
float spx_blend;
|
||||
INTFLOAT spx_blend;
|
||||
int bin, master_spx_coord;
|
||||
|
||||
s->first_spx_coords[ch] = 0;
|
||||
spx_blend = get_bits(gbc, 5) * (1.0f/32);
|
||||
spx_blend = AC3_SPX_BLEND(get_bits(gbc, 5));
|
||||
master_spx_coord = get_bits(gbc, 2) * 3;
|
||||
|
||||
bin = s->spx_src_start_freq;
|
||||
for (bnd = 0; bnd < s->num_spx_bands; bnd++) {
|
||||
int bandsize;
|
||||
int spx_coord_exp, spx_coord_mant;
|
||||
float nratio, sblend, nblend, spx_coord;
|
||||
INTFLOAT nratio, sblend, nblend;
|
||||
#if CONFIG_AC3_FIXED
|
||||
int64_t accu;
|
||||
/* calculate blending factors */
|
||||
bandsize = s->spx_band_sizes[bnd];
|
||||
accu = (int64_t)((bin << 23) + (bandsize << 22)) * s->spx_dst_end_freq;
|
||||
nratio = (int)(accu >> 32);
|
||||
nratio -= spx_blend << 18;
|
||||
|
||||
if (nratio < 0) {
|
||||
nblend = 0;
|
||||
sblend = 0x800000;
|
||||
} else if (nratio > 0x7fffff) {
|
||||
nblend = 0x800000;
|
||||
sblend = 0;
|
||||
} else {
|
||||
nblend = fixed_sqrt(nratio, 23);
|
||||
accu = (int64_t)nblend * 1859775393;
|
||||
nblend = (int)((accu + (1<<29)) >> 30);
|
||||
sblend = fixed_sqrt(0x800000 - nratio, 23);
|
||||
}
|
||||
#else
|
||||
float spx_coord;
|
||||
|
||||
/* calculate blending factors */
|
||||
bandsize = s->spx_band_sizes[bnd];
|
||||
@ -886,6 +937,7 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3)
|
||||
// to give unity variance
|
||||
sblend = sqrtf(1.0f - nratio);
|
||||
#endif
|
||||
bin += bandsize;
|
||||
|
||||
/* decode spx coordinates */
|
||||
@ -894,11 +946,18 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
if (spx_coord_exp == 15) spx_coord_mant <<= 1;
|
||||
else spx_coord_mant += 4;
|
||||
spx_coord_mant <<= (25 - spx_coord_exp - master_spx_coord);
|
||||
spx_coord = spx_coord_mant * (1.0f / (1 << 23));
|
||||
|
||||
/* multiply noise and signal blending factors by spx coordinate */
|
||||
#if CONFIG_AC3_FIXED
|
||||
accu = (int64_t)nblend * spx_coord_mant;
|
||||
s->spx_noise_blend[ch][bnd] = (int)((accu + (1<<22)) >> 23);
|
||||
accu = (int64_t)sblend * spx_coord_mant;
|
||||
s->spx_signal_blend[ch][bnd] = (int)((accu + (1<<22)) >> 23);
|
||||
#else
|
||||
spx_coord = spx_coord_mant * (1.0f / (1 << 23));
|
||||
s->spx_noise_blend [ch][bnd] = nblend * spx_coord;
|
||||
s->spx_signal_blend[ch][bnd] = sblend * spx_coord;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1255,14 +1314,19 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
|
||||
/* apply scaling to coefficients (headroom, dynrng) */
|
||||
for (ch = 1; ch <= s->channels; ch++) {
|
||||
float gain = 1.0 / 4194304.0f;
|
||||
if (s->channel_mode == AC3_CHMODE_DUALMONO) {
|
||||
gain *= s->dynamic_range[2 - ch];
|
||||
INTFLOAT gain;
|
||||
if(s->channel_mode == AC3_CHMODE_DUALMONO) {
|
||||
gain = s->dynamic_range[2-ch];
|
||||
} else {
|
||||
gain *= s->dynamic_range[0];
|
||||
gain = s->dynamic_range[0];
|
||||
}
|
||||
#if CONFIG_AC3_FIXED
|
||||
scale_coefs(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain, 256);
|
||||
#else
|
||||
gain *= 1.0 / 4194304.0f;
|
||||
s->fmt_conv.int32_to_float_fmul_scalar(s->transform_coeffs[ch],
|
||||
s->fixed_coeffs[ch], gain, 256);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* apply spectral extension to high frequency bins */
|
||||
@ -1287,19 +1351,24 @@ static int decode_audio_block(AC3DecodeContext *s, int blk)
|
||||
do_imdct(s, s->channels);
|
||||
|
||||
if (downmix_output) {
|
||||
#if CONFIG_AC3_FIXED
|
||||
ac3_downmix_c_fixed16(s->outptr, s->downmix_coeffs,
|
||||
s->out_channels, s->fbw_channels, 256);
|
||||
#else
|
||||
s->ac3dsp.downmix(s->outptr, s->downmix_coeffs,
|
||||
s->out_channels, s->fbw_channels, 256);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (downmix_output) {
|
||||
s->ac3dsp.downmix(s->xcfptr + 1, s->downmix_coeffs,
|
||||
s->out_channels, s->fbw_channels, 256);
|
||||
s->ac3dsp.AC3_RENAME(downmix)(s->xcfptr + 1, s->downmix_coeffs,
|
||||
s->out_channels, s->fbw_channels, 256);
|
||||
}
|
||||
|
||||
if (downmix_output && !s->downmixed) {
|
||||
s->downmixed = 1;
|
||||
s->ac3dsp.downmix(s->dlyptr, s->downmix_coeffs, s->out_channels,
|
||||
s->fbw_channels, 128);
|
||||
s->ac3dsp.AC3_RENAME(downmix)(s->dlyptr, s->downmix_coeffs,
|
||||
s->out_channels, s->fbw_channels, 128);
|
||||
}
|
||||
|
||||
do_imdct(s, s->out_channels);
|
||||
@ -1320,7 +1389,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
|
||||
AC3DecodeContext *s = avctx->priv_data;
|
||||
int blk, ch, err, ret;
|
||||
const uint8_t *channel_map;
|
||||
const float *output[AC3_MAX_CHANNELS];
|
||||
const SHORTFLOAT *output[AC3_MAX_CHANNELS];
|
||||
enum AVMatrixEncoding matrix_encoding;
|
||||
AVDownmixInfo *downmix_info;
|
||||
|
||||
@ -1447,7 +1516,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
|
||||
}
|
||||
for (ch = 0; ch < s->channels; ch++) {
|
||||
if (ch < s->out_channels)
|
||||
s->outptr[channel_map[ch]] = (float *)frame->data[ch];
|
||||
s->outptr[channel_map[ch]] = (SHORTFLOAT *)frame->data[ch];
|
||||
}
|
||||
for (blk = 0; blk < s->num_blocks; blk++) {
|
||||
if (!err && decode_audio_block(s, blk)) {
|
||||
@ -1456,7 +1525,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
|
||||
}
|
||||
if (err)
|
||||
for (ch = 0; ch < s->out_channels; ch++)
|
||||
memcpy(((float*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], sizeof(**output) * AC3_BLOCK_SIZE);
|
||||
memcpy(((SHORTFLOAT*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
|
||||
for (ch = 0; ch < s->out_channels; ch++)
|
||||
output[ch] = s->outptr[channel_map[ch]];
|
||||
for (ch = 0; ch < s->out_channels; ch++) {
|
||||
@ -1469,7 +1538,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data,
|
||||
|
||||
/* keep last block for error concealment in next frame */
|
||||
for (ch = 0; ch < s->out_channels; ch++)
|
||||
memcpy(s->output[ch], output[ch], sizeof(**output) * AC3_BLOCK_SIZE);
|
||||
memcpy(s->output[ch], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
|
||||
|
||||
/*
|
||||
* AVMatrixEncoding
|
||||
@ -1540,66 +1609,12 @@ static av_cold int ac3_decode_end(AVCodecContext *avctx)
|
||||
AC3DecodeContext *s = avctx->priv_data;
|
||||
ff_mdct_end(&s->imdct_512);
|
||||
ff_mdct_end(&s->imdct_256);
|
||||
#if (CONFIG_AC3_FIXED)
|
||||
av_free(s->fdsp);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OFFSET(x) offsetof(AC3DecodeContext, x)
|
||||
#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM)
|
||||
static const AVOption options[] = {
|
||||
{ "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
|
||||
|
||||
{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 2, 0, "dmix_mode"},
|
||||
{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
|
||||
{ NULL},
|
||||
};
|
||||
|
||||
static const AVClass ac3_decoder_class = {
|
||||
.class_name = "AC3 decoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
AVCodec ff_ac3_decoder = {
|
||||
.name = "ac3",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_AC3,
|
||||
.priv_data_size = sizeof (AC3DecodeContext),
|
||||
.init = ac3_decode_init,
|
||||
.close = ac3_decode_end,
|
||||
.decode = ac3_decode_frame,
|
||||
.capabilities = CODEC_CAP_DR1,
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &ac3_decoder_class,
|
||||
};
|
||||
|
||||
#if CONFIG_EAC3_DECODER
|
||||
static const AVClass eac3_decoder_class = {
|
||||
.class_name = "E-AC3 decoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
AVCodec ff_eac3_decoder = {
|
||||
.name = "eac3",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"),
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_EAC3,
|
||||
.priv_data_size = sizeof (AC3DecodeContext),
|
||||
.init = ac3_decode_init,
|
||||
.close = ac3_decode_end,
|
||||
.decode = ac3_decode_frame,
|
||||
.capabilities = CODEC_CAP_DR1,
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &eac3_decoder_class,
|
||||
};
|
||||
#endif
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define AVCODEC_AC3DEC_H
|
||||
|
||||
#include "libavutil/float_dsp.h"
|
||||
#include "libavutil/fixed_dsp.h"
|
||||
#include "libavutil/lfg.h"
|
||||
#include "ac3.h"
|
||||
#include "ac3dsp.h"
|
||||
@ -138,8 +139,8 @@ typedef struct AC3DecodeContext {
|
||||
int num_spx_bands; ///< number of spx bands (nspxbnds)
|
||||
uint8_t spx_band_sizes[SPX_MAX_BANDS]; ///< number of bins in each spx band
|
||||
uint8_t first_spx_coords[AC3_MAX_CHANNELS]; ///< first spx coordinates states (firstspxcos)
|
||||
float spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact)
|
||||
float spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS];///< spx signal blending factor (sblendfact)
|
||||
INTFLOAT spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact)
|
||||
INTFLOAT spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS];///< spx signal blending factor (sblendfact)
|
||||
///@}
|
||||
|
||||
///@name Adaptive hybrid transform
|
||||
@ -151,15 +152,15 @@ typedef struct AC3DecodeContext {
|
||||
int fbw_channels; ///< number of full-bandwidth channels
|
||||
int channels; ///< number of total channels
|
||||
int lfe_ch; ///< index of LFE channel
|
||||
float downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients
|
||||
SHORTFLOAT downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients
|
||||
int downmixed; ///< indicates if coeffs are currently downmixed
|
||||
int output_mode; ///< output channel configuration
|
||||
int out_channels; ///< number of output channels
|
||||
///@}
|
||||
|
||||
///@name Dynamic range
|
||||
float dynamic_range[2]; ///< dynamic range
|
||||
float drc_scale; ///< percentage of dynamic range compression to be applied
|
||||
INTFLOAT dynamic_range[2]; ///< dynamic range
|
||||
INTFLOAT drc_scale; ///< percentage of dynamic range compression to be applied
|
||||
///@}
|
||||
|
||||
///@name Bandwidth
|
||||
@ -207,22 +208,26 @@ typedef struct AC3DecodeContext {
|
||||
|
||||
///@name Optimization
|
||||
DSPContext dsp; ///< for optimization
|
||||
#if CONFIG_AC3_FIXED
|
||||
AVFixedDSPContext *fdsp;
|
||||
#else
|
||||
AVFloatDSPContext fdsp;
|
||||
#endif
|
||||
AC3DSPContext ac3dsp;
|
||||
FmtConvertContext fmt_conv; ///< optimized conversion functions
|
||||
///@}
|
||||
|
||||
float *outptr[AC3_MAX_CHANNELS];
|
||||
float *xcfptr[AC3_MAX_CHANNELS];
|
||||
float *dlyptr[AC3_MAX_CHANNELS];
|
||||
SHORTFLOAT *outptr[AC3_MAX_CHANNELS];
|
||||
INTFLOAT *xcfptr[AC3_MAX_CHANNELS];
|
||||
INTFLOAT *dlyptr[AC3_MAX_CHANNELS];
|
||||
|
||||
///@name Aligned arrays
|
||||
DECLARE_ALIGNED(16, int32_t, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients
|
||||
DECLARE_ALIGNED(32, float, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients
|
||||
DECLARE_ALIGNED(32, float, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block
|
||||
DECLARE_ALIGNED(32, float, window)[AC3_BLOCK_SIZE]; ///< window coefficients
|
||||
DECLARE_ALIGNED(32, float, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing
|
||||
DECLARE_ALIGNED(32, float, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing
|
||||
DECLARE_ALIGNED(16, int, fixed_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< fixed-point transform coefficients
|
||||
DECLARE_ALIGNED(32, INTFLOAT, transform_coeffs)[AC3_MAX_CHANNELS][AC3_MAX_COEFS]; ///< transform coefficients
|
||||
DECLARE_ALIGNED(32, INTFLOAT, delay)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< delay - added to the next block
|
||||
DECLARE_ALIGNED(32, INTFLOAT, window)[AC3_BLOCK_SIZE]; ///< window coefficients
|
||||
DECLARE_ALIGNED(32, INTFLOAT, tmp_output)[AC3_BLOCK_SIZE]; ///< temporary storage for output before windowing
|
||||
DECLARE_ALIGNED(32, SHORTFLOAT, output)[AC3_MAX_CHANNELS][AC3_BLOCK_SIZE]; ///< output after imdct transform and windowing
|
||||
DECLARE_ALIGNED(32, uint8_t, input_buffer)[AC3_FRAME_BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; ///< temp buffer to prevent overread
|
||||
///@}
|
||||
} AC3DecodeContext;
|
||||
|
176
libavcodec/ac3dec_fixed.c
Normal file
176
libavcodec/ac3dec_fixed.c
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2012
|
||||
* MIPS Technologies, Inc., California.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Author: Stanislav Ocovaj (socovaj@mips.com)
|
||||
*
|
||||
* AC3 fixed-point decoder for MIPS platforms
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FFT_FLOAT 0
|
||||
#define CONFIG_AC3_FIXED 1
|
||||
#define FFT_FIXED_32 1
|
||||
#include "ac3dec.h"
|
||||
|
||||
|
||||
/**
|
||||
* Table for center mix levels
|
||||
* reference: Section 5.4.2.4 cmixlev
|
||||
*/
|
||||
static const uint8_t center_levels[4] = { 4, 5, 6, 5 };
|
||||
|
||||
/**
|
||||
* Table for surround mix levels
|
||||
* reference: Section 5.4.2.5 surmixlev
|
||||
*/
|
||||
static const uint8_t surround_levels[4] = { 4, 6, 7, 6 };
|
||||
|
||||
int end_freq_inv_tab[8] =
|
||||
{
|
||||
50529027, 44278013, 39403370, 32292987, 27356480, 23729101, 20951060, 18755316
|
||||
};
|
||||
|
||||
static void scale_coefs (
|
||||
int32_t *dst,
|
||||
const int32_t *src,
|
||||
int dynrng,
|
||||
int len)
|
||||
{
|
||||
int i, shift, round;
|
||||
int16_t mul;
|
||||
int temp, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
|
||||
|
||||
mul = (dynrng & 0x1f) + 0x20;
|
||||
shift = 4 - ((dynrng << 24) >> 29);
|
||||
round = 1 << (shift-1);
|
||||
for (i=0; i<len; i+=8) {
|
||||
|
||||
temp = src[i] * mul;
|
||||
temp1 = src[i+1] * mul;
|
||||
temp = temp + round;
|
||||
temp2 = src[i+2] * mul;
|
||||
|
||||
temp1 = temp1 + round;
|
||||
dst[i] = temp >> shift;
|
||||
temp3 = src[i+3] * mul;
|
||||
temp2 = temp2 + round;
|
||||
|
||||
dst[i+1] = temp1 >> shift;
|
||||
temp4 = src[i + 4] * mul;
|
||||
temp3 = temp3 + round;
|
||||
dst[i+2] = temp2 >> shift;
|
||||
|
||||
temp5 = src[i+5] * mul;
|
||||
temp4 = temp4 + round;
|
||||
dst[i+3] = temp3 >> shift;
|
||||
temp6 = src[i+6] * mul;
|
||||
|
||||
dst[i+4] = temp4 >> shift;
|
||||
temp5 = temp5 + round;
|
||||
temp7 = src[i+7] * mul;
|
||||
temp6 = temp6 + round;
|
||||
|
||||
dst[i+5] = temp5 >> shift;
|
||||
temp7 = temp7 + round;
|
||||
dst[i+6] = temp6 >> shift;
|
||||
dst[i+7] = temp7 >> shift;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
static void ac3_downmix_c_fixed16(int16_t **samples, int16_t (*matrix)[2],
|
||||
int out_ch, int in_ch, int len)
|
||||
{
|
||||
int i, j;
|
||||
int v0, v1;
|
||||
if (out_ch == 2) {
|
||||
for (i = 0; i < len; i++) {
|
||||
v0 = v1 = 0;
|
||||
for (j = 0; j < in_ch; j++) {
|
||||
v0 += samples[j][i] * matrix[j][0];
|
||||
v1 += samples[j][i] * matrix[j][1];
|
||||
}
|
||||
samples[0][i] = (v0+2048)>>12;
|
||||
samples[1][i] = (v1+2048)>>12;
|
||||
}
|
||||
} else if (out_ch == 1) {
|
||||
for (i = 0; i < len; i++) {
|
||||
v0 = 0;
|
||||
for (j = 0; j < in_ch; j++)
|
||||
v0 += samples[j][i] * matrix[j][0];
|
||||
samples[0][i] = (v0+2048)>>12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "ac3dec.c"
|
||||
|
||||
static const AVOption options[] = {
|
||||
{ NULL},
|
||||
};
|
||||
|
||||
static const AVClass ac3_decoder_class = {
|
||||
.class_name = "Fixed-Point AC-3 Decoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
AVCodec ff_ac3_fixed_decoder = {
|
||||
.name = "ac3_fixed",
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = CODEC_ID_AC3,
|
||||
.priv_data_size = sizeof (AC3DecodeContext),
|
||||
.init = ac3_decode_init,
|
||||
.close = ac3_decode_end,
|
||||
.decode = ac3_decode_frame,
|
||||
.capabilities = CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &ac3_decoder_class,
|
||||
};
|
89
libavcodec/ac3dec_float.c
Normal file
89
libavcodec/ac3dec_float.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* AC-3 Audio Decoder
|
||||
* This code was developed as part of Google Summer of Code 2006.
|
||||
* E-AC-3 support was added as part of Google Summer of Code 2007.
|
||||
*
|
||||
* Copyright (c) 2006 Kartikey Mahendra BHATT (bhattkm at gmail dot com)
|
||||
* Copyright (c) 2007-2008 Bartlomiej Wolowiec <bartek.wolowiec@gmail.com>
|
||||
* Copyright (c) 2007 Justin Ruggles <justin.ruggles@gmail.com>
|
||||
*
|
||||
* This file is part of FFmpeg.
|
||||
*
|
||||
* FFmpeg is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* FFmpeg is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with FFmpeg; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Upmix delay samples from stereo to original channel layout.
|
||||
*/
|
||||
#include "ac3dec.h"
|
||||
#include "ac3dec.c"
|
||||
|
||||
static const AVOption options[] = {
|
||||
{ "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
|
||||
|
||||
{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 2, 0, "dmix_mode"},
|
||||
{"ltrt_cmixlev", "Lt/Rt Center Mix Level", OFFSET(ltrt_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
{"loro_cmixlev", "Lo/Ro Center Mix Level", OFFSET(loro_center_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level), AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
|
||||
|
||||
{ NULL},
|
||||
};
|
||||
|
||||
static const AVClass ac3_decoder_class = {
|
||||
.class_name = "AC3 decoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
AVCodec ff_ac3_decoder = {
|
||||
.name = "ac3",
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_AC3,
|
||||
.priv_data_size = sizeof (AC3DecodeContext),
|
||||
.init = ac3_decode_init,
|
||||
.close = ac3_decode_end,
|
||||
.decode = ac3_decode_frame,
|
||||
.capabilities = CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &ac3_decoder_class,
|
||||
};
|
||||
|
||||
#if CONFIG_EAC3_DECODER
|
||||
static const AVClass eac3_decoder_class = {
|
||||
.class_name = "E-AC3 decoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
AVCodec ff_eac3_decoder = {
|
||||
.name = "eac3",
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_EAC3,
|
||||
.priv_data_size = sizeof (AC3DecodeContext),
|
||||
.init = ac3_decode_init,
|
||||
.close = ac3_decode_end,
|
||||
.decode = ac3_decode_frame,
|
||||
.capabilities = CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"),
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.priv_class = &eac3_decoder_class,
|
||||
};
|
||||
#endif
|
@ -239,6 +239,31 @@ static void ac3_downmix_c(float **samples, float (*matrix)[2],
|
||||
}
|
||||
}
|
||||
|
||||
static void ac3_downmix_c_fixed(int32_t **samples, int16_t (*matrix)[2],
|
||||
int out_ch, int in_ch, int len)
|
||||
{
|
||||
int i, j;
|
||||
int64_t v0, v1;
|
||||
if (out_ch == 2) {
|
||||
for (i = 0; i < len; i++) {
|
||||
v0 = v1 = 0;
|
||||
for (j = 0; j < in_ch; j++) {
|
||||
v0 += (int64_t)samples[j][i] * matrix[j][0];
|
||||
v1 += (int64_t)samples[j][i] * matrix[j][1];
|
||||
}
|
||||
samples[0][i] = (v0+2048)>>12;
|
||||
samples[1][i] = (v1+2048)>>12;
|
||||
}
|
||||
} else if (out_ch == 1) {
|
||||
for (i = 0; i < len; i++) {
|
||||
v0 = 0;
|
||||
for (j = 0; j < in_ch; j++)
|
||||
v0 += (int64_t)samples[j][i] * matrix[j][0];
|
||||
samples[0][i] = (v0+2048)>>12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_window_int16_c(int16_t *output, const int16_t *input,
|
||||
const int16_t *window, unsigned int len)
|
||||
{
|
||||
@ -266,6 +291,7 @@ av_cold void ff_ac3dsp_init(AC3DSPContext *c, int bit_exact)
|
||||
c->sum_square_butterfly_int32 = ac3_sum_square_butterfly_int32_c;
|
||||
c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_c;
|
||||
c->downmix = ac3_downmix_c;
|
||||
c->downmix_fixed = ac3_downmix_c_fixed;
|
||||
c->apply_window_int16 = apply_window_int16_c;
|
||||
|
||||
if (ARCH_ARM)
|
||||
|
@ -135,6 +135,9 @@ typedef struct AC3DSPContext {
|
||||
void (*downmix)(float **samples, float (*matrix)[2], int out_ch,
|
||||
int in_ch, int len);
|
||||
|
||||
void (*downmix_fixed)(int32_t **samples, int16_t (*matrix)[2], int out_ch,
|
||||
int in_ch, int len);
|
||||
|
||||
/**
|
||||
* Apply symmetric window in 16-bit fixed-point.
|
||||
* @param output destination array
|
||||
|
@ -323,7 +323,7 @@ void avcodec_register_all(void)
|
||||
REGISTER_ENCDEC (AAC, aac);
|
||||
REGISTER_DECODER(AAC_LATM, aac_latm);
|
||||
REGISTER_ENCDEC (AC3, ac3);
|
||||
REGISTER_ENCODER(AC3_FIXED, ac3_fixed);
|
||||
REGISTER_ENCDEC (AC3_FIXED, ac3_fixed);
|
||||
REGISTER_ENCDEC (ALAC, alac);
|
||||
REGISTER_DECODER(ALS, als);
|
||||
REGISTER_DECODER(AMRNB, amrnb);
|
||||
|
@ -45,3 +45,13 @@ av_cold void ff_kbd_window_init(float *window, float alpha, int n)
|
||||
for (i = 0; i < n; i++)
|
||||
window[i] = sqrt(local_window[i] / sum);
|
||||
}
|
||||
|
||||
av_cold void ff_kbd_window_init_fixed(int32_t *window, float alpha, int n)
|
||||
{
|
||||
int i;
|
||||
float local_window[FF_KBD_WINDOW_MAX];
|
||||
|
||||
ff_kbd_window_init(local_window, alpha, n);
|
||||
for (i = 0; i < n; i++)
|
||||
window[i] = (int)floor(2147483647.0 * local_window[i] + 0.5);
|
||||
}
|
||||
|
@ -31,5 +31,6 @@
|
||||
* @param n size of half window, max FF_KBD_WINDOW_MAX
|
||||
*/
|
||||
void ff_kbd_window_init(float *window, float alpha, int n);
|
||||
void ff_kbd_window_init_fixed(int32_t *window, float alpha, int n);
|
||||
|
||||
#endif /* AVCODEC_KBDWIN_H */
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVCODEC_VERSION_MAJOR 55
|
||||
#define LIBAVCODEC_VERSION_MINOR 55
|
||||
#define LIBAVCODEC_VERSION_MINOR 56
|
||||
#define LIBAVCODEC_VERSION_MICRO 107
|
||||
|
||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user