From 1914e6f010b3320025c7b692aaea51d9b9a992a8 Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Mon, 16 Sep 2013 13:03:15 -0700 Subject: [PATCH] aacdec: Add support for LD (Low Delay) AAC --- Changelog | 1 + libavcodec/aac.h | 1 + libavcodec/aacdec.c | 67 +++++++++++++++++++++++++++++++++++++++++--- libavcodec/aactab.c | 36 ++++++++++++++++++++++++ libavcodec/aactab.h | 3 ++ libavcodec/version.h | 2 +- 6 files changed, 105 insertions(+), 5 deletions(-) diff --git a/Changelog b/Changelog index 58daaa559e..10ad63bf21 100644 --- a/Changelog +++ b/Changelog @@ -35,6 +35,7 @@ version 10: - incomplete Voxware MetaSound decoder - WebP decoder - Error Resilient AAC syntax (ER AAC LC) decoding +- Low Delay AAC (ER AAC LD) decoding version 9: diff --git a/libavcodec/aac.h b/libavcodec/aac.h index a7c9995a31..40e8dfb50a 100644 --- a/libavcodec/aac.h +++ b/libavcodec/aac.h @@ -289,6 +289,7 @@ typedef struct AACContext { */ FFTContext mdct; FFTContext mdct_small; + FFTContext mdct_ld; FFTContext mdct_ltp; FmtConvertContext fmt_conv; AVFloatDSPContext fdsp; diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index a7c4151e82..35efb8c689 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -817,6 +817,13 @@ static int decode_audio_specific_config(AACContext *ac, m4ac->sampling_index); return AVERROR_INVALIDDATA; } + if (m4ac->object_type == AOT_ER_AAC_LD && + (m4ac->sampling_index < 3 || m4ac->sampling_index > 7)) { + av_log(avctx, AV_LOG_ERROR, + "invalid low delay sampling rate index %d\n", + m4ac->sampling_index); + return AVERROR_INVALIDDATA; + } skip_bits_long(&gb, i); @@ -825,6 +832,7 @@ static int decode_audio_specific_config(AACContext *ac, case AOT_AAC_LC: case AOT_AAC_LTP: case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: if ((ret = decode_ga_specific_config(ac, avctx, &gb, m4ac, m4ac->chan_config)) < 0) return ret; @@ -985,12 +993,15 @@ static av_cold int aac_decode_init(AVCodecContext *avctx) 352); ff_mdct_init(&ac->mdct, 11, 1, 1.0 / (32768.0 * 1024.0)); + ff_mdct_init(&ac->mdct_ld, 10, 1, 1.0 / (32768.0 * 512.0)); ff_mdct_init(&ac->mdct_small, 8, 1, 1.0 / (32768.0 * 128.0)); ff_mdct_init(&ac->mdct_ltp, 11, 0, -2.0 * 32768.0); // window initialization ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); + ff_kbd_window_init(ff_aac_kbd_long_512, 4.0, 512); ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); ff_init_ff_sine_windows(10); + ff_init_ff_sine_windows( 9); ff_init_ff_sine_windows( 7); cbrt_tableinit(); @@ -1063,6 +1074,14 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, } ics->window_sequence[1] = ics->window_sequence[0]; ics->window_sequence[0] = get_bits(gb, 2); + if (ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD && + ics->window_sequence[0] != ONLY_LONG_SEQUENCE) { + av_log(ac->avctx, AV_LOG_ERROR, + "AAC LD is only defined for ONLY_LONG_SEQUENCE but " + "window sequence %d found.\n", ics->window_sequence[0]); + ics->window_sequence[0] = ONLY_LONG_SEQUENCE; + return AVERROR_INVALIDDATA; + } ics->use_kb_window[1] = ics->use_kb_window[0]; ics->use_kb_window[0] = get_bits1(gb); ics->num_window_groups = 1; @@ -1086,8 +1105,15 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, } else { ics->max_sfb = get_bits(gb, 6); ics->num_windows = 1; - ics->swb_offset = ff_swb_offset_1024[ac->oc[1].m4ac.sampling_index]; - ics->num_swb = ff_aac_num_swb_1024[ac->oc[1].m4ac.sampling_index]; + if (ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD) { + ics->swb_offset = ff_swb_offset_512[ac->oc[1].m4ac.sampling_index]; + ics->num_swb = ff_aac_num_swb_512[ac->oc[1].m4ac.sampling_index]; + if (!ics->num_swb || !ics->swb_offset) + return AVERROR_BUG; + } else { + ics->swb_offset = ff_swb_offset_1024[ac->oc[1].m4ac.sampling_index]; + ics->num_swb = ff_aac_num_swb_1024[ac->oc[1].m4ac.sampling_index]; + } ics->tns_max_bands = ff_tns_max_bands_1024[ac->oc[1].m4ac.sampling_index]; ics->predictor_present = get_bits1(gb); ics->predictor_reset_group = 0; @@ -1102,6 +1128,11 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, "Prediction is not allowed in AAC-LC.\n"); return AVERROR_INVALIDDATA; } else { + if (ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD) { + av_log(ac->avctx, AV_LOG_ERROR, + "LTP in ER AAC LD not yet implemented.\n"); + return AVERROR_PATCHWELCOME; + } if ((ics->ltp.present = get_bits(gb, 1))) decode_ltp(&ics->ltp, gb, ics->max_sfb); } @@ -2314,6 +2345,25 @@ static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce) } } +static void imdct_and_windowing_ld(AACContext *ac, SingleChannelElement *sce) +{ + IndividualChannelStream *ics = &sce->ics; + float *in = sce->coeffs; + float *out = sce->ret; + float *saved = sce->saved; + const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_512 : ff_sine_512; + float *buf = ac->buf_mdct; + + // imdct + ac->mdct.imdct_half(&ac->mdct_ld, buf, in); + + // window overlapping + ac->fdsp.vector_fmul_window(out, saved, buf, lwindow_prev, 256); + + // buffer update + memcpy(saved, buf + 256, 256 * sizeof(float)); +} + /** * Apply dependent channel coupling (applied before IMDCT). * @@ -2410,6 +2460,11 @@ static void apply_channel_coupling(AACContext *ac, ChannelElement *cc, static void spectral_to_sample(AACContext *ac) { int i, type; + void (*imdct_and_window)(AACContext *ac, SingleChannelElement *sce); + if (ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD) + imdct_and_window = imdct_and_windowing_ld; + else + imdct_and_window = imdct_and_windowing; for (type = 3; type >= 0; type--) { for (i = 0; i < MAX_ELEM_ID; i++) { ChannelElement *che = ac->che[type][i]; @@ -2431,11 +2486,11 @@ static void spectral_to_sample(AACContext *ac) if (type <= TYPE_CPE) apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling); if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) { - imdct_and_windowing(ac, &che->ch[0]); + imdct_and_window(ac, &che->ch[0]); if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) update_ltp(ac, &che->ch[0]); if (type == TYPE_CPE) { - imdct_and_windowing(ac, &che->ch[1]); + imdct_and_window(ac, &che->ch[1]); if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) update_ltp(ac, &che->ch[1]); } @@ -2503,6 +2558,9 @@ static int aac_decode_er_frame(AVCodecContext *avctx, void *data, int samples = 1024; int chan_config = ac->oc[1].m4ac.chan_config; + if (ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD) + samples >>= 1; + ac->frame = data; if ((err = frame_configure_elements(avctx)) < 0) @@ -2757,6 +2815,7 @@ static av_cold int aac_decode_close(AVCodecContext *avctx) ff_mdct_end(&ac->mdct); ff_mdct_end(&ac->mdct_small); + ff_mdct_end(&ac->mdct_ld); ff_mdct_end(&ac->mdct_ltp); return 0; } diff --git a/libavcodec/aactab.c b/libavcodec/aactab.c index 9176e37d48..b96a7d5273 100644 --- a/libavcodec/aactab.c +++ b/libavcodec/aactab.c @@ -34,12 +34,17 @@ #include DECLARE_ALIGNED(32, float, ff_aac_kbd_long_1024)[1024]; +DECLARE_ALIGNED(32, float, ff_aac_kbd_long_512 )[512]; DECLARE_ALIGNED(32, float, ff_aac_kbd_short_128)[128]; const uint8_t ff_aac_num_swb_1024[] = { 41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40, 40 }; +const uint8_t ff_aac_num_swb_512[] = { + 0, 0, 0, 36, 36, 37, 31, 31, 0, 0, 0, 0, 0 +}; + const uint8_t ff_aac_num_swb_128[] = { 12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15 }; @@ -1114,6 +1119,14 @@ static const uint16_t swb_offset_1024_48[] = { 928, 1024 }; +static const uint16_t swb_offset_512_48[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + 68, 76, 84, 92, 100, 112, 124, 136, + 148, 164, 184, 208, 236, 268, 300, 332, + 364, 396, 428, 460, 512 +}; + static const uint16_t swb_offset_128_48[] = { 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128 @@ -1129,6 +1142,14 @@ static const uint16_t swb_offset_1024_32[] = { 928, 960, 992, 1024 }; +static const uint16_t swb_offset_512_32[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 64, + 72, 80, 88, 96, 108, 120, 132, 144, + 160, 176, 192, 212, 236, 260, 288, 320, + 352, 384, 416, 448, 480, 512 +}; + static const uint16_t swb_offset_1024_24[] = { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76, @@ -1138,6 +1159,13 @@ static const uint16_t swb_offset_1024_24[] = { 600, 652, 704, 768, 832, 896, 960, 1024 }; +static const uint16_t swb_offset_512_24[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 52, 60, 68, 80, + 92, 104, 120, 140, 164, 192, 224, 256, + 288, 320, 352, 384, 416, 448, 480, 512, +}; + static const uint16_t swb_offset_128_24[] = { 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128 @@ -1179,6 +1207,14 @@ const uint16_t * const ff_swb_offset_1024[] = { swb_offset_1024_8 }; +const uint16_t * const ff_swb_offset_512[] = { + NULL, NULL, NULL, + swb_offset_512_48, swb_offset_512_48, swb_offset_512_32, + swb_offset_512_24, swb_offset_512_24, NULL, + NULL, NULL, NULL, + NULL +}; + const uint16_t * const ff_swb_offset_128[] = { /* The last entry on the following row is swb_offset_128_64 but is a duplicate of swb_offset_128_96. */ diff --git a/libavcodec/aactab.h b/libavcodec/aactab.h index 56e5796be9..bf1576ef71 100644 --- a/libavcodec/aactab.h +++ b/libavcodec/aactab.h @@ -45,6 +45,7 @@ * @{ */ DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_1024)[1024]; +DECLARE_ALIGNED(32, extern float, ff_aac_kbd_long_512 )[512]; DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_128)[128]; // @} @@ -52,6 +53,7 @@ DECLARE_ALIGNED(32, extern float, ff_aac_kbd_short_128)[128]; * @{ */ extern const uint8_t ff_aac_num_swb_1024[]; +extern const uint8_t ff_aac_num_swb_512 []; extern const uint8_t ff_aac_num_swb_128 []; // @} @@ -69,6 +71,7 @@ extern const float *ff_aac_codebook_vector_vals[]; extern const uint16_t *ff_aac_codebook_vector_idx[]; extern const uint16_t * const ff_swb_offset_1024[13]; +extern const uint16_t * const ff_swb_offset_512 [13]; extern const uint16_t * const ff_swb_offset_128 [13]; extern const uint8_t ff_tns_max_bands_1024[13]; diff --git a/libavcodec/version.h b/libavcodec/version.h index 9775a650e4..574e02a7e2 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -27,7 +27,7 @@ */ #define LIBAVCODEC_VERSION_MAJOR 55 -#define LIBAVCODEC_VERSION_MINOR 19 +#define LIBAVCODEC_VERSION_MINOR 20 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \