diff mbox

[FFmpeg-devel] avcodec/aac: add 960/120 MDCT window

Message ID 20170716172831.23647-1-onemda@gmail.com
State New
Headers show

Commit Message

Paul B Mahol July 16, 2017, 5:28 p.m. UTC
Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
Signed-off-by: Alex Converse <alex.converse@gmail.com>
Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 Changelog                     |   1 +
 libavcodec/aac.h              |   3 +
 libavcodec/aacdec_template.c  | 126 +++++++++++++++++++++++++++++++++++++++---
 libavcodec/aacsbr_template.c  |   3 +-
 libavcodec/aactab.c           | 122 ++++++++++++++++++++++++++++++++++++++++
 libavcodec/aactab.h           |   8 +++
 libavcodec/sinewin.h          |   4 +-
 libavcodec/sinewin_tablegen.h |   5 +-
 8 files changed, 259 insertions(+), 13 deletions(-)

Comments

Paul B Mahol July 25, 2017, 7:46 a.m. UTC | #1
On 7/16/17, Paul B Mahol <onemda@gmail.com> wrote:
> Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
> Signed-off-by: Alex Converse <alex.converse@gmail.com>
> Signed-off-by: Paul B Mahol <onemda@gmail.com>
> ---
>  Changelog                     |   1 +
>  libavcodec/aac.h              |   3 +
>  libavcodec/aacdec_template.c  | 126
> +++++++++++++++++++++++++++++++++++++++---
>  libavcodec/aacsbr_template.c  |   3 +-
>  libavcodec/aactab.c           | 122
> ++++++++++++++++++++++++++++++++++++++++
>  libavcodec/aactab.h           |   8 +++
>  libavcodec/sinewin.h          |   4 +-
>  libavcodec/sinewin_tablegen.h |   5 +-
>  8 files changed, 259 insertions(+), 13 deletions(-)
>

ping
Hendrik Leppkes July 25, 2017, 8:35 a.m. UTC | #2
2017-07-25 9:46 GMT+02:00 Paul B Mahol <onemda@gmail.com>:
> On 7/16/17, Paul B Mahol <onemda@gmail.com> wrote:
>> Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
>> Signed-off-by: Alex Converse <alex.converse@gmail.com>
>> Signed-off-by: Paul B Mahol <onemda@gmail.com>
>> ---
>>  Changelog                     |   1 +
>>  libavcodec/aac.h              |   3 +
>>  libavcodec/aacdec_template.c  | 126
>> +++++++++++++++++++++++++++++++++++++++---
>>  libavcodec/aacsbr_template.c  |   3 +-
>>  libavcodec/aactab.c           | 122
>> ++++++++++++++++++++++++++++++++++++++++
>>  libavcodec/aactab.h           |   8 +++
>>  libavcodec/sinewin.h          |   4 +-
>>  libavcodec/sinewin_tablegen.h |   5 +-
>>  8 files changed, 259 insertions(+), 13 deletions(-)
>>
>
> ping

Can you document the limitations that 960 support still has? IIRC it
doesn't work with SBR yet? Anything else?
Is it supported both in float and fixed mode?

Not saying any of this needs to be fixed, just having the "state"
clearly documented in the commit would be nice for future
improvements. :)

- Hendrik
diff mbox

Patch

diff --git a/Changelog b/Changelog
index 927cf1c..e0065fe 100644
--- a/Changelog
+++ b/Changelog
@@ -28,6 +28,7 @@  version <next>:
 - support for decoding through D3D11VA in ffmpeg
 - limiter video filter
 - libvmaf video filter
+- aac 960/120 frame length support
 
 version 3.3:
 - CrystalHD decoder moved to new decode API
diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 97a2df6..c6d06b6 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -306,6 +306,7 @@  struct AACContext {
     ChannelElement  *tag_che_map[4][MAX_ELEM_ID];
     int tags_mapped;
     int warned_remapping_once;
+    int warned_960_sbr;
     /** @} */
 
     /**
@@ -327,7 +328,9 @@  struct AACContext {
 #if USE_FIXED
     AVFixedDSPContext *fdsp;
 #else
+    MDCT15Context *mdct120;
     MDCT15Context *mdct480;
+    MDCT15Context *mdct960;
     AVFloatDSPContext *fdsp;
 #endif /* USE_FIXED */
     int random_state;
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index c60a6ca..d1d21d1 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -811,11 +811,21 @@  static int decode_ga_specific_config(AACContext *ac, AVCodecContext *avctx,
     uint8_t layout_map[MAX_ELEM_ID*4][3];
     int tags = 0;
 
-    if (get_bits1(gb)) { // frameLengthFlag
-        avpriv_request_sample(avctx, "960/120 MDCT window");
+#if USE_FIXED
+    if (get_bits1(gb)) {
+        avpriv_report_missing_feature(avctx, "960/120 MDCT window");
         return AVERROR_PATCHWELCOME;
     }
-    m4ac->frame_length_short = 0;
+#else
+    m4ac->frame_length_short = get_bits1(gb);
+#endif
+    if (m4ac->frame_length_short) {
+        if (!ac->warned_960_sbr)
+            avpriv_report_missing_feature(avctx, "SBR with a 960 frame length");
+        ac->warned_960_sbr = 1;
+        m4ac->sbr = 0;
+        m4ac->ps = 0;
+    }
 
     if (get_bits1(gb))       // dependsOnCoreCoder
         skip_bits(gb, 14);   // coreCoderDelay
@@ -1126,6 +1136,10 @@  static av_cold void aac_static_table_init(void)
     // window initialization
     AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_long_1024), 4.0, 1024);
     AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_short_128), 6.0, 128);
+    AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_long_960), 4.0, 960);
+    AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(ff_aac_kbd_short_120), 6.0, 120);
+    AAC_RENAME(ff_sine_window_init)(AAC_RENAME(ff_sine_960), 960);
+    AAC_RENAME(ff_sine_window_init)(AAC_RENAME(ff_sine_120), 120);
     AAC_RENAME(ff_init_ff_sine_windows)(10);
     AAC_RENAME(ff_init_ff_sine_windows)( 9);
     AAC_RENAME(ff_init_ff_sine_windows)( 7);
@@ -1214,6 +1228,12 @@  static av_cold int aac_decode_init(AVCodecContext *avctx)
     ret = ff_mdct15_init(&ac->mdct480, 1, 5, 1.0f/(16*1024*960));
     if (ret < 0)
         return ret;
+    ret = ff_mdct15_init(&ac->mdct120, 1, 3, 1.0 / RANGE15(120.0));
+    if (ret < 0)
+        return ret;
+    ret = ff_mdct15_init(&ac->mdct960, 1, 6, 1.0 / RANGE15(960.0));
+    if (ret < 0)
+        return ret;
 #endif
 
     return 0;
@@ -1314,8 +1334,13 @@  static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics,
             }
         }
         ics->num_windows       = 8;
