PR #20941 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20941
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20941.patch


>From ac98c3e731bccf35480a3bddebc930627cd2d482 Mon Sep 17 00:00:00 2001
From: Lynne <[email protected]>
Date: Sat, 20 May 2023 16:09:22 +0200
Subject: [PATCH] aacdec: add support for 960-frame HE-AAC

---
 libavcodec/aac/aacdec.c      |  22 +----
 libavcodec/aac/aacdec.h      |   6 +-
 libavcodec/aac/aacdec_usac.c |   6 +-
 libavcodec/aacps.c           |  11 ++-
 libavcodec/aacps.h           |   7 +-
 libavcodec/aacps_common.c    |   3 +-
 libavcodec/aacsbr.h          |  15 ++-
 libavcodec/aacsbr_template.c | 179 +++++++++++++++++++++--------------
 libavcodec/sbr.h             |  16 ++--
 libavcodec/sbrdsp.c          |  52 ++++++++++
 libavcodec/sbrdsp.h          |  12 +--
 libavcodec/sbrdsp_template.c |  43 +++++++--
 libavcodec/x86/sbrdsp_init.c |  28 +++---
 13 files changed, 263 insertions(+), 137 deletions(-)

diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 9b42014ee8..394365e9b2 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -883,12 +883,6 @@ static int decode_ga_specific_config(AACDecContext *ac, 
AVCodecContext *avctx,
     int tags = 0;
 
     m4ac->frame_length_short = get_bits1(gb);
-    if (m4ac->frame_length_short && m4ac->sbr == 1) {
-      avpriv_report_missing_feature(avctx, "SBR with 960 frame length");
-      if (ac) ac->warned_960_sbr = 1;
-      m4ac->sbr = 0;
-      m4ac->ps = 0;
-    }
 
     if (get_bits1(gb))       // dependsOnCoreCoder
         skip_bits(gb, 14);   // coreCoderDelay
@@ -1089,10 +1083,10 @@ static int 
decode_audio_specific_config_gb(AACDecContext *ac,
     }
 
     ff_dlog(avctx,
-            "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
+            "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d MDCT 
%d\n",
             m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
             m4ac->sample_rate, m4ac->sbr,
-            m4ac->ps);
+            m4ac->ps, m4ac->frame_length_short ? 960 : 1024);
 
     return get_bits_count(gb);
 }
@@ -1944,13 +1938,6 @@ static int decode_extension_payload(AACDecContext *ac, 
GetBitContext *gb, int cn
         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 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);
@@ -1971,7 +1958,8 @@ static int decode_extension_payload(AACDecContext *ac, 
GetBitContext *gb, int cn
             ac->avctx->profile = AV_PROFILE_AAC_HE;
         }
 
-        ac->proc.sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
+        ac->proc.sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type,
+                                      ac->oc[1].m4ac.frame_length_short);
 
         if (ac->oc[1].m4ac.ps == 1 && !ac->warned_he_aac_mono) {
             av_log(ac->avctx, AV_LOG_VERBOSE, "Treating HE-AAC mono as 
stereo.\n");
@@ -2082,7 +2070,7 @@ static void spectral_to_sample(AACDecContext *ac, int 
samples)
                     if (ac->oc[1].m4ac.sbr > 0) {
                         ac->proc.sbr_apply(ac, che, type,
                                            che->ch[0].output,
-                                           che->ch[1].output);
+                                           che->ch[1].output, 
ac->oc[1].m4ac.frame_length_short);
                     }
                 }
                 if (type <= TYPE_CCE)
diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index b3763fdccc..ff72a15903 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -402,9 +402,11 @@ typedef struct AACDecProc {
 
     int (*sbr_ctx_alloc_init)(AACDecContext *ac, ChannelElement **che, int 
id_aac);
     int (*sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
-                                GetBitContext *gb, int crc, int cnt, int 
id_aac);
+                                GetBitContext *gb, int crc, int cnt, int 
id_aac,
+                                int frame_length_short);
     void (*sbr_apply)(AACDecContext *ac, ChannelElement *che,
-                      int id_aac, void /* INTFLOAT */ *L, void /* INTFLOAT */ 
*R);
+                      int id_aac, void /* INTFLOAT */ *L, void /* INTFLOAT */ 
*R,
+                      int frame_length_short);
     void (*sbr_ctx_close)(ChannelElement *che);
 } AACDecProc;
 
diff --git a/libavcodec/aac/aacdec_usac.c b/libavcodec/aac/aacdec_usac.c
index c4b821bbba..a9ab5ca93a 100644
--- a/libavcodec/aac/aacdec_usac.c
+++ b/libavcodec/aac/aacdec_usac.c
@@ -1477,7 +1477,8 @@ static int decode_usac_core_coder(AACDecContext *ac, 
AACUSACConfig *usac,
             !(ec->stereo_config_index == 0 || ec->stereo_config_index == 3))
             sbr_ch = 1;
 
-        ret = ff_aac_sbr_decode_usac_data(ac, che, ec, gb, sbr_ch, indep_flag);
+        ret = ff_aac_sbr_decode_usac_data(ac, che, ec, gb, sbr_ch, indep_flag,
+                                          ac->oc[1].m4ac.frame_length_short);
         if (ret < 0)
             return ret;
     }
@@ -1492,7 +1493,8 @@ static int decode_usac_core_coder(AACDecContext *ac, 
AACUSACConfig *usac,
     if (ac->oc[1].m4ac.sbr > 0) {
         ac->proc.sbr_apply(ac, che, nb_channels == 2 ? TYPE_CPE : TYPE_SCE,
                            che->ch[0].output,
-                           che->ch[1].output);
+                           che->ch[1].output,
+                           ac->oc[1].m4ac.frame_length_short);
     }
 
     return 0;
diff --git a/libavcodec/aacps.c b/libavcodec/aacps.c
index 6008edd332..69cebea655 100644
--- a/libavcodec/aacps.c
+++ b/libavcodec/aacps.c
@@ -396,7 +396,8 @@ static void map_val_20_to_34(INTFLOAT par[PS_MAX_NR_IIDICC])
     par[ 1] = AAC_HALF_SUM(par[ 0], par[ 1]);
 }
 
-static void decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const 
INTFLOAT (*s)[32][2], int is34)
+static void decorrelation(PSContext *ps, INTFLOAT (*out)[32][2], const 
INTFLOAT (*s)[32][2], int is34,
+                          int frame_length_short)
 {
     LOCAL_ALIGNED_16(INTFLOAT, power, [34], [PS_QMF_TIME_SLOTS]);
     LOCAL_ALIGNED_16(INTFLOAT, transient_gain, [34], [PS_QMF_TIME_SLOTS]);
@@ -405,6 +406,7 @@ static void decorrelation(PSContext *ps, INTFLOAT 
(*out)[32][2], const INTFLOAT
     INTFLOAT *peak_decay_diff_smooth = ps->peak_decay_diff_smooth;
     INTFLOAT (*delay)[PS_QMF_TIME_SLOTS + PS_MAX_DELAY][2] = ps->delay;
     INTFLOAT (*ap_delay)[PS_AP_LINKS][PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2] 
= ps->ap_delay;
+    const int numQMFSlots = frame_length_short ? 30 : 32;
 #if !USE_FIXED
     const float transient_impact  = 1.5f;
     const float a_smooth          = 0.25f; ///< Smoothing coefficient
@@ -716,11 +718,12 @@ static void stereo_processing(PSContext *ps, INTFLOAT 
(*l)[32][2], INTFLOAT (*r)
     }
 }
 
-int AAC_RENAME(ff_ps_apply)(PSContext *ps, INTFLOAT L[2][38][64], INTFLOAT 
R[2][38][64], int top)
+int AAC_RENAME(ff_ps_apply)(PSContext *ps, INTFLOAT L[2][38][64], INTFLOAT 
R[2][38][64], int top,
+                            int frame_length_short)
 {
     INTFLOAT (*Lbuf)[32][2] = ps->Lbuf;
     INTFLOAT (*Rbuf)[32][2] = ps->Rbuf;
-    const int len = 32;
+    const int len = frame_length_short ? 30 : 32; // TODO NOT SURE
     int is34 = ps->common.is34bands;
 
     top += NR_BANDS[is34] - 64;
@@ -729,7 +732,7 @@ int AAC_RENAME(ff_ps_apply)(PSContext *ps, INTFLOAT 
L[2][38][64], INTFLOAT R[2][
         memset(ps->ap_delay + top, 0, (NR_ALLPASS_BANDS[is34] - 
top)*sizeof(ps->ap_delay[0]));
 
     hybrid_analysis(&ps->dsp, Lbuf, ps->in_buf, L, is34, len);
-    decorrelation(ps, Rbuf, (const INTFLOAT (*)[32][2]) Lbuf, is34);
+    decorrelation(ps, Rbuf, (const INTFLOAT (*)[32][2]) Lbuf, is34, 
frame_length_short);
     stereo_processing(ps, Lbuf, Rbuf, is34);
     hybrid_synthesis(&ps->dsp, L, Lbuf, is34, len);
     hybrid_synthesis(&ps->dsp, R, Rbuf, is34, len);
diff --git a/libavcodec/aacps.h b/libavcodec/aacps.h
index 08c92dc404..a6554ea441 100644
--- a/libavcodec/aacps.h
+++ b/libavcodec/aacps.h
@@ -42,8 +42,6 @@
                        ///< Baseline implies 10 or 20 stereo bands,
                        ///< mixing mode A, and no ipd/opd
 
-#define numQMFSlots 32 //numTimeSlots * RATE
-
 typedef struct PSCommonContext {
     int    start;
     int    enable_iid;
@@ -100,7 +98,8 @@ static inline void AAC_RENAME(ff_ps_ctx_init)(PSContext *ps)
 }
 
 int ff_ps_read_data(void *logctx, GetBitContext *gb,
-                     PSCommonContext *ps, int bits_left);
-int AAC_RENAME(ff_ps_apply)(PSContext *ps, INTFLOAT L[2][38][64], INTFLOAT 
R[2][38][64], int top);
+                     PSCommonContext *ps, int bits_left, int 
frame_length_short);
+int AAC_RENAME(ff_ps_apply)(PSContext *ps, INTFLOAT L[2][38][64], INTFLOAT 
R[2][38][64], int top,
+                            int frame_length_short);
 
 #endif /* AVCODEC_AACPS_H */
diff --git a/libavcodec/aacps_common.c b/libavcodec/aacps_common.c
index 74fa005aaf..ce2dcbb49a 100644
--- a/libavcodec/aacps_common.c
+++ b/libavcodec/aacps_common.c
@@ -131,13 +131,14 @@ static int ps_read_extension_data(GetBitContext *gb, 
PSCommonContext *ps,
 }
 
 int ff_ps_read_data(void *logctx, GetBitContext *gb_host,
-                    PSCommonContext *ps, int bits_left)
+                    PSCommonContext *ps, int bits_left, int frame_length_short)
 {
     int e;
     int bit_count_start = get_bits_count(gb_host);
     int header;
     int bits_consumed;
     GetBitContext gbc = *gb_host, *gb = &gbc;
+    const int numQMFSlots = frame_length_short ? 30 : 32;
 
     header = get_bits1(gb);
     if (header) {     //enable_ps_header
diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h
index 3958b43b91..f3d03338cb 100644
--- a/libavcodec/aacsbr.h
+++ b/libavcodec/aacsbr.h
@@ -84,9 +84,11 @@ void ff_aac_sbr_ctx_close_fixed(ChannelElement *che);
 
 /** Decode one SBR element. */
 int ff_aac_sbr_decode_extension(AACDecContext *ac, ChannelElement *che,
-                                GetBitContext *gb, int crc, int cnt, int 
id_aac);
+                                GetBitContext *gb, int crc, int cnt, int 
id_aac,
+                                int frame_length_short);
 int ff_aac_sbr_decode_extension_fixed(AACDecContext *ac, ChannelElement *che,
-                                      GetBitContext *gb, int crc, int cnt, int 
id_aac);
+                                      GetBitContext *gb, int crc, int cnt, int 
id_aac,
+                                      int frame_length_short);
 
 /** Due to channel allocation not being known upon SBR parameter transmission,
  * supply the parameters separately.
@@ -97,13 +99,16 @@ int ff_aac_sbr_config_usac(AACDecContext *ac, 
ChannelElement *che,
 /** Decode frame SBR data, USAC. */
 int ff_aac_sbr_decode_usac_data(AACDecContext *ac, ChannelElement *che,
                                 AACUsacElemConfig *ue, GetBitContext *gb,
-                                int sbr_ch, int indep_flag);
+                                int sbr_ch, int indep_flag,
+                                int frame_length_short);
 
 /** Apply one SBR element to one AAC element. */
 void ff_aac_sbr_apply(AACDecContext *ac, ChannelElement *che,
-                      int id_aac, void /* float */ *L, void /* float */ *R);
+                      int id_aac, void /* float */ *L, void /* float */ *R,
+                      int frame_length_short);
 void ff_aac_sbr_apply_fixed(AACDecContext *ac, ChannelElement *che,
-                            int id_aac, void /* int */ *L, void /* int */ *R);
+                            int id_aac, void /* int */ *L, void /* int */ *R,
+                            int frame_length_short);
 
 FF_VISIBILITY_POP_HIDDEN
 
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index 3c39da509d..a745e1f5b2 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -91,15 +91,29 @@ av_cold int 
AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac,
      * mdct scale factors are adjusted to scale up from +/-1.0 at analysis
      * and scale back down at synthesis. */
 
+    scale = USE_FIXED ? 1 : 1.0 / (60 * 32768);
+    ret = av_tx_init(&sbr->mdct60, &sbr->mdct60_fn,
+                     USE_FIXED ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT,
+                     1, 60, &scale, 0);
+    if (ret < 0)
+        return ret;
+
+    scale = USE_FIXED ? -1.0 : -2.0 * 32768;
+    ret = av_tx_init(&sbr->mdct60_ana, &sbr->mdct60_ana_fn,
+                     USE_FIXED ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT,
+                     1, 60, &scale, 0);
+    if (ret < 0)
+        return ret;
+
     scale = USE_FIXED ? 1 : 1.0 / (64 * 32768);
-    ret = av_tx_init(&sbr->mdct, &sbr->mdct_fn,
+    ret = av_tx_init(&sbr->mdct64, &sbr->mdct64_fn,
                      USE_FIXED ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT,
                      1, 64, &scale, 0);
     if (ret < 0)
         return ret;
 
     scale = USE_FIXED ? -1.0 : -2.0 * 32768;
-    ret = av_tx_init(&sbr->mdct_ana, &sbr->mdct_ana_fn,
+    ret = av_tx_init(&sbr->mdct64_ana, &sbr->mdct64_ana_fn,
                      USE_FIXED ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT,
                      1, 64, &scale, 0);
     if (ret < 0)
@@ -115,8 +129,10 @@ av_cold int 
AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac,
 av_cold void AAC_RENAME(ff_aac_sbr_ctx_close)(ChannelElement *che)
 {
     SpectralBandReplication *sbr = get_sbr(che);
-    av_tx_uninit(&sbr->mdct);
-    av_tx_uninit(&sbr->mdct_ana);
+    av_tx_uninit(&sbr->mdct60);
+    av_tx_uninit(&sbr->mdct60_ana);
+    av_tx_uninit(&sbr->mdct64);
+    av_tx_uninit(&sbr->mdct64_ana);
 }
 
 static int qsort_comparison_function_int16(const void *a, const void *b)
@@ -636,12 +652,12 @@ static const int8_t ceil_log2[] = {
 };
 
 static int read_sbr_grid(AACDecContext *ac, SpectralBandReplication *sbr,
-                         GetBitContext *gb, SBRData *ch_data)
+                         GetBitContext *gb, SBRData *ch_data,
+                         int frame_length_short)
 {
     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 = 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;
@@ -964,7 +980,7 @@ static int read_sbr_noise(AACDecContext *ac, 
SpectralBandReplication *sbr, GetBi
 }
 
 static void read_sbr_extension(AACDecContext *ac, SpectralBandReplication *sbr,
-                               GetBitContext *gb,
+                               GetBitContext *gb, int frame_length_short,
                                int bs_extension_id, int *num_bits_left)
 {
     switch (bs_extension_id) {
@@ -974,7 +990,8 @@ static void read_sbr_extension(AACDecContext *ac, 
SpectralBandReplication *sbr,
             skip_bits_long(gb, *num_bits_left); // bs_fill_bits
             *num_bits_left = 0;
         } else {
-            *num_bits_left -= ff_ps_read_data(ac->avctx, gb, &sbr->ps.common, 
*num_bits_left);
+            *num_bits_left -= ff_ps_read_data(ac->avctx, gb, &sbr->ps.common, 
*num_bits_left,
+                                              frame_length_short);
             ac->avctx->profile = AV_PROFILE_AAC_HE_V2;
             // ensure the warning is not printed if PS extension is present
             ac->warned_he_aac_mono = 1;
@@ -992,14 +1009,15 @@ static void read_sbr_extension(AACDecContext *ac, 
SpectralBandReplication *sbr,
 
 static int read_sbr_single_channel_element(AACDecContext *ac,
                                             SpectralBandReplication *sbr,
-                                            GetBitContext *gb)
+                                            GetBitContext *gb,
+                                            int frame_length_short)
 {
     int ret;
 
     if (get_bits1(gb)) // bs_data_extra
         skip_bits(gb, 4); // bs_reserved
 
-    if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]))
+    if (read_sbr_grid(ac, sbr, gb, &sbr->data[0], frame_length_short))
         return -1;
     read_sbr_dtdf(sbr, gb, &sbr->data[0], 0);
     read_sbr_invf(sbr, gb, &sbr->data[0]);
@@ -1016,7 +1034,8 @@ static int read_sbr_single_channel_element(AACDecContext 
*ac,
 
 static int read_sbr_channel_pair_element(AACDecContext *ac,
                                           SpectralBandReplication *sbr,
-                                          GetBitContext *gb)
+                                          GetBitContext *gb,
+                                          int frame_length_short)
 {
     int ret;
 
@@ -1024,7 +1043,7 @@ static int read_sbr_channel_pair_element(AACDecContext 
*ac,
         skip_bits(gb, 8); // bs_reserved
 
     if ((sbr->bs_coupling = get_bits1(gb))) {
-        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]))
+        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0], frame_length_short))
             return -1;
         copy_sbr_grid(&sbr->data[1], &sbr->data[0]);
         read_sbr_dtdf(sbr, gb, &sbr->data[0], 0);
@@ -1041,8 +1060,8 @@ static int read_sbr_channel_pair_element(AACDecContext 
*ac,
         if((ret = read_sbr_noise(ac, sbr, gb, &sbr->data[1], 1)) < 0)
             return ret;
     } else {
-        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]) ||
-            read_sbr_grid(ac, sbr, gb, &sbr->data[1]))
+        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0], frame_length_short) ||
+            read_sbr_grid(ac, sbr, gb, &sbr->data[1], frame_length_short))
             return -1;
         read_sbr_dtdf(sbr, gb, &sbr->data[0], 0);
         read_sbr_dtdf(sbr, gb, &sbr->data[1], 0);
@@ -1067,7 +1086,8 @@ static int read_sbr_channel_pair_element(AACDecContext 
*ac,
 }
 
 static unsigned int read_sbr_data(AACDecContext *ac, SpectralBandReplication 
*sbr,
-                                  GetBitContext *gb, int id_aac)
+                                  GetBitContext *gb, int id_aac,
+                                  int frame_length_short)
 {
     unsigned int cnt = get_bits_count(gb);
 
@@ -1075,12 +1095,12 @@ static unsigned int read_sbr_data(AACDecContext *ac, 
SpectralBandReplication *sb
     sbr->ready_for_dequant = 1;
 
     if (id_aac == TYPE_SCE || id_aac == TYPE_CCE) {
-        if (read_sbr_single_channel_element(ac, sbr, gb)) {
+        if (read_sbr_single_channel_element(ac, sbr, gb, frame_length_short)) {
             sbr_turnoff(sbr);
             return get_bits_count(gb) - cnt;
         }
     } else if (id_aac == TYPE_CPE) {
-        if (read_sbr_channel_pair_element(ac, sbr, gb)) {
+        if (read_sbr_channel_pair_element(ac, sbr, gb, frame_length_short)) {
             sbr_turnoff(sbr);
             return get_bits_count(gb) - cnt;
         }
@@ -1098,7 +1118,7 @@ static unsigned int read_sbr_data(AACDecContext *ac, 
SpectralBandReplication *sb
         num_bits_left <<= 3;
         while (num_bits_left > 7) {
             num_bits_left -= 2;
-            read_sbr_extension(ac, sbr, gb, get_bits(gb, 2), &num_bits_left); 
// bs_extension_id
+            read_sbr_extension(ac, sbr, gb, frame_length_short, get_bits(gb, 
2), &num_bits_left); // bs_extension_id
         }
         if (num_bits_left < 0) {
             av_log(ac->avctx, AV_LOG_ERROR, "SBR Extension over read.\n");
@@ -1133,7 +1153,8 @@ static void sbr_reset(AACDecContext *ac, 
SpectralBandReplication *sbr)
  */
 int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext *ac, ChannelElement 
*che,
                                             GetBitContext *gb_host, int crc,
-                                            int cnt, int id_aac)
+                                            int cnt, int id_aac,
+                                            int frame_length_short)
 {
     SpectralBandReplication *sbr = get_sbr(che);
     unsigned int num_sbr_bits = 0, num_align_bits;
@@ -1166,7 +1187,7 @@ int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext 
*ac, ChannelElement *c
         sbr_reset(ac, sbr);
 
     if (sbr->start)
-        num_sbr_bits  += read_sbr_data(ac, sbr, gb, id_aac);
+        num_sbr_bits  += read_sbr_data(ac, sbr, gb, id_aac, 
frame_length_short);
 
     num_align_bits = ((cnt << 3) - 4 - num_sbr_bits) & 7;
     bytes_read = ((num_sbr_bits + num_align_bits + 4) >> 3);
@@ -1208,7 +1229,8 @@ int ff_aac_sbr_config_usac(AACDecContext *ac, 
ChannelElement *che,
 
 int ff_aac_sbr_decode_usac_data(AACDecContext *ac, ChannelElement *che,
                                 AACUsacElemConfig *ue, GetBitContext *gb,
-                                int sbr_ch, int indep_flag)
+                                int sbr_ch, int indep_flag,
+                                int frame_length_short)
 {
     int ret;
     SpectralBandReplication *sbr = get_sbr(che);
@@ -1272,7 +1294,7 @@ int ff_aac_sbr_decode_usac_data(AACDecContext *ac, 
ChannelElement *che,
     if (sbr_ch == 1) { /* sbr_single_channel_element */
         /* if (harmonicSBR) ... */
 
-        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]))
+        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0], frame_length_short))
             return -1;
 
         read_sbr_dtdf(sbr, gb, &sbr->data[0], indep_flag);
@@ -1289,7 +1311,7 @@ int ff_aac_sbr_decode_usac_data(AACDecContext *ac, 
ChannelElement *che,
     } else if (get_bits1(gb)) { /* bs_coupling == 1 */
         /* if (harmonicSBR) ... */
 
-        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]))
+        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0], frame_length_short))
             return -1;
         copy_sbr_grid(&sbr->data[1], &sbr->data[0]);
 
@@ -1318,9 +1340,9 @@ int ff_aac_sbr_decode_usac_data(AACDecContext *ac, 
ChannelElement *che,
             get_bits1_vector(gb, sbr->data[1].bs_add_harmonic, sbr->n[1]);
     } else { /* bs_coupling == 0 */
         /* if (harmonicSBR) ... */
-        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0]))
+        if (read_sbr_grid(ac, sbr, gb, &sbr->data[0], frame_length_short))
             return -1;
-        if (read_sbr_grid(ac, sbr, gb, &sbr->data[1]))
+        if (read_sbr_grid(ac, sbr, gb, &sbr->data[1], frame_length_short))
             return -1;
 
         read_sbr_dtdf(sbr, gb, &sbr->data[0], indep_flag);
@@ -1364,19 +1386,23 @@ static void sbr_qmf_analysis(AVFloatDSPContext *dsp, 
AVTXContext *mdct,
                              av_tx_fn mdct_fn,
 #endif /* USE_FIXED */
                              SBRDSPContext *sbrdsp, const INTFLOAT *in, 
INTFLOAT *x,
-                             INTFLOAT z[320], INTFLOAT W[2][32][32][2], int 
buf_idx)
+                             INTFLOAT z[320], INTFLOAT W[2][32][32][2], int 
buf_idx,
+                             int frame_length_short)
 {
     int i;
+    const int lp = frame_length_short ? 15*2 : 16*2;
+    const int frameLength = frame_length_short ? 960 : 1024;
 #if USE_FIXED
     int j;
 #endif
-    memcpy(x    , x+1024, (320-32)*sizeof(x[0]));
-    memcpy(x+288, in,         1024*sizeof(x[0]));
-    for (i = 0; i < 32; i++) { // numTimeSlots*RATE = 16*2 as 960 sample frames
-                               // are not supported
+
+    memcpy(x      , x + frameLength,  (320 - 32) * sizeof(x[0]));
+    memcpy(x + 288,              in, frameLength * sizeof(x[0]));
+
+    for (i = 0; i < lp; i++) {
         dsp->vector_fmul_reverse(z, sbr_qmf_window_ds, x, 320);
-        sbrdsp->sum64x5(z);
-        sbrdsp->qmf_pre_shuffle(z);
+        sbrdsp->sum64x5[frame_length_short](z);
+        sbrdsp->qmf_pre_shuffle[frame_length_short](z);
 #if USE_FIXED
         for (j = 64; j < 128; j++) {
             if (z[j] > 1<<24) {
@@ -1392,9 +1418,9 @@ static void sbr_qmf_analysis(AVFloatDSPContext *dsp, 
AVTXContext *mdct,
             }
         }
 #endif
-        mdct_fn(mdct, z, z + 64, sizeof(INTFLOAT));
-        sbrdsp->qmf_post_shuffle(W[buf_idx][i], z);
-        x += 32;
+        mdct_fn(mdct, z, z + lp*2, sizeof(INTFLOAT));
+        sbrdsp->qmf_post_shuffle[frame_length_short](W[buf_idx][i], z);
+        x += lp;
     }
 }
 #endif
@@ -1412,15 +1438,18 @@ static void sbr_qmf_synthesis(AVTXContext *mdct, 
av_tx_fn mdct_fn,
 #endif /* USE_FIXED */
                               INTFLOAT *out, INTFLOAT X[2][38][64],
                               INTFLOAT mdct_buf[2][64],
-                              INTFLOAT *v0, int *v_off, const unsigned int div)
+                              INTFLOAT *v0, int *v_off, const unsigned int div,
+                              int frame_length_short)
 {
     int i, n;
     const INTFLOAT *sbr_qmf_window = div ? sbr_qmf_window_ds : 
sbr_qmf_window_us;
-    const int step = 128 >> div;
+    const int lp = frame_length_short ? 15*2 : 16*2;
+    const int lf = frame_length_short ? 60 : 64;
+    const int step = lf*2 >> div;
     INTFLOAT *v;
-    for (i = 0; i < 32; i++) {
+    for (i = 0; i < lp; i++) {
         if (*v_off < step) {
-            int saved_samples = (1280 - 128) >> div;
+            int saved_samples = (1200 - lf*2) >> div;
             memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, 
saved_samples * sizeof(INTFLOAT));
             *v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - step;
         } else {
@@ -1428,29 +1457,29 @@ static void sbr_qmf_synthesis(AVTXContext *mdct, 
av_tx_fn mdct_fn,
         }
         v = v0 + *v_off;
         if (div) {
-            for (n = 0; n < 32; n++) {
+            for (n = 0; n < lp; n++) {
                 X[0][i][   n] = -X[0][i][n];
-                X[0][i][32+n] =  X[1][i][31-n];
+                X[0][i][lp+n] =  X[1][i][lp - 1 - n];
             }
             mdct_fn(mdct, mdct_buf[0], X[0][i], sizeof(INTFLOAT));
-            sbrdsp->qmf_deint_neg(v, mdct_buf[0]);
+            sbrdsp->qmf_deint_neg[frame_length_short](v, mdct_buf[0]);
         } else {
-            sbrdsp->neg_odd_64(X[1][i]);
+            sbrdsp->neg_odd_64[frame_length_short](X[1][i]);
             mdct_fn(mdct, mdct_buf[0], X[0][i], sizeof(INTFLOAT));
             mdct_fn(mdct, mdct_buf[1], X[1][i], sizeof(INTFLOAT));
-            sbrdsp->qmf_deint_bfly(v, mdct_buf[1], mdct_buf[0]);
+            sbrdsp->qmf_deint_bfly[frame_length_short](v, mdct_buf[1], 
mdct_buf[0]);
         }
-        dsp->vector_fmul    (out, v                , sbr_qmf_window            
           , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 192 >> div), sbr_qmf_window + ( 64 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 256 >> div), sbr_qmf_window + (128 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 448 >> div), sbr_qmf_window + (192 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 512 >> div), sbr_qmf_window + (256 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 704 >> div), sbr_qmf_window + (320 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 768 >> div), sbr_qmf_window + (384 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + ( 960 >> div), sbr_qmf_window + (448 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + (1024 >> div), sbr_qmf_window + (512 >> 
div), out   , 64 >> div);
-        dsp->vector_fmul_add(out, v + (1216 >> div), sbr_qmf_window + (576 >> 
div), out   , 64 >> div);
-        out += 64 >> div;
+        dsp->vector_fmul    (out, v                 , sbr_qmf_window           
             , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*3  >> div), sbr_qmf_window + (lf*1 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*4  >> div), sbr_qmf_window + (lf*2 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*7  >> div), sbr_qmf_window + (lf*3 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*8  >> div), sbr_qmf_window + (lf*4 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*11 >> div), sbr_qmf_window + (lf*5 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*12 >> div), sbr_qmf_window + (lf*6 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*15 >> div), sbr_qmf_window + (lf*7 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*16 >> div), sbr_qmf_window + (lf*8 
>> div), out   , lf >> div);
+        dsp->vector_fmul_add(out, v + (lf*18 >> div), sbr_qmf_window + (lf*9 
>> div), out   , lf >> div);
+        out += lf >> div;
     }
 }
 #endif
@@ -1458,11 +1487,11 @@ static void sbr_qmf_synthesis(AVTXContext *mdct, 
av_tx_fn mdct_fn,
 /// Generate the subband filtered lowband
 static int sbr_lf_gen(SpectralBandReplication *sbr,
                       INTFLOAT X_low[32][40][2], const INTFLOAT 
W[2][32][32][2],
-                      int buf_idx)
+                      int buf_idx, int frame_length_short)
 {
     int i, k;
     const int t_HFGen = 8;
-    const int i_f = 32;
+    const int i_f = frame_length_short ? 15*2 : 16*2;
     memset(X_low, 0, 32*sizeof(*X_low));
     for (k = 0; k < sbr->kx[1]; k++) {
         for (i = t_HFGen; i < i_f + t_HFGen; i++) {
@@ -1518,10 +1547,11 @@ static int sbr_hf_gen(AACDecContext *ac, 
SpectralBandReplication *sbr,
 /// Generate the subband filtered lowband
 static int sbr_x_gen(SpectralBandReplication *sbr, INTFLOAT X[2][38][64],
                      const INTFLOAT Y0[38][64][2], const INTFLOAT 
Y1[38][64][2],
-                     const INTFLOAT X_low[32][40][2], int ch)
+                     const INTFLOAT X_low[32][40][2], int ch,
+                     int frame_length_short)
 {
     int k, i;
-    const int i_f = 32;
+    const int i_f = frame_length_short ? 15*2 : 16*2;
     const int i_Temp = FFMAX(2*sbr->data[ch].t_env_num_env_old - i_f, 0);
     memset(X, 0, 2*sizeof(*X));
     for (k = 0; k < sbr->kx[0]; k++) {
@@ -1676,10 +1706,17 @@ static void sbr_env_estimate(AAC_FLOAT (*e_curr)[48], 
INTFLOAT X_high[64][40][2]
 }
 
 void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, ChannelElement *che,
-                                  int id_aac, void *L_, void *R_)
+                                  int id_aac, void *L_, void *R_,
+                                  int frame_length_short)
 {
     INTFLOAT *L = L_, *R = R_;
     SpectralBandReplication *sbr = get_sbr(che);
+
+    AVTXContext *mdct = frame_length_short ? sbr->mdct60 : sbr->mdct64;
+    av_tx_fn mdct_fn = frame_length_short ? sbr->mdct60_fn : sbr->mdct64_fn;
+    AVTXContext *mdcta = frame_length_short ? sbr->mdct60_ana : 
sbr->mdct64_ana;
+    av_tx_fn mdcta_fn = frame_length_short ? sbr->mdct60_ana_fn : 
sbr->mdct64_ana_fn;
+
     int downsampled = ac->oc[1].m4ac.ext_sample_rate < sbr->sample_rate;
     int ch;
     int nch = (id_aac == TYPE_CPE) ? 2 : 1;
@@ -1710,13 +1747,14 @@ void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, 
ChannelElement *che,
     }
     for (ch = 0; ch < nch; ch++) {
         /* decode channel */
-        sbr_qmf_analysis(ac->fdsp, sbr->mdct_ana, sbr->mdct_ana_fn, &sbr->dsp,
+        sbr_qmf_analysis(ac->fdsp, mdcta, mdcta_fn, &sbr->dsp,
                          ch ? R : L, sbr->data[ch].analysis_filterbank_samples,
                          (INTFLOAT*)sbr->qmf_filter_scratch,
-                         sbr->data[ch].W, sbr->data[ch].Ypos);
+                         sbr->data[ch].W, sbr->data[ch].Ypos,
+                         frame_length_short);
         sbr->c.sbr_lf_gen(sbr, sbr->X_low,
                           (const INTFLOAT (*)[32][32][2]) sbr->data[ch].W,
-                          sbr->data[ch].Ypos);
+                          sbr->data[ch].Ypos, frame_length_short);
         sbr->data[ch].Ypos ^= 1;
         if (sbr->start) {
             sbr->c.sbr_hf_inverse_filter(&sbr->dsp, sbr->alpha0, sbr->alpha1,
@@ -1746,29 +1784,30 @@ void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, 
ChannelElement *che,
         sbr->c.sbr_x_gen(sbr, sbr->X[ch],
                   (const INTFLOAT (*)[64][2]) 
sbr->data[ch].Y[1-sbr->data[ch].Ypos],
                   (const INTFLOAT (*)[64][2]) sbr->data[ch].Y[  
sbr->data[ch].Ypos],
-                  (const INTFLOAT (*)[40][2]) sbr->X_low, ch);
+                  (const INTFLOAT (*)[40][2]) sbr->X_low, ch, 
frame_length_short);
     }
 
     if (ac->oc[1].m4ac.ps == 1) {
         if (sbr->ps.common.start) {
-            AAC_RENAME(ff_ps_apply)(&sbr->ps, sbr->X[0], sbr->X[1], sbr->kx[1] 
+ sbr->m[1]);
+            AAC_RENAME(ff_ps_apply)(&sbr->ps, sbr->X[0], sbr->X[1], sbr->kx[1] 
+ sbr->m[1],
+                                    frame_length_short);
         } else {
             memcpy(sbr->X[1], sbr->X[0], sizeof(sbr->X[0]));
         }
         nch = 2;
     }
 
-    sbr_qmf_synthesis(sbr->mdct, sbr->mdct_fn, &sbr->dsp, ac->fdsp,
+    sbr_qmf_synthesis(mdct, mdct_fn, &sbr->dsp, ac->fdsp,
                       L, sbr->X[0], sbr->qmf_filter_scratch,
                       sbr->data[0].synthesis_filterbank_samples,
                       &sbr->data[0].synthesis_filterbank_samples_offset,
-                      downsampled);
+                      downsampled, frame_length_short);
     if (nch == 2)
-        sbr_qmf_synthesis(sbr->mdct, sbr->mdct_fn, &sbr->dsp, ac->fdsp,
+        sbr_qmf_synthesis(mdct, mdct_fn, &sbr->dsp, ac->fdsp,
                           R, sbr->X[1], sbr->qmf_filter_scratch,
                           sbr->data[1].synthesis_filterbank_samples,
                           &sbr->data[1].synthesis_filterbank_samples_offset,
-                          downsampled);
+                          downsampled, frame_length_short);
 }
 
 static void aacsbr_func_ptr_init(AACSBRContext *c)
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index 40bb30e04d..1d2f29fb48 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -124,14 +124,14 @@ typedef struct SpectralBandReplication 
SpectralBandReplication;
 typedef struct AACSBRContext {
     int (*sbr_lf_gen)(SpectralBandReplication *sbr,
                       INTFLOAT X_low[32][40][2], const INTFLOAT 
W[2][32][32][2],
-                      int buf_idx);
+                      int buf_idx, int frame_length_short);
     void (*sbr_hf_assemble)(INTFLOAT Y1[38][64][2],
                             const INTFLOAT X_high[64][40][2],
                             SpectralBandReplication *sbr, SBRData *ch_data,
                             const int e_a[2]);
     int (*sbr_x_gen)(SpectralBandReplication *sbr, INTFLOAT X[2][38][64],
                      const INTFLOAT Y0[38][64][2], const INTFLOAT 
Y1[38][64][2],
-                     const INTFLOAT X_low[32][40][2], int ch);
+                     const INTFLOAT X_low[32][40][2], int ch, int 
frame_length_short);
     void (*sbr_hf_inverse_filter)(SBRDSPContext *dsp,
                                   INTFLOAT (*alpha0)[2], INTFLOAT (*alpha1)[2],
                                   const INTFLOAT X_low[32][40][2], int k0);
@@ -215,10 +215,14 @@ struct SpectralBandReplication {
     AAC_FLOAT          s_m[8][48];
     AAC_FLOAT          gain[8][48];
     DECLARE_ALIGNED(32, INTFLOAT, qmf_filter_scratch)[5][64];
-    AVTXContext       *mdct_ana;
-    av_tx_fn           mdct_ana_fn;
-    AVTXContext       *mdct;
-    av_tx_fn           mdct_fn;
+    AVTXContext       *mdct60_ana;
+    av_tx_fn           mdct60_ana_fn;
+    AVTXContext       *mdct60;
+    av_tx_fn           mdct60_fn;
+    AVTXContext       *mdct64_ana;
+    av_tx_fn           mdct64_ana_fn;
+    AVTXContext       *mdct64;
+    av_tx_fn           mdct64_fn;
     SBRDSPContext      dsp;
     AACSBRContext      c;
 };
diff --git a/libavcodec/sbrdsp.c b/libavcodec/sbrdsp.c
index 8d6ffdfe7e..54c42e8c86 100644
--- a/libavcodec/sbrdsp.c
+++ b/libavcodec/sbrdsp.c
@@ -53,6 +53,16 @@ static void sbr_neg_odd_64_c(float *x)
     }
 }
 
+static void sbr_neg_odd_60_c(float *x)
+{
+    union av_intfloat32 *xi = (union av_intfloat32*) x;
+    int i;
+    for (i = 1; i < 60; i += 4) {
+        xi[i + 0].i ^= 1U << 31;
+        xi[i + 2].i ^= 1U << 31;
+    }
+}
+
 static void sbr_qmf_pre_shuffle_c(float *z)
 {
     union av_intfloat32 *zi = (union av_intfloat32*) z;
@@ -94,6 +104,48 @@ static void sbr_qmf_deint_neg_c(float *v, const float *src)
     }
 }
 
+static void sbr_qmf_pre_shuffle_short_c(float *z)
+{
+    union av_intfloat32 *zi = (union av_intfloat32*) z;
+    int k;
+    zi[60].i = zi[0].i;
+    zi[61].i = zi[1].i;
+    for (k = 1; k < 29; k += 2) {
+        zi[60 + 2 * k + 0].i = zi[60 - k].i ^ (1U << 31);
+        zi[60 + 2 * k + 1].i = zi[ k + 1].i;
+        zi[60 + 2 * k + 2].i = zi[59 - k].i ^ (1U << 31);
+        zi[60 + 2 * k + 3].i = zi[ k + 2].i;
+    }
+
+    zi[60 + 2 * 29 + 0].i = zi[60 - 29].i ^ (1U << 31);
+    zi[60 + 2 * 29 + 1].i = zi[29 +  1].i;
+}
+
+static void sbr_qmf_post_shuffle_short_c(float W[32][2], const float *z)
+{
+    const union av_intfloat32 *zi = (const union av_intfloat32*) z;
+    union av_intfloat32 *Wi       = (union av_intfloat32*) W;
+    int k;
+    for (k = 0; k < 30; k += 2) {
+        Wi[2 * k + 0].i = zi[59 - k].i ^ (1U << 31);
+        Wi[2 * k + 1].i = zi[ k + 0].i;
+        Wi[2 * k + 2].i = zi[58 - k].i ^ (1U << 31);
+        Wi[2 * k + 3].i = zi[ k + 1].i;
+    }
+}
+
+static void sbr_qmf_deint_neg_short_c(float *v, const float *src)
+{
+    const union av_intfloat32 *si = (const union av_intfloat32*)src;
+    union av_intfloat32 *vi = (union av_intfloat32*)v;
+    int i;
+    for (i = 0; i < 30; i++) {
+        vi[     i].i = si[59 - 2 * i    ].i;
+        vi[59 - i].i = si[59 - 2 * i - 1].i ^ (1U << 31);
+    }
+}
+
+
 #if 0
     /* This code is slower because it multiplies memory accesses.
      * It is left for educational purposes and because it may offer
diff --git a/libavcodec/sbrdsp.h b/libavcodec/sbrdsp.h
index 09b2cbfc10..878ac15264 100644
--- a/libavcodec/sbrdsp.h
+++ b/libavcodec/sbrdsp.h
@@ -25,13 +25,13 @@
 #include "aac_defines.h"
 
 typedef struct SBRDSPContext {
-    void (*sum64x5)(INTFLOAT *z);
+    void (*sum64x5[2])(INTFLOAT *z);
     AAC_FLOAT (*sum_square)(INTFLOAT (*x)[2], int n);
-    void (*neg_odd_64)(INTFLOAT *x);
-    void (*qmf_pre_shuffle)(INTFLOAT *z);
-    void (*qmf_post_shuffle)(INTFLOAT W[32][2], const INTFLOAT *z);
-    void (*qmf_deint_neg)(INTFLOAT *v, const INTFLOAT *src);
-    void (*qmf_deint_bfly)(INTFLOAT *v, const INTFLOAT *src0, const INTFLOAT 
*src1);
+    void (*neg_odd_64[2])(INTFLOAT *x);
+    void (*qmf_pre_shuffle[2])(INTFLOAT *z);
+    void (*qmf_post_shuffle[2])(INTFLOAT W[32][2], const INTFLOAT *z);
+    void (*qmf_deint_neg[2])(INTFLOAT *v, const INTFLOAT *src);
+    void (*qmf_deint_bfly[2])(INTFLOAT *v, const INTFLOAT *src0, const 
INTFLOAT *src1);
     void (*autocorrelate)(const INTFLOAT x[40][2], AAC_FLOAT phi[3][2][2]);
     void (*hf_gen)(INTFLOAT (*X_high)[2], const INTFLOAT (*X_low)[2],
                    const INTFLOAT alpha0[2], const INTFLOAT alpha1[2],
diff --git a/libavcodec/sbrdsp_template.c b/libavcodec/sbrdsp_template.c
index 9a94af8670..dce05ad499 100644
--- a/libavcodec/sbrdsp_template.c
+++ b/libavcodec/sbrdsp_template.c
@@ -47,6 +47,30 @@ static void sbr_qmf_deint_bfly_c(INTFLOAT *v, const INTFLOAT 
*src0, const INTFLO
     }
 }
 
+static void sbr_sum60x5_c(INTFLOAT *z)
+{
+    int k;
+    for (k = 0; k < 60; k++) {
+        INTFLOAT f = z[k] + z[k + 60] + z[k + 120] + z[k + 180] + z[k + 240];
+        z[k] = f;
+    }
+}
+
+static void sbr_qmf_deint_bfly_short_c(INTFLOAT *v, const INTFLOAT *src0, 
const INTFLOAT *src1)
+{
+    int i;
+    for (i = 0; i < 60; i++) {
+#if USE_FIXED
+        v[      i] = (int)(0x10U + src0[i] - src1[59 - i]) >> 5;
+        v[119 - i] = (int)(0x10U + src0[i] + src1[59 - i]) >> 5;
+#else
+        v[      i] = src0[i] - src1[59 - i];
+        v[119 - i] = src0[i] + src1[59 - i];
+#endif
+    }
+}
+
+
 static void sbr_hf_apply_noise_0(INTFLOAT (*Y)[2], const AAC_FLOAT *s_m,
                                  const AAC_FLOAT *q_filt, int noise,
                                  int kx, int m_max)
@@ -79,17 +103,24 @@ static void sbr_hf_apply_noise_3(INTFLOAT (*Y)[2], const 
AAC_FLOAT *s_m,
 
 av_cold void AAC_RENAME(ff_sbrdsp_init)(SBRDSPContext *s)
 {
-    s->sum64x5 = sbr_sum64x5_c;
+    s->sum64x5[0] = sbr_sum64x5_c;
     s->sum_square = sbr_sum_square_c;
-    s->neg_odd_64 = sbr_neg_odd_64_c;
-    s->qmf_pre_shuffle = sbr_qmf_pre_shuffle_c;
-    s->qmf_post_shuffle = sbr_qmf_post_shuffle_c;
-    s->qmf_deint_neg = sbr_qmf_deint_neg_c;
-    s->qmf_deint_bfly = sbr_qmf_deint_bfly_c;
+    s->neg_odd_64[0] = sbr_neg_odd_64_c;
+    s->qmf_pre_shuffle[0] = sbr_qmf_pre_shuffle_c;
+    s->qmf_post_shuffle[0] = sbr_qmf_post_shuffle_c;
+    s->qmf_deint_neg[0] = sbr_qmf_deint_neg_c;
+    s->qmf_deint_bfly[0] = sbr_qmf_deint_bfly_c;
     s->autocorrelate = sbr_autocorrelate_c;
     s->hf_gen = sbr_hf_gen_c;
     s->hf_g_filt = sbr_hf_g_filt_c;
 
+    s->sum64x5[1] = sbr_sum60x5_c;
+    s->neg_odd_64[1] = sbr_neg_odd_60_c;
+    s->qmf_pre_shuffle[1] = sbr_qmf_pre_shuffle_short_c;
+    s->qmf_post_shuffle[1] = sbr_qmf_post_shuffle_short_c;
+    s->qmf_deint_neg[1] = sbr_qmf_deint_neg_short_c;
+    s->qmf_deint_bfly[1] = sbr_qmf_deint_bfly_short_c;
+
     s->hf_apply_noise[0] = sbr_hf_apply_noise_0;
     s->hf_apply_noise[1] = sbr_hf_apply_noise_1;
     s->hf_apply_noise[2] = sbr_hf_apply_noise_2;
diff --git a/libavcodec/x86/sbrdsp_init.c b/libavcodec/x86/sbrdsp_init.c
index 999f681220..6b78dd574b 100644
--- a/libavcodec/x86/sbrdsp_init.c
+++ b/libavcodec/x86/sbrdsp_init.c
@@ -60,23 +60,23 @@ av_cold void ff_sbrdsp_init_x86(SBRDSPContext *s)
     int cpu_flags = av_get_cpu_flags();
 
     if (EXTERNAL_SSE(cpu_flags)) {
-        s->neg_odd_64 = ff_sbr_neg_odd_64_sse;
-        s->sum_square = ff_sbr_sum_square_sse;
-        s->sum64x5    = ff_sbr_sum64x5_sse;
-        s->hf_g_filt  = ff_sbr_hf_g_filt_sse;
-        s->hf_gen     = ff_sbr_hf_gen_sse;
-        s->qmf_post_shuffle = ff_sbr_qmf_post_shuffle_sse;
-        s->qmf_deint_neg    = ff_sbr_qmf_deint_neg_sse;
-        s->autocorrelate    = ff_sbr_autocorrelate_sse;
+        s->neg_odd_64[0]       = ff_sbr_neg_odd_64_sse;
+        s->sum_square          = ff_sbr_sum_square_sse;
+        s->sum64x5[0]          = ff_sbr_sum64x5_sse;
+        s->hf_g_filt           = ff_sbr_hf_g_filt_sse;
+        s->hf_gen              = ff_sbr_hf_gen_sse;
+        s->qmf_post_shuffle[0] = ff_sbr_qmf_post_shuffle_sse;
+        s->qmf_deint_neg[0]    = ff_sbr_qmf_deint_neg_sse;
+        s->autocorrelate       = ff_sbr_autocorrelate_sse;
     }
 
     if (EXTERNAL_SSE2(cpu_flags)) {
-        s->qmf_deint_bfly   = ff_sbr_qmf_deint_bfly_sse2;
-        s->qmf_pre_shuffle  = ff_sbr_qmf_pre_shuffle_sse2;
-        s->hf_apply_noise[0] = ff_sbr_hf_apply_noise_0_sse2;
-        s->hf_apply_noise[1] = ff_sbr_hf_apply_noise_1_sse2;
-        s->hf_apply_noise[2] = ff_sbr_hf_apply_noise_2_sse2;
-        s->hf_apply_noise[3] = ff_sbr_hf_apply_noise_3_sse2;
+        s->qmf_deint_bfly[0]  = ff_sbr_qmf_deint_bfly_sse2;
+        s->qmf_pre_shuffle[0] = ff_sbr_qmf_pre_shuffle_sse2;
+        s->hf_apply_noise[0]  = ff_sbr_hf_apply_noise_0_sse2;
+        s->hf_apply_noise[1]  = ff_sbr_hf_apply_noise_1_sse2;
+        s->hf_apply_noise[2]  = ff_sbr_hf_apply_noise_2_sse2;
+        s->hf_apply_noise[3]  = ff_sbr_hf_apply_noise_3_sse2;
     }
 
     if (EXTERNAL_SSE3(cpu_flags)) {
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to