diff options
author | Nedeljko Babic <nbabic@mips.com> | 2014-04-01 16:31:08 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-04-01 19:01:57 +0200 |
commit | 696e34a6e15d9d9d655191a953779d06dc3b5897 (patch) | |
tree | 4401c485e31b7cc878179d44481635213eecd7a6 | |
parent | d506deaeaa98013505241d8149d82327efea0379 (diff) | |
download | ffmpeg-696e34a6e15d9d9d655191a953779d06dc3b5897.tar.gz |
libavcodec: Implementation of AC3 fixedpoint decoder
Signed-off-by: Nedeljko Babic <nbabic@mips.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | Changelog | 1 | ||||
-rwxr-xr-x | configure | 1 | ||||
-rw-r--r-- | doc/general.texi | 2 | ||||
-rw-r--r-- | libavcodec/Makefile | 3 | ||||
-rw-r--r-- | libavcodec/ac3.h | 46 | ||||
-rw-r--r-- | libavcodec/ac3dec.c | 197 | ||||
-rw-r--r-- | libavcodec/ac3dec.h | 33 | ||||
-rw-r--r-- | libavcodec/ac3dec_fixed.c | 176 | ||||
-rw-r--r-- | libavcodec/ac3dec_float.c | 89 | ||||
-rw-r--r-- | libavcodec/ac3dsp.c | 26 | ||||
-rw-r--r-- | libavcodec/ac3dsp.h | 3 | ||||
-rw-r--r-- | libavcodec/allcodecs.c | 2 | ||||
-rw-r--r-- | libavcodec/kbdwin.c | 10 | ||||
-rw-r--r-- | libavcodec/kbdwin.h | 1 | ||||
-rw-r--r-- | libavcodec/version.h | 2 |
15 files changed, 483 insertions, 109 deletions
@@ -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 @@ -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" diff --git a/doc/general.texi b/doc/general.texi index e9087df349..9f17d488e1 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -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 diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 70a6e25e9a..f68371a329 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -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 diff --git a/libavcodec/ac3.h b/libavcodec/ac3.h index 0cc9e2c98a..ac3936d7f3 100644 --- a/libavcodec/ac3.h +++ b/libavcodec/ac3.h @@ -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 diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 3a6a7ad5ac..1d97df95f9 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -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 diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 58d8ee69bb..255b9df25e 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -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; diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c new file mode 100644 index 0000000000..1eb9a0b278 --- /dev/null +++ b/libavcodec/ac3dec_fixed.c @@ -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, +}; diff --git a/libavcodec/ac3dec_float.c b/libavcodec/ac3dec_float.c new file mode 100644 index 0000000000..7108921701 --- /dev/null +++ b/libavcodec/ac3dec_float.c @@ -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 diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index 0d5ea39d08..b746817c9d 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -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) diff --git a/libavcodec/ac3dsp.h b/libavcodec/ac3dsp.h index f18583c446..ed98c8ce6a 100644 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@ -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 diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 10edd39cdb..c55a809ccd 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -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); diff --git a/libavcodec/kbdwin.c b/libavcodec/kbdwin.c index 5a62e9da2b..bf32aeb317 100644 --- a/libavcodec/kbdwin.c +++ b/libavcodec/kbdwin.c @@ -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); +} diff --git a/libavcodec/kbdwin.h b/libavcodec/kbdwin.h index 4b939756c1..2e02e10764 100644 --- a/libavcodec/kbdwin.h +++ b/libavcodec/kbdwin.h @@ -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 */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 21f5dea786..19b49340be 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.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, \ |