-        ics->swb_offset        =    ff_swb_offset_128[sampling_index];
-        ics->num_swb           =   ff_aac_num_swb_128[sampling_index];
+        if (m4ac->frame_length_short) {
+            ics->swb_offset    =  ff_swb_offset_120[sampling_index];
+            ics->num_swb       = ff_aac_num_swb_120[sampling_index];
+        } else {
+            ics->swb_offset    =  ff_swb_offset_128[sampling_index];
+            ics->num_swb       = ff_aac_num_swb_128[sampling_index];
+        }
         ics->tns_max_bands     = ff_tns_max_bands_128[sampling_index];
         ics->predictor_present = 0;
     } else {
@@ -1334,8 +1359,13 @@  static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics,
             if (!ics->num_swb || !ics->swb_offset)
                 return AVERROR_BUG;
         } else {
-            ics->swb_offset    =    ff_swb_offset_1024[sampling_index];
-            ics->num_swb       =   ff_aac_num_swb_1024[sampling_index];
+            if (m4ac->frame_length_short) {
+                ics->num_swb    = ff_aac_num_swb_960[sampling_index];
+                ics->swb_offset = ff_swb_offset_960[sampling_index];
+            } else {
+                ics->num_swb    = ff_aac_num_swb_1024[sampling_index];
+                ics->swb_offset = ff_swb_offset_1024[sampling_index];
+            }
             ics->tns_max_bands = ff_tns_max_bands_1024[sampling_index];
         }
         if (aot != AOT_ER_AAC_ELD) {
@@ -2348,6 +2378,12 @@  static int decode_extension_payload(AACContext *ac, GetBitContext *gb, int cnt,
         if (!che) {
             av_log(ac->avctx, AV_LOG_ERROR, "SBR was found before the first channel element.\n");
             return res;
+        } else if (ac->oc[1].m4ac.frame_length_short) {
+            if (!ac->warned_960_sbr)
+                avpriv_report_missing_feature(ac->avctx, "SBR with a 960 frame length");
+            ac->warned_960_sbr = 1;
+            skip_bits_long(gb, 8 * cnt - 4);
+            return res;
         } else if (!ac->oc[1].m4ac.sbr) {
             av_log(ac->avctx, AV_LOG_ERROR, "SBR signaled to be not-present but was found in the bitstream.\n");
             skip_bits_long(gb, 8 * cnt - 4);
@@ -2607,6 +2643,73 @@  static void imdct_and_windowing(AACContext *ac, SingleChannelElement *sce)
     }
 }
 
+/**
+ * Conduct IMDCT and windowing.
+ */
+static void imdct_and_windowing_960(AACContext *ac, SingleChannelElement *sce)
+{
+#if !USE_FIXED
+    IndividualChannelStream *ics = &sce->ics;
+    INTFLOAT *in    = sce->coeffs;
+    INTFLOAT *out   = sce->ret;
+    INTFLOAT *saved = sce->saved;
+    const INTFLOAT *swindow      = ics->use_kb_window[0] ? AAC_RENAME(ff_aac_kbd_short_120) : AAC_RENAME(ff_sine_120);
+    const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_long_960) : AAC_RENAME(ff_sine_960);
+    const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(ff_aac_kbd_short_120) : AAC_RENAME(ff_sine_120);
+    INTFLOAT *buf  = ac->buf_mdct;
+    INTFLOAT *temp = ac->temp;
+    int i;
+
+    // imdct
+    if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+        for (i = 0; i < 8; i++)
+            ac->mdct120->imdct_half(ac->mdct120, buf + i * 120, in + i * 128, 1);
+    } else {
+        ac->mdct960->imdct_half(ac->mdct960, buf, in, 1);
+    }
+
+    /* window overlapping
+     * NOTE: To simplify the overlapping code, all 'meaningless' short to long
+     * and long to short transitions are considered to be short to short
+     * transitions. This leaves just two cases (long to long and short to short)
+     * with a little special sauce for EIGHT_SHORT_SEQUENCE.
+     */
+
+    if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
+        (ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
+        ac->fdsp->vector_fmul_window(    out,               saved,            buf,         lwindow_prev, 480);
+    } else {
+        memcpy(                          out,               saved,            420 * sizeof(*out));
+
+        if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+            ac->fdsp->vector_fmul_window(out + 420 + 0*120, saved + 420,      buf + 0*120, swindow_prev, 60);
+            ac->fdsp->vector_fmul_window(out + 420 + 1*120, buf + 0*120 + 60, buf + 1*120, swindow,      60);
+            ac->fdsp->vector_fmul_window(out + 420 + 2*120, buf + 1*120 + 60, buf + 2*120, swindow,      60);
+            ac->fdsp->vector_fmul_window(out + 420 + 3*120, buf + 2*120 + 60, buf + 3*120, swindow,      60);
+            ac->fdsp->vector_fmul_window(temp,              buf + 3*120 + 60, buf + 4*120, swindow,      60);
+            memcpy(                      out + 420 + 4*120, temp, 60 * sizeof(*out));
+        } else {
+            ac->fdsp->vector_fmul_window(out + 420,         saved + 420,      buf,         swindow_prev, 60);
+            memcpy(                      out + 540,         buf + 60,         420 * sizeof(*out));
+        }
+    }
+
+    // buffer update
+    if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+        memcpy(                      saved,       temp + 60,         60 * sizeof(*saved));
+        ac->fdsp->vector_fmul_window(saved + 60,  buf + 4*120 + 60, buf + 5*120, swindow, 60);
+        ac->fdsp->vector_fmul_window(saved + 180, buf + 5*120 + 60, buf + 6*120, swindow, 60);
+        ac->fdsp->vector_fmul_window(saved + 300, buf + 6*120 + 60, buf + 7*120, swindow, 60);
+        memcpy(                      saved + 420, buf + 7*120 + 60,  60 * sizeof(*saved));
+    } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
+        memcpy(                      saved,       buf + 480,        420 * sizeof(*saved));
+        memcpy(                      saved + 420, buf + 7*120 + 60,  60 * sizeof(*saved));
+    } else { // LONG_STOP or ONLY_LONG
+        memcpy(                      saved,       buf + 480,        480 * sizeof(*saved));
+    }
+#endif
+}
+
 static void imdct_and_windowing_ld(AACContext *ac, SingleChannelElement *sce)
 {
     IndividualChannelStream *ics = &sce->ics;
@@ -2758,7 +2861,10 @@  static void spectral_to_sample(AACContext *ac, int samples)
         imdct_and_window = imdct_and_windowing_eld;
         break;
     default:
-        imdct_and_window = ac->imdct_and_windowing;
+        if (ac->oc[1].m4ac.frame_length_short)
+            imdct_and_window = imdct_and_windowing_960;
+        else
+            imdct_and_window = ac->imdct_and_windowing;
     }
     for (type = 3; type >= 0; type--) {
         for (i = 0; i < MAX_ELEM_ID; i++) {
@@ -3002,7 +3108,7 @@  static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
                 err = AVERROR_INVALIDDATA;
                 goto fail;
             }
-            samples = 1024;
+            samples = ac->oc[1].m4ac.frame_length_short ? 960 : 1024;
             che->present = 1;
         }
 
@@ -3229,7 +3335,9 @@  static av_cold int aac_decode_close(AVCodecContext *avctx)
     ff_mdct_end(&ac->mdct_ld);
     ff_mdct_end(&ac->mdct_ltp);
 #if !USE_FIXED
+    ff_mdct15_uninit(&ac->mdct120);
     ff_mdct15_uninit(&ac->mdct480);
+    ff_mdct15_uninit(&ac->mdct960);
 #endif
     av_freep(&ac->fdsp);
     return 0;
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index 930d33e..0ce9fcb 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -620,8 +620,7 @@  static int read_sbr_grid(AACContext *ac, SpectralBandReplication *sbr,
 {
     int i;
     int bs_pointer = 0;
-    // frameLengthFlag ? 15 : 16; 960 sample length frames unsupported; this value is numTimeSlots
-    int abs_bord_trail = 16;
+    int abs_bord_trail = ac->oc[1].m4ac.frame_length_short ? 15 : 16;
     int num_rel_lead, num_rel_trail;
     unsigned bs_num_env_old = ch_data->bs_num_env;
     int bs_frame_class, bs_num_env;
diff --git a/libavcodec/aactab.c b/libavcodec/aactab.c
index 77d8732..057485a 100644
--- a/libavcodec/aactab.c
+++ b/libavcodec/aactab.c
@@ -37,6 +37,10 @@  float ff_aac_pow34sf_tab[428];
 
 DECLARE_ALIGNED(32, float,  ff_aac_kbd_long_1024)[1024];
 DECLARE_ALIGNED(32, float,  ff_aac_kbd_short_128)[128];
+DECLARE_ALIGNED(32, float,  ff_aac_kbd_long_960)[960];
+DECLARE_ALIGNED(32, float,  ff_aac_kbd_short_120)[120];
+DECLARE_ALIGNED(32, int,    ff_aac_kbd_long_960_fixed)[960];
+DECLARE_ALIGNED(32, int,    ff_aac_kbd_short_120_fixed)[120];
 DECLARE_ALIGNED(32, int,    ff_aac_kbd_long_1024_fixed)[1024];
 DECLARE_ALIGNED(32, int,    ff_aac_kbd_short_128_fixed)[128];
 
@@ -44,6 +48,10 @@  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_960[] = {
+    40, 40, 46, 49, 49, 49, 46, 46, 42, 42, 42, 40, 40
+};
+
 const uint8_t ff_aac_num_swb_512[] = {
      0,  0,  0, 36, 36, 37, 31, 31,  0,  0,  0,  0,  0
 };
@@ -56,6 +64,10 @@  const uint8_t ff_aac_num_swb_128[] = {
     12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15
 };
 
+const uint8_t ff_aac_num_swb_120[] = {
+    12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15
+};
+
 const uint8_t ff_aac_pred_sfb_max[] = {
     33, 33, 38, 40, 40, 40, 41, 41, 37, 37, 37, 34, 34
 };
@@ -1229,6 +1241,100 @@  static const uint16_t swb_offset_128_8[] = {
     36,  44,  52,  60,  72,  88, 108, 128
 };
 
+static const uint16_t swb_offset_960_96[] =
+{
+    0,   4,   8,   12,  16,  20,  24,  28,  32,  36,
+    40,  44,  48,  52,  56,  64,  72,  80,  88,  96,
+    108, 120, 132, 144, 156, 172, 188, 212, 240, 276,
+    320, 384, 448, 512, 576, 640, 704, 768, 832, 896,
+    960
+};
+
+static const uint16_t swb_offset_960_64[] =
+{
+    0,   4,   8,   12,  16,  20,  24,  28,  32,  36,
+    40,  44,  48,  52,  56,  64,  72,  80,  88,  100,
+    112, 124, 140, 156, 172, 192, 216, 240, 268, 304,
+    344, 384, 424, 464, 504, 544, 584, 624, 664, 704,
+    744, 784, 824, 864, 904, 944, 960
+};
+
+static const uint16_t swb_offset_960_48[] =
+{
+    0,   4,   8,   12,  16,  20,  24,  28,  32,  36,
+    40,  48,  56,  64,  72,  80,  88,  96,  108, 120,
+    132, 144, 160, 176, 196, 216, 240, 264, 292, 320,
+    352, 384, 416, 448, 480, 512, 544, 576, 608, 640,
+    672, 704, 736, 768, 800, 832, 864, 896, 928, 960
+};
+
+static const uint16_t swb_offset_960_32[] =
+{
+    0,   4,   8,   12,  16,  20,  24,  28,  32,  36,
+    40,  48,  56,  64,  72,  80,  88,  96,  108, 120,
+    132, 144, 160, 176, 196, 216, 240, 264, 292, 320,
+    352, 384, 416, 448, 480, 512, 544, 576, 608, 640,
+    672, 704, 736, 768, 800, 832, 864, 896, 928, 960
+};
+
+static const uint16_t swb_offset_960_24[] =
+{
+    0,   4,   8,   12,  16,  20,  24,  28,  32,  36,
+    40,  44,  52,  60,  68,  76,  84,  92,  100, 108,
+    116, 124, 136, 148, 160, 172, 188, 204, 220, 240,
+    260, 284, 308, 336, 364, 396, 432, 468, 508, 552,
+    600, 652, 704, 768, 832, 896, 960
+};
+
+static const uint16_t swb_offset_960_16[] =
+{
+    0,   8,   16,  24,  32,  40,  48,  56,  64,  72,
+    80,  88,  100, 112, 124, 136, 148, 160, 172, 184,
+    196, 212, 228, 244, 260, 280, 300, 320, 344, 368,
+    396, 424, 456, 492, 532, 572, 616, 664, 716, 772,
+    832, 896, 960
+};
+
+static const uint16_t swb_offset_960_8[] =
+{
+    0,   12,  24,  36,  48,  60,  72,  84,  96,  108,
+    120, 132, 144, 156, 172, 188, 204, 220, 236, 252,
+    268, 288, 308, 328, 348, 372, 396, 420, 448, 476,
+    508, 544, 580, 620, 664, 712, 764, 820, 880, 944,
+    960
+};
+
+
+static const uint16_t swb_offset_120_96[] =
+{
+    0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 120
+};
+
+static const uint16_t swb_offset_120_64[] =
+{
+    0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 120
+};
+
+static const uint16_t swb_offset_120_48[] =
+{
+    0,  4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 120
+};
+
+static const uint16_t swb_offset_120_24[] =
+{
+    0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 120
+};
+
+static const uint16_t swb_offset_120_16[] =
+{
+    0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 120
+};
+
+static const uint16_t swb_offset_120_8[] =
+{
+    0, 4, 8, 12, 16,  20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 120
+};
+
 const uint16_t * const ff_swb_offset_1024[] = {
     swb_offset_1024_96, swb_offset_1024_96, swb_offset_1024_64,
     swb_offset_1024_48, swb_offset_1024_48, swb_offset_1024_32,
@@ -1237,6 +1343,14 @@  const uint16_t * const ff_swb_offset_1024[] = {
     swb_offset_1024_8
 };
 
+const uint16_t * const ff_swb_offset_960[] = {
+    swb_offset_960_96, swb_offset_960_96, swb_offset_960_64,
+    swb_offset_960_48, swb_offset_960_48, swb_offset_960_32,
+    swb_offset_960_24, swb_offset_960_24, swb_offset_960_16,
+    swb_offset_960_16, swb_offset_960_16, swb_offset_960_8,
+    swb_offset_960_8
+};
+
 const uint16_t * const ff_swb_offset_512[] = {
     NULL,               NULL,               NULL,
     swb_offset_512_48,  swb_offset_512_48,  swb_offset_512_32,
@@ -1263,6 +1377,14 @@  const uint16_t * const ff_swb_offset_128[] = {
     swb_offset_128_8
 };
 
+const uint16_t * const ff_swb_offset_120[] = {
+    swb_offset_120_96, swb_offset_120_96, swb_offset_120_96,
+    swb_offset_120_48, swb_offset_120_48, swb_offset_120_48,
+    swb_offset_120_24, swb_offset_120_24, swb_offset_120_16,
+    swb_offset_120_16, swb_offset_120_16, swb_offset_120_8,
+    swb_offset_120_8
+};
+
 // @}
 
 /* @name ff_tns_max_bands
diff --git a/libavcodec/aactab.h b/libavcodec/aactab.h
index 48ca0fd..03e0d8f 100644
--- a/libavcodec/aactab.h
+++ b/libavcodec/aactab.h
@@ -136,6 +136,10 @@  static const INTFLOAT * const tns_tmp2_map[4] = {
  */
 DECLARE_ALIGNED(32, extern float,  ff_aac_kbd_long_1024)[1024];
 DECLARE_ALIGNED(32, extern float,  ff_aac_kbd_short_128)[128];
+DECLARE_ALIGNED(32, extern float,  ff_aac_kbd_long_960)[960];
+DECLARE_ALIGNED(32, extern float,  ff_aac_kbd_short_120)[120];
+DECLARE_ALIGNED(32, extern int,    ff_aac_kbd_long_960_fixed)[960];
+DECLARE_ALIGNED(32, extern int,    ff_aac_kbd_short_120_fixed)[120];
 DECLARE_ALIGNED(32, extern int,    ff_aac_kbd_long_1024_fixed)[1024];
 DECLARE_ALIGNED(32, extern int,    ff_aac_kbd_long_512_fixed)[512];
 DECLARE_ALIGNED(32, extern int,    ff_aac_kbd_short_128_fixed)[128];
@@ -149,9 +153,11 @@  DECLARE_ALIGNED(32, extern const int,   ff_aac_eld_window_480_fixed)[1800];
  * @{
  */
 extern const uint8_t ff_aac_num_swb_1024[];
+extern const uint8_t ff_aac_num_swb_960 [];
 extern const uint8_t ff_aac_num_swb_512 [];
 extern const uint8_t ff_aac_num_swb_480 [];
 extern const uint8_t ff_aac_num_swb_128 [];
+extern const uint8_t ff_aac_num_swb_120 [];
 // @}
 
 extern const uint8_t ff_aac_pred_sfb_max [];
@@ -168,9 +174,11 @@  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_960 [13];
 extern const uint16_t * const ff_swb_offset_512 [13];
 extern const uint16_t * const ff_swb_offset_480 [13];
 extern const uint16_t * const ff_swb_offset_128 [13];
+extern const uint16_t * const ff_swb_offset_120 [13];
 
 extern const uint8_t ff_tns_max_bands_1024[13];
 extern const uint8_t ff_tns_max_bands_512 [13];
diff --git a/libavcodec/sinewin.h b/libavcodec/sinewin.h
index 27c107c..6b97a71 100644
--- a/libavcodec/sinewin.h
+++ b/libavcodec/sinewin.h
@@ -52,14 +52,16 @@  void AAC_RENAME(ff_init_ff_sine_windows)(int index);
 
 extern SINETABLE(  32);
 extern SINETABLE(  64);
+extern SINETABLE( 120);
 extern SINETABLE( 128);
 extern SINETABLE( 256);
 extern SINETABLE( 512);
+extern SINETABLE( 960);
 extern SINETABLE(1024);
 extern SINETABLE(2048);
 extern SINETABLE(4096);
 extern SINETABLE(8192);
 
-extern SINETABLE_CONST INTFLOAT * const AAC_RENAME(ff_sine_windows)[14];
+extern SINETABLE_CONST INTFLOAT * const AAC_RENAME(ff_sine_windows)[16];
 
 #endif /* AVCODEC_SINEWIN_H */
diff --git a/libavcodec/sinewin_tablegen.h b/libavcodec/sinewin_tablegen.h
index 4432135..30c8cbf 100644
--- a/libavcodec/sinewin_tablegen.h
+++ b/libavcodec/sinewin_tablegen.h
@@ -34,9 +34,11 @@ 
 #if !CONFIG_HARDCODED_TABLES
 SINETABLE(  32);
 SINETABLE(  64);
+SINETABLE( 120);
 SINETABLE( 128);
 SINETABLE( 256);
 SINETABLE( 512);
+SINETABLE( 960);
 SINETABLE(1024);
 SINETABLE(2048);
 SINETABLE(4096);
@@ -59,7 +61,8 @@  SINETABLE_CONST INTFLOAT * const AAC_RENAME(ff_sine_windows)[] = {
     NULL, NULL, NULL, NULL, NULL, // unused
     AAC_RENAME(ff_sine_32) , AAC_RENAME(ff_sine_64), AAC_RENAME(ff_sine_128),
     AAC_RENAME(ff_sine_256), AAC_RENAME(ff_sine_512), AAC_RENAME(ff_sine_1024),
-    AAC_RENAME(ff_sine_2048), AAC_RENAME(ff_sine_4096), AAC_RENAME(ff_sine_8192)
+    AAC_RENAME(ff_sine_2048), AAC_RENAME(ff_sine_4096), AAC_RENAME(ff_sine_8192),
+    AAC_RENAME(ff_sine_120), AAC_RENAME(ff_sine_960),
 };
 
 // Generate a sine window.