* [FFmpeg-devel] [PATCHSET] AAC decoder refactor
@ 2024-04-08 7:36 Lynne
[not found] ` <NuwZLzA--3-9@lynne.ee-NuwcmRV----9>
0 siblings, 1 reply; 12+ messages in thread
From: Lynne @ 2024-04-08 7:36 UTC (permalink / raw)
To: Ffmpeg Devel
[-- Attachment #1: Type: text/plain, Size: 507 bytes --]
The following patchset refactors the AAC decoder step by step,
removing all large-scale templating and abstracting away typed
DSP functions from symbol parsing.
This series saves 110Kib of binary data from libavcodec.so
when compiled with Clang 18 with -O3, after stripping.
The patchset can also be viewed here:
https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
Fate passes on each step, and I've been running this patchset for
a week with no issues.
This also prepares the decoder for USAC support.
[-- Attachment #2: 0038-aacdec-initialize-float-fixed-SBR-tables-only-when-e.patch --]
[-- Type: text/x-diff, Size: 6124 bytes --]
From 593ee3964bb8807fab7f7fd0faf440ab07b4649c Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Fri, 22 Mar 2024 07:13:08 +0100
Subject: [PATCH 38/38] aacdec: initialize float/fixed SBR tables only when
either is needed
---
libavcodec/aac/aacdec.c | 29 +++++++++++++++--------------
libavcodec/aac/aacdec_fixed.c | 3 +++
libavcodec/aac/aacdec_float.c | 3 +++
3 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 01a10468fa..4a29c1b092 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -29,6 +29,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/* We use several quantization functions here (Q31, Q30),
+ * for which we need this to be defined for them to work as expected. */
+#define USE_FIXED 1
+
#include <limits.h>
#include <stddef.h>
@@ -184,8 +188,8 @@ static int frame_configure_elements(AVCodecContext *avctx)
for (id = 0; id < MAX_ELEM_ID; id++) {
ChannelElement *che = ac->che[type][id];
if (che) {
- che->ch[0].AAC_RENAME(output) = che->ch[0].AAC_RENAME(ret_buf);
- che->ch[1].AAC_RENAME(output) = che->ch[1].AAC_RENAME(ret_buf);
+ che->ch[0].output = che->ch[0].ret_buf;
+ che->ch[1].output = che->ch[1].ret_buf;
}
}
}
@@ -202,7 +206,7 @@ static int frame_configure_elements(AVCodecContext *avctx)
/* map output channel pointers to AVFrame data */
for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
if (ac->output_element[ch])
- ac->output_element[ch]->AAC_RENAME(output) = (INTFLOAT *)ac->frame->extended_data[ch];
+ ac->output_element[ch]->output = (void *)ac->frame->extended_data[ch];
}
return 0;
@@ -1107,9 +1111,6 @@ static int sample_rate_idx (int rate)
static av_cold void aac_static_table_init(void)
{
- ff_aac_sbr_init();
- ff_aac_sbr_init_fixed();
-
ff_aacdec_common_init_once();
}
static AVOnce aac_table_init = AV_ONCE_INIT;
@@ -1118,8 +1119,8 @@ static av_cold int decode_close(AVCodecContext *avctx)
{
AACDecContext *ac = avctx->priv_data;
int is_fixed = ac->is_fixed;
- void (*sbr_close)(ChannelElement *che) = is_fixed ? RENAME_FIXED(ff_aac_sbr_ctx_close)
- : ff_aac_sbr_ctx_close;
+ void (*sbr_close)(ChannelElement *che) = is_fixed ? ff_aac_sbr_ctx_close_fixed :
+ ff_aac_sbr_ctx_close;
for (int type = 0; type < FF_ARRAY_ELEMS(ac->che); type++) {
for (int i = 0; i < MAX_ELEM_ID; i++) {
@@ -2069,10 +2070,10 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
}
}
if (che->ch[0].tns.present)
- ac->dsp.apply_tns(che->ch[0].AAC_RENAME(coeffs),
+ ac->dsp.apply_tns(che->ch[0].coeffs,
&che->ch[0].tns, &che->ch[0].ics, 1);
if (che->ch[1].tns.present)
- ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
+ ac->dsp.apply_tns(che->ch[1].coeffs,
&che->ch[1].tns, &che->ch[1].ics, 1);
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling);
@@ -2088,12 +2089,12 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
if (ac->oc[1].m4ac.sbr > 0) {
if (ac->is_fixed)
ff_aac_sbr_apply_fixed(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
+ (void *)che->ch[0].output,
+ (void *)che->ch[1].output);
else
ff_aac_sbr_apply(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
+ (void *)che->ch[0].output,
+ (void *)che->ch[1].output);
}
}
if (type <= TYPE_CCE)
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index a65ba19137..92204180a1 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -41,6 +41,7 @@
#include "libavcodec/sinewin_fixed_tablegen.h"
#include "libavcodec/kbdwin.h"
#include "libavcodec/cbrt_data.h"
+#include "libavcodec/aacsbr.h"
DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME2(aac_kbd_long_1024))[1024];
DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME2(aac_kbd_short_128))[128];
@@ -57,6 +58,8 @@ static void init_tables_fixed_fn(void)
AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960);
AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120);
+ AAC_RENAME(ff_aac_sbr_init)();
+
init_sine_windows_fixed();
}
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index f0e69579f5..63c5fb7897 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -42,6 +42,7 @@
#include "libavcodec/kbdwin.h"
#include "libavcodec/cbrt_data.h"
#include "libavutil/mathematics.h"
+#include "libavcodec/aacsbr.h"
DECLARE_ALIGNED(32, static float, sine_120)[120];
DECLARE_ALIGNED(32, static float, sine_960)[960];
@@ -61,6 +62,8 @@ static void init_tables_float_fn(void)
AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_960), 960);
AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_120), 120);
AAC_RENAME(ff_init_ff_sine_windows)(9);
+
+ AAC_RENAME(ff_aac_sbr_init)();
}
static int init(AACDecContext *ac)
--
2.43.0.381.gb435a96ce8
[-- Attachment #3: 0037-aacsbr-constify-the-only-SBR-table.patch --]
[-- Type: text/x-diff, Size: 9295 bytes --]
From 8731cfe17d73f7ef5cad604db25aec8aeaa21ea9 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Fri, 22 Mar 2024 06:43:16 +0100
Subject: [PATCH 37/38] aacsbr: constify the only SBR table
---
libavcodec/aacsbr_template.c | 10 ---
libavcodec/aacsbrdata.h | 164 ++++++++++++++++++++++++++++++++++-
2 files changed, 163 insertions(+), 11 deletions(-)
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index a7469eb92b..dcfe3f0590 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -48,18 +48,8 @@ static inline SpectralBandReplication *get_sbr(ChannelElement *ch)
return &((ExtChannelElement*)ch)->sbr;
}
-static av_cold void aacsbr_tableinit(void)
-{
- int n;
-
- for (n = 0; n < 320; n++)
- sbr_qmf_window_ds[n] = sbr_qmf_window_us[2*n];
-}
-
av_cold void AAC_RENAME(ff_aac_sbr_init)(void)
{
- aacsbr_tableinit();
-
AAC_RENAME(ff_ps_init)();
}
diff --git a/libavcodec/aacsbrdata.h b/libavcodec/aacsbrdata.h
index b0585309e0..9c25098240 100644
--- a/libavcodec/aacsbrdata.h
+++ b/libavcodec/aacsbrdata.h
@@ -42,7 +42,169 @@ static const int8_t sbr_offset[6][16] = {
};
///< window coefficients for analysis/synthesis QMF banks
-static DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_ds)[320];
+static const DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_ds)[320] = {
+ Q31( 0.0000000000f), Q31(-0.0005617692f),
+ Q31(-0.0004875227f), Q31(-0.0005040714f),
+ Q31(-0.0005466565f), Q31(-0.0005870930f),
+ Q31(-0.0006312493f), Q31(-0.0006777690f),
+ Q31(-0.0007157736f), Q31(-0.0007440941f),
+ Q31(-0.0007681371f), Q31(-0.0007834332f),
+ Q31(-0.0007803664f), Q31(-0.0007757977f),
+ Q31(-0.0007530001f), Q31(-0.0007215391f),
+ Q31(-0.0006650415f), Q31(-0.0005946118f),
+ Q31(-0.0005145572f), Q31(-0.0004095121f),
+ Q31(-0.0002896981f), Q31(-0.0001446380f),
+ Q31( 0.0000134949f), Q31( 0.0002043017f),
+ Q31( 0.0004026540f), Q31( 0.0006239376f),
+ Q31( 0.0008608443f), Q31( 0.0011250155f),
+ Q31( 0.0013902494f), Q31( 0.0016868083f),
+ Q31( 0.0019841140f), Q31( 0.0023017254f),
+ Q31( 0.0026201758f), Q31( 0.0029469447f),
+ Q31( 0.0032739613f), Q31( 0.0036008268f),
+ Q31( 0.0039207432f), Q31( 0.0042264269f),
+ Q31( 0.0045209852f), Q31( 0.0047932560f),
+ Q31( 0.0050393022f), Q31( 0.0052461166f),
+ Q31( 0.0054196775f), Q31( 0.0055475714f),
+ Q31( 0.0056220643f), Q31( 0.0056389199f),
+ Q31( 0.0055917128f), Q31( 0.0054753783f),
+ Q31( 0.0052715758f), Q31( 0.0049839687f),
+ Q31( 0.0046039530f), Q31( 0.0041251642f),
+ Q31( 0.0035401246f), Q31( 0.0028446757f),
+ Q31( 0.0020274176f), Q31( 0.0010902329f),
+ Q31( 0.0000276045f), Q31(-0.0011568135f),
+ Q31(-0.0024826723f), Q31(-0.0039401124f),
+ Q31(-0.0055337211f), Q31(-0.0072615816f),
+ Q31(-0.0091325329f), Q31(-0.0111315548f),
+ Q31( 0.0132718220f), Q31( 0.0155405553f),
+ Q31( 0.0179433381f), Q31( 0.0204531793f),
+ Q31( 0.0230680169f), Q31( 0.0257875847f),
+ Q31( 0.0286072173f), Q31( 0.0315017608f),
+ Q31( 0.0344620948f), Q31( 0.0374812850f),
+ Q31( 0.0405349170f), Q31( 0.0436097542f),
+ Q31( 0.0466843027f), Q31( 0.0497385755f),
+ Q31( 0.0527630746f), Q31( 0.0557173648f),
+ Q31( 0.0585915683f), Q31( 0.0613455171f),
+ Q31( 0.0639715898f), Q31( 0.0664367512f),
+ Q31( 0.0687043828f), Q31( 0.0707628710f),
+ Q31( 0.0725682583f), Q31( 0.0741003642f),
+ Q31( 0.0753137336f), Q31( 0.0761992479f),
+ Q31( 0.0767093490f), Q31( 0.0768230011f),
+ Q31( 0.0765050718f), Q31( 0.0757305756f),
+ Q31( 0.0744664394f), Q31( 0.0726774642f),
+ Q31( 0.0703533073f), Q31( 0.0674525021f),
+ Q31( 0.0639444805f), Q31( 0.0598166570f),
+ Q31( 0.0550460034f), Q31( 0.0495978676f),
+ Q31( 0.0434768782f), Q31( 0.0366418116f),
+ Q31( 0.0290824006f), Q31( 0.0207997072f),
+ Q31( 0.0117623832f), Q31( 0.0019765601f),
+ Q31(-0.0085711749f), Q31(-0.0198834129f),
+ Q31(-0.0319531274f), Q31(-0.0447806821f),
+ Q31(-0.0583705326f), Q31(-0.0726943300f),
+ Q31(-0.0877547536f), Q31(-0.1035329531f),
+ Q31(-0.1200077984f), Q31(-0.1371551761f),
+ Q31(-0.1549607071f), Q31(-0.1733808172f),
+ Q31(-0.1923966745f), Q31(-0.2119735853f),
+ Q31(-0.2320690870f), Q31(-0.2526480309f),
+ Q31(-0.2736634040f), Q31(-0.2950716717f),
+ Q31(-0.3168278913f), Q31(-0.3388722693f),
+ Q31( 0.3611589903f), Q31( 0.3836350013f),
+ Q31( 0.4062317676f), Q31( 0.4289119920f),
+ Q31( 0.4515996535f), Q31( 0.4742453214f),
+ Q31( 0.4967708254f), Q31( 0.5191234970f),
+ Q31( 0.5412553448f), Q31( 0.5630789140f),
+ Q31( 0.5845403235f), Q31( 0.6055783538f),
+ Q31( 0.6261242695f), Q31( 0.6461269695f),
+ Q31( 0.6655139880f), Q31( 0.6842353293f),
+ Q31( 0.7022388719f), Q31( 0.7194462634f),
+ Q31( 0.7358211758f), Q31( 0.7513137456f),
+ Q31( 0.7658674865f), Q31( 0.7794287519f),
+ Q31( 0.7919735841f), Q31( 0.8034485751f),
+ Q31( 0.8138191270f), Q31( 0.8230419890f),
+ Q31( 0.8311038457f), Q31( 0.8379717337f),
+ Q31( 0.8436238281f), Q31( 0.8480315777f),
+ Q31( 0.8511971524f), Q31( 0.8531020949f),
+ Q31( 0.8537385600f), Q31( 0.8531020949f),
+ Q31( 0.8511971524f), Q31( 0.8480315777f),
+ Q31( 0.8436238281f), Q31( 0.8379717337f),
+ Q31( 0.8311038457f), Q31( 0.8230419890f),
+ Q31( 0.8138191270f), Q31( 0.8034485751f),
+ Q31( 0.7919735841f), Q31( 0.7794287519f),
+ Q31( 0.7658674865f), Q31( 0.7513137456f),
+ Q31( 0.7358211758f), Q31( 0.7194462634f),
+ Q31( 0.7022388719f), Q31( 0.6842353293f),
+ Q31( 0.6655139880f), Q31( 0.6461269695f),
+ Q31( 0.6261242695f), Q31( 0.6055783538f),
+ Q31( 0.5845403235f), Q31( 0.5630789140f),
+ Q31( 0.5412553448f), Q31( 0.5191234970f),
+ Q31( 0.4967708254f), Q31( 0.4742453214f),
+ Q31( 0.4515996535f), Q31( 0.4289119920f),
+ Q31( 0.4062317676f), Q31( 0.3836350013f),
+ -Q31( 0.3611589903f), Q31(-0.3388722693f),
+ Q31(-0.3168278913f), Q31(-0.2950716717f),
+ Q31(-0.2736634040f), Q31(-0.2526480309f),
+ Q31(-0.2320690870f), Q31(-0.2119735853f),
+ Q31(-0.1923966745f), Q31(-0.1733808172f),
+ Q31(-0.1549607071f), Q31(-0.1371551761f),
+ Q31(-0.1200077984f), Q31(-0.1035329531f),
+ Q31(-0.0877547536f), Q31(-0.0726943300f),
+ Q31(-0.0583705326f), Q31(-0.0447806821f),
+ Q31(-0.0319531274f), Q31(-0.0198834129f),
+ Q31(-0.0085711749f), Q31( 0.0019765601f),
+ Q31( 0.0117623832f), Q31( 0.0207997072f),
+ Q31( 0.0290824006f), Q31( 0.0366418116f),
+ Q31( 0.0434768782f), Q31( 0.0495978676f),
+ Q31( 0.0550460034f), Q31( 0.0598166570f),
+ Q31( 0.0639444805f), Q31( 0.0674525021f),
+ Q31( 0.0703533073f), Q31( 0.0726774642f),
+ Q31( 0.0744664394f), Q31( 0.0757305756f),
+ Q31( 0.0765050718f), Q31( 0.0768230011f),
+ Q31( 0.0767093490f), Q31( 0.0761992479f),
+ Q31( 0.0753137336f), Q31( 0.0741003642f),
+ Q31( 0.0725682583f), Q31( 0.0707628710f),
+ Q31( 0.0687043828f), Q31( 0.0664367512f),
+ Q31( 0.0639715898f), Q31( 0.0613455171f),
+ Q31( 0.0585915683f), Q31( 0.0557173648f),
+ Q31( 0.0527630746f), Q31( 0.0497385755f),
+ Q31( 0.0466843027f), Q31( 0.0436097542f),
+ Q31( 0.0405349170f), Q31( 0.0374812850f),
+ Q31( 0.0344620948f), Q31( 0.0315017608f),
+ Q31( 0.0286072173f), Q31( 0.0257875847f),
+ Q31( 0.0230680169f), Q31( 0.0204531793f),
+ Q31( 0.0179433381f), Q31( 0.0155405553f),
+ -Q31( 0.0132718220f), Q31(-0.0111315548f),
+ Q31(-0.0091325329f), Q31(-0.0072615816f),
+ Q31(-0.0055337211f), Q31(-0.0039401124f),
+ Q31(-0.0024826723f), Q31(-0.0011568135f),
+ Q31( 0.0000276045f), Q31( 0.0010902329f),
+ Q31( 0.0020274176f), Q31( 0.0028446757f),
+ Q31( 0.0035401246f), Q31( 0.0041251642f),
+ Q31( 0.0046039530f), Q31( 0.0049839687f),
+ Q31( 0.0052715758f), Q31( 0.0054753783f),
+ Q31( 0.0055917128f), Q31( 0.0056389199f),
+ Q31( 0.0056220643f), Q31( 0.0055475714f),
+ Q31( 0.0054196775f), Q31( 0.0052461166f),
+ Q31( 0.0050393022f), Q31( 0.0047932560f),
+ Q31( 0.0045209852f), Q31( 0.0042264269f),
+ Q31( 0.0039207432f), Q31( 0.0036008268f),
+ Q31( 0.0032739613f), Q31( 0.0029469447f),
+ Q31( 0.0026201758f), Q31( 0.0023017254f),
+ Q31( 0.0019841140f), Q31( 0.0016868083f),
+ Q31( 0.0013902494f), Q31( 0.0011250155f),
+ Q31( 0.0008608443f), Q31( 0.0006239376f),
+ Q31( 0.0004026540f), Q31( 0.0002043017f),
+ Q31( 0.0000134949f), Q31(-0.0001446380f),
+ Q31(-0.0002896981f), Q31(-0.0004095121f),
+ Q31(-0.0005145572f), Q31(-0.0005946118f),
+ Q31(-0.0006650415f), Q31(-0.0007215391f),
+ Q31(-0.0007530001f), Q31(-0.0007757977f),
+ Q31(-0.0007803664f), Q31(-0.0007834332f),
+ Q31(-0.0007681371f), Q31(-0.0007440941f),
+ Q31(-0.0007157736f), Q31(-0.0006777690f),
+ Q31(-0.0006312493f), Q31(-0.0005870930f),
+ Q31(-0.0005466565f), Q31(-0.0005040714f),
+ Q31(-0.0004875227f), Q31(-0.0005617692f),
+};
+
/* This table contains redundancy: It is symmetric about the entry #320
* with the exception of entries 384 and 512 which are negated. */
static const DECLARE_ALIGNED(32, INTFLOAT, sbr_qmf_window_us)[640] = {
--
2.43.0.381.gb435a96ce8
[-- Attachment #4: 0036-aacdec-remove-AAC-specific-MIPS-optimizations.patch --]
[-- Type: text/x-diff, Size: 132960 bytes --]
From fe77b812bb426b79b0f8c058b451e0e2ef5e87ab Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 21 Mar 2024 08:23:55 +0100
Subject: [PATCH 36/38] aacdec: remove AAC-specific MIPS optimizations
The code was written in 2012, but seems to have been broken
for just as long. Compilation is broken on every MIPS/MIPS64
system with an FPU (which the code depends on).
---
libavcodec/aac/aacdec.h | 2 -
libavcodec/aacpsy.c | 4 -
libavcodec/aacsbr.c | 4 -
libavcodec/mips/Makefile | 7 +-
libavcodec/mips/aacdec_mips.c | 471 ------------------------
libavcodec/mips/aacdec_mips.h | 253 -------------
libavcodec/mips/aacpsdsp_mips.c | 465 ------------------------
libavcodec/mips/aacpsy_mips.h | 238 ------------
libavcodec/mips/aacsbr_mips.c | 625 --------------------------------
libavcodec/mips/aacsbr_mips.h | 496 -------------------------
10 files changed, 1 insertion(+), 2564 deletions(-)
delete mode 100644 libavcodec/mips/aacdec_mips.c
delete mode 100644 libavcodec/mips/aacdec_mips.h
delete mode 100644 libavcodec/mips/aacpsdsp_mips.c
delete mode 100644 libavcodec/mips/aacpsy_mips.h
delete mode 100644 libavcodec/mips/aacsbr_mips.c
delete mode 100644 libavcodec/mips/aacsbr_mips.h
diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index 9674f897b1..a500d40fb2 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -345,8 +345,6 @@ extern const AACDecDSP aac_dsp_fixed;
extern const AACDecProc aac_proc;
extern const AACDecProc aac_proc_fixed;
-void ff_aacdec_init_mips(AACDecContext *c);
-
int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
GetBitContext *gb, int common_window, int scale_flag);
diff --git a/libavcodec/aacpsy.c b/libavcodec/aacpsy.c
index 1fbd259e51..e6a1542ba9 100644
--- a/libavcodec/aacpsy.c
+++ b/libavcodec/aacpsy.c
@@ -222,10 +222,6 @@ static const float psy_fir_coeffs[] = {
-5.52212e-17 * 2, -0.313819 * 2
};
-#if ARCH_MIPS
-# include "mips/aacpsy_mips.h"
-#endif /* ARCH_MIPS */
-
/**
* Calculate the ABR attack threshold from the above LAME psymodel table.
*/
diff --git a/libavcodec/aacsbr.c b/libavcodec/aacsbr.c
index aafc00049a..78f0aead8e 100644
--- a/libavcodec/aacsbr.c
+++ b/libavcodec/aacsbr.c
@@ -43,10 +43,6 @@
#include <float.h>
#include <math.h>
-#if ARCH_MIPS
-#include "mips/aacsbr_mips.h"
-#endif /* ARCH_MIPS */
-
/**
* 2^(x) for integer x
* @return correctly rounded float
diff --git a/libavcodec/mips/Makefile b/libavcodec/mips/Makefile
index 50fe38a50e..0647c0142a 100644
--- a/libavcodec/mips/Makefile
+++ b/libavcodec/mips/Makefile
@@ -1,5 +1,4 @@
-ARCH_HEADERS = aacsbr_mips.h aacpsy_mips.h \
- cabac.h compute_antialias_fixed.h \
+ARCH_HEADERS = cabac.h compute_antialias_fixed.h \
compute_antialias_float.h \
MIPSFPU-OBJS-$(CONFIG_AMRNB_DECODER) += mips/acelp_filters_mips.o \
@@ -15,10 +14,6 @@ MIPSFPU-OBJS-$(CONFIG_MPEGAUDIODSP) += mips/mpegaudiodsp_mips_float.o
MIPSDSP-OBJS-$(CONFIG_MPEGAUDIODSP) += mips/mpegaudiodsp_mips_fixed.o
MIPSFPU-OBJS-$(CONFIG_FMTCONVERT) += mips/fmtconvert_mips.o
OBJS-$(CONFIG_AC3DSP) += mips/ac3dsp_mips.o
-OBJS-$(CONFIG_AAC_DECODER) += mips/aacdec_mips.o \
- mips/aacsbr_mips.o \
- mips/sbrdsp_mips.o \
- mips/aacpsdsp_mips.o
MIPSFPU-OBJS-$(CONFIG_AAC_ENCODER) += mips/iirfilter_mips.o
OBJS-$(CONFIG_HEVC_DECODER) += mips/hevcdsp_init_mips.o \
mips/hevcpred_init_mips.o
diff --git a/libavcodec/mips/aacdec_mips.c b/libavcodec/mips/aacdec_mips.c
deleted file mode 100644
index dee135b032..0000000000
--- a/libavcodec/mips/aacdec_mips.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * 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.
- *
- * Authors: Darko Laus (darko@mips.com)
- * Djordje Pesut (djordje@mips.com)
- * Mirjana Vulin (mvulin@mips.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
- */
-
-/**
- * @file
- * Reference: libavcodec/aacdec.c
- */
-
-#include "libavutil/attributes.h"
-#include "libavcodec/aacdec.h"
-#include "aacdec_mips.h"
-#include "libavcodec/aactab.h"
-#include "libavcodec/sinewin.h"
-#include "libavutil/mips/asmdefs.h"
-
-#if HAVE_INLINE_ASM
-#if HAVE_MIPSFPU
-static av_always_inline void float_copy(float *dst, const float *src, int count)
-{
- // Copy 'count' floats from src to dst
- const float *loop_end = src + count;
- int temp[8];
-
- // count must be a multiple of 8
- av_assert2(count % 8 == 0);
-
- // loop unrolled 8 times
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "lw %[temp4], 16(%[src]) \n\t"
- "lw %[temp5], 20(%[src]) \n\t"
- "lw %[temp6], 24(%[src]) \n\t"
- "lw %[temp7], 28(%[src]) \n\t"
- PTR_ADDIU "%[src], %[src], 32 \n\t"
- "sw %[temp0], 0(%[dst]) \n\t"
- "sw %[temp1], 4(%[dst]) \n\t"
- "sw %[temp2], 8(%[dst]) \n\t"
- "sw %[temp3], 12(%[dst]) \n\t"
- "sw %[temp4], 16(%[dst]) \n\t"
- "sw %[temp5], 20(%[dst]) \n\t"
- "sw %[temp6], 24(%[dst]) \n\t"
- "sw %[temp7], 28(%[dst]) \n\t"
- "bne %[src], %[loop_end], 1b \n\t"
- PTR_ADDIU "%[dst], %[dst], 32 \n\t"
- ".set pop \n\t"
-
- : [temp0]"=&r"(temp[0]), [temp1]"=&r"(temp[1]),
- [temp2]"=&r"(temp[2]), [temp3]"=&r"(temp[3]),
- [temp4]"=&r"(temp[4]), [temp5]"=&r"(temp[5]),
- [temp6]"=&r"(temp[6]), [temp7]"=&r"(temp[7]),
- [src]"+r"(src), [dst]"+r"(dst)
- : [loop_end]"r"(loop_end)
- : "memory"
- );
-}
-
-static av_always_inline int lcg_random(unsigned previous_val)
-{
- union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 };
- return v.s;
-}
-
-static void imdct_and_windowing_mips(AACDecContext *ac, SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- float *in = sce->coeffs;
- float *out = sce->output;
- float *saved = sce->saved;
- const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
- const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;
- const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;
- float *buf = ac->buf_mdct;
- int i;
-
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- for (i = 0; i < 1024; i += 128)
- ac->mdct128_fn(ac->mdct128, buf + i, in + i, sizeof(float));
- } else
- ac->mdct1024_fn(ac->mdct1024, buf, in, sizeof(float));
-
- /* 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, 512);
- } else {
- float_copy(out, saved, 448);
-
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- {
- float wi;
- float wj;
- int i;
- float temp0, temp1, temp2, temp3;
- float *dst0 = out + 448 + 0*128;
- float *dst1 = dst0 + 64 + 63;
- float *dst2 = saved + 63;
- float *win0 = (float*)swindow;
- float *win1 = win0 + 64 + 63;
- float *win0_prev = (float*)swindow_prev;
- float *win1_prev = win0_prev + 64 + 63;
- float *src0_prev = saved + 448;
- float *src1_prev = buf + 0*128 + 63;
- float *src0 = buf + 0*128 + 64;
- float *src1 = buf + 1*128 + 63;
-
- for(i = 0; i < 64; i++)
- {
- temp0 = src0_prev[0];
- temp1 = src1_prev[0];
- wi = *win0_prev;
- wj = *win1_prev;
- temp2 = src0[0];
- temp3 = src1[0];
- dst0[0] = temp0 * wj - temp1 * wi;
- dst1[0] = temp0 * wi + temp1 * wj;
-
- wi = *win0;
- wj = *win1;
-
- temp0 = src0[128];
- temp1 = src1[128];
- dst0[128] = temp2 * wj - temp3 * wi;
- dst1[128] = temp2 * wi + temp3 * wj;
-
- temp2 = src0[256];
- temp3 = src1[256];
- dst0[256] = temp0 * wj - temp1 * wi;
- dst1[256] = temp0 * wi + temp1 * wj;
- dst0[384] = temp2 * wj - temp3 * wi;
- dst1[384] = temp2 * wi + temp3 * wj;
-
- temp0 = src0[384];
- temp1 = src1[384];
- dst0[512] = temp0 * wj - temp1 * wi;
- dst2[0] = temp0 * wi + temp1 * wj;
-
- src0++;
- src1--;
- src0_prev++;
- src1_prev--;
- win0++;
- win1--;
- win0_prev++;
- win1_prev--;
- dst0++;
- dst1--;
- dst2--;
- }
- }
- } else {
- ac->fdsp->vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64);
- float_copy(out + 576, buf + 64, 448);
- }
- }
-
- // buffer update
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- ac->fdsp->vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64);
- ac->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
- ac->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
- float_copy(saved + 448, buf + 7*128 + 64, 64);
- } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
- float_copy(saved, buf + 512, 448);
- float_copy(saved + 448, buf + 7*128 + 64, 64);
- } else { // LONG_STOP or ONLY_LONG
- float_copy(saved, buf + 512, 512);
- }
-}
-
-/**
- * Apply windowing and MDCT to obtain the spectral
- * coefficient from the predicted sample by LTP.
- */
-static inline void windowing_and_mdct_ltp(AACDecContext *ac,
- float *out, float *in,
- IndividualChannelStream *ics)
-{
- const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024) : ff_sine_1024;
- const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128) : ff_sine_128;
- const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024) : ff_sine_1024;
- const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128) : ff_sine_128;
-
- if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
- ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
- } else {
- memset(in, 0, 448 * sizeof(*in));
- ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
- }
- if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
- ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
- } else {
- ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
- memset(in + 1024 + 576, 0, 448 * sizeof(*in));
- }
- ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
-}
-
-static void apply_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
-{
- const LongTermPrediction *ltp = &sce->ics.ltp;
- const uint16_t *offsets = sce->ics.swb_offset;
- int i, sfb;
- int j, k;
-
- if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
- float *predTime = sce->output;
- float *predFreq = ac->buf_mdct;
- float *p_predTime;
- int16_t num_samples = 2048;
-
- if (ltp->lag < 1024)
- num_samples = ltp->lag + 1024;
- j = (2048 - num_samples) >> 2;
- k = (2048 - num_samples) & 3;
- p_predTime = &predTime[num_samples];
-
- for (i = 0; i < num_samples; i++)
- predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef;
- for (i = 0; i < j; i++) {
-
- /* loop unrolled 4 times */
- __asm__ volatile (
- "sw $0, 0(%[p_predTime]) \n\t"
- "sw $0, 4(%[p_predTime]) \n\t"
- "sw $0, 8(%[p_predTime]) \n\t"
- "sw $0, 12(%[p_predTime]) \n\t"
- PTR_ADDIU "%[p_predTime], %[p_predTime], 16 \n\t"
-
- : [p_predTime]"+r"(p_predTime)
- :
- : "memory"
- );
- }
- for (i = 0; i < k; i++) {
-
- __asm__ volatile (
- "sw $0, 0(%[p_predTime]) \n\t"
- PTR_ADDIU "%[p_predTime], %[p_predTime], 4 \n\t"
-
- : [p_predTime]"+r"(p_predTime)
- :
- : "memory"
- );
- }
-
- windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
-
- if (sce->tns.present)
- ac->dsp.apply_tns(predFreq, &sce->tns, &sce->ics, 0);
-
- for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
- if (ltp->used[sfb])
- for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
- sce->coeffs[i] += predFreq[i];
- }
-}
-
-static av_always_inline void fmul_and_reverse(float *dst, const float *src0, const float *src1, int count)
-{
- /* Multiply 'count' floats in src0 by src1 and store the results in dst in reverse */
- /* This should be equivalent to a normal fmul, followed by reversing dst */
-
- // count must be a multiple of 4
- av_assert2(count % 4 == 0);
-
- // move src0 and src1 to the last element of their arrays
- src0 += count - 1;
- src1 += count - 1;
-
- for (; count > 0; count -= 4){
- float temp[12];
-
- /* loop unrolled 4 times */
- __asm__ volatile (
- "lwc1 %[temp0], 0(%[ptr2]) \n\t"
- "lwc1 %[temp1], -4(%[ptr2]) \n\t"
- "lwc1 %[temp2], -8(%[ptr2]) \n\t"
- "lwc1 %[temp3], -12(%[ptr2]) \n\t"
- "lwc1 %[temp4], 0(%[ptr3]) \n\t"
- "lwc1 %[temp5], -4(%[ptr3]) \n\t"
- "lwc1 %[temp6], -8(%[ptr3]) \n\t"
- "lwc1 %[temp7], -12(%[ptr3]) \n\t"
- "mul.s %[temp8], %[temp0], %[temp4] \n\t"
- "mul.s %[temp9], %[temp1], %[temp5] \n\t"
- "mul.s %[temp10], %[temp2], %[temp6] \n\t"
- "mul.s %[temp11], %[temp3], %[temp7] \n\t"
- "swc1 %[temp8], 0(%[ptr1]) \n\t"
- "swc1 %[temp9], 4(%[ptr1]) \n\t"
- "swc1 %[temp10], 8(%[ptr1]) \n\t"
- "swc1 %[temp11], 12(%[ptr1]) \n\t"
- PTR_ADDIU "%[ptr1], %[ptr1], 16 \n\t"
- PTR_ADDIU "%[ptr2], %[ptr2], -16 \n\t"
- PTR_ADDIU "%[ptr3], %[ptr3], -16 \n\t"
-
- : [temp0]"=&f"(temp[0]), [temp1]"=&f"(temp[1]),
- [temp2]"=&f"(temp[2]), [temp3]"=&f"(temp[3]),
- [temp4]"=&f"(temp[4]), [temp5]"=&f"(temp[5]),
- [temp6]"=&f"(temp[6]), [temp7]"=&f"(temp[7]),
- [temp8]"=&f"(temp[8]), [temp9]"=&f"(temp[9]),
- [temp10]"=&f"(temp[10]), [temp11]"=&f"(temp[11]),
- [ptr1]"+r"(dst), [ptr2]"+r"(src0), [ptr3]"+r"(src1)
- :
- : "memory"
- );
- }
-}
-
-static void update_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- float *saved = sce->saved;
- float *saved_ltp = sce->coeffs;
- const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024 : ff_sine_1024;
- const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
- uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
-
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- float *p_saved_ltp = saved_ltp + 576;
- float *loop_end1 = p_saved_ltp + 448;
-
- float_copy(saved_ltp, saved, 512);
-
- /* loop unrolled 8 times */
- __asm__ volatile (
- "1: \n\t"
- "sw $0, 0(%[p_saved_ltp]) \n\t"
- "sw $0, 4(%[p_saved_ltp]) \n\t"
- "sw $0, 8(%[p_saved_ltp]) \n\t"
- "sw $0, 12(%[p_saved_ltp]) \n\t"
- "sw $0, 16(%[p_saved_ltp]) \n\t"
- "sw $0, 20(%[p_saved_ltp]) \n\t"
- "sw $0, 24(%[p_saved_ltp]) \n\t"
- "sw $0, 28(%[p_saved_ltp]) \n\t"
- PTR_ADDIU "%[p_saved_ltp],%[p_saved_ltp], 32 \n\t"
- "bne %[p_saved_ltp], %[loop_end1], 1b \n\t"
-
- : [p_saved_ltp]"+r"(p_saved_ltp)
- : [loop_end1]"r"(loop_end1)
- : "memory"
- );
-
- ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
- fmul_and_reverse(saved_ltp + 512, ac->buf_mdct + 960, swindow, 64);
- } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
- float *buff0 = saved;
- float *buff1 = saved_ltp;
- float *loop_end = saved + 448;
-
- /* loop unrolled 8 times */
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
- "1: \n\t"
- "lw %[temp0], 0(%[src]) \n\t"
- "lw %[temp1], 4(%[src]) \n\t"
- "lw %[temp2], 8(%[src]) \n\t"
- "lw %[temp3], 12(%[src]) \n\t"
- "lw %[temp4], 16(%[src]) \n\t"
- "lw %[temp5], 20(%[src]) \n\t"
- "lw %[temp6], 24(%[src]) \n\t"
- "lw %[temp7], 28(%[src]) \n\t"
- PTR_ADDIU "%[src], %[src], 32 \n\t"
- "sw %[temp0], 0(%[dst]) \n\t"
- "sw %[temp1], 4(%[dst]) \n\t"
- "sw %[temp2], 8(%[dst]) \n\t"
- "sw %[temp3], 12(%[dst]) \n\t"
- "sw %[temp4], 16(%[dst]) \n\t"
- "sw %[temp5], 20(%[dst]) \n\t"
- "sw %[temp6], 24(%[dst]) \n\t"
- "sw %[temp7], 28(%[dst]) \n\t"
- "sw $0, 2304(%[dst]) \n\t"
- "sw $0, 2308(%[dst]) \n\t"
- "sw $0, 2312(%[dst]) \n\t"
- "sw $0, 2316(%[dst]) \n\t"
- "sw $0, 2320(%[dst]) \n\t"
- "sw $0, 2324(%[dst]) \n\t"
- "sw $0, 2328(%[dst]) \n\t"
- "sw $0, 2332(%[dst]) \n\t"
- "bne %[src], %[loop_end], 1b \n\t"
- PTR_ADDIU "%[dst], %[dst], 32 \n\t"
- ".set pop \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7),
- [src]"+r"(buff0), [dst]"+r"(buff1)
- : [loop_end]"r"(loop_end)
- : "memory"
- );
- ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
- fmul_and_reverse(saved_ltp + 512, ac->buf_mdct + 960, swindow, 64);
- } else { // LONG_STOP or ONLY_LONG
- ac->fdsp->vector_fmul_reverse(saved_ltp, ac->buf_mdct + 512, &lwindow[512], 512);
- fmul_and_reverse(saved_ltp + 512, ac->buf_mdct + 512, lwindow, 512);
- }
-
- float_copy(sce->ltp_state, sce->ltp_state + 1024, 1024);
- float_copy(sce->ltp_state + 1024, sce->output, 1024);
- float_copy(sce->ltp_state + 2048, saved_ltp, 1024);
-}
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-
-void ff_aacdec_init_mips(AACDecContext *c)
-{
-#if HAVE_INLINE_ASM
-#if HAVE_MIPSFPU
- c->dsp.imdct_and_windowing = imdct_and_windowing_mips;
- c->dsp.apply_ltp = apply_ltp_mips;
- c->update_ltp = update_ltp_mips;
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-}
diff --git a/libavcodec/mips/aacdec_mips.h b/libavcodec/mips/aacdec_mips.h
deleted file mode 100644
index 71581986dc..0000000000
--- a/libavcodec/mips/aacdec_mips.h
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * 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.
- *
- * Authors: Darko Laus (darko@mips.com)
- * Djordje Pesut (djordje@mips.com)
- * Mirjana Vulin (mvulin@mips.com)
- *
- * AAC Spectral Band Replication decoding functions optimized for MIPS
- *
- * 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
- */
-
-/**
- * @file
- * Reference: libavcodec/aacdec.c
- */
-
-#ifndef AVCODEC_MIPS_AACDEC_MIPS_H
-#define AVCODEC_MIPS_AACDEC_MIPS_H
-
-#include "libavcodec/aacdec.h"
-#include "libavutil/mips/asmdefs.h"
-
-#if HAVE_INLINE_ASM && HAVE_MIPSFPU
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
-static inline float *VMUL2_mips(float *dst, const float *v, unsigned idx,
- const float *scale)
-{
- float temp0, temp1, temp2;
- int temp3, temp4;
- float *ret;
-
- __asm__ volatile(
- "andi %[temp3], %[idx], 0x0F \n\t"
- "andi %[temp4], %[idx], 0xF0 \n\t"
- "sll %[temp3], %[temp3], 2 \n\t"
- "srl %[temp4], %[temp4], 2 \n\t"
- "lwc1 %[temp2], 0(%[scale]) \n\t"
- "lwxc1 %[temp0], %[temp3](%[v]) \n\t"
- "lwxc1 %[temp1], %[temp4](%[v]) \n\t"
- "mul.s %[temp0], %[temp0], %[temp2] \n\t"
- "mul.s %[temp1], %[temp1], %[temp2] \n\t"
- PTR_ADDIU "%[ret], %[dst], 8 \n\t"
- "swc1 %[temp0], 0(%[dst]) \n\t"
- "swc1 %[temp1], 4(%[dst]) \n\t"
-
- : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1),
- [temp2]"=&f"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [ret]"=&r"(ret)
- : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v),
- [dst]"r"(dst)
- : "memory"
- );
- return ret;
-}
-
-static inline float *VMUL4_mips(float *dst, const float *v, unsigned idx,
- const float *scale)
-{
- int temp0, temp1, temp2, temp3;
- float temp4, temp5, temp6, temp7, temp8;
- float *ret;
-
- __asm__ volatile(
- "andi %[temp0], %[idx], 0x03 \n\t"
- "andi %[temp1], %[idx], 0x0C \n\t"
- "andi %[temp2], %[idx], 0x30 \n\t"
- "andi %[temp3], %[idx], 0xC0 \n\t"
- "sll %[temp0], %[temp0], 2 \n\t"
- "srl %[temp2], %[temp2], 2 \n\t"
- "srl %[temp3], %[temp3], 4 \n\t"
- "lwc1 %[temp4], 0(%[scale]) \n\t"
- "lwxc1 %[temp5], %[temp0](%[v]) \n\t"
- "lwxc1 %[temp6], %[temp1](%[v]) \n\t"
- "lwxc1 %[temp7], %[temp2](%[v]) \n\t"
- "lwxc1 %[temp8], %[temp3](%[v]) \n\t"
- "mul.s %[temp5], %[temp5], %[temp4] \n\t"
- "mul.s %[temp6], %[temp6], %[temp4] \n\t"
- "mul.s %[temp7], %[temp7], %[temp4] \n\t"
- "mul.s %[temp8], %[temp8], %[temp4] \n\t"
- PTR_ADDIU "%[ret], %[dst], 16 \n\t"
- "swc1 %[temp5], 0(%[dst]) \n\t"
- "swc1 %[temp6], 4(%[dst]) \n\t"
- "swc1 %[temp7], 8(%[dst]) \n\t"
- "swc1 %[temp8], 12(%[dst]) \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&f"(temp4), [temp5]"=&f"(temp5),
- [temp6]"=&f"(temp6), [temp7]"=&f"(temp7),
- [temp8]"=&f"(temp8), [ret]"=&r"(ret)
- : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v),
- [dst]"r"(dst)
- : "memory"
- );
- return ret;
-}
-
-static inline float *VMUL2S_mips(float *dst, const float *v, unsigned idx,
- unsigned sign, const float *scale)
-{
- int temp0, temp1, temp2, temp3, temp4, temp5;
- float temp6, temp7, temp8, temp9;
- float *ret;
-
- __asm__ volatile(
- "andi %[temp0], %[idx], 0x0F \n\t"
- "andi %[temp1], %[idx], 0xF0 \n\t"
- "lw %[temp4], 0(%[scale]) \n\t"
- "srl %[temp2], %[sign], 1 \n\t"
- "sll %[temp3], %[sign], 31 \n\t"
- "sll %[temp2], %[temp2], 31 \n\t"
- "sll %[temp0], %[temp0], 2 \n\t"
- "srl %[temp1], %[temp1], 2 \n\t"
- "lwxc1 %[temp8], %[temp0](%[v]) \n\t"
- "lwxc1 %[temp9], %[temp1](%[v]) \n\t"
- "xor %[temp5], %[temp4], %[temp2] \n\t"
- "xor %[temp4], %[temp4], %[temp3] \n\t"
- "mtc1 %[temp5], %[temp6] \n\t"
- "mtc1 %[temp4], %[temp7] \n\t"
- "mul.s %[temp8], %[temp8], %[temp6] \n\t"
- "mul.s %[temp9], %[temp9], %[temp7] \n\t"
- PTR_ADDIU "%[ret], %[dst], 8 \n\t"
- "swc1 %[temp8], 0(%[dst]) \n\t"
- "swc1 %[temp9], 4(%[dst]) \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&f"(temp6), [temp7]"=&f"(temp7),
- [temp8]"=&f"(temp8), [temp9]"=&f"(temp9),
- [ret]"=&r"(ret)
- : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v),
- [dst]"r"(dst), [sign]"r"(sign)
- : "memory"
- );
- return ret;
-}
-
-static inline float *VMUL4S_mips(float *dst, const float *v, unsigned idx,
- unsigned sign, const float *scale)
-{
- int temp0, temp1, temp2, temp3, temp4;
- float temp10, temp11, temp12, temp13, temp14, temp15, temp16, temp17;
- float *ret;
- unsigned int mask = 1U << 31;
-
- __asm__ volatile(
- "lw %[temp0], 0(%[scale]) \n\t"
- "andi %[temp1], %[idx], 0x03 \n\t"
- "andi %[temp2], %[idx], 0x0C \n\t"
- "andi %[temp3], %[idx], 0x30 \n\t"
- "andi %[temp4], %[idx], 0xC0 \n\t"
- "sll %[temp1], %[temp1], 2 \n\t"
- "srl %[temp3], %[temp3], 2 \n\t"
- "srl %[temp4], %[temp4], 4 \n\t"
- "lwxc1 %[temp10], %[temp1](%[v]) \n\t"
- "lwxc1 %[temp11], %[temp2](%[v]) \n\t"
- "lwxc1 %[temp12], %[temp3](%[v]) \n\t"
- "lwxc1 %[temp13], %[temp4](%[v]) \n\t"
- "and %[temp1], %[sign], %[mask] \n\t"
- "srl %[temp2], %[idx], 12 \n\t"
- "srl %[temp3], %[idx], 13 \n\t"
- "srl %[temp4], %[idx], 14 \n\t"
- "andi %[temp2], %[temp2], 1 \n\t"
- "andi %[temp3], %[temp3], 1 \n\t"
- "andi %[temp4], %[temp4], 1 \n\t"
- "sllv %[sign], %[sign], %[temp2] \n\t"
- "xor %[temp1], %[temp0], %[temp1] \n\t"
- "and %[temp2], %[sign], %[mask] \n\t"
- "mtc1 %[temp1], %[temp14] \n\t"
- "xor %[temp2], %[temp0], %[temp2] \n\t"
- "sllv %[sign], %[sign], %[temp3] \n\t"
- "mtc1 %[temp2], %[temp15] \n\t"
- "and %[temp3], %[sign], %[mask] \n\t"
- "sllv %[sign], %[sign], %[temp4] \n\t"
- "xor %[temp3], %[temp0], %[temp3] \n\t"
- "and %[temp4], %[sign], %[mask] \n\t"
- "mtc1 %[temp3], %[temp16] \n\t"
- "xor %[temp4], %[temp0], %[temp4] \n\t"
- "mtc1 %[temp4], %[temp17] \n\t"
- "mul.s %[temp10], %[temp10], %[temp14] \n\t"
- "mul.s %[temp11], %[temp11], %[temp15] \n\t"
- "mul.s %[temp12], %[temp12], %[temp16] \n\t"
- "mul.s %[temp13], %[temp13], %[temp17] \n\t"
- PTR_ADDIU "%[ret], %[dst], 16 \n\t"
- "swc1 %[temp10], 0(%[dst]) \n\t"
- "swc1 %[temp11], 4(%[dst]) \n\t"
- "swc1 %[temp12], 8(%[dst]) \n\t"
- "swc1 %[temp13], 12(%[dst]) \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp10]"=&f"(temp10),
- [temp11]"=&f"(temp11), [temp12]"=&f"(temp12),
- [temp13]"=&f"(temp13), [temp14]"=&f"(temp14),
- [temp15]"=&f"(temp15), [temp16]"=&f"(temp16),
- [temp17]"=&f"(temp17), [ret]"=&r"(ret),
- [sign]"+r"(sign)
- : [idx]"r"(idx), [scale]"r"(scale), [v]"r"(v),
- [dst]"r"(dst), [mask]"r"(mask)
- : "memory"
- );
- return ret;
-}
-
-#define VMUL2 VMUL2_mips
-#define VMUL4 VMUL4_mips
-#define VMUL2S VMUL2S_mips
-#define VMUL4S VMUL4S_mips
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_INLINE_ASM && HAVE_MIPSFPU */
-
-#endif /* AVCODEC_MIPS_AACDEC_MIPS_H */
diff --git a/libavcodec/mips/aacpsdsp_mips.c b/libavcodec/mips/aacpsdsp_mips.c
deleted file mode 100644
index f63541330d..0000000000
--- a/libavcodec/mips/aacpsdsp_mips.c
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * 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.
- *
- * Authors: Darko Laus (darko@mips.com)
- * Djordje Pesut (djordje@mips.com)
- * Mirjana Vulin (mvulin@mips.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
- */
-
-/**
- * @file
- * Reference: libavcodec/aacpsdsp.c
- */
-
-#include "config.h"
-#include "libavcodec/aacpsdsp.h"
-#include "libavutil/mips/asmdefs.h"
-
-#if HAVE_INLINE_ASM
-#if HAVE_MIPSFPU
-static void ps_hybrid_analysis_ileave_mips(float (*out)[32][2], float L[2][38][64],
- int i, int len)
-{
- int temp0, temp1, temp2, temp3;
- int temp4, temp5, temp6, temp7;
- float *out1=&out[i][0][0];
- float *L1=&L[0][0][i];
- float *j=out1+ len*2;
-
- for (; i < 64; i++) {
-
- /* loop unrolled 8 times */
- __asm__ volatile (
- "1: \n\t"
- "lw %[temp0], 0(%[L1]) \n\t"
- "lw %[temp1], 9728(%[L1]) \n\t"
- "lw %[temp2], 256(%[L1]) \n\t"
- "lw %[temp3], 9984(%[L1]) \n\t"
- "lw %[temp4], 512(%[L1]) \n\t"
- "lw %[temp5], 10240(%[L1]) \n\t"
- "lw %[temp6], 768(%[L1]) \n\t"
- "lw %[temp7], 10496(%[L1]) \n\t"
- "sw %[temp0], 0(%[out1]) \n\t"
- "sw %[temp1], 4(%[out1]) \n\t"
- "sw %[temp2], 8(%[out1]) \n\t"
- "sw %[temp3], 12(%[out1]) \n\t"
- "sw %[temp4], 16(%[out1]) \n\t"
- "sw %[temp5], 20(%[out1]) \n\t"
- "sw %[temp6], 24(%[out1]) \n\t"
- "sw %[temp7], 28(%[out1]) \n\t"
- PTR_ADDIU "%[out1], %[out1], 32 \n\t"
- PTR_ADDIU "%[L1], %[L1], 1024 \n\t"
- "bne %[out1], %[j], 1b \n\t"
-
- : [out1]"+r"(out1), [L1]"+r"(L1), [j]"+r"(j),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
- : [len]"r"(len)
- : "memory"
- );
- out1-=(len<<1)-64;
- L1-=(len<<6)-1;
- j+=len*2;
- }
-}
-
-static void ps_hybrid_synthesis_deint_mips(float out[2][38][64],
- float (*in)[32][2],
- int i, int len)
-{
- int n;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- float *out1 = (float*)out + i;
- float *out2 = (float*)out + 2432 + i;
- float *in1 = (float*)in + 64 * i;
- float *in2 = (float*)in + 64 * i + 1;
-
- for (; i < 64; i++) {
- for (n = 0; n < 7; n++) {
-
- /* loop unrolled 8 times */
- __asm__ volatile (
- "lw %[temp0], 0(%[in1]) \n\t"
- "lw %[temp1], 0(%[in2]) \n\t"
- "lw %[temp2], 8(%[in1]) \n\t"
- "lw %[temp3], 8(%[in2]) \n\t"
- "lw %[temp4], 16(%[in1]) \n\t"
- "lw %[temp5], 16(%[in2]) \n\t"
- "lw %[temp6], 24(%[in1]) \n\t"
- "lw %[temp7], 24(%[in2]) \n\t"
- PTR_ADDIU "%[out1], %[out1], 1024 \n\t"
- PTR_ADDIU "%[out2], %[out2], 1024 \n\t"
- PTR_ADDIU "%[in1], %[in1], 32 \n\t"
- PTR_ADDIU "%[in2], %[in2], 32 \n\t"
- "sw %[temp0], -1024(%[out1]) \n\t"
- "sw %[temp1], -1024(%[out2]) \n\t"
- "sw %[temp2], -768(%[out1]) \n\t"
- "sw %[temp3], -768(%[out2]) \n\t"
- "sw %[temp4], -512(%[out1]) \n\t"
- "sw %[temp5], -512(%[out2]) \n\t"
- "sw %[temp6], -256(%[out1]) \n\t"
- "sw %[temp7], -256(%[out2]) \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7),
- [out1]"+r"(out1), [out2]"+r"(out2),
- [in1]"+r"(in1), [in2]"+r"(in2)
- :
- : "memory"
- );
- }
- /* loop unrolled 8 times */
- __asm__ volatile (
- "lw %[temp0], 0(%[in1]) \n\t"
- "lw %[temp1], 0(%[in2]) \n\t"
- "lw %[temp2], 8(%[in1]) \n\t"
- "lw %[temp3], 8(%[in2]) \n\t"
- "lw %[temp4], 16(%[in1]) \n\t"
- "lw %[temp5], 16(%[in2]) \n\t"
- "lw %[temp6], 24(%[in1]) \n\t"
- "lw %[temp7], 24(%[in2]) \n\t"
- PTR_ADDIU "%[out1], %[out1], -7164 \n\t"
- PTR_ADDIU "%[out2], %[out2], -7164 \n\t"
- PTR_ADDIU "%[in1], %[in1], 32 \n\t"
- PTR_ADDIU "%[in2], %[in2], 32 \n\t"
- "sw %[temp0], 7164(%[out1]) \n\t"
- "sw %[temp1], 7164(%[out2]) \n\t"
- "sw %[temp2], 7420(%[out1]) \n\t"
- "sw %[temp3], 7420(%[out2]) \n\t"
- "sw %[temp4], 7676(%[out1]) \n\t"
- "sw %[temp5], 7676(%[out2]) \n\t"
- "sw %[temp6], 7932(%[out1]) \n\t"
- "sw %[temp7], 7932(%[out2]) \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7),
- [out1]"+r"(out1), [out2]"+r"(out2),
- [in1]"+r"(in1), [in2]"+r"(in2)
- :
- : "memory"
- );
- }
-}
-
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
-static void ps_add_squares_mips(float *dst, const float (*src)[2], int n)
-{
- int i;
- float temp0, temp1, temp2, temp3, temp4, temp5;
- float temp6, temp7, temp8, temp9, temp10, temp11;
- float *src0 = (float*)&src[0][0];
- float *dst0 = &dst[0];
-
- for (i = 0; i < 8; i++) {
- /* loop unrolled 4 times */
- __asm__ volatile (
- "lwc1 %[temp0], 0(%[src0]) \n\t"
- "lwc1 %[temp1], 4(%[src0]) \n\t"
- "lwc1 %[temp2], 8(%[src0]) \n\t"
- "lwc1 %[temp3], 12(%[src0]) \n\t"
- "lwc1 %[temp4], 16(%[src0]) \n\t"
- "lwc1 %[temp5], 20(%[src0]) \n\t"
- "lwc1 %[temp6], 24(%[src0]) \n\t"
- "lwc1 %[temp7], 28(%[src0]) \n\t"
- "lwc1 %[temp8], 0(%[dst0]) \n\t"
- "lwc1 %[temp9], 4(%[dst0]) \n\t"
- "lwc1 %[temp10], 8(%[dst0]) \n\t"
- "lwc1 %[temp11], 12(%[dst0]) \n\t"
- "mul.s %[temp1], %[temp1], %[temp1] \n\t"
- "mul.s %[temp3], %[temp3], %[temp3] \n\t"
- "mul.s %[temp5], %[temp5], %[temp5] \n\t"
- "mul.s %[temp7], %[temp7], %[temp7] \n\t"
- "madd.s %[temp0], %[temp1], %[temp0], %[temp0] \n\t"
- "madd.s %[temp2], %[temp3], %[temp2], %[temp2] \n\t"
- "madd.s %[temp4], %[temp5], %[temp4], %[temp4] \n\t"
- "madd.s %[temp6], %[temp7], %[temp6], %[temp6] \n\t"
- "add.s %[temp0], %[temp8], %[temp0] \n\t"
- "add.s %[temp2], %[temp9], %[temp2] \n\t"
- "add.s %[temp4], %[temp10], %[temp4] \n\t"
- "add.s %[temp6], %[temp11], %[temp6] \n\t"
- "swc1 %[temp0], 0(%[dst0]) \n\t"
- "swc1 %[temp2], 4(%[dst0]) \n\t"
- "swc1 %[temp4], 8(%[dst0]) \n\t"
- "swc1 %[temp6], 12(%[dst0]) \n\t"
- PTR_ADDIU "%[dst0], %[dst0], 16 \n\t"
- PTR_ADDIU "%[src0], %[src0], 32 \n\t"
-
- : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2),
- [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5),
- [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8),
- [temp9]"=&f"(temp9), [dst0]"+r"(dst0), [src0]"+r"(src0),
- [temp10]"=&f"(temp10), [temp11]"=&f"(temp11)
- :
- : "memory"
- );
- }
-}
-
-static void ps_mul_pair_single_mips(float (*dst)[2], float (*src0)[2], float *src1,
- int n)
-{
- float temp0, temp1, temp2;
- float *p_d, *p_s0, *p_s1, *end;
- p_d = &dst[0][0];
- p_s0 = &src0[0][0];
- p_s1 = &src1[0];
- end = p_s1 + n;
-
- __asm__ volatile(
- ".set push \n\t"
- ".set noreorder \n\t"
- "1: \n\t"
- "lwc1 %[temp2], 0(%[p_s1]) \n\t"
- "lwc1 %[temp0], 0(%[p_s0]) \n\t"
- "lwc1 %[temp1], 4(%[p_s0]) \n\t"
- PTR_ADDIU "%[p_d], %[p_d], 8 \n\t"
- "mul.s %[temp0], %[temp0], %[temp2] \n\t"
- "mul.s %[temp1], %[temp1], %[temp2] \n\t"
- PTR_ADDIU "%[p_s0], %[p_s0], 8 \n\t"
- "swc1 %[temp0], -8(%[p_d]) \n\t"
- "swc1 %[temp1], -4(%[p_d]) \n\t"
- "bne %[p_s1], %[end], 1b \n\t"
- PTR_ADDIU "%[p_s1], %[p_s1], 4 \n\t"
- ".set pop \n\t"
-
- : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1),
- [temp2]"=&f"(temp2), [p_d]"+r"(p_d),
- [p_s0]"+r"(p_s0), [p_s1]"+r"(p_s1)
- : [end]"r"(end)
- : "memory"
- );
-}
-
-static void ps_decorrelate_mips(float (*out)[2], float (*delay)[2],
- float (*ap_delay)[PS_QMF_TIME_SLOTS + PS_MAX_AP_DELAY][2],
- const float phi_fract[2], const float (*Q_fract)[2],
- const float *transient_gain,
- float g_decay_slope,
- int len)
-{
- float *p_delay = &delay[0][0];
- float *p_out = &out[0][0];
- float *p_ap_delay = &ap_delay[0][0][0];
- const float *p_t_gain = transient_gain;
- const float *p_Q_fract = &Q_fract[0][0];
- float ag0, ag1, ag2;
- float phi_fract0 = phi_fract[0];
- float phi_fract1 = phi_fract[1];
- float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9;
- float f1, f2, f3;
-
- float *p_delay_end = (p_delay + (len << 1));
-
- /* merged 2 loops */
- f1 = 0.65143905753106;
- f2 = 0.56471812200776;
- f3 = 0.48954165955695;
- __asm__ volatile(
- ".set push \n\t"
- ".set noreorder \n\t"
- "mul.s %[ag0], %[ag0], %[g_decay_slope] \n\t"
- "mul.s %[ag1], %[ag1], %[g_decay_slope] \n\t"
- "mul.s %[ag2], %[ag2], %[g_decay_slope] \n\t"
- "1: \n\t"
- "lwc1 %[temp0], 0(%[p_delay]) \n\t"
- "lwc1 %[temp1], 4(%[p_delay]) \n\t"
- "lwc1 %[temp4], 16(%[p_ap_delay]) \n\t"
- "lwc1 %[temp5], 20(%[p_ap_delay]) \n\t"
- "mul.s %[temp3], %[temp0], %[phi_fract1] \n\t"
- "lwc1 %[temp6], 0(%[p_Q_fract]) \n\t"
- "mul.s %[temp2], %[temp1], %[phi_fract1] \n\t"
- "lwc1 %[temp7], 4(%[p_Q_fract]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp1], %[phi_fract0] \n\t"
- "msub.s %[temp2], %[temp2], %[temp0], %[phi_fract0] \n\t"
- "mul.s %[temp8], %[temp5], %[temp7] \n\t"
- "mul.s %[temp9], %[temp4], %[temp7] \n\t"
- "lwc1 %[temp7], 12(%[p_Q_fract]) \n\t"
- "mul.s %[temp0], %[ag0], %[temp2] \n\t"
- "mul.s %[temp1], %[ag0], %[temp3] \n\t"
- "msub.s %[temp8], %[temp8], %[temp4], %[temp6] \n\t"
- "lwc1 %[temp4], 304(%[p_ap_delay]) \n\t"
- "madd.s %[temp9], %[temp9], %[temp5], %[temp6] \n\t"
- "lwc1 %[temp5], 308(%[p_ap_delay]) \n\t"
- "sub.s %[temp0], %[temp8], %[temp0] \n\t"
- "sub.s %[temp1], %[temp9], %[temp1] \n\t"
- "madd.s %[temp2], %[temp2], %[ag0], %[temp0] \n\t"
- "lwc1 %[temp6], 8(%[p_Q_fract]) \n\t"
- "madd.s %[temp3], %[temp3], %[ag0], %[temp1] \n\t"
- "mul.s %[temp8], %[temp5], %[temp7] \n\t"
- "mul.s %[temp9], %[temp4], %[temp7] \n\t"
- "lwc1 %[temp7], 20(%[p_Q_fract]) \n\t"
- "msub.s %[temp8], %[temp8], %[temp4], %[temp6] \n\t"
- "swc1 %[temp2], 40(%[p_ap_delay]) \n\t"
- "mul.s %[temp2], %[ag1], %[temp0] \n\t"
- "swc1 %[temp3], 44(%[p_ap_delay]) \n\t"
- "mul.s %[temp3], %[ag1], %[temp1] \n\t"
- "lwc1 %[temp4], 592(%[p_ap_delay]) \n\t"
- "madd.s %[temp9], %[temp9], %[temp5], %[temp6] \n\t"
- "lwc1 %[temp5], 596(%[p_ap_delay]) \n\t"
- "sub.s %[temp2], %[temp8], %[temp2] \n\t"
- "sub.s %[temp3], %[temp9], %[temp3] \n\t"
- "lwc1 %[temp6], 16(%[p_Q_fract]) \n\t"
- "madd.s %[temp0], %[temp0], %[ag1], %[temp2] \n\t"
- "madd.s %[temp1], %[temp1], %[ag1], %[temp3] \n\t"
- "mul.s %[temp8], %[temp5], %[temp7] \n\t"
- "mul.s %[temp9], %[temp4], %[temp7] \n\t"
- "msub.s %[temp8], %[temp8], %[temp4], %[temp6] \n\t"
- "madd.s %[temp9], %[temp9], %[temp5], %[temp6] \n\t"
- "swc1 %[temp0], 336(%[p_ap_delay]) \n\t"
- "mul.s %[temp0], %[ag2], %[temp2] \n\t"
- "swc1 %[temp1], 340(%[p_ap_delay]) \n\t"
- "mul.s %[temp1], %[ag2], %[temp3] \n\t"
- "lwc1 %[temp4], 0(%[p_t_gain]) \n\t"
- "sub.s %[temp0], %[temp8], %[temp0] \n\t"
- PTR_ADDIU "%[p_ap_delay], %[p_ap_delay], 8 \n\t"
- "sub.s %[temp1], %[temp9], %[temp1] \n\t"
- PTR_ADDIU "%[p_t_gain], %[p_t_gain], 4 \n\t"
- "madd.s %[temp2], %[temp2], %[ag2], %[temp0] \n\t"
- PTR_ADDIU "%[p_delay], %[p_delay], 8 \n\t"
- "madd.s %[temp3], %[temp3], %[ag2], %[temp1] \n\t"
- PTR_ADDIU "%[p_out], %[p_out], 8 \n\t"
- "mul.s %[temp5], %[temp4], %[temp0] \n\t"
- "mul.s %[temp6], %[temp4], %[temp1] \n\t"
- "swc1 %[temp2], 624(%[p_ap_delay]) \n\t"
- "swc1 %[temp3], 628(%[p_ap_delay]) \n\t"
- "swc1 %[temp5], -8(%[p_out]) \n\t"
- "swc1 %[temp6], -4(%[p_out]) \n\t"
- "bne %[p_delay], %[p_delay_end],1b \n\t"
- " swc1 %[temp6], -4(%[p_out]) \n\t"
- ".set pop \n\t"
-
- : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2),
- [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5),
- [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8),
- [temp9]"=&f"(temp9), [p_delay]"+r"(p_delay), [p_ap_delay]"+r"(p_ap_delay),
- [p_Q_fract]"+r"(p_Q_fract), [p_t_gain]"+r"(p_t_gain), [p_out]"+r"(p_out)
- : [phi_fract0]"f"(phi_fract0), [phi_fract1]"f"(phi_fract1),
- [p_delay_end]"r"(p_delay_end), [g_decay_slope]"f"(g_decay_slope),
- [ag0]"f"(f1), [ag1]"f"(f2), [ag2]"f"(f3)
- : "memory"
- );
-}
-
-static void ps_stereo_interpolate_mips(float (*l)[2], float (*r)[2],
- float h[2][4], float h_step[2][4],
- int len)
-{
- float h0 = h[0][0];
- float h1 = h[0][1];
- float h2 = h[0][2];
- float h3 = h[0][3];
- float hs0 = h_step[0][0];
- float hs1 = h_step[0][1];
- float hs2 = h_step[0][2];
- float hs3 = h_step[0][3];
- float temp0, temp1, temp2, temp3;
- float l_re, l_im, r_re, r_im;
-
- float *l_end = ((float *)l + (len << 1));
-
- __asm__ volatile(
- ".set push \n\t"
- ".set noreorder \n\t"
- "1: \n\t"
- "add.s %[h0], %[h0], %[hs0] \n\t"
- "lwc1 %[l_re], 0(%[l]) \n\t"
- "add.s %[h1], %[h1], %[hs1] \n\t"
- "lwc1 %[r_re], 0(%[r]) \n\t"
- "add.s %[h2], %[h2], %[hs2] \n\t"
- "lwc1 %[l_im], 4(%[l]) \n\t"
- "add.s %[h3], %[h3], %[hs3] \n\t"
- "lwc1 %[r_im], 4(%[r]) \n\t"
- "mul.s %[temp0], %[h0], %[l_re] \n\t"
- PTR_ADDIU "%[l], %[l], 8 \n\t"
- "mul.s %[temp2], %[h1], %[l_re] \n\t"
- PTR_ADDIU "%[r], %[r], 8 \n\t"
- "madd.s %[temp0], %[temp0], %[h2], %[r_re] \n\t"
- "madd.s %[temp2], %[temp2], %[h3], %[r_re] \n\t"
- "mul.s %[temp1], %[h0], %[l_im] \n\t"
- "mul.s %[temp3], %[h1], %[l_im] \n\t"
- "madd.s %[temp1], %[temp1], %[h2], %[r_im] \n\t"
- "madd.s %[temp3], %[temp3], %[h3], %[r_im] \n\t"
- "swc1 %[temp0], -8(%[l]) \n\t"
- "swc1 %[temp2], -8(%[r]) \n\t"
- "swc1 %[temp1], -4(%[l]) \n\t"
- "bne %[l], %[l_end], 1b \n\t"
- " swc1 %[temp3], -4(%[r]) \n\t"
- ".set pop \n\t"
-
- : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1),
- [temp2]"=&f"(temp2), [temp3]"=&f"(temp3),
- [h0]"+f"(h0), [h1]"+f"(h1), [h2]"+f"(h2),
- [h3]"+f"(h3), [l]"+r"(l), [r]"+r"(r),
- [l_re]"=&f"(l_re), [l_im]"=&f"(l_im),
- [r_re]"=&f"(r_re), [r_im]"=&f"(r_im)
- : [hs0]"f"(hs0), [hs1]"f"(hs1), [hs2]"f"(hs2),
- [hs3]"f"(hs3), [l_end]"r"(l_end)
- : "memory"
- );
-}
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-
-void ff_psdsp_init_mips(PSDSPContext *s)
-{
-#if HAVE_INLINE_ASM
-#if HAVE_MIPSFPU
- s->hybrid_analysis_ileave = ps_hybrid_analysis_ileave_mips;
- s->hybrid_synthesis_deint = ps_hybrid_synthesis_deint_mips;
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
- s->add_squares = ps_add_squares_mips;
- s->mul_pair_single = ps_mul_pair_single_mips;
- s->decorrelate = ps_decorrelate_mips;
- s->stereo_interpolate[0] = ps_stereo_interpolate_mips;
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-}
diff --git a/libavcodec/mips/aacpsy_mips.h b/libavcodec/mips/aacpsy_mips.h
deleted file mode 100644
index 7d27d32f18..0000000000
--- a/libavcodec/mips/aacpsy_mips.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * 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: Bojan Zivkovic (bojan@mips.com)
- *
- * AAC encoder psychoacoustic model routines optimized
- * for MIPS floating-point architecture
- *
- * 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
- */
-
-/**
- * @file
- * Reference: libavcodec/aacpsy.c
- */
-
-#ifndef AVCODEC_MIPS_AACPSY_MIPS_H
-#define AVCODEC_MIPS_AACPSY_MIPS_H
-
-#include "libavutil/mips/asmdefs.h"
-
-#if HAVE_INLINE_ASM && HAVE_MIPSFPU && ( PSY_LAME_FIR_LEN == 21 )
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
-static void calc_thr_3gpp_mips(const FFPsyWindowInfo *wi, const int num_bands,
- AacPsyChannel *pch, const uint8_t *band_sizes,
- const float *coefs, const int cutoff)
-{
- int i, w, g;
- int start = 0, wstart = 0;
- for (w = 0; w < wi->num_windows*16; w += 16) {
- wstart = 0;
- for (g = 0; g < num_bands; g++) {
- AacPsyBand *band = &pch->band[w+g];
-
- float form_factor = 0.0f;
- float Temp;
- band->energy = 0.0f;
- if (wstart < cutoff) {
- for (i = 0; i < band_sizes[g]; i+=4) {
- float a, b, c, d;
- float ax, bx, cx, dx;
- float *cf = (float *)&coefs[start+i];
-
- __asm__ volatile (
- "lwc1 %[a], 0(%[cf]) \n\t"
- "lwc1 %[b], 4(%[cf]) \n\t"
- "lwc1 %[c], 8(%[cf]) \n\t"
- "lwc1 %[d], 12(%[cf]) \n\t"
- "abs.s %[a], %[a] \n\t"
- "abs.s %[b], %[b] \n\t"
- "abs.s %[c], %[c] \n\t"
- "abs.s %[d], %[d] \n\t"
- "sqrt.s %[ax], %[a] \n\t"
- "sqrt.s %[bx], %[b] \n\t"
- "sqrt.s %[cx], %[c] \n\t"
- "sqrt.s %[dx], %[d] \n\t"
- "madd.s %[e], %[e], %[a], %[a] \n\t"
- "madd.s %[e], %[e], %[b], %[b] \n\t"
- "madd.s %[e], %[e], %[c], %[c] \n\t"
- "madd.s %[e], %[e], %[d], %[d] \n\t"
- "add.s %[f], %[f], %[ax] \n\t"
- "add.s %[f], %[f], %[bx] \n\t"
- "add.s %[f], %[f], %[cx] \n\t"
- "add.s %[f], %[f], %[dx] \n\t"
-
- : [a]"=&f"(a), [b]"=&f"(b),
- [c]"=&f"(c), [d]"=&f"(d),
- [e]"+f"(band->energy), [f]"+f"(form_factor),
- [ax]"=&f"(ax), [bx]"=&f"(bx),
- [cx]"=&f"(cx), [dx]"=&f"(dx)
- : [cf]"r"(cf)
- : "memory"
- );
- }
- }
-
- Temp = sqrtf((float)band_sizes[g] / band->energy);
- band->thr = band->energy * 0.001258925f;
- band->nz_lines = form_factor * sqrtf(Temp);
- start += band_sizes[g];
- wstart += band_sizes[g];
- }
- }
-}
-
-static void psy_hp_filter_mips(const float *firbuf, float *hpfsmpl, const float * psy_fir_coeffs)
-{
- float sum1, sum2, sum3, sum4;
- float *fb = (float*)firbuf;
- float *fb_end = fb + AAC_BLOCK_SIZE_LONG;
- float *hp = hpfsmpl;
-
- float coeff0 = psy_fir_coeffs[1];
- float coeff1 = psy_fir_coeffs[3];
- float coeff2 = psy_fir_coeffs[5];
- float coeff3 = psy_fir_coeffs[7];
- float coeff4 = psy_fir_coeffs[9];
-
- float f1 = 32768.0;
- __asm__ volatile (
- ".set push \n\t"
- ".set noreorder \n\t"
-
- "1: \n\t"
- "lwc1 $f0, 40(%[fb]) \n\t"
- "lwc1 $f1, 4(%[fb]) \n\t"
- "lwc1 $f2, 80(%[fb]) \n\t"
- "lwc1 $f3, 44(%[fb]) \n\t"
- "lwc1 $f4, 8(%[fb]) \n\t"
- "madd.s %[sum1], $f0, $f1, %[coeff0] \n\t"
- "lwc1 $f5, 84(%[fb]) \n\t"
- "lwc1 $f6, 48(%[fb]) \n\t"
- "madd.s %[sum2], $f3, $f4, %[coeff0] \n\t"
- "lwc1 $f7, 12(%[fb]) \n\t"
- "madd.s %[sum1], %[sum1], $f2, %[coeff0] \n\t"
- "lwc1 $f8, 88(%[fb]) \n\t"
- "lwc1 $f9, 52(%[fb]) \n\t"
- "madd.s %[sum2], %[sum2], $f5, %[coeff0] \n\t"
- "madd.s %[sum3], $f6, $f7, %[coeff0] \n\t"
- "lwc1 $f10, 16(%[fb]) \n\t"
- "lwc1 $f11, 92(%[fb]) \n\t"
- "madd.s %[sum1], %[sum1], $f7, %[coeff1] \n\t"
- "lwc1 $f1, 72(%[fb]) \n\t"
- "madd.s %[sum3], %[sum3], $f8, %[coeff0] \n\t"
- "madd.s %[sum4], $f9, $f10, %[coeff0] \n\t"
- "madd.s %[sum2], %[sum2], $f10, %[coeff1] \n\t"
- "madd.s %[sum1], %[sum1], $f1, %[coeff1] \n\t"
- "lwc1 $f4, 76(%[fb]) \n\t"
- "lwc1 $f8, 20(%[fb]) \n\t"
- "madd.s %[sum4], %[sum4], $f11, %[coeff0] \n\t"
- "lwc1 $f11, 24(%[fb]) \n\t"
- "madd.s %[sum2], %[sum2], $f4, %[coeff1] \n\t"
- "madd.s %[sum1], %[sum1], $f8, %[coeff2] \n\t"
- "madd.s %[sum3], %[sum3], $f8, %[coeff1] \n\t"
- "madd.s %[sum4], %[sum4], $f11, %[coeff1] \n\t"
- "lwc1 $f7, 64(%[fb]) \n\t"
- "madd.s %[sum2], %[sum2], $f11, %[coeff2] \n\t"
- "lwc1 $f10, 68(%[fb]) \n\t"
- "madd.s %[sum3], %[sum3], $f2, %[coeff1] \n\t"
- "madd.s %[sum4], %[sum4], $f5, %[coeff1] \n\t"
- "madd.s %[sum1], %[sum1], $f7, %[coeff2] \n\t"
- "madd.s %[sum2], %[sum2], $f10, %[coeff2] \n\t"
- "lwc1 $f2, 28(%[fb]) \n\t"
- "lwc1 $f5, 32(%[fb]) \n\t"
- "lwc1 $f8, 56(%[fb]) \n\t"
- "lwc1 $f11, 60(%[fb]) \n\t"
- "madd.s %[sum3], %[sum3], $f2, %[coeff2] \n\t"
- "madd.s %[sum4], %[sum4], $f5, %[coeff2] \n\t"
- "madd.s %[sum1], %[sum1], $f2, %[coeff3] \n\t"
- "madd.s %[sum2], %[sum2], $f5, %[coeff3] \n\t"
- "madd.s %[sum3], %[sum3], $f1, %[coeff2] \n\t"
- "madd.s %[sum4], %[sum4], $f4, %[coeff2] \n\t"
- "madd.s %[sum1], %[sum1], $f8, %[coeff3] \n\t"
- "madd.s %[sum2], %[sum2], $f11, %[coeff3] \n\t"
- "lwc1 $f1, 36(%[fb]) \n\t"
- PTR_ADDIU "%[fb], %[fb], 16 \n\t"
- "madd.s %[sum4], %[sum4], $f0, %[coeff3] \n\t"
- "madd.s %[sum3], %[sum3], $f1, %[coeff3] \n\t"
- "madd.s %[sum1], %[sum1], $f1, %[coeff4] \n\t"
- "madd.s %[sum2], %[sum2], $f0, %[coeff4] \n\t"
- "madd.s %[sum4], %[sum4], $f10, %[coeff3] \n\t"
- "madd.s %[sum3], %[sum3], $f7, %[coeff3] \n\t"
- "madd.s %[sum1], %[sum1], $f6, %[coeff4] \n\t"
- "madd.s %[sum2], %[sum2], $f9, %[coeff4] \n\t"
- "madd.s %[sum4], %[sum4], $f6, %[coeff4] \n\t"
- "madd.s %[sum3], %[sum3], $f3, %[coeff4] \n\t"
- "mul.s %[sum1], %[sum1], %[f1] \n\t"
- "mul.s %[sum2], %[sum2], %[f1] \n\t"
- "madd.s %[sum4], %[sum4], $f11, %[coeff4] \n\t"
- "madd.s %[sum3], %[sum3], $f8, %[coeff4] \n\t"
- "swc1 %[sum1], 0(%[hp]) \n\t"
- "swc1 %[sum2], 4(%[hp]) \n\t"
- "mul.s %[sum4], %[sum4], %[f1] \n\t"
- "mul.s %[sum3], %[sum3], %[f1] \n\t"
- "swc1 %[sum4], 12(%[hp]) \n\t"
- "swc1 %[sum3], 8(%[hp]) \n\t"
- "bne %[fb], %[fb_end], 1b \n\t"
- PTR_ADDIU "%[hp], %[hp], 16 \n\t"
-
- ".set pop \n\t"
-
- : [sum1]"=&f"(sum1), [sum2]"=&f"(sum2),
- [sum3]"=&f"(sum3), [sum4]"=&f"(sum4),
- [fb]"+r"(fb), [hp]"+r"(hp)
- : [coeff0]"f"(coeff0), [coeff1]"f"(coeff1),
- [coeff2]"f"(coeff2), [coeff3]"f"(coeff3),
- [coeff4]"f"(coeff4), [fb_end]"r"(fb_end), [f1]"f"(f1)
- : "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6",
- "$f7", "$f8", "$f9", "$f10", "$f11",
- "memory"
- );
-}
-
-#define calc_thr_3gpp calc_thr_3gpp_mips
-#define psy_hp_filter psy_hp_filter_mips
-
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_INLINE_ASM && HAVE_MIPSFPU */
-#endif /* AVCODEC_MIPS_AACPSY_MIPS_H */
diff --git a/libavcodec/mips/aacsbr_mips.c b/libavcodec/mips/aacsbr_mips.c
deleted file mode 100644
index eea48b360b..0000000000
--- a/libavcodec/mips/aacsbr_mips.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * 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.
- *
- * Authors: Djordje Pesut (djordje@mips.com)
- * Mirjana Vulin (mvulin@mips.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
- */
-
-/**
- * @file
- * Reference: libavcodec/aacsbr.c
- */
-
-#include "libavcodec/aacdec.h"
-#include "libavcodec/aacsbr.h"
-#include "libavcodec/sbr.h"
-#include "libavutil/mem_internal.h"
-#include "libavutil/mips/asmdefs.h"
-
-#define ENVELOPE_ADJUSTMENT_OFFSET 2
-
-#if HAVE_INLINE_ASM
-#if HAVE_MIPSFPU
-static int sbr_lf_gen_mips(SpectralBandReplication *sbr,
- float X_low[32][40][2], const float W[2][32][32][2],
- int buf_idx)
-{
- int i, k;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
- float *p_x_low = &X_low[0][8][0];
- float *p_w = (float*)&W[buf_idx][0][0][0];
- float *p_x1_low = &X_low[0][0][0];
- float *p_w1 = (float*)&W[1-buf_idx][24][0][0];
-
- float *loop_end=p_x1_low + 2560;
-
- /* loop unrolled 8 times */
- __asm__ volatile (
- "1: \n\t"
- "sw $0, 0(%[p_x1_low]) \n\t"
- "sw $0, 4(%[p_x1_low]) \n\t"
- "sw $0, 8(%[p_x1_low]) \n\t"
- "sw $0, 12(%[p_x1_low]) \n\t"
- "sw $0, 16(%[p_x1_low]) \n\t"
- "sw $0, 20(%[p_x1_low]) \n\t"
- "sw $0, 24(%[p_x1_low]) \n\t"
- "sw $0, 28(%[p_x1_low]) \n\t"
- PTR_ADDIU "%[p_x1_low],%[p_x1_low], 32 \n\t"
- "bne %[p_x1_low], %[loop_end], 1b \n\t"
- PTR_ADDIU "%[p_x1_low],%[p_x1_low], -10240 \n\t"
-
- : [p_x1_low]"+r"(p_x1_low)
- : [loop_end]"r"(loop_end)
- : "memory"
- );
-
- for (k = 0; k < sbr->kx[1]; k++) {
- for (i = 0; i < 32; i+=4) {
- /* loop unrolled 4 times */
- __asm__ volatile (
- "lw %[temp0], 0(%[p_w]) \n\t"
- "lw %[temp1], 4(%[p_w]) \n\t"
- "lw %[temp2], 256(%[p_w]) \n\t"
- "lw %[temp3], 260(%[p_w]) \n\t"
- "lw %[temp4], 512(%[p_w]) \n\t"
- "lw %[temp5], 516(%[p_w]) \n\t"
- "lw %[temp6], 768(%[p_w]) \n\t"
- "lw %[temp7], 772(%[p_w]) \n\t"
- "sw %[temp0], 0(%[p_x_low]) \n\t"
- "sw %[temp1], 4(%[p_x_low]) \n\t"
- "sw %[temp2], 8(%[p_x_low]) \n\t"
- "sw %[temp3], 12(%[p_x_low]) \n\t"
- "sw %[temp4], 16(%[p_x_low]) \n\t"
- "sw %[temp5], 20(%[p_x_low]) \n\t"
- "sw %[temp6], 24(%[p_x_low]) \n\t"
- "sw %[temp7], 28(%[p_x_low]) \n\t"
- PTR_ADDIU "%[p_x_low], %[p_x_low], 32 \n\t"
- PTR_ADDIU "%[p_w], %[p_w], 1024 \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7),
- [p_w]"+r"(p_w), [p_x_low]"+r"(p_x_low)
- :
- : "memory"
- );
- }
- p_x_low += 16;
- p_w -= 2046;
- }
-
- for (k = 0; k < sbr->kx[0]; k++) {
- for (i = 0; i < 2; i++) {
-
- /* loop unrolled 4 times */
- __asm__ volatile (
- "lw %[temp0], 0(%[p_w1]) \n\t"
- "lw %[temp1], 4(%[p_w1]) \n\t"
- "lw %[temp2], 256(%[p_w1]) \n\t"
- "lw %[temp3], 260(%[p_w1]) \n\t"
- "lw %[temp4], 512(%[p_w1]) \n\t"
- "lw %[temp5], 516(%[p_w1]) \n\t"
- "lw %[temp6], 768(%[p_w1]) \n\t"
- "lw %[temp7], 772(%[p_w1]) \n\t"
- "sw %[temp0], 0(%[p_x1_low]) \n\t"
- "sw %[temp1], 4(%[p_x1_low]) \n\t"
- "sw %[temp2], 8(%[p_x1_low]) \n\t"
- "sw %[temp3], 12(%[p_x1_low]) \n\t"
- "sw %[temp4], 16(%[p_x1_low]) \n\t"
- "sw %[temp5], 20(%[p_x1_low]) \n\t"
- "sw %[temp6], 24(%[p_x1_low]) \n\t"
- "sw %[temp7], 28(%[p_x1_low]) \n\t"
- PTR_ADDIU "%[p_x1_low], %[p_x1_low], 32 \n\t"
- PTR_ADDIU "%[p_w1], %[p_w1], 1024 \n\t"
-
- : [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7),
- [p_w1]"+r"(p_w1), [p_x1_low]"+r"(p_x1_low)
- :
- : "memory"
- );
- }
- p_x1_low += 64;
- p_w1 -= 510;
- }
- return 0;
-}
-
-static int sbr_x_gen_mips(SpectralBandReplication *sbr, float X[2][38][64],
- const float Y0[38][64][2], const float Y1[38][64][2],
- const float X_low[32][40][2], int ch)
-{
- int k, i;
- const int i_f = 32;
- int temp0, temp1, temp2, temp3;
- const float *X_low1, *Y01, *Y11;
- float *x1=&X[0][0][0];
- float *j=x1+4864;
- const int i_Temp = FFMAX(2*sbr->data[ch].t_env_num_env_old - i_f, 0);
-
- /* loop unrolled 8 times */
- __asm__ volatile (
- "1: \n\t"
- "sw $0, 0(%[x1]) \n\t"
- "sw $0, 4(%[x1]) \n\t"
- "sw $0, 8(%[x1]) \n\t"
- "sw $0, 12(%[x1]) \n\t"
- "sw $0, 16(%[x1]) \n\t"
- "sw $0, 20(%[x1]) \n\t"
- "sw $0, 24(%[x1]) \n\t"
- "sw $0, 28(%[x1]) \n\t"
- PTR_ADDIU "%[x1],%[x1], 32 \n\t"
- "bne %[x1], %[j], 1b \n\t"
- PTR_ADDIU "%[x1],%[x1], -19456 \n\t"
-
- : [x1]"+r"(x1)
- : [j]"r"(j)
- : "memory"
- );
-
- if (i_Temp != 0) {
-
- X_low1=&X_low[0][2][0];
-
- for (k = 0; k < sbr->kx[0]; k++) {
-
- __asm__ volatile (
- "move %[i], $zero \n\t"
- "2: \n\t"
- "lw %[temp0], 0(%[X_low1]) \n\t"
- "lw %[temp1], 4(%[X_low1]) \n\t"
- "sw %[temp0], 0(%[x1]) \n\t"
- "sw %[temp1], 9728(%[x1]) \n\t"
- PTR_ADDIU "%[x1], %[x1], 256 \n\t"
- PTR_ADDIU "%[X_low1], %[X_low1], 8 \n\t"
- "addiu %[i], %[i], 1 \n\t"
- "bne %[i], %[i_Temp], 2b \n\t"
-
- : [x1]"+r"(x1), [X_low1]"+r"(X_low1), [i]"=&r"(i),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
- : [i_Temp]"r"(i_Temp)
- : "memory"
- );
- x1-=(i_Temp<<6)-1;
- X_low1-=(i_Temp<<1)-80;
- }
-
- x1=&X[0][0][k];
- Y01=(float*)&Y0[32][k][0];
-
- for (; k < sbr->kx[0] + sbr->m[0]; k++) {
- __asm__ volatile (
- "move %[i], $zero \n\t"
- "3: \n\t"
- "lw %[temp0], 0(%[Y01]) \n\t"
- "lw %[temp1], 4(%[Y01]) \n\t"
- "sw %[temp0], 0(%[x1]) \n\t"
- "sw %[temp1], 9728(%[x1]) \n\t"
- PTR_ADDIU "%[x1], %[x1], 256 \n\t"
- PTR_ADDIU "%[Y01], %[Y01], 512 \n\t"
- "addiu %[i], %[i], 1 \n\t"
- "bne %[i], %[i_Temp], 3b \n\t"
-
- : [x1]"+r"(x1), [Y01]"+r"(Y01), [i]"=&r"(i),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
- : [i_Temp]"r"(i_Temp)
- : "memory"
- );
- x1 -=(i_Temp<<6)-1;
- Y01 -=(i_Temp<<7)-2;
- }
- }
-
- x1=&X[0][i_Temp][0];
- X_low1=&X_low[0][i_Temp+2][0];
- temp3=38;
-
- for (k = 0; k < sbr->kx[1]; k++) {
-
- __asm__ volatile (
- "move %[i], %[i_Temp] \n\t"
- "4: \n\t"
- "lw %[temp0], 0(%[X_low1]) \n\t"
- "lw %[temp1], 4(%[X_low1]) \n\t"
- "sw %[temp0], 0(%[x1]) \n\t"
- "sw %[temp1], 9728(%[x1]) \n\t"
- PTR_ADDIU "%[x1], %[x1], 256 \n\t"
- PTR_ADDIU "%[X_low1],%[X_low1], 8 \n\t"
- "addiu %[i], %[i], 1 \n\t"
- "bne %[i], %[temp3], 4b \n\t"
-
- : [x1]"+r"(x1), [X_low1]"+r"(X_low1), [i]"=&r"(i),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2)
- : [i_Temp]"r"(i_Temp), [temp3]"r"(temp3)
- : "memory"
- );
- x1 -= ((38-i_Temp)<<6)-1;
- X_low1 -= ((38-i_Temp)<<1)- 80;
- }
-
- x1=&X[0][i_Temp][k];
- Y11=&Y1[i_Temp][k][0];
- temp2=32;
-
- for (; k < sbr->kx[1] + sbr->m[1]; k++) {
-
- __asm__ volatile (
- "move %[i], %[i_Temp] \n\t"
- "5: \n\t"
- "lw %[temp0], 0(%[Y11]) \n\t"
- "lw %[temp1], 4(%[Y11]) \n\t"
- "sw %[temp0], 0(%[x1]) \n\t"
- "sw %[temp1], 9728(%[x1]) \n\t"
- PTR_ADDIU "%[x1], %[x1], 256 \n\t"
- PTR_ADDIU "%[Y11], %[Y11], 512 \n\t"
- "addiu %[i], %[i], 1 \n\t"
- "bne %[i], %[temp2], 5b \n\t"
-
- : [x1]"+r"(x1), [Y11]"+r"(Y11), [i]"=&r"(i),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1)
- : [i_Temp]"r"(i_Temp), [temp3]"r"(temp3),
- [temp2]"r"(temp2)
- : "memory"
- );
-
- x1 -= ((32-i_Temp)<<6)-1;
- Y11 -= ((32-i_Temp)<<7)-2;
- }
- return 0;
-}
-
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
-static void sbr_hf_assemble_mips(float Y1[38][64][2],
- const float X_high[64][40][2],
- SpectralBandReplication *sbr, SBRData *ch_data,
- const int e_a[2])
-{
- int e, i, j, m;
- const int h_SL = 4 * !sbr->bs_smoothing_mode;
- const int kx = sbr->kx[1];
- const int m_max = sbr->m[1];
- static const float h_smooth[5] = {
- 0.33333333333333,
- 0.30150283239582,
- 0.21816949906249,
- 0.11516383427084,
- 0.03183050093751,
- };
-
- float (*g_temp)[48] = ch_data->g_temp, (*q_temp)[48] = ch_data->q_temp;
- int indexnoise = ch_data->f_indexnoise;
- int indexsine = ch_data->f_indexsine;
- float *g_temp1, *q_temp1, *pok, *pok1;
- uint32_t temp1, temp2, temp3, temp4;
- int size = m_max;
-
- if (sbr->reset) {
- for (i = 0; i < h_SL; i++) {
- memcpy(g_temp[i + 2*ch_data->t_env[0]], sbr->gain[0], m_max * sizeof(sbr->gain[0][0]));
- memcpy(q_temp[i + 2*ch_data->t_env[0]], sbr->q_m[0], m_max * sizeof(sbr->q_m[0][0]));
- }
- } else if (h_SL) {
- memcpy(g_temp[2*ch_data->t_env[0]], g_temp[2*ch_data->t_env_num_env_old], 4*sizeof(g_temp[0]));
- memcpy(q_temp[2*ch_data->t_env[0]], q_temp[2*ch_data->t_env_num_env_old], 4*sizeof(q_temp[0]));
- }
-
- for (e = 0; e < ch_data->bs_num_env; e++) {
- for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) {
- g_temp1 = g_temp[h_SL + i];
- pok = sbr->gain[e];
- q_temp1 = q_temp[h_SL + i];
- pok1 = sbr->q_m[e];
-
- /* loop unrolled 4 times */
- for (j=0; j<(size>>2); j++) {
- __asm__ volatile (
- "lw %[temp1], 0(%[pok]) \n\t"
- "lw %[temp2], 4(%[pok]) \n\t"
- "lw %[temp3], 8(%[pok]) \n\t"
- "lw %[temp4], 12(%[pok]) \n\t"
- "sw %[temp1], 0(%[g_temp1]) \n\t"
- "sw %[temp2], 4(%[g_temp1]) \n\t"
- "sw %[temp3], 8(%[g_temp1]) \n\t"
- "sw %[temp4], 12(%[g_temp1]) \n\t"
- "lw %[temp1], 0(%[pok1]) \n\t"
- "lw %[temp2], 4(%[pok1]) \n\t"
- "lw %[temp3], 8(%[pok1]) \n\t"
- "lw %[temp4], 12(%[pok1]) \n\t"
- "sw %[temp1], 0(%[q_temp1]) \n\t"
- "sw %[temp2], 4(%[q_temp1]) \n\t"
- "sw %[temp3], 8(%[q_temp1]) \n\t"
- "sw %[temp4], 12(%[q_temp1]) \n\t"
- PTR_ADDIU "%[pok], %[pok], 16 \n\t"
- PTR_ADDIU "%[g_temp1], %[g_temp1], 16 \n\t"
- PTR_ADDIU "%[pok1], %[pok1], 16 \n\t"
- PTR_ADDIU "%[q_temp1], %[q_temp1], 16 \n\t"
-
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
- [pok]"+r"(pok), [g_temp1]"+r"(g_temp1),
- [pok1]"+r"(pok1), [q_temp1]"+r"(q_temp1)
- :
- : "memory"
- );
- }
-
- for (j=0; j<(size&3); j++) {
- __asm__ volatile (
- "lw %[temp1], 0(%[pok]) \n\t"
- "lw %[temp2], 0(%[pok1]) \n\t"
- "sw %[temp1], 0(%[g_temp1]) \n\t"
- "sw %[temp2], 0(%[q_temp1]) \n\t"
- PTR_ADDIU "%[pok], %[pok], 4 \n\t"
- PTR_ADDIU "%[g_temp1], %[g_temp1], 4 \n\t"
- PTR_ADDIU "%[pok1], %[pok1], 4 \n\t"
- PTR_ADDIU "%[q_temp1], %[q_temp1], 4 \n\t"
-
- : [temp1]"=&r"(temp1), [temp2]"=&r"(temp2),
- [temp3]"=&r"(temp3), [temp4]"=&r"(temp4),
- [pok]"+r"(pok), [g_temp1]"+r"(g_temp1),
- [pok1]"+r"(pok1), [q_temp1]"+r"(q_temp1)
- :
- : "memory"
- );
- }
- }
- }
-
- for (e = 0; e < ch_data->bs_num_env; e++) {
- for (i = 2 * ch_data->t_env[e]; i < 2 * ch_data->t_env[e + 1]; i++) {
- LOCAL_ALIGNED_16(float, g_filt_tab, [48]);
- LOCAL_ALIGNED_16(float, q_filt_tab, [48]);
- float *g_filt, *q_filt;
-
- if (h_SL && e != e_a[0] && e != e_a[1]) {
- g_filt = g_filt_tab;
- q_filt = q_filt_tab;
-
- for (m = 0; m < m_max; m++) {
- const int idx1 = i + h_SL;
- g_filt[m] = 0.0f;
- q_filt[m] = 0.0f;
-
- for (j = 0; j <= h_SL; j++) {
- g_filt[m] += g_temp[idx1 - j][m] * h_smooth[j];
- q_filt[m] += q_temp[idx1 - j][m] * h_smooth[j];
- }
- }
- } else {
- g_filt = g_temp[i + h_SL];
- q_filt = q_temp[i];
- }
-
- sbr->dsp.hf_g_filt(Y1[i] + kx, X_high + kx, g_filt, m_max,
- i + ENVELOPE_ADJUSTMENT_OFFSET);
-
- if (e != e_a[0] && e != e_a[1]) {
- sbr->dsp.hf_apply_noise[indexsine](Y1[i] + kx, sbr->s_m[e],
- q_filt, indexnoise,
- kx, m_max);
- } else {
- int idx = indexsine&1;
- int A = (1-((indexsine+(kx & 1))&2));
- int B = (A^(-idx)) + idx;
- float *out = &Y1[i][kx][idx];
- float *in = sbr->s_m[e];
- float temp0, temp1, temp2, temp3, temp4, temp5;
- float A_f = (float)A;
- float B_f = (float)B;
-
- for (m = 0; m+1 < m_max; m+=2) {
-
- temp2 = out[0];
- temp3 = out[2];
-
- __asm__ volatile(
- "lwc1 %[temp0], 0(%[in]) \n\t"
- "lwc1 %[temp1], 4(%[in]) \n\t"
- "madd.s %[temp4], %[temp2], %[temp0], %[A_f] \n\t"
- "madd.s %[temp5], %[temp3], %[temp1], %[B_f] \n\t"
- "swc1 %[temp4], 0(%[out]) \n\t"
- "swc1 %[temp5], 8(%[out]) \n\t"
- PTR_ADDIU "%[in], %[in], 8 \n\t"
- PTR_ADDIU "%[out], %[out], 16 \n\t"
-
- : [temp0]"=&f" (temp0), [temp1]"=&f"(temp1),
- [temp4]"=&f" (temp4), [temp5]"=&f"(temp5),
- [in]"+r"(in), [out]"+r"(out)
- : [A_f]"f"(A_f), [B_f]"f"(B_f), [temp2]"f"(temp2),
- [temp3]"f"(temp3)
- : "memory"
- );
- }
- if(m_max&1)
- out[2*m ] += in[m ] * A;
- }
- indexnoise = (indexnoise + m_max) & 0x1ff;
- indexsine = (indexsine + 1) & 3;
- }
- }
- ch_data->f_indexnoise = indexnoise;
- ch_data->f_indexsine = indexsine;
-}
-
-static void sbr_hf_inverse_filter_mips(SBRDSPContext *dsp,
- float (*alpha0)[2], float (*alpha1)[2],
- const float X_low[32][40][2], int k0)
-{
- int k;
- float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, c;
- float *phi1, *alpha_1, *alpha_0, res1, res2, temp_real, temp_im;
-
- c = 1.000001f;
-
- for (k = 0; k < k0; k++) {
- LOCAL_ALIGNED_16(float, phi, [3], [2][2]);
- float dk;
- phi1 = &phi[0][0][0];
- alpha_1 = &alpha1[k][0];
- alpha_0 = &alpha0[k][0];
- dsp->autocorrelate(X_low[k], phi);
-
- __asm__ volatile (
- "lwc1 %[temp0], 40(%[phi1]) \n\t"
- "lwc1 %[temp1], 16(%[phi1]) \n\t"
- "lwc1 %[temp2], 24(%[phi1]) \n\t"
- "lwc1 %[temp3], 28(%[phi1]) \n\t"
- "mul.s %[dk], %[temp0], %[temp1] \n\t"
- "lwc1 %[temp4], 0(%[phi1]) \n\t"
- "mul.s %[res2], %[temp2], %[temp2] \n\t"
- "lwc1 %[temp5], 4(%[phi1]) \n\t"
- "madd.s %[res2], %[res2], %[temp3], %[temp3] \n\t"
- "lwc1 %[temp6], 8(%[phi1]) \n\t"
- "div.s %[res2], %[res2], %[c] \n\t"
- "lwc1 %[temp0], 12(%[phi1]) \n\t"
- "sub.s %[dk], %[dk], %[res2] \n\t"
-
- : [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2),
- [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5),
- [temp6]"=&f"(temp6), [res2]"=&f"(res2), [dk]"=&f"(dk)
- : [phi1]"r"(phi1), [c]"f"(c)
- : "memory"
- );
-
- if (!dk) {
- alpha_1[0] = 0;
- alpha_1[1] = 0;
- } else {
- __asm__ volatile (
- "mul.s %[temp_real], %[temp4], %[temp2] \n\t"
- "nmsub.s %[temp_real], %[temp_real], %[temp5], %[temp3] \n\t"
- "nmsub.s %[temp_real], %[temp_real], %[temp6], %[temp1] \n\t"
- "mul.s %[temp_im], %[temp4], %[temp3] \n\t"
- "madd.s %[temp_im], %[temp_im], %[temp5], %[temp2] \n\t"
- "nmsub.s %[temp_im], %[temp_im], %[temp0], %[temp1] \n\t"
- "div.s %[temp_real], %[temp_real], %[dk] \n\t"
- "div.s %[temp_im], %[temp_im], %[dk] \n\t"
- "swc1 %[temp_real], 0(%[alpha_1]) \n\t"
- "swc1 %[temp_im], 4(%[alpha_1]) \n\t"
-
- : [temp_real]"=&f" (temp_real), [temp_im]"=&f"(temp_im)
- : [phi1]"r"(phi1), [temp0]"f"(temp0), [temp1]"f"(temp1),
- [temp2]"f"(temp2), [temp3]"f"(temp3), [temp4]"f"(temp4),
- [temp5]"f"(temp5), [temp6]"f"(temp6),
- [alpha_1]"r"(alpha_1), [dk]"f"(dk)
- : "memory"
- );
- }
-
- if (!phi1[4]) {
- alpha_0[0] = 0;
- alpha_0[1] = 0;
- } else {
- __asm__ volatile (
- "lwc1 %[temp6], 0(%[alpha_1]) \n\t"
- "lwc1 %[temp7], 4(%[alpha_1]) \n\t"
- "mul.s %[temp_real], %[temp6], %[temp2] \n\t"
- "add.s %[temp_real], %[temp_real], %[temp4] \n\t"
- "madd.s %[temp_real], %[temp_real], %[temp7], %[temp3] \n\t"
- "mul.s %[temp_im], %[temp7], %[temp2] \n\t"
- "add.s %[temp_im], %[temp_im], %[temp5] \n\t"
- "nmsub.s %[temp_im], %[temp_im], %[temp6], %[temp3] \n\t"
- "div.s %[temp_real], %[temp_real], %[temp1] \n\t"
- "div.s %[temp_im], %[temp_im], %[temp1] \n\t"
- "neg.s %[temp_real], %[temp_real] \n\t"
- "neg.s %[temp_im], %[temp_im] \n\t"
- "swc1 %[temp_real], 0(%[alpha_0]) \n\t"
- "swc1 %[temp_im], 4(%[alpha_0]) \n\t"
-
- : [temp_real]"=&f"(temp_real), [temp_im]"=&f"(temp_im),
- [temp6]"=&f"(temp6), [temp7]"=&f"(temp7),
- [res1]"=&f"(res1), [res2]"=&f"(res2)
- : [alpha_1]"r"(alpha_1), [alpha_0]"r"(alpha_0),
- [temp0]"f"(temp0), [temp1]"f"(temp1), [temp2]"f"(temp2),
- [temp3]"f"(temp3), [temp4]"f"(temp4), [temp5]"f"(temp5)
- : "memory"
- );
- }
-
- __asm__ volatile (
- "lwc1 %[temp1], 0(%[alpha_1]) \n\t"
- "lwc1 %[temp2], 4(%[alpha_1]) \n\t"
- "lwc1 %[temp_real], 0(%[alpha_0]) \n\t"
- "lwc1 %[temp_im], 4(%[alpha_0]) \n\t"
- "mul.s %[res1], %[temp1], %[temp1] \n\t"
- "madd.s %[res1], %[res1], %[temp2], %[temp2] \n\t"
- "mul.s %[res2], %[temp_real], %[temp_real] \n\t"
- "madd.s %[res2], %[res2], %[temp_im], %[temp_im] \n\t"
-
- : [temp_real]"=&f"(temp_real), [temp_im]"=&f"(temp_im),
- [temp1]"=&f"(temp1), [temp2]"=&f"(temp2),
- [res1]"=&f"(res1), [res2]"=&f"(res2)
- : [alpha_1]"r"(alpha_1), [alpha_0]"r"(alpha_0)
- : "memory"
- );
-
- if (res1 >= 16.0f || res2 >= 16.0f) {
- alpha_1[0] = 0;
- alpha_1[1] = 0;
- alpha_0[0] = 0;
- alpha_0[1] = 0;
- }
- }
-}
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-
-void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c)
-{
-#if HAVE_INLINE_ASM
-#if HAVE_MIPSFPU
- c->sbr_lf_gen = sbr_lf_gen_mips;
- c->sbr_x_gen = sbr_x_gen_mips;
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
- c->sbr_hf_inverse_filter = sbr_hf_inverse_filter_mips;
- c->sbr_hf_assemble = sbr_hf_assemble_mips;
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-}
diff --git a/libavcodec/mips/aacsbr_mips.h b/libavcodec/mips/aacsbr_mips.h
deleted file mode 100644
index 447393164a..0000000000
--- a/libavcodec/mips/aacsbr_mips.h
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * 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.
- *
- * Authors: Djordje Pesut (djordje@mips.com)
- * Mirjana Vulin (mvulin@mips.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
- */
-
-/**
- * @file
- * Reference: libavcodec/aacsbr.c
- */
-
-#ifndef AVCODEC_MIPS_AACSBR_MIPS_H
-#define AVCODEC_MIPS_AACSBR_MIPS_H
-
-#include "libavcodec/aacdec.h"
-#include "libavcodec/sbr.h"
-#include "libavutil/mips/asmdefs.h"
-
-#if HAVE_INLINE_ASM
-static void sbr_qmf_analysis_mips(AVFloatDSPContext *fdsp, AVTXContext *mdct, av_tx_fn mdct_fn,
- SBRDSPContext *sbrdsp, const float *in, float *x,
- float z[320], float W[2][32][32][2], int buf_idx)
-{
- int i;
- float *w0;
- float *w1;
- int temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
-
- w0 = x;
- w1 = x + 1024;
- for(i = 0; i < 36; i++)
- {
- /* loop unrolled 8 times */
- __asm__ volatile(
- "lw %[temp0], 0(%[w1]) \n\t"
- "lw %[temp1], 4(%[w1]) \n\t"
- "lw %[temp2], 8(%[w1]) \n\t"
- "lw %[temp3], 12(%[w1]) \n\t"
- "lw %[temp4], 16(%[w1]) \n\t"
- "lw %[temp5], 20(%[w1]) \n\t"
- "lw %[temp6], 24(%[w1]) \n\t"
- "lw %[temp7], 28(%[w1]) \n\t"
- "sw %[temp0], 0(%[w0]) \n\t"
- "sw %[temp1], 4(%[w0]) \n\t"
- "sw %[temp2], 8(%[w0]) \n\t"
- "sw %[temp3], 12(%[w0]) \n\t"
- "sw %[temp4], 16(%[w0]) \n\t"
- "sw %[temp5], 20(%[w0]) \n\t"
- "sw %[temp6], 24(%[w0]) \n\t"
- "sw %[temp7], 28(%[w0]) \n\t"
- PTR_ADDIU " %[w0], %[w0], 32 \n\t"
- PTR_ADDIU " %[w1], %[w1], 32 \n\t"
-
- : [w0]"+r"(w0), [w1]"+r"(w1),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
- :
- : "memory"
- );
- }
-
- w0 = x + 288;
- w1 = (float*)in;
- for(i = 0; i < 128; i++)
- {
- /* loop unrolled 8 times */
- __asm__ volatile(
- "lw %[temp0], 0(%[w1]) \n\t"
- "lw %[temp1], 4(%[w1]) \n\t"
- "lw %[temp2], 8(%[w1]) \n\t"
- "lw %[temp3], 12(%[w1]) \n\t"
- "lw %[temp4], 16(%[w1]) \n\t"
- "lw %[temp5], 20(%[w1]) \n\t"
- "lw %[temp6], 24(%[w1]) \n\t"
- "lw %[temp7], 28(%[w1]) \n\t"
- "sw %[temp0], 0(%[w0]) \n\t"
- "sw %[temp1], 4(%[w0]) \n\t"
- "sw %[temp2], 8(%[w0]) \n\t"
- "sw %[temp3], 12(%[w0]) \n\t"
- "sw %[temp4], 16(%[w0]) \n\t"
- "sw %[temp5], 20(%[w0]) \n\t"
- "sw %[temp6], 24(%[w0]) \n\t"
- "sw %[temp7], 28(%[w0]) \n\t"
- PTR_ADDIU " %[w0], %[w0], 32 \n\t"
- PTR_ADDIU " %[w1], %[w1], 32 \n\t"
-
- : [w0]"+r"(w0), [w1]"+r"(w1),
- [temp0]"=&r"(temp0), [temp1]"=&r"(temp1),
- [temp2]"=&r"(temp2), [temp3]"=&r"(temp3),
- [temp4]"=&r"(temp4), [temp5]"=&r"(temp5),
- [temp6]"=&r"(temp6), [temp7]"=&r"(temp7)
- :
- : "memory"
- );
- }
-
- for (i = 0; i < 32; i++) { // numTimeSlots*RATE = 16*2 as 960 sample frames
- // are not supported
- fdsp->vector_fmul_reverse(z, sbr_qmf_window_ds, x, 320);
- sbrdsp->sum64x5(z);
- sbrdsp->qmf_pre_shuffle(z);
- mdct_fn(mdct, z, z+64, sizeof(float));
- sbrdsp->qmf_post_shuffle(W[buf_idx][i], z);
- x += 32;
- }
-}
-
-#if HAVE_MIPSFPU
-#if !HAVE_MIPS32R6 && !HAVE_MIPS64R6
-static void sbr_qmf_synthesis_mips(AVTXContext *mdct, av_tx_fn mdct_fn,
- SBRDSPContext *sbrdsp, AVFloatDSPContext *fdsp,
- float *out, float X[2][38][64],
- float mdct_buf[2][64],
- float *v0, int *v_off, const unsigned int div)
-{
- int i, n;
- const float *sbr_qmf_window = div ? sbr_qmf_window_ds : sbr_qmf_window_us;
- const int step = 128 >> div;
- float *v;
- float temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8, temp9, temp10, temp11, temp12, temp13;
- float temp14, temp15, temp16, temp17, temp18, temp19;
- float *vv0, *s0, *dst;
- dst = out;
-
- for (i = 0; i < 32; i++) {
- if (*v_off < step) {
- int saved_samples = (1280 - 128) >> div;
- memcpy(&v0[SBR_SYNTHESIS_BUF_SIZE - saved_samples], v0, saved_samples * sizeof(float));
- *v_off = SBR_SYNTHESIS_BUF_SIZE - saved_samples - step;
- } else {
- *v_off -= step;
- }
- v = v0 + *v_off;
- if (div) {
- for (n = 0; n < 32; n++) {
- X[0][i][ n] = -X[0][i][n];
- X[0][i][32+n] = X[1][i][31-n];
- }
- mdct_fn(mdct, mdct_buf[0], X[0][i], sizeof(float));
- sbrdsp->qmf_deint_neg(v, mdct_buf[0]);
- } else {
- sbrdsp->neg_odd_64(X[1][i]);
- mdct_fn(mdct, mdct_buf[0], X[0][i], sizeof(float));
- mdct_fn(mdct, mdct_buf[1], X[1][i], sizeof(float));
- sbrdsp->qmf_deint_bfly(v, mdct_buf[1], mdct_buf[0]);
- }
-
- if(div == 0)
- {
- float *v0_end;
- vv0 = v;
- v0_end = v + 60;
- s0 = (float*)sbr_qmf_window;
-
- /* 10 calls of function vector_fmul_add merged into one loop
- and loop unrolled 4 times */
- __asm__ volatile(
- ".set push \n\t"
- ".set noreorder \n\t"
- "lwc1 %[temp4], 0(%[v0]) \n\t"
- "lwc1 %[temp5], 0(%[s0]) \n\t"
- "lwc1 %[temp6], 4(%[v0]) \n\t"
- "lwc1 %[temp7], 4(%[s0]) \n\t"
- "lwc1 %[temp8], 8(%[v0]) \n\t"
- "lwc1 %[temp9], 8(%[s0]) \n\t"
- "lwc1 %[temp10], 12(%[v0]) \n\t"
- "lwc1 %[temp11], 12(%[s0]) \n\t"
- "lwc1 %[temp12], 768(%[v0]) \n\t"
- "lwc1 %[temp13], 256(%[s0]) \n\t"
- "lwc1 %[temp14], 772(%[v0]) \n\t"
- "lwc1 %[temp15], 260(%[s0]) \n\t"
- "lwc1 %[temp16], 776(%[v0]) \n\t"
- "lwc1 %[temp17], 264(%[s0]) \n\t"
- "lwc1 %[temp18], 780(%[v0]) \n\t"
- "lwc1 %[temp19], 268(%[s0]) \n\t"
- "1: \n\t"
- "mul.s %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 1024(%[v0]) \n\t"
- "mul.s %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 512(%[s0]) \n\t"
- "mul.s %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 1028(%[v0]) \n\t"
- "mul.s %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 516(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 1032(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 520(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 1036(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 524(%[s0]) \n\t"
- "lwc1 %[temp12], 1792(%[v0]) \n\t"
- "lwc1 %[temp13], 768(%[s0]) \n\t"
- "lwc1 %[temp14], 1796(%[v0]) \n\t"
- "lwc1 %[temp15], 772(%[s0]) \n\t"
- "lwc1 %[temp16], 1800(%[v0]) \n\t"
- "lwc1 %[temp17], 776(%[s0]) \n\t"
- "lwc1 %[temp18], 1804(%[v0]) \n\t"
- "lwc1 %[temp19], 780(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 2048(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 1024(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 2052(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 1028(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 2056(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 1032(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 2060(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 1036(%[s0]) \n\t"
- "lwc1 %[temp12], 2816(%[v0]) \n\t"
- "lwc1 %[temp13], 1280(%[s0]) \n\t"
- "lwc1 %[temp14], 2820(%[v0]) \n\t"
- "lwc1 %[temp15], 1284(%[s0]) \n\t"
- "lwc1 %[temp16], 2824(%[v0]) \n\t"
- "lwc1 %[temp17], 1288(%[s0]) \n\t"
- "lwc1 %[temp18], 2828(%[v0]) \n\t"
- "lwc1 %[temp19], 1292(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 3072(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 1536(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 3076(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 1540(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 3080(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 1544(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 3084(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 1548(%[s0]) \n\t"
- "lwc1 %[temp12], 3840(%[v0]) \n\t"
- "lwc1 %[temp13], 1792(%[s0]) \n\t"
- "lwc1 %[temp14], 3844(%[v0]) \n\t"
- "lwc1 %[temp15], 1796(%[s0]) \n\t"
- "lwc1 %[temp16], 3848(%[v0]) \n\t"
- "lwc1 %[temp17], 1800(%[s0]) \n\t"
- "lwc1 %[temp18], 3852(%[v0]) \n\t"
- "lwc1 %[temp19], 1804(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 4096(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 2048(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 4100(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 2052(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 4104(%[v0]) \n\t"
- PTR_ADDIU "%[dst], %[dst], 16 \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 2056(%[s0]) \n\t"
- PTR_ADDIU " %[s0], %[s0], 16 \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 4108(%[v0]) \n\t"
- PTR_ADDIU " %[v0], %[v0], 16 \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 2044(%[s0]) \n\t"
- "lwc1 %[temp12], 4848(%[v0]) \n\t"
- "lwc1 %[temp13], 2288(%[s0]) \n\t"
- "lwc1 %[temp14], 4852(%[v0]) \n\t"
- "lwc1 %[temp15], 2292(%[s0]) \n\t"
- "lwc1 %[temp16], 4856(%[v0]) \n\t"
- "lwc1 %[temp17], 2296(%[s0]) \n\t"
- "lwc1 %[temp18], 4860(%[v0]) \n\t"
- "lwc1 %[temp19], 2300(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 0(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 0(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 4(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 4(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 8(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 8(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 12(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 12(%[s0]) \n\t"
- "lwc1 %[temp12], 768(%[v0]) \n\t"
- "lwc1 %[temp13], 256(%[s0]) \n\t"
- "lwc1 %[temp14], 772(%[v0]) \n\t"
- "lwc1 %[temp15], 260(%[s0]) \n\t"
- "lwc1 %[temp16], 776(%[v0]) \n\t"
- "lwc1 %[temp17], 264(%[s0]) \n\t"
- "lwc1 %[temp18], 780(%[v0]) \n\t"
- "lwc1 %[temp19], 268(%[s0]) \n\t"
- "swc1 %[temp0], -16(%[dst]) \n\t"
- "swc1 %[temp1], -12(%[dst]) \n\t"
- "swc1 %[temp2], -8(%[dst]) \n\t"
- "bne %[v0], %[v0_end], 1b \n\t"
- " swc1 %[temp3], -4(%[dst]) \n\t"
- "mul.s %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 1024(%[v0]) \n\t"
- "mul.s %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 512(%[s0]) \n\t"
- "mul.s %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 1028(%[v0]) \n\t"
- "mul.s %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 516(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 1032(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 520(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 1036(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 524(%[s0]) \n\t"
- "lwc1 %[temp12], 1792(%[v0]) \n\t"
- "lwc1 %[temp13], 768(%[s0]) \n\t"
- "lwc1 %[temp14], 1796(%[v0]) \n\t"
- "lwc1 %[temp15], 772(%[s0]) \n\t"
- "lwc1 %[temp16], 1800(%[v0]) \n\t"
- "lwc1 %[temp17], 776(%[s0]) \n\t"
- "lwc1 %[temp18], 1804(%[v0]) \n\t"
- "lwc1 %[temp19], 780(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 2048(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 1024(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 2052(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 1028(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 2056(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 1032(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 2060(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 1036(%[s0]) \n\t"
- "lwc1 %[temp12], 2816(%[v0]) \n\t"
- "lwc1 %[temp13], 1280(%[s0]) \n\t"
- "lwc1 %[temp14], 2820(%[v0]) \n\t"
- "lwc1 %[temp15], 1284(%[s0]) \n\t"
- "lwc1 %[temp16], 2824(%[v0]) \n\t"
- "lwc1 %[temp17], 1288(%[s0]) \n\t"
- "lwc1 %[temp18], 2828(%[v0]) \n\t"
- "lwc1 %[temp19], 1292(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 3072(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 1536(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 3076(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 1540(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 3080(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 1544(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 3084(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 1548(%[s0]) \n\t"
- "lwc1 %[temp12], 3840(%[v0]) \n\t"
- "lwc1 %[temp13], 1792(%[s0]) \n\t"
- "lwc1 %[temp14], 3844(%[v0]) \n\t"
- "lwc1 %[temp15], 1796(%[s0]) \n\t"
- "lwc1 %[temp16], 3848(%[v0]) \n\t"
- "lwc1 %[temp17], 1800(%[s0]) \n\t"
- "lwc1 %[temp18], 3852(%[v0]) \n\t"
- "lwc1 %[temp19], 1804(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp4], 4096(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp5], 2048(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp6], 4100(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp7], 2052(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- "lwc1 %[temp8], 4104(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "lwc1 %[temp9], 2056(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "lwc1 %[temp10], 4108(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "lwc1 %[temp11], 2060(%[s0]) \n\t"
- "lwc1 %[temp12], 4864(%[v0]) \n\t"
- "lwc1 %[temp13], 2304(%[s0]) \n\t"
- "lwc1 %[temp14], 4868(%[v0]) \n\t"
- "lwc1 %[temp15], 2308(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp4], %[temp5] \n\t"
- "lwc1 %[temp16], 4872(%[v0]) \n\t"
- "madd.s %[temp1], %[temp1], %[temp6], %[temp7] \n\t"
- "lwc1 %[temp17], 2312(%[s0]) \n\t"
- "madd.s %[temp2], %[temp2], %[temp8], %[temp9] \n\t"
- "lwc1 %[temp18], 4876(%[v0]) \n\t"
- "madd.s %[temp3], %[temp3], %[temp10], %[temp11] \n\t"
- "lwc1 %[temp19], 2316(%[s0]) \n\t"
- "madd.s %[temp0], %[temp0], %[temp12], %[temp13] \n\t"
- PTR_ADDIU "%[dst], %[dst], 16 \n\t"
- "madd.s %[temp1], %[temp1], %[temp14], %[temp15] \n\t"
- "madd.s %[temp2], %[temp2], %[temp16], %[temp17] \n\t"
- "madd.s %[temp3], %[temp3], %[temp18], %[temp19] \n\t"
- "swc1 %[temp0], -16(%[dst]) \n\t"
- "swc1 %[temp1], -12(%[dst]) \n\t"
- "swc1 %[temp2], -8(%[dst]) \n\t"
- "swc1 %[temp3], -4(%[dst]) \n\t"
- ".set pop \n\t"
-
- : [dst]"+r"(dst), [v0]"+r"(vv0), [s0]"+r"(s0),
- [temp0]"=&f"(temp0), [temp1]"=&f"(temp1), [temp2]"=&f"(temp2),
- [temp3]"=&f"(temp3), [temp4]"=&f"(temp4), [temp5]"=&f"(temp5),
- [temp6]"=&f"(temp6), [temp7]"=&f"(temp7), [temp8]"=&f"(temp8),
- [temp9]"=&f"(temp9), [temp10]"=&f"(temp10), [temp11]"=&f"(temp11),
- [temp12]"=&f"(temp12), [temp13]"=&f"(temp13), [temp14]"=&f"(temp14),
- [temp15]"=&f"(temp15), [temp16]"=&f"(temp16), [temp17]"=&f"(temp17),
- [temp18]"=&f"(temp18), [temp19]"=&f"(temp19)
- : [v0_end]"r"(v0_end)
- : "memory"
- );
- }
- else
- {
- fdsp->vector_fmul (out, v , sbr_qmf_window , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 192 >> div), sbr_qmf_window + ( 64 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 256 >> div), sbr_qmf_window + (128 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 448 >> div), sbr_qmf_window + (192 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 512 >> div), sbr_qmf_window + (256 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 704 >> div), sbr_qmf_window + (320 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 768 >> div), sbr_qmf_window + (384 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + ( 960 >> div), sbr_qmf_window + (448 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + (1024 >> div), sbr_qmf_window + (512 >> div), out , 64 >> div);
- fdsp->vector_fmul_add(out, v + (1216 >> div), sbr_qmf_window + (576 >> div), out , 64 >> div);
- out += 64 >> div;
- }
- }
-}
-
-#define sbr_qmf_analysis sbr_qmf_analysis_mips
-#define sbr_qmf_synthesis sbr_qmf_synthesis_mips
-
-#endif /* !HAVE_MIPS32R6 && !HAVE_MIPS64R6 */
-#endif /* HAVE_MIPSFPU */
-#endif /* HAVE_INLINE_ASM */
-
-#endif /* AVCODEC_MIPS_AACSBR_MIPS_H */
--
2.43.0.381.gb435a96ce8
[-- Attachment #5: 0035-aac-move-aacdec.c-to-aac-aacdec.c.patch --]
[-- Type: text/x-diff, Size: 190066 bytes --]
From dd42a5cba06478d6898c939c19dc04f7ab5fbea2 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 21 Mar 2024 08:20:43 +0100
Subject: [PATCH 35/38] aac: move aacdec.c to aac/aacdec.c
---
libavcodec/Makefile | 2 +-
libavcodec/aac/aacdec.c | 2545 +++++++++++++++++++++++++++++++++-
libavcodec/aac/aacdec.h | 7 +-
libavcodec/aac/aacdec_latm.h | 2 +-
libavcodec/aacdec.c | 2495 ---------------------------------
5 files changed, 2493 insertions(+), 2558 deletions(-)
delete mode 100644 libavcodec/aacdec.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6ba4a4140e..4da575903f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -178,7 +178,7 @@ OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o
OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
-OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o \
+OBJS-$(CONFIG_AAC_DECODER) += aactab.o \
aacsbr.o aacps_common.o aacps_float.o \
kbdwin.o \
sbrdsp.o aacpsdsp_float.o cbrt_data.o
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index dfbc309583..01a10468fa 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -32,10 +32,20 @@
#include <limits.h>
#include <stddef.h>
+#include "aacdec.h"
+#include "aacdec_tab.h"
+
#include "libavcodec/aac.h"
#include "libavcodec/aacsbr.h"
-#include "aacdec.h"
+#include "libavcodec/aactab.h"
+#include "libavcodec/adts_header.h"
+
#include "libavcodec/avcodec.h"
+#include "libavcodec/internal.h"
+#include "libavcodec/codec_internal.h"
+#include "libavcodec/decode.h"
+#include "libavcodec/profiles.h"
+
#include "libavutil/attributes.h"
#include "libavutil/error.h"
#include "libavutil/log.h"
@@ -44,89 +54,2468 @@
#include "libavutil/opt.h"
#include "libavutil/tx.h"
#include "libavutil/version.h"
+#include "libavutil/thread.h"
+
+/*
+ * supported tools
+ *
+ * Support? Name
+ * N (code in SoC repo) gain control
+ * Y block switching
+ * Y window shapes - standard
+ * N window shapes - Low Delay
+ * Y filterbank - standard
+ * N (code in SoC repo) filterbank - Scalable Sample Rate
+ * Y Temporal Noise Shaping
+ * Y Long Term Prediction
+ * Y intensity stereo
+ * Y channel coupling
+ * Y frequency domain prediction
+ * Y Perceptual Noise Substitution
+ * Y Mid/Side stereo
+ * N Scalable Inverse AAC Quantization
+ * N Frequency Selective Switch
+ * N upsampling filter
+ * Y quantization & coding - AAC
+ * N quantization & coding - TwinVQ
+ * N quantization & coding - BSAC
+ * N AAC Error Resilience tools
+ * N Error Resilience payload syntax
+ * N Error Protection tool
+ * N CELP
+ * N Silence Compression
+ * N HVXC
+ * N HVXC 4kbits/s VR
+ * N Structured Audio tools
+ * N Structured Audio Sample Bank Format
+ * N MIDI
+ * N Harmonic and Individual Lines plus Noise
+ * N Text-To-Speech Interface
+ * Y Spectral Band Replication
+ * Y (not in this code) Layer-1
+ * Y (not in this code) Layer-2
+ * Y (not in this code) Layer-3
+ * N SinuSoidal Coding (Transient, Sinusoid, Noise)
+ * Y Parametric Stereo
+ * N Direct Stream Transfer
+ * Y (not in fixed point code) Enhanced AAC Low Delay (ER AAC ELD)
+ *
+ * Note: - HE AAC v1 comprises LC AAC with Spectral Band Replication.
+ * - HE AAC v2 comprises LC AAC with Spectral Band Replication and
+ Parametric Stereo.
+ */
+
+static int output_configure(AACDecContext *ac,
+ uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
+ enum OCStatus oc_type, int get_new_frame);
+
+#define overread_err "Input buffer exhausted before END element found\n"
+
+static int count_channels(uint8_t (*layout)[3], int tags)
+{
+ int i, sum = 0;
+ for (i = 0; i < tags; i++) {
+ int syn_ele = layout[i][0];
+ int pos = layout[i][2];
+ sum += (1 + (syn_ele == TYPE_CPE)) *
+ (pos != AAC_CHANNEL_OFF && pos != AAC_CHANNEL_CC);
+ }
+ return sum;
+}
+
+/**
+ * Check for the channel element in the current channel position configuration.
+ * If it exists, make sure the appropriate element is allocated and map the
+ * channel order to match the internal FFmpeg channel layout.
+ *
+ * @param che_pos current channel position configuration
+ * @param type channel element type
+ * @param id channel element id
+ * @param channels count of the number of channels in the configuration
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static av_cold int che_configure(AACDecContext *ac,
+ enum ChannelPosition che_pos,
+ int type, int id, int *channels)
+{
+ if (*channels >= MAX_CHANNELS)
+ return AVERROR_INVALIDDATA;
+ if (che_pos) {
+ if (!ac->che[type][id]) {
+ int ret;
+ if (ac->is_fixed)
+ ret = ff_aac_sbr_ctx_alloc_init_fixed(ac, &ac->che[type][id], type);
+ else
+ ret = ff_aac_sbr_ctx_alloc_init(ac, &ac->che[type][id], type);
+ if (ret < 0)
+ return ret;
+ }
+ if (type != TYPE_CCE) {
+ if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) {
+ av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n");
+ return AVERROR_INVALIDDATA;
+ }
+ ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0];
+ if (type == TYPE_CPE ||
+ (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
+ ac->output_element[(*channels)++] = &ac->che[type][id]->ch[1];
+ }
+ }
+ } else {
+ if (ac->che[type][id]) {
+ if (ac->is_fixed)
+ ff_aac_sbr_ctx_close_fixed(ac->che[type][id]);
+ else
+ ff_aac_sbr_ctx_close(ac->che[type][id]);
+ }
+ av_freep(&ac->che[type][id]);
+ }
+ return 0;
+}
+
+static int frame_configure_elements(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int type, id, ch, ret;
+
+ /* set channel pointers to internal buffers by default */
+ for (type = 0; type < 4; type++) {
+ for (id = 0; id < MAX_ELEM_ID; id++) {
+ ChannelElement *che = ac->che[type][id];
+ if (che) {
+ che->ch[0].AAC_RENAME(output) = che->ch[0].AAC_RENAME(ret_buf);
+ che->ch[1].AAC_RENAME(output) = che->ch[1].AAC_RENAME(ret_buf);
+ }
+ }
+ }
+
+ /* get output buffer */
+ av_frame_unref(ac->frame);
+ if (!avctx->ch_layout.nb_channels)
+ return 1;
+
+ ac->frame->nb_samples = 2048;
+ if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
+ return ret;
+
+ /* map output channel pointers to AVFrame data */
+ for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
+ if (ac->output_element[ch])
+ ac->output_element[ch]->AAC_RENAME(output) = (INTFLOAT *)ac->frame->extended_data[ch];
+ }
+
+ return 0;
+}
+
+struct elem_to_channel {
+ uint64_t av_position;
+ uint8_t syn_ele;
+ uint8_t elem_id;
+ uint8_t aac_position;
+};
+
+static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID],
+ uint8_t (*layout_map)[3], int offset, uint64_t left,
+ uint64_t right, int pos, uint64_t *layout)
+{
+ if (layout_map[offset][0] == TYPE_CPE) {
+ e2c_vec[offset] = (struct elem_to_channel) {
+ .av_position = left | right,
+ .syn_ele = TYPE_CPE,
+ .elem_id = layout_map[offset][1],
+ .aac_position = pos
+ };
+ if (e2c_vec[offset].av_position != UINT64_MAX)
+ *layout |= e2c_vec[offset].av_position;
+
+ return 1;
+ } else {
+ e2c_vec[offset] = (struct elem_to_channel) {
+ .av_position = left,
+ .syn_ele = TYPE_SCE,
+ .elem_id = layout_map[offset][1],
+ .aac_position = pos
+ };
+ e2c_vec[offset + 1] = (struct elem_to_channel) {
+ .av_position = right,
+ .syn_ele = TYPE_SCE,
+ .elem_id = layout_map[offset + 1][1],
+ .aac_position = pos
+ };
+ if (left != UINT64_MAX)
+ *layout |= left;
+
+ if (right != UINT64_MAX)
+ *layout |= right;
+
+ return 2;
+ }
+}
+
+static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
+ int current)
+{
+ int num_pos_channels = 0;
+ int first_cpe = 0;
+ int sce_parity = 0;
+ int i;
+ for (i = current; i < tags; i++) {
+ if (layout_map[i][2] != pos)
+ break;
+ if (layout_map[i][0] == TYPE_CPE) {
+ if (sce_parity) {
+ if (pos == AAC_CHANNEL_FRONT && !first_cpe) {
+ sce_parity = 0;
+ } else {
+ return -1;
+ }
+ }
+ num_pos_channels += 2;
+ first_cpe = 1;
+ } else {
+ num_pos_channels++;
+ sce_parity ^= (pos != AAC_CHANNEL_LFE);
+ }
+ }
+ if (sce_parity &&
+ (pos == AAC_CHANNEL_FRONT && first_cpe))
+ return -1;
+
+ return num_pos_channels;
+}
+
+static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t (*layout_map)[3],
+ uint64_t *layout, int tags, int layer, int pos, int *current)
+{
+ int i = *current, j = 0;
+ int nb_channels = count_paired_channels(layout_map, tags, pos, i);
+
+ if (nb_channels < 0 || nb_channels > 5)
+ return 0;
+
+ if (pos == AAC_CHANNEL_LFE) {
+ while (nb_channels) {
+ if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE)
+ return -1;
+ e2c_vec[i] = (struct elem_to_channel) {
+ .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][j],
+ .syn_ele = layout_map[i][0],
+ .elem_id = layout_map[i][1],
+ .aac_position = pos
+ };
+ *layout |= e2c_vec[i].av_position;
+ i++;
+ j++;
+ nb_channels--;
+ }
+ *current = i;
+
+ return 0;
+ }
+
+ while (nb_channels & 1) {
+ if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE)
+ return -1;
+ if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED)
+ break;
+ e2c_vec[i] = (struct elem_to_channel) {
+ .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][0],
+ .syn_ele = layout_map[i][0],
+ .elem_id = layout_map[i][1],
+ .aac_position = pos
+ };
+ *layout |= e2c_vec[i].av_position;
+ i++;
+ nb_channels--;
+ }
+
+ j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1;
+ while (nb_channels >= 2) {
+ if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE ||
+ ff_aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE)
+ return -1;
+ i += assign_pair(e2c_vec, layout_map, i,
+ 1ULL << ff_aac_channel_map[layer][pos - 1][j],
+ 1ULL << ff_aac_channel_map[layer][pos - 1][j+1],
+ pos, layout);
+ j += 2;
+ nb_channels -= 2;
+ }
+ while (nb_channels & 1) {
+ if (ff_aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE)
+ return -1;
+ e2c_vec[i] = (struct elem_to_channel) {
+ .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][5],
+ .syn_ele = layout_map[i][0],
+ .elem_id = layout_map[i][1],
+ .aac_position = pos
+ };
+ *layout |= e2c_vec[i].av_position;
+ i++;
+ nb_channels--;
+ }
+ if (nb_channels)
+ return -1;
+
+ *current = i;
+
+ return 0;
+}
+
+static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
+{
+ int i, n, total_non_cc_elements;
+ struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
+ uint64_t layout = 0;
+
+ if (FF_ARRAY_ELEMS(e2c_vec) < tags)
+ return 0;
+
+ for (n = 0, i = 0; n < 3 && i < tags; n++) {
+ int ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_FRONT, &i);
+ if (ret < 0)
+ return 0;
+ ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_SIDE, &i);
+ if (ret < 0)
+ return 0;
+ ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_BACK, &i);
+ if (ret < 0)
+ return 0;
+ ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_LFE, &i);
+ if (ret < 0)
+ return 0;
+ }
+
+ total_non_cc_elements = n = i;
+
+ if (layout == AV_CH_LAYOUT_22POINT2) {
+ // For 22.2 reorder the result as needed
+ FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[0]); // FL & FR first (final), FC third
+ FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[1]); // FC second (final), FLc & FRc third
+ FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[2]); // LFE1 third (final), FLc & FRc seventh
+ FFSWAP(struct elem_to_channel, e2c_vec[4], e2c_vec[3]); // BL & BR fourth (final), SiL & SiR fifth
+ FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[4]); // FLc & FRc fifth (final), SiL & SiR seventh
+ FFSWAP(struct elem_to_channel, e2c_vec[7], e2c_vec[6]); // LFE2 seventh (final), SiL & SiR eight (final)
+ FFSWAP(struct elem_to_channel, e2c_vec[9], e2c_vec[8]); // TpFL & TpFR ninth (final), TFC tenth (final)
+ FFSWAP(struct elem_to_channel, e2c_vec[11], e2c_vec[10]); // TC eleventh (final), TpSiL & TpSiR twelth
+ FFSWAP(struct elem_to_channel, e2c_vec[12], e2c_vec[11]); // TpBL & TpBR twelth (final), TpSiL & TpSiR thirteenth (final)
+ } else {
+ // For everything else, utilize the AV channel position define as a
+ // stable sort.
+ do {
+ int next_n = 0;
+ for (i = 1; i < n; i++)
+ if (e2c_vec[i - 1].av_position > e2c_vec[i].av_position) {
+ FFSWAP(struct elem_to_channel, e2c_vec[i - 1], e2c_vec[i]);
+ next_n = i;
+ }
+ n = next_n;
+ } while (n > 0);
+
+ }
+
+ for (i = 0; i < total_non_cc_elements; i++) {
+ layout_map[i][0] = e2c_vec[i].syn_ele;
+ layout_map[i][1] = e2c_vec[i].elem_id;
+ layout_map[i][2] = e2c_vec[i].aac_position;
+ }
+
+ return layout;
+}
+
+/**
+ * Save current output configuration if and only if it has been locked.
+ */
+static int push_output_configuration(AACDecContext *ac)
+{
+ int pushed = 0;
+
+ if (ac->oc[1].status == OC_LOCKED || ac->oc[0].status == OC_NONE) {
+ ac->oc[0] = ac->oc[1];
+ pushed = 1;
+ }
+ ac->oc[1].status = OC_NONE;
+ return pushed;
+}
+
+/**
+ * Restore the previous output configuration if and only if the current
+ * configuration is unlocked.
+ */
+static void pop_output_configuration(AACDecContext *ac)
+{
+ if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
+ ac->oc[1] = ac->oc[0];
+ ac->avctx->ch_layout = ac->oc[1].ch_layout;
+ output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
+ ac->oc[1].status, 0);
+ }
+}
+
+/**
+ * Configure output channel order based on the current program
+ * configuration element.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int output_configure(AACDecContext *ac,
+ uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags,
+ enum OCStatus oc_type, int get_new_frame)
+{
+ AVCodecContext *avctx = ac->avctx;
+ int i, channels = 0, ret;
+ uint64_t layout = 0;
+ uint8_t id_map[TYPE_END][MAX_ELEM_ID] = {{ 0 }};
+ uint8_t type_counts[TYPE_END] = { 0 };
+
+ if (ac->oc[1].layout_map != layout_map) {
+ memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0]));
+ ac->oc[1].layout_map_tags = tags;
+ }
+ for (i = 0; i < tags; i++) {
+ int type = layout_map[i][0];
+ int id = layout_map[i][1];
+ id_map[type][id] = type_counts[type]++;
+ if (id_map[type][id] >= MAX_ELEM_ID) {
+ avpriv_request_sample(ac->avctx, "Too large remapped id");
+ return AVERROR_PATCHWELCOME;
+ }
+ }
+ // Try to sniff a reasonable channel order, otherwise output the
+ // channels in the order the PCE declared them.
+ if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT)
+ layout = sniff_channel_order(layout_map, tags);
+ for (i = 0; i < tags; i++) {
+ int type = layout_map[i][0];
+ int id = layout_map[i][1];
+ int iid = id_map[type][id];
+ int position = layout_map[i][2];
+ // Allocate or free elements depending on if they are in the
+ // current program configuration.
+ ret = che_configure(ac, position, type, iid, &channels);
+ if (ret < 0)
+ return ret;
+ ac->tag_che_map[type][id] = ac->che[type][iid];
+ }
+ if (ac->oc[1].m4ac.ps == 1 && channels == 2) {
+ if (layout == AV_CH_FRONT_CENTER) {
+ layout = AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT;
+ } else {
+ layout = 0;
+ }
+ }
+
+ av_channel_layout_uninit(&ac->oc[1].ch_layout);
+ if (layout)
+ av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
+ else {
+ ac->oc[1].ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ac->oc[1].ch_layout.nb_channels = channels;
+ }
+
+ av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
+ ac->oc[1].status = oc_type;
+
+ if (get_new_frame) {
+ if ((ret = frame_configure_elements(ac->avctx)) < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void flush(AVCodecContext *avctx)
+{
+ AACDecContext *ac= avctx->priv_data;
+ int type, i, j;
+
+ for (type = 3; type >= 0; type--) {
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *che = ac->che[type][i];
+ if (che) {
+ for (j = 0; j <= 1; j++) {
+ memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Set up channel positions based on a default channel configuration
+ * as specified in table 1.17.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int set_default_channel_config(AACDecContext *ac, AVCodecContext *avctx,
+ uint8_t (*layout_map)[3],
+ int *tags,
+ int channel_config)
+{
+ if (channel_config < 1 || (channel_config > 7 && channel_config < 11) ||
+ channel_config > 14) {
+ av_log(avctx, AV_LOG_ERROR,
+ "invalid default channel configuration (%d)\n",
+ channel_config);
+ return AVERROR_INVALIDDATA;
+ }
+ *tags = ff_tags_per_config[channel_config];
+ memcpy(layout_map, ff_aac_channel_layout_map[channel_config - 1],
+ *tags * sizeof(*layout_map));
+
+ /*
+ * AAC specification has 7.1(wide) as a default layout for 8-channel streams.
+ * However, at least Nero AAC encoder encodes 7.1 streams using the default
+ * channel config 7, mapping the side channels of the original audio stream
+ * to the second AAC_CHANNEL_FRONT pair in the AAC stream. Similarly, e.g. FAAD
+ * decodes the second AAC_CHANNEL_FRONT pair as side channels, therefore decoding
+ * the incorrect streams as if they were correct (and as the encoder intended).
+ *
+ * As actual intended 7.1(wide) streams are very rare, default to assuming a
+ * 7.1 layout was intended.
+ */
+ if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) {
+ layout_map[2][2] = AAC_CHANNEL_BACK;
+
+ if (!ac || !ac->warned_71_wide++) {
+ av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout"
+ " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode"
+ " according to the specification instead.\n", FF_COMPLIANCE_STRICT);
+ }
+ }
+
+ return 0;
+}
+
+static ChannelElement *get_che(AACDecContext *ac, int type, int elem_id)
+{
+ /* For PCE based channel configurations map the channels solely based
+ * on tags. */
+ if (!ac->oc[1].m4ac.chan_config) {
+ return ac->tag_che_map[type][elem_id];
+ }
+ // Allow single CPE stereo files to be signalled with mono configuration.
+ if (!ac->tags_mapped && type == TYPE_CPE &&
+ ac->oc[1].m4ac.chan_config == 1) {
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int layout_map_tags;
+ push_output_configuration(ac);
+
+ av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n");
+
+ if (set_default_channel_config(ac, ac->avctx, layout_map,
+ &layout_map_tags, 2) < 0)
+ return NULL;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ OC_TRIAL_FRAME, 1) < 0)
+ return NULL;
+
+ ac->oc[1].m4ac.chan_config = 2;
+ ac->oc[1].m4ac.ps = 0;
+ }
+ // And vice-versa
+ if (!ac->tags_mapped && type == TYPE_SCE &&
+ ac->oc[1].m4ac.chan_config == 2) {
+ uint8_t layout_map[MAX_ELEM_ID * 4][3];
+ int layout_map_tags;
+ push_output_configuration(ac);
+
+ av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n");
+
+ layout_map_tags = 2;
+ layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
+ layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
+ layout_map[0][1] = 0;
+ layout_map[1][1] = 1;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ OC_TRIAL_FRAME, 1) < 0)
+ return NULL;
+
+ if (ac->oc[1].m4ac.sbr)
+ ac->oc[1].m4ac.ps = -1;
+ }
+ /* For indexed channel configurations map the channels solely based
+ * on position. */
+ switch (ac->oc[1].m4ac.chan_config) {
+ case 14:
+ if (ac->tags_mapped > 2 && ((type == TYPE_CPE && elem_id < 3) ||
+ (type == TYPE_LFE && elem_id < 1))) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
+ }
+ case 13:
+ if (ac->tags_mapped > 3 && ((type == TYPE_CPE && elem_id < 8) ||
+ (type == TYPE_SCE && elem_id < 6) ||
+ (type == TYPE_LFE && elem_id < 2))) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
+ }
+ case 12:
+ case 7:
+ if (ac->tags_mapped == 3 && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
+ }
+ case 11:
+ if (ac->tags_mapped == 3 && type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 6:
+ /* Some streams incorrectly code 5.1 audio as
+ * SCE[0] CPE[0] CPE[1] SCE[1]
+ * instead of
+ * SCE[0] CPE[0] CPE[1] LFE[0].
+ * If we seem to have encountered such a stream, transfer
+ * the LFE[0] element to the SCE[1]'s mapping */
+ if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
+ if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) {
+ av_log(ac->avctx, AV_LOG_WARNING,
+ "This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n",
+ type == TYPE_SCE ? "SCE" : "LFE", elem_id);
+ ac->warned_remapping_once++;
+ }
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
+ }
+ case 5:
+ if (ac->tags_mapped == 2 && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
+ }
+ case 4:
+ /* Some streams incorrectly code 4.0 audio as
+ * SCE[0] CPE[0] LFE[0]
+ * instead of
+ * SCE[0] CPE[0] SCE[1].
+ * If we seem to have encountered such a stream, transfer
+ * the SCE[1] element to the LFE[0]'s mapping */
+ if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
+ if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) {
+ av_log(ac->avctx, AV_LOG_WARNING,
+ "This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n",
+ type == TYPE_SCE ? "SCE" : "LFE", elem_id);
+ ac->warned_remapping_once++;
+ }
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ if (ac->tags_mapped == 2 &&
+ ac->oc[1].m4ac.chan_config == 4 &&
+ type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 3:
+ case 2:
+ if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) &&
+ type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0];
+ } else if (ac->tags_mapped == 1 && ac->oc[1].m4ac.chan_config == 2 &&
+ type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 1:
+ if (!ac->tags_mapped && type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
+ }
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Decode an array of 4 bit element IDs, optionally interleaved with a
+ * stereo/mono switching bit.
+ *
+ * @param type speaker type/position for these channels
+ */
+static void decode_channel_map(uint8_t layout_map[][3],
+ enum ChannelPosition type,
+ GetBitContext *gb, int n)
+{
+ while (n--) {
+ enum RawDataBlockType syn_ele;
+ switch (type) {
+ case AAC_CHANNEL_FRONT:
+ case AAC_CHANNEL_BACK:
+ case AAC_CHANNEL_SIDE:
+ syn_ele = get_bits1(gb);
+ break;
+ case AAC_CHANNEL_CC:
+ skip_bits1(gb);
+ syn_ele = TYPE_CCE;
+ break;
+ case AAC_CHANNEL_LFE:
+ syn_ele = TYPE_LFE;
+ break;
+ default:
+ // AAC_CHANNEL_OFF has no channel map
+ av_assert0(0);
+ }
+ layout_map[0][0] = syn_ele;
+ layout_map[0][1] = get_bits(gb, 4);
+ layout_map[0][2] = type;
+ layout_map++;
+ }
+}
+
+static inline void relative_align_get_bits(GetBitContext *gb,
+ int reference_position) {
+ int n = (reference_position - get_bits_count(gb) & 7);
+ if (n)
+ skip_bits(gb, n);
+}
+
+/**
+ * Decode program configuration element; reference: table 4.2.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
+ uint8_t (*layout_map)[3],
+ GetBitContext *gb, int byte_align_ref)
+{
+ int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc;
+ int sampling_index;
+ int comment_len;
+ int tags;
+
+ skip_bits(gb, 2); // object_type
+
+ sampling_index = get_bits(gb, 4);
+ if (m4ac->sampling_index != sampling_index)
+ av_log(avctx, AV_LOG_WARNING,
+ "Sample rate index in program config element does not "
+ "match the sample rate index configured by the container.\n");
+
+ num_front = get_bits(gb, 4);
+ num_side = get_bits(gb, 4);
+ num_back = get_bits(gb, 4);
+ num_lfe = get_bits(gb, 2);
+ num_assoc_data = get_bits(gb, 3);
+ num_cc = get_bits(gb, 4);
+
+ if (get_bits1(gb))
+ skip_bits(gb, 4); // mono_mixdown_tag
+ if (get_bits1(gb))
+ skip_bits(gb, 4); // stereo_mixdown_tag
+
+ if (get_bits1(gb))
+ skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
+
+ if (get_bits_left(gb) < 5 * (num_front + num_side + num_back + num_cc) + 4 *(num_lfe + num_assoc_data + num_cc)) {
+ av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
+ return -1;
+ }
+ decode_channel_map(layout_map , AAC_CHANNEL_FRONT, gb, num_front);
+ tags = num_front;
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE, gb, num_side);
+ tags += num_side;
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK, gb, num_back);
+ tags += num_back;
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE, gb, num_lfe);
+ tags += num_lfe;
+
+ skip_bits_long(gb, 4 * num_assoc_data);
+
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_CC, gb, num_cc);
+ tags += num_cc;
+
+ relative_align_get_bits(gb, byte_align_ref);
+
+ /* comment field, first byte is length */
+ comment_len = get_bits(gb, 8) * 8;
+ if (get_bits_left(gb) < comment_len) {
+ av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ skip_bits_long(gb, comment_len);
+ return tags;
+}
+
+/**
+ * Decode GA "General Audio" specific configuration; reference: table 4.1.
+ *
+ * @param ac pointer to AACDecContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_ga_specific_config(AACDecContext *ac, AVCodecContext *avctx,
+ GetBitContext *gb,
+ int get_bit_alignment,
+ MPEG4AudioConfig *m4ac,
+ int channel_config)
+{
+ int extension_flag, ret, ep_config, res_flags;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ 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
+ extension_flag = get_bits1(gb);
+
+ if (m4ac->object_type == AOT_AAC_SCALABLE ||
+ m4ac->object_type == AOT_ER_AAC_SCALABLE)
+ skip_bits(gb, 3); // layerNr
+
+ if (channel_config == 0) {
+ skip_bits(gb, 4); // element_instance_tag
+ tags = decode_pce(avctx, m4ac, layout_map, gb, get_bit_alignment);
+ if (tags < 0)
+ return tags;
+ } else {
+ if ((ret = set_default_channel_config(ac, avctx, layout_map,
+ &tags, channel_config)))
+ return ret;
+ }
+
+ if (count_channels(layout_map, tags) > 1) {
+ m4ac->ps = 0;
+ } else if (m4ac->sbr == 1 && m4ac->ps == -1)
+ m4ac->ps = 1;
+
+ if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
+ return ret;
+
+ if (extension_flag) {
+ switch (m4ac->object_type) {
+ case AOT_ER_BSAC:
+ skip_bits(gb, 5); // numOfSubFrame
+ skip_bits(gb, 11); // layer_length
+ break;
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_SCALABLE:
+ case AOT_ER_AAC_LD:
+ res_flags = get_bits(gb, 3);
+ if (res_flags) {
+ avpriv_report_missing_feature(avctx,
+ "AAC data resilience (flags %x)",
+ res_flags);
+ return AVERROR_PATCHWELCOME;
+ }
+ break;
+ }
+ skip_bits1(gb); // extensionFlag3 (TBD in version 3)
+ }
+ switch (m4ac->object_type) {
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_SCALABLE:
+ case AOT_ER_AAC_LD:
+ ep_config = get_bits(gb, 2);
+ if (ep_config) {
+ avpriv_report_missing_feature(avctx,
+ "epConfig %d", ep_config);
+ return AVERROR_PATCHWELCOME;
+ }
+ }
+ return 0;
+}
+
+static int decode_eld_specific_config(AACDecContext *ac, AVCodecContext *avctx,
+ GetBitContext *gb,
+ MPEG4AudioConfig *m4ac,
+ int channel_config)
+{
+ int ret, ep_config, res_flags;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int tags = 0;
+ const int ELDEXT_TERM = 0;
+
+ m4ac->ps = 0;
+ m4ac->sbr = 0;
+ m4ac->frame_length_short = get_bits1(gb);
+
+ res_flags = get_bits(gb, 3);
+ if (res_flags) {
+ avpriv_report_missing_feature(avctx,
+ "AAC data resilience (flags %x)",
+ res_flags);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (get_bits1(gb)) { // ldSbrPresentFlag
+ avpriv_report_missing_feature(avctx,
+ "Low Delay SBR");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ while (get_bits(gb, 4) != ELDEXT_TERM) {
+ int len = get_bits(gb, 4);
+ if (len == 15)
+ len += get_bits(gb, 8);
+ if (len == 15 + 255)
+ len += get_bits(gb, 16);
+ if (get_bits_left(gb) < len * 8 + 4) {
+ av_log(avctx, AV_LOG_ERROR, overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ skip_bits_long(gb, 8 * len);
+ }
+
+ if ((ret = set_default_channel_config(ac, avctx, layout_map,
+ &tags, channel_config)))
+ return ret;
+
+ if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
+ return ret;
+
+ ep_config = get_bits(gb, 2);
+ if (ep_config) {
+ avpriv_report_missing_feature(avctx,
+ "epConfig %d", ep_config);
+ return AVERROR_PATCHWELCOME;
+ }
+ return 0;
+}
+
+/**
+ * Decode audio specific configuration; reference: table 1.13.
+ *
+ * @param ac pointer to AACDecContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ * @param m4ac pointer to MPEG4AudioConfig, used for parsing
+ * @param gb buffer holding an audio specific config
+ * @param get_bit_alignment relative alignment for byte align operations
+ * @param sync_extension look for an appended sync extension
+ *
+ * @return Returns error status or number of consumed bits. <0 - error
+ */
+static int decode_audio_specific_config_gb(AACDecContext *ac,
+ AVCodecContext *avctx,
+ MPEG4AudioConfig *m4ac,
+ GetBitContext *gb,
+ int get_bit_alignment,
+ int sync_extension)
+{
+ int i, ret;
+ GetBitContext gbc = *gb;
+ MPEG4AudioConfig m4ac_bak = *m4ac;
+
+ if ((i = ff_mpeg4audio_get_config_gb(m4ac, &gbc, sync_extension, avctx)) < 0) {
+ *m4ac = m4ac_bak;
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (m4ac->sampling_index > 12) {
+ av_log(avctx, AV_LOG_ERROR,
+ "invalid sampling rate index %d\n",
+ m4ac->sampling_index);
+ *m4ac = m4ac_bak;
+ 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);
+ *m4ac = m4ac_bak;
+ return AVERROR_INVALIDDATA;
+ }
+
+ skip_bits_long(gb, i);
+
+ switch (m4ac->object_type) {
+ case AOT_AAC_MAIN:
+ case AOT_AAC_LC:
+ case AOT_AAC_SSR:
+ case AOT_AAC_LTP:
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LD:
+ if ((ret = decode_ga_specific_config(ac, avctx, gb, get_bit_alignment,
+ m4ac, m4ac->chan_config)) < 0)
+ return ret;
+ break;
+ case AOT_ER_AAC_ELD:
+ if ((ret = decode_eld_specific_config(ac, avctx, gb,
+ m4ac, m4ac->chan_config)) < 0)
+ return ret;
+ break;
+ default:
+ avpriv_report_missing_feature(avctx,
+ "Audio object type %s%d",
+ m4ac->sbr == 1 ? "SBR+" : "",
+ m4ac->object_type);
+ return AVERROR(ENOSYS);
+ }
+
+ ff_dlog(avctx,
+ "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
+ m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
+ m4ac->sample_rate, m4ac->sbr,
+ m4ac->ps);
+
+ return get_bits_count(gb);
+}
+
+static int decode_audio_specific_config(AACDecContext *ac,
+ AVCodecContext *avctx,
+ MPEG4AudioConfig *m4ac,
+ const uint8_t *data, int64_t bit_size,
+ int sync_extension)
+{
+ int i, ret;
+ GetBitContext gb;
+
+ if (bit_size < 0 || bit_size > INT_MAX) {
+ av_log(avctx, AV_LOG_ERROR, "Audio specific config size is invalid\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ ff_dlog(avctx, "audio specific config size %d\n", (int)bit_size >> 3);
+ for (i = 0; i < bit_size >> 3; i++)
+ ff_dlog(avctx, "%02x ", data[i]);
+ ff_dlog(avctx, "\n");
+
+ if ((ret = init_get_bits(&gb, data, bit_size)) < 0)
+ return ret;
+
+ return decode_audio_specific_config_gb(ac, avctx, m4ac, &gb, 0,
+ sync_extension);
+}
+
+static int sample_rate_idx (int rate)
+{
+ if (92017 <= rate) return 0;
+ else if (75132 <= rate) return 1;
+ else if (55426 <= rate) return 2;
+ else if (46009 <= rate) return 3;
+ else if (37566 <= rate) return 4;
+ else if (27713 <= rate) return 5;
+ else if (23004 <= rate) return 6;
+ else if (18783 <= rate) return 7;
+ else if (13856 <= rate) return 8;
+ else if (11502 <= rate) return 9;
+ else if (9391 <= rate) return 10;
+ else return 11;
+}
+
+static av_cold void aac_static_table_init(void)
+{
+ ff_aac_sbr_init();
+ ff_aac_sbr_init_fixed();
+
+ ff_aacdec_common_init_once();
+}
+static AVOnce aac_table_init = AV_ONCE_INIT;
+
+static av_cold int decode_close(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int is_fixed = ac->is_fixed;
+ void (*sbr_close)(ChannelElement *che) = is_fixed ? RENAME_FIXED(ff_aac_sbr_ctx_close)
+ : ff_aac_sbr_ctx_close;
+
+ for (int type = 0; type < FF_ARRAY_ELEMS(ac->che); type++) {
+ for (int i = 0; i < MAX_ELEM_ID; i++) {
+ if (ac->che[type][i]) {
+ sbr_close(ac->che[type][i]);
+ av_freep(&ac->che[type][i]);
+ }
+ }
+ }
+
+ av_tx_uninit(&ac->mdct120);
+ av_tx_uninit(&ac->mdct128);
+ av_tx_uninit(&ac->mdct480);
+ av_tx_uninit(&ac->mdct512);
+ av_tx_uninit(&ac->mdct960);
+ av_tx_uninit(&ac->mdct1024);
+ av_tx_uninit(&ac->mdct_ltp);
+
+ // Compiler will optimize this branch away.
+ if (is_fixed)
+ av_freep(&ac->RENAME_FIXED(fdsp));
+ else
+ av_freep(&ac->fdsp);
+
+ return 0;
+}
+
+static av_cold int init_dsp(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int is_fixed = ac->is_fixed, ret;
+ float scale_fixed, scale_float;
+ const float *const scalep = is_fixed ? &scale_fixed : &scale_float;
+ enum AVTXType tx_type = is_fixed ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT;
+
+ if (avctx->ch_layout.nb_channels > MAX_CHANNELS) {
+ av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ ac->random_state = 0x1f2e3d4c;
+
+#define MDCT_INIT(s, fn, len, sval) \
+ scale_fixed = (sval) * 128.0f; \
+ scale_float = (sval) / 32768.0f; \
+ ret = av_tx_init(&s, &fn, tx_type, 1, len, scalep, 0); \
+ if (ret < 0) \
+ return ret
+
+ MDCT_INIT(ac->mdct120, ac->mdct120_fn, 120, 1.0/120);
+ MDCT_INIT(ac->mdct128, ac->mdct128_fn, 128, 1.0/128);
+ MDCT_INIT(ac->mdct480, ac->mdct480_fn, 480, 1.0/480);
+ MDCT_INIT(ac->mdct512, ac->mdct512_fn, 512, 1.0/512);
+ MDCT_INIT(ac->mdct960, ac->mdct960_fn, 960, 1.0/960);
+ MDCT_INIT(ac->mdct1024, ac->mdct1024_fn, 1024, 1.0/1024);
+#undef MDCT_INIT
+
+ /* LTP forward MDCT */
+ scale_fixed = -1.0;
+ scale_float = -32786.0*2 + 36;
+ ret = av_tx_init(&ac->mdct_ltp, &ac->mdct_ltp_fn, tx_type, 0, 1024, scalep, 0);
+ if (ret < 0)
+ return ret;
+
+ ac->dsp = is_fixed ? aac_dsp_fixed : aac_dsp;
+ ac->proc = is_fixed ? aac_proc_fixed : aac_proc;
+
+ return ac->dsp.init(ac);
+}
+
+static av_cold int aac_decode_init_internal(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int ret;
+
+ if (avctx->sample_rate > 96000)
+ return AVERROR_INVALIDDATA;
+
+ ret = ff_thread_once(&aac_table_init, &aac_static_table_init);
+ if (ret != 0)
+ return AVERROR_UNKNOWN;
+
+ ac->avctx = avctx;
+ ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
+
+ if (ac->is_fixed)
+ avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
+ else
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+
+ if (avctx->extradata_size > 0) {
+ if ((ret = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
+ avctx->extradata,
+ avctx->extradata_size * 8LL,
+ 1)) < 0)
+ return ret;
+ } else {
+ int sr, i;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int layout_map_tags;
+
+ sr = sample_rate_idx(avctx->sample_rate);
+ ac->oc[1].m4ac.sampling_index = sr;
+ ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels;
+ ac->oc[1].m4ac.sbr = -1;
+ ac->oc[1].m4ac.ps = -1;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
+ if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels)
+ break;
+ if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
+ i = 0;
+ }
+ ac->oc[1].m4ac.chan_config = i;
+
+ if (ac->oc[1].m4ac.chan_config) {
+ int ret = set_default_channel_config(ac, avctx, layout_map,
+ &layout_map_tags, ac->oc[1].m4ac.chan_config);
+ if (!ret)
+ output_configure(ac, layout_map, layout_map_tags,
+ OC_GLOBAL_HDR, 0);
+ else if (avctx->err_recognition & AV_EF_EXPLODE)
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ return init_dsp(avctx);
+}
+
+static av_cold int aac_decode_init(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ac->is_fixed = 0;
+ return aac_decode_init_internal(avctx);
+}
+
+static av_cold int aac_decode_init_fixed(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ac->is_fixed = 1;
+ return aac_decode_init_internal(avctx);
+}
+
+/**
+ * Skip data_stream_element; reference: table 4.10.
+ */
+static int skip_data_stream_element(AACDecContext *ac, GetBitContext *gb)
+{
+ int byte_align = get_bits1(gb);
+ int count = get_bits(gb, 8);
+ if (count == 255)
+ count += get_bits(gb, 8);
+ if (byte_align)
+ align_get_bits(gb);
+
+ if (get_bits_left(gb) < 8 * count) {
+ av_log(ac->avctx, AV_LOG_ERROR, "skip_data_stream_element: "overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ skip_bits_long(gb, 8 * count);
+ return 0;
+}
+
+static int decode_prediction(AACDecContext *ac, IndividualChannelStream *ics,
+ GetBitContext *gb)
+{
+ int sfb;
+ if (get_bits1(gb)) {
+ ics->predictor_reset_group = get_bits(gb, 5);
+ if (ics->predictor_reset_group == 0 ||
+ ics->predictor_reset_group > 30) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Invalid Predictor Reset Group.\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]); sfb++) {
+ ics->prediction_used[sfb] = get_bits1(gb);
+ }
+ return 0;
+}
+
+/**
+ * Decode Long Term Prediction data; reference: table 4.xx.
+ */
+static void decode_ltp(AACDecContext *ac, LongTermPrediction *ltp,
+ GetBitContext *gb, uint8_t max_sfb)
+{
+ int sfb;
+
+ ltp->lag = get_bits(gb, 11);
+ if (ac->is_fixed)
+ ltp->coef_fixed = Q30(ff_ltp_coef[get_bits(gb, 3)]);
+ else
+ ltp->coef = ff_ltp_coef[get_bits(gb, 3)];
+
+ for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ ltp->used[sfb] = get_bits1(gb);
+}
+
+/**
+ * Decode Individual Channel Stream info; reference: table 4.6.
+ */
+static int decode_ics_info(AACDecContext *ac, IndividualChannelStream *ics,
+ GetBitContext *gb)
+{
+ const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
+ const int aot = m4ac->object_type;
+ const int sampling_index = m4ac->sampling_index;
+ int ret_fail = AVERROR_INVALIDDATA;
+
+ if (aot != AOT_ER_AAC_ELD) {
+ if (get_bits1(gb)) {
+ av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n");
+ if (ac->avctx->err_recognition & AV_EF_BITSTREAM)
+ return AVERROR_INVALIDDATA;
+ }
+ ics->window_sequence[1] = ics->window_sequence[0];
+ ics->window_sequence[0] = get_bits(gb, 2);
+ if (aot == 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;
+ ics->group_len[0] = 1;
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ int i;
+ ics->max_sfb = get_bits(gb, 4);
+ for (i = 0; i < 7; i++) {
+ if (get_bits1(gb)) {
+ ics->group_len[ics->num_window_groups - 1]++;
+ } else {
+ ics->num_window_groups++;
+ ics->group_len[ics->num_window_groups - 1] = 1;
+ }
+ }
+ ics->num_windows = 8;
+ 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 {
+ ics->max_sfb = get_bits(gb, 6);
+ ics->num_windows = 1;
+ if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) {
+ if (m4ac->frame_length_short) {
+ ics->swb_offset = ff_swb_offset_480[sampling_index];
+ ics->num_swb = ff_aac_num_swb_480[sampling_index];
+ ics->tns_max_bands = ff_tns_max_bands_480[sampling_index];
+ } else {
+ ics->swb_offset = ff_swb_offset_512[sampling_index];
+ ics->num_swb = ff_aac_num_swb_512[sampling_index];
+ ics->tns_max_bands = ff_tns_max_bands_512[sampling_index];
+ }
+ if (!ics->num_swb || !ics->swb_offset) {
+ ret_fail = AVERROR_BUG;
+ goto fail;
+ }
+ } else {
+ 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) {
+ ics->predictor_present = get_bits1(gb);
+ ics->predictor_reset_group = 0;
+ }
+ if (ics->predictor_present) {
+ if (aot == AOT_AAC_MAIN) {
+ if (decode_prediction(ac, ics, gb)) {
+ goto fail;
+ }
+ } else if (aot == AOT_AAC_LC ||
+ aot == AOT_ER_AAC_LC) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Prediction is not allowed in AAC-LC.\n");
+ goto fail;
+ } else {
+ if (aot == AOT_ER_AAC_LD) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "LTP in ER AAC LD not yet implemented.\n");
+ ret_fail = AVERROR_PATCHWELCOME;
+ goto fail;
+ }
+ if ((ics->ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
+ }
+ }
+ }
+
+ if (ics->max_sfb > ics->num_swb) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Number of scalefactor bands in group (%d) "
+ "exceeds limit (%d).\n",
+ ics->max_sfb, ics->num_swb);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ ics->max_sfb = 0;
+ return ret_fail;
+}
+
+/**
+ * Decode band types (section_data payload); reference: table 4.46.
+ *
+ * @param band_type array of the used band type
+ * @param band_type_run_end array of the last scalefactor band of a band type run
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_band_types(AACDecContext *ac, enum BandType band_type[120],
+ int band_type_run_end[120], GetBitContext *gb,
+ IndividualChannelStream *ics)
+{
+ int g, idx = 0;
+ const int bits = (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) ? 3 : 5;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ int k = 0;
+ while (k < ics->max_sfb) {
+ uint8_t sect_end = k;
+ int sect_len_incr;
+ int sect_band_type = get_bits(gb, 4);
+ if (sect_band_type == 12) {
+ av_log(ac->avctx, AV_LOG_ERROR, "invalid band type\n");
+ return AVERROR_INVALIDDATA;
+ }
+ do {
+ sect_len_incr = get_bits(gb, bits);
+ sect_end += sect_len_incr;
+ if (get_bits_left(gb) < 0) {
+ av_log(ac->avctx, AV_LOG_ERROR, "decode_band_types: "overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ if (sect_end > ics->max_sfb) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Number of bands (%d) exceeds limit (%d).\n",
+ sect_end, ics->max_sfb);
+ return AVERROR_INVALIDDATA;
+ }
+ } while (sect_len_incr == (1 << bits) - 1);
+ for (; k < sect_end; k++) {
+ band_type [idx] = sect_band_type;
+ band_type_run_end[idx++] = sect_end;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Decode scalefactors; reference: table 4.47.
+ *
+ * @param global_gain first scalefactor value as scalefactors are differentially coded
+ * @param band_type array of the used band type
+ * @param band_type_run_end array of the last scalefactor band of a band type run
+ * @param sf array of scalefactors or intensity stereo positions
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_scalefactors(AACDecContext *ac, int sfo[120],
+ GetBitContext *gb,
+ unsigned int global_gain,
+ IndividualChannelStream *ics,
+ enum BandType band_type[120],
+ int band_type_run_end[120])
+{
+ int g, i, idx = 0;
+ int offset[3] = { global_gain, global_gain - NOISE_OFFSET, 0 };
+ int clipped_offset;
+ int noise_flag = 1;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb;) {
+ int run_end = band_type_run_end[idx];
+ switch (band_type[idx]) {
+ case ZERO_BT:
+ for (; i < run_end; i++, idx++)
+ sfo[idx] = 0;
+ break;
+ case INTENSITY_BT: /* fallthrough */
+ case INTENSITY_BT2:
+ for (; i < run_end; i++, idx++) {
+ offset[2] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
+ clipped_offset = av_clip(offset[2], -155, 100);
+ if (offset[2] != clipped_offset) {
+ avpriv_request_sample(ac->avctx,
+ "If you heard an audible artifact, there may be a bug in the decoder. "
+ "Clipped intensity stereo position (%d -> %d)",
+ offset[2], clipped_offset);
+ }
+ sfo[idx] = clipped_offset;
+ }
+ break;
+ case NOISE_BT:
+ for (; i < run_end; i++, idx++) {
+ if (noise_flag-- > 0)
+ offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE;
+ else
+ offset[1] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
+ clipped_offset = av_clip(offset[1], -100, 155);
+ if (offset[1] != clipped_offset) {
+ avpriv_request_sample(ac->avctx,
+ "If you heard an audible artifact, there may be a bug in the decoder. "
+ "Clipped noise gain (%d -> %d)",
+ offset[1], clipped_offset);
+ }
+ sfo[idx] = clipped_offset;
+ }
+ break;
+ default:
+ for (; i < run_end; i++, idx++) {
+ offset[0] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
+ if (offset[0] > 255U) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Scalefactor (%d) out of range.\n", offset[0]);
+ return AVERROR_INVALIDDATA;
+ }
+ sfo[idx] = offset[0];
+ }
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Decode pulse data; reference: table 4.7.
+ */
+static int decode_pulses(Pulse *pulse, GetBitContext *gb,
+ const uint16_t *swb_offset, int num_swb)
+{
+ int i, pulse_swb;
+ pulse->num_pulse = get_bits(gb, 2) + 1;
+ pulse_swb = get_bits(gb, 6);
+ if (pulse_swb >= num_swb)
+ return -1;
+ pulse->pos[0] = swb_offset[pulse_swb];
+ pulse->pos[0] += get_bits(gb, 5);
+ if (pulse->pos[0] >= swb_offset[num_swb])
+ return -1;
+ pulse->amp[0] = get_bits(gb, 4);
+ for (i = 1; i < pulse->num_pulse; i++) {
+ pulse->pos[i] = get_bits(gb, 5) + pulse->pos[i - 1];
+ if (pulse->pos[i] >= swb_offset[num_swb])
+ return -1;
+ pulse->amp[i] = get_bits(gb, 4);
+ }
+ return 0;
+}
+
+/**
+ * Decode Temporal Noise Shaping data; reference: table 4.48.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
+ GetBitContext *gb, const IndividualChannelStream *ics)
+{
+ int w, filt, i, coef_len, coef_res, coef_compress;
+ const int is8 = ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE;
+ const int tns_max_order = is8 ? 7 : ac->oc[1].m4ac.object_type == AOT_AAC_MAIN ? 20 : 12;
+ for (w = 0; w < ics->num_windows; w++) {
+ if ((tns->n_filt[w] = get_bits(gb, 2 - is8))) {
+ coef_res = get_bits1(gb);
+
+ for (filt = 0; filt < tns->n_filt[w]; filt++) {
+ int tmp2_idx;
+ tns->length[w][filt] = get_bits(gb, 6 - 2 * is8);
+
+ if ((tns->order[w][filt] = get_bits(gb, 5 - 2 * is8)) > tns_max_order) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "TNS filter order %d is greater than maximum %d.\n",
+ tns->order[w][filt], tns_max_order);
+ tns->order[w][filt] = 0;
+ return AVERROR_INVALIDDATA;
+ }
+ if (tns->order[w][filt]) {
+ tns->direction[w][filt] = get_bits1(gb);
+ coef_compress = get_bits1(gb);
+ coef_len = coef_res + 3 - coef_compress;
+ tmp2_idx = 2 * coef_compress + coef_res;
+
+ for (i = 0; i < tns->order[w][filt]; i++) {
+ if (ac->is_fixed)
+ tns->coef_fixed[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
+ else
+ tns->coef[w][filt][i] = ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)];
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Decode Mid/Side data; reference: table 4.54.
+ *
+ * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
+ * [1] mask is decoded from bitstream; [2] mask is all 1s;
+ * [3] reserved for scalable AAC
+ */
+static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
+ int ms_present)
+{
+ int idx;
+ int max_idx = cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb;
+ if (ms_present == 1) {
+ for (idx = 0; idx < max_idx; idx++)
+ cpe->ms_mask[idx] = get_bits1(gb);
+ } else if (ms_present == 2) {
+ memset(cpe->ms_mask, 1, max_idx * sizeof(cpe->ms_mask[0]));
+ }
+}
+
+static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
+{
+ // wd_num, wd_test, aloc_size
+ static const uint8_t gain_mode[4][3] = {
+ {1, 0, 5}, // ONLY_LONG_SEQUENCE = 0,
+ {2, 1, 2}, // LONG_START_SEQUENCE,
+ {8, 0, 2}, // EIGHT_SHORT_SEQUENCE,
+ {2, 1, 5}, // LONG_STOP_SEQUENCE
+ };
-extern const AACDecDSP aac_dsp;
-extern const AACDecDSP aac_dsp_fixed;
+ const int mode = sce->ics.window_sequence[0];
+ uint8_t bd, wd, ad;
-extern const AACDecProc aac_proc;
-extern const AACDecProc aac_proc_fixed;
+ // FIXME: Store the gain control data on |sce| and do something with it.
+ uint8_t max_band = get_bits(gb, 2);
+ for (bd = 0; bd < max_band; bd++) {
+ for (wd = 0; wd < gain_mode[mode][0]; wd++) {
+ uint8_t adjust_num = get_bits(gb, 3);
+ for (ad = 0; ad < adjust_num; ad++) {
+ skip_bits(gb, 4 + ((wd == 0 && gain_mode[mode][1])
+ ? 4
+ : gain_mode[mode][2]));
+ }
+ }
+ }
+}
-av_cold int ff_aac_decode_close(AVCodecContext *avctx)
+/**
+ * Decode an individual_channel_stream payload; reference: table 4.44.
+ *
+ * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
+ * @param scale_flag scalable [1] or non-scalable [0] AAC (Unused until scalable AAC is implemented.)
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
+ GetBitContext *gb, int common_window, int scale_flag)
{
- AACDecContext *ac = avctx->priv_data;
- int is_fixed = ac->is_fixed;
- void (*sbr_close)(ChannelElement *che) = is_fixed ? RENAME_FIXED(ff_aac_sbr_ctx_close)
- : ff_aac_sbr_ctx_close;
+ Pulse pulse;
+ TemporalNoiseShaping *tns = &sce->tns;
+ IndividualChannelStream *ics = &sce->ics;
+ int global_gain, eld_syntax, er_syntax, pulse_present = 0;
+ int ret;
- for (int type = 0; type < FF_ARRAY_ELEMS(ac->che); type++) {
- for (int i = 0; i < MAX_ELEM_ID; i++) {
- if (ac->che[type][i]) {
- sbr_close(ac->che[type][i]);
- av_freep(&ac->che[type][i]);
+ eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
+ er_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_LC ||
+ ac->oc[1].m4ac.object_type == AOT_ER_AAC_LTP ||
+ ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD ||
+ ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
+
+ /* This assignment is to silence a GCC warning about the variable being used
+ * uninitialized when in fact it always is.
+ */
+ pulse.num_pulse = 0;
+
+ global_gain = get_bits(gb, 8);
+
+ if (!common_window && !scale_flag) {
+ ret = decode_ics_info(ac, ics, gb);
+ if (ret < 0)
+ goto fail;
+ }
+
+ if ((ret = decode_band_types(ac, sce->band_type,
+ sce->band_type_run_end, gb, ics)) < 0)
+ goto fail;
+ if ((ret = decode_scalefactors(ac, sce->sfo, gb, global_gain, ics,
+ sce->band_type, sce->band_type_run_end)) < 0)
+ goto fail;
+
+ ac->dsp.dequant_scalefactors(sce);
+
+ pulse_present = 0;
+ if (!scale_flag) {
+ if (!eld_syntax && (pulse_present = get_bits1(gb))) {
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Pulse tool not allowed in eight short sequence.\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ if (decode_pulses(&pulse, gb, ics->swb_offset, ics->num_swb)) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Pulse data corrupt or invalid.\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ tns->present = get_bits1(gb);
+ if (tns->present && !er_syntax) {
+ ret = decode_tns(ac, tns, gb, ics);
+ if (ret < 0)
+ goto fail;
+ }
+ if (!eld_syntax && get_bits1(gb)) {
+ decode_gain_control(sce, gb);
+ if (!ac->warned_gain_control) {
+ avpriv_report_missing_feature(ac->avctx, "Gain control");
+ ac->warned_gain_control = 1;
}
}
+ // I see no textual basis in the spec for this occurring after SSR gain
+ // control, but this is what both reference and real implmentations do
+ if (tns->present && er_syntax) {
+ ret = decode_tns(ac, tns, gb, ics);
+ if (ret < 0)
+ goto fail;
+ }
}
- av_tx_uninit(&ac->mdct120);
- av_tx_uninit(&ac->mdct128);
- av_tx_uninit(&ac->mdct480);
- av_tx_uninit(&ac->mdct512);
- av_tx_uninit(&ac->mdct960);
- av_tx_uninit(&ac->mdct1024);
- av_tx_uninit(&ac->mdct_ltp);
+ ret = ac->proc.decode_spectrum_and_dequant(ac, gb,
+ pulse_present ? &pulse : NULL,
+ sce);
+ if (ret < 0)
+ goto fail;
- // Compiler will optimize this branch away.
- if (is_fixed)
- av_freep(&ac->RENAME_FIXED(fdsp));
- else
- av_freep(&ac->fdsp);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window)
+ ac->dsp.apply_prediction(ac, sce);
+
+ return 0;
+fail:
+ tns->present = 0;
+ return ret;
+}
+
+/**
+ * Decode a channel_pair_element; reference: table 4.4.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
+{
+ int i, ret, common_window, ms_present = 0;
+ int eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
+
+ common_window = eld_syntax || get_bits1(gb);
+ if (common_window) {
+ if (decode_ics_info(ac, &cpe->ch[0].ics, gb))
+ return AVERROR_INVALIDDATA;
+ i = cpe->ch[1].ics.use_kb_window[0];
+ cpe->ch[1].ics = cpe->ch[0].ics;
+ cpe->ch[1].ics.use_kb_window[1] = i;
+ if (cpe->ch[1].ics.predictor_present &&
+ (ac->oc[1].m4ac.object_type != AOT_AAC_MAIN))
+ if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
+ ms_present = get_bits(gb, 2);
+ if (ms_present == 3) {
+ av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
+ return AVERROR_INVALIDDATA;
+ } else if (ms_present)
+ decode_mid_side_stereo(cpe, gb, ms_present);
+ }
+ if ((ret = ff_aac_decode_ics(ac, &cpe->ch[0], gb, common_window, 0)))
+ return ret;
+ if ((ret = ff_aac_decode_ics(ac, &cpe->ch[1], gb, common_window, 0)))
+ return ret;
+
+ if (common_window) {
+ if (ms_present)
+ ac->dsp.apply_mid_side_stereo(ac, cpe);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) {
+ ac->dsp.apply_prediction(ac, &cpe->ch[0]);
+ ac->dsp.apply_prediction(ac, &cpe->ch[1]);
+ }
+ }
+
+ ac->dsp.apply_intensity_stereo(ac, cpe, ms_present);
+ return 0;
+}
+
+/**
+ * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
+ *
+ * @return Returns number of bytes consumed.
+ */
+static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc,
+ GetBitContext *gb)
+{
+ int i;
+ int num_excl_chan = 0;
+
+ do {
+ for (i = 0; i < 7; i++)
+ che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb);
+ } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb));
+
+ return num_excl_chan / 7;
+}
+
+/**
+ * Decode dynamic range information; reference: table 4.52.
+ *
+ * @return Returns number of bytes consumed.
+ */
+static int decode_dynamic_range(DynamicRangeControl *che_drc,
+ GetBitContext *gb)
+{
+ int n = 1;
+ int drc_num_bands = 1;
+ int i;
+
+ /* pce_tag_present? */
+ if (get_bits1(gb)) {
+ che_drc->pce_instance_tag = get_bits(gb, 4);
+ skip_bits(gb, 4); // tag_reserved_bits
+ n++;
+ }
+
+ /* excluded_chns_present? */
+ if (get_bits1(gb)) {
+ n += decode_drc_channel_exclusions(che_drc, gb);
+ }
+
+ /* drc_bands_present? */
+ if (get_bits1(gb)) {
+ che_drc->band_incr = get_bits(gb, 4);
+ che_drc->interpolation_scheme = get_bits(gb, 4);
+ n++;
+ drc_num_bands += che_drc->band_incr;
+ for (i = 0; i < drc_num_bands; i++) {
+ che_drc->band_top[i] = get_bits(gb, 8);
+ n++;
+ }
+ }
+
+ /* prog_ref_level_present? */
+ if (get_bits1(gb)) {
+ che_drc->prog_ref_level = get_bits(gb, 7);
+ skip_bits1(gb); // prog_ref_level_reserved_bits
+ n++;
+ }
+
+ for (i = 0; i < drc_num_bands; i++) {
+ che_drc->dyn_rng_sgn[i] = get_bits1(gb);
+ che_drc->dyn_rng_ctl[i] = get_bits(gb, 7);
+ n++;
+ }
+
+ return n;
+}
+
+static int decode_fill(AACDecContext *ac, GetBitContext *gb, int len) {
+ uint8_t buf[256];
+ int i, major, minor;
+
+ if (len < 13+7*8)
+ goto unknown;
+
+ get_bits(gb, 13); len -= 13;
+
+ for(i=0; i+1<sizeof(buf) && len>=8; i++, len-=8)
+ buf[i] = get_bits(gb, 8);
+
+ buf[i] = 0;
+ if (ac->avctx->debug & FF_DEBUG_PICT_INFO)
+ av_log(ac->avctx, AV_LOG_DEBUG, "FILL:%s\n", buf);
+
+ if (sscanf(buf, "libfaac %d.%d", &major, &minor) == 2){
+ ac->avctx->internal->skip_samples = 1024;
+ }
+
+unknown:
+ skip_bits_long(gb, len);
return 0;
}
-av_cold int ff_aac_decode_init_common(AVCodecContext *avctx)
+/**
+ * Decode extension data (incomplete); reference: table 4.51.
+ *
+ * @param cnt length of TYPE_FIL syntactic element in bytes
+ *
+ * @return Returns number of bytes consumed
+ */
+static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cnt,
+ ChannelElement *che, enum RawDataBlockType elem_type)
+{
+ int crc_flag = 0;
+ int res = cnt;
+ int type = get_bits(gb, 4);
+
+ if (ac->avctx->debug & FF_DEBUG_STARTCODE)
+ av_log(ac->avctx, AV_LOG_DEBUG, "extension type: %d len:%d\n", type, cnt);
+
+ switch (type) { // extension type
+ case EXT_SBR_DATA_CRC:
+ crc_flag++;
+ case EXT_SBR_DATA:
+ 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);
+ return res;
+ } else if (ac->oc[1].m4ac.sbr == -1 && ac->oc[1].status == OC_LOCKED) {
+ av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n");
+ skip_bits_long(gb, 8 * cnt - 4);
+ return res;
+ } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED &&
+ ac->avctx->ch_layout.nb_channels == 1) {
+ ac->oc[1].m4ac.sbr = 1;
+ ac->oc[1].m4ac.ps = 1;
+ ac->avctx->profile = AV_PROFILE_AAC_HE_V2;
+ output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
+ ac->oc[1].status, 1);
+ } else {
+ ac->oc[1].m4ac.sbr = 1;
+ ac->avctx->profile = AV_PROFILE_AAC_HE;
+ }
+
+ if (ac->is_fixed)
+ res = ff_aac_sbr_decode_extension_fixed(ac, che, gb, crc_flag, cnt, elem_type);
+ else
+ res = ff_aac_sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
+
+
+ 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");
+ ac->warned_he_aac_mono = 1;
+ }
+ break;
+ case EXT_DYNAMIC_RANGE:
+ res = decode_dynamic_range(&ac->che_drc, gb);
+ break;
+ case EXT_FILL:
+ decode_fill(ac, gb, 8 * cnt - 4);
+ break;
+ case EXT_FILL_DATA:
+ case EXT_DATA_ELEMENT:
+ default:
+ skip_bits_long(gb, 8 * cnt - 4);
+ break;
+ };
+ return res;
+}
+
+/**
+ * channel coupling transformation interface
+ *
+ * @param apply_coupling_method pointer to (in)dependent coupling function
+ */
+static void apply_channel_coupling(AACDecContext *ac, ChannelElement *cc,
+ enum RawDataBlockType type, int elem_id,
+ enum CouplingPoint coupling_point,
+ void (*apply_coupling_method)(AACDecContext *ac, SingleChannelElement *target, ChannelElement *cce, int index))
+{
+ int i, c;
+
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *cce = ac->che[TYPE_CCE][i];
+ int index = 0;
+
+ if (cce && cce->coup.coupling_point == coupling_point) {
+ ChannelCoupling *coup = &cce->coup;
+
+ for (c = 0; c <= coup->num_coupled; c++) {
+ if (coup->type[c] == type && coup->id_select[c] == elem_id) {
+ if (coup->ch_select[c] != 1) {
+ apply_coupling_method(ac, &cc->ch[0], cce, index);
+ if (coup->ch_select[c] != 0)
+ index++;
+ }
+ if (coup->ch_select[c] != 2)
+ apply_coupling_method(ac, &cc->ch[1], cce, index++);
+ } else
+ index += 1 + (coup->ch_select[c] == 3);
+ }
+ }
+ }
+}
+
+/**
+ * Convert spectral data to samples, applying all supported tools as appropriate.
+ */
+static void spectral_to_sample(AACDecContext *ac, int samples)
+{
+ int i, type;
+ void (*imdct_and_window)(AACDecContext *ac, SingleChannelElement *sce);
+ switch (ac->oc[1].m4ac.object_type) {
+ case AOT_ER_AAC_LD:
+ imdct_and_window = ac->dsp.imdct_and_windowing_ld;
+ break;
+ case AOT_ER_AAC_ELD:
+ imdct_and_window = ac->dsp.imdct_and_windowing_eld;
+ break;
+ default:
+ if (ac->oc[1].m4ac.frame_length_short)
+ imdct_and_window = ac->dsp.imdct_and_windowing_960;
+ else
+ imdct_and_window = ac->dsp.imdct_and_windowing;
+ }
+ for (type = 3; type >= 0; type--) {
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *che = ac->che[type][i];
+ if (che && che->present) {
+ if (type <= TYPE_CPE)
+ apply_channel_coupling(ac, che, type, i, BEFORE_TNS, ac->dsp.apply_dependent_coupling);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
+ if (che->ch[0].ics.predictor_present) {
+ if (che->ch[0].ics.ltp.present)
+ ac->dsp.apply_ltp(ac, &che->ch[0]);
+ if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
+ ac->dsp.apply_ltp(ac, &che->ch[1]);
+ }
+ }
+ if (che->ch[0].tns.present)
+ ac->dsp.apply_tns(che->ch[0].AAC_RENAME(coeffs),
+ &che->ch[0].tns, &che->ch[0].ics, 1);
+ if (che->ch[1].tns.present)
+ ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
+ &che->ch[1].tns, &che->ch[1].ics, 1);
+ if (type <= TYPE_CPE)
+ apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling);
+ if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
+ imdct_and_window(ac, &che->ch[0]);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
+ ac->dsp.update_ltp(ac, &che->ch[0]);
+ if (type == TYPE_CPE) {
+ imdct_and_window(ac, &che->ch[1]);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
+ ac->dsp.update_ltp(ac, &che->ch[1]);
+ }
+ if (ac->oc[1].m4ac.sbr > 0) {
+ if (ac->is_fixed)
+ ff_aac_sbr_apply_fixed(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
+ else
+ ff_aac_sbr_apply(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
+ }
+ }
+ if (type <= TYPE_CCE)
+ apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling);
+ ac->dsp.clip_output(ac, che, type, samples);
+ che->present = 0;
+ } else if (che) {
+ av_log(ac->avctx, AV_LOG_VERBOSE, "ChannelElement %d.%d missing \n", type, i);
+ }
+ }
+ }
+}
+
+static int parse_adts_frame_header(AACDecContext *ac, GetBitContext *gb)
+{
+ int size;
+ AACADTSHeaderInfo hdr_info;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int layout_map_tags, ret;
+
+ size = ff_adts_header_parse(gb, &hdr_info);
+ if (size > 0) {
+ if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
+ // This is 2 for "VLB " audio in NSV files.
+ // See samples/nsv/vlb_audio.
+ avpriv_report_missing_feature(ac->avctx,
+ "More than one AAC RDB per ADTS frame");
+ ac->warned_num_aac_frames = 1;
+ }
+ push_output_configuration(ac);
+ if (hdr_info.chan_config) {
+ ac->oc[1].m4ac.chan_config = hdr_info.chan_config;
+ if ((ret = set_default_channel_config(ac, ac->avctx,
+ layout_map,
+ &layout_map_tags,
+ hdr_info.chan_config)) < 0)
+ return ret;
+ if ((ret = output_configure(ac, layout_map, layout_map_tags,
+ FFMAX(ac->oc[1].status,
+ OC_TRIAL_FRAME), 0)) < 0)
+ return ret;
+ } else {
+ ac->oc[1].m4ac.chan_config = 0;
+ /**
+ * dual mono frames in Japanese DTV can have chan_config 0
+ * WITHOUT specifying PCE.
+ * thus, set dual mono as default.
+ */
+ if (ac->dmono_mode && ac->oc[0].status == OC_NONE) {
+ layout_map_tags = 2;
+ layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
+ layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
+ layout_map[0][1] = 0;
+ layout_map[1][1] = 1;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ OC_TRIAL_FRAME, 0))
+ return -7;
+ }
+ }
+ ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate;
+ ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index;
+ ac->oc[1].m4ac.object_type = hdr_info.object_type;
+ ac->oc[1].m4ac.frame_length_short = 0;
+ if (ac->oc[0].status != OC_LOCKED ||
+ ac->oc[0].m4ac.chan_config != hdr_info.chan_config ||
+ ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) {
+ ac->oc[1].m4ac.sbr = -1;
+ ac->oc[1].m4ac.ps = -1;
+ }
+ if (!hdr_info.crc_absent)
+ skip_bits(gb, 16);
+ }
+ return size;
+}
+
+static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, GetBitContext *gb)
{
AACDecContext *ac = avctx->priv_data;
- int is_fixed = ac->is_fixed, ret;
- float scale_fixed, scale_float;
- const float *const scalep = is_fixed ? &scale_fixed : &scale_float;
- enum AVTXType tx_type = is_fixed ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT;
+ const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
+ ChannelElement *che;
+ int err, i;
+ int samples = m4ac->frame_length_short ? 960 : 1024;
+ int chan_config = m4ac->chan_config;
+ int aot = m4ac->object_type;
- if (avctx->ch_layout.nb_channels > MAX_CHANNELS) {
- av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
+ if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD)
+ samples >>= 1;
+
+ ac->frame = frame;
+
+ if ((err = frame_configure_elements(avctx)) < 0)
+ return err;
+
+ // The AV_PROFILE_AAC_* defines are all object_type - 1
+ // This may lead to an undefined profile being signaled
+ ac->avctx->profile = aot - 1;
+
+ ac->tags_mapped = 0;
+
+ if (chan_config < 0 || (chan_config >= 8 && chan_config < 11) || chan_config >= 13) {
+ avpriv_request_sample(avctx, "Unknown ER channel configuration %d",
+ chan_config);
return AVERROR_INVALIDDATA;
}
+ for (i = 0; i < ff_tags_per_config[chan_config]; i++) {
+ const int elem_type = ff_aac_channel_layout_map[chan_config-1][i][0];
+ const int elem_id = ff_aac_channel_layout_map[chan_config-1][i][1];
+ if (!(che=get_che(ac, elem_type, elem_id))) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "channel element %d.%d is not allocated\n",
+ elem_type, elem_id);
+ return AVERROR_INVALIDDATA;
+ }
+ che->present = 1;
+ if (aot != AOT_ER_AAC_ELD)
+ skip_bits(gb, 4);
+ switch (elem_type) {
+ case TYPE_SCE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ break;
+ case TYPE_CPE:
+ err = decode_cpe(ac, gb, che);
+ break;
+ case TYPE_LFE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ break;
+ }
+ if (err < 0)
+ return err;
+ }
- ac->random_state = 0x1f2e3d4c;
+ spectral_to_sample(ac, samples);
-#define MDCT_INIT(s, fn, len, sval) \
- scale_fixed = (sval) * 128.0f; \
- scale_float = (sval) / 32768.0f; \
- ret = av_tx_init(&s, &fn, tx_type, 1, len, scalep, 0); \
- if (ret < 0) \
- return ret
+ if (!ac->frame->data[0] && samples) {
+ av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
+ return AVERROR_INVALIDDATA;
+ }
- MDCT_INIT(ac->mdct120, ac->mdct120_fn, 120, 1.0/120);
- MDCT_INIT(ac->mdct128, ac->mdct128_fn, 128, 1.0/128);
- MDCT_INIT(ac->mdct480, ac->mdct480_fn, 480, 1.0/480);
- MDCT_INIT(ac->mdct512, ac->mdct512_fn, 512, 1.0/512);
- MDCT_INIT(ac->mdct960, ac->mdct960_fn, 960, 1.0/960);
- MDCT_INIT(ac->mdct1024, ac->mdct1024_fn, 1024, 1.0/1024);
-#undef MDCT_INIT
+ ac->frame->nb_samples = samples;
+ ac->frame->sample_rate = avctx->sample_rate;
+ *got_frame_ptr = 1;
- /* LTP forward MDCT */
- scale_fixed = -1.0;
- scale_float = -32786.0*2 + 36;
- ret = av_tx_init(&ac->mdct_ltp, &ac->mdct_ltp_fn, tx_type, 0, 1024, scalep, 0);
- if (ret < 0)
- return ret;
+ skip_bits_long(gb, get_bits_left(gb));
+ return 0;
+}
- ac->dsp = is_fixed ? aac_dsp_fixed : aac_dsp;
- ac->proc = is_fixed ? aac_proc_fixed : aac_proc;
+static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, GetBitContext *gb,
+ const AVPacket *avpkt)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ChannelElement *che = NULL, *che_prev = NULL;
+ enum RawDataBlockType elem_type, che_prev_type = TYPE_END;
+ int err, elem_id;
+ int samples = 0, multiplier, audio_found = 0, pce_found = 0;
+ int is_dmono, sce_count = 0;
+ int payload_alignment;
+ uint8_t che_presence[4][MAX_ELEM_ID] = {{0}};
- return ac->dsp.init(ac);
+ ac->frame = frame;
+
+ if (show_bits(gb, 12) == 0xfff) {
+ if ((err = parse_adts_frame_header(ac, gb)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n");
+ goto fail;
+ }
+ if (ac->oc[1].m4ac.sampling_index > 12) {
+ av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->oc[1].m4ac.sampling_index);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+
+ if ((err = frame_configure_elements(avctx)) < 0)
+ goto fail;
+
+ // The AV_PROFILE_AAC_* defines are all object_type - 1
+ // This may lead to an undefined profile being signaled
+ ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
+
+ payload_alignment = get_bits_count(gb);
+ ac->tags_mapped = 0;
+ // parse
+ while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
+ elem_id = get_bits(gb, 4);
+
+ if (avctx->debug & FF_DEBUG_STARTCODE)
+ av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id);
+
+ if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ if (elem_type < TYPE_DSE) {
+ if (che_presence[elem_type][elem_id]) {
+ int error = che_presence[elem_type][elem_id] > 1;
+ av_log(ac->avctx, error ? AV_LOG_ERROR : AV_LOG_DEBUG, "channel element %d.%d duplicate\n",
+ elem_type, elem_id);
+ if (error) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ che_presence[elem_type][elem_id]++;
+
+ if (!(che=get_che(ac, elem_type, elem_id))) {
+ av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
+ elem_type, elem_id);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ samples = ac->oc[1].m4ac.frame_length_short ? 960 : 1024;
+ che->present = 1;
+ }
+
+ switch (elem_type) {
+
+ case TYPE_SCE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ audio_found = 1;
+ sce_count++;
+ break;
+
+ case TYPE_CPE:
+ err = decode_cpe(ac, gb, che);
+ audio_found = 1;
+ break;
+
+ case TYPE_CCE:
+ err = ac->proc.decode_cce(ac, gb, che);
+ break;
+
+ case TYPE_LFE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ audio_found = 1;
+ break;
+
+ case TYPE_DSE:
+ err = skip_data_stream_element(ac, gb);
+ break;
+
+ case TYPE_PCE: {
+ uint8_t layout_map[MAX_ELEM_ID*4][3] = {{0}};
+ int tags;
+
+ int pushed = push_output_configuration(ac);
+ if (pce_found && !pushed) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ tags = decode_pce(avctx, &ac->oc[1].m4ac, layout_map, gb,
+ payload_alignment);
+ if (tags < 0) {
+ err = tags;
+ break;
+ }
+ if (pce_found) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Not evaluating a further program_config_element as this construct is dubious at best.\n");
+ pop_output_configuration(ac);
+ } else {
+ err = output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1);
+ if (!err)
+ ac->oc[1].m4ac.chan_config = 0;
+ pce_found = 1;
+ }
+ break;
+ }
+
+ case TYPE_FIL:
+ if (elem_id == 15)
+ elem_id += get_bits(gb, 8) - 1;
+ if (get_bits_left(gb) < 8 * elem_id) {
+ av_log(avctx, AV_LOG_ERROR, "TYPE_FIL: "overread_err);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ err = 0;
+ while (elem_id > 0) {
+ int ret = decode_extension_payload(ac, gb, elem_id, che_prev, che_prev_type);
+ if (ret < 0) {
+ err = ret;
+ break;
+ }
+ elem_id -= ret;
+ }
+ break;
+
+ default:
+ err = AVERROR_BUG; /* should not happen, but keeps compiler happy */
+ break;
+ }
+
+ if (elem_type < TYPE_DSE) {
+ che_prev = che;
+ che_prev_type = elem_type;
+ }
+
+ if (err)
+ goto fail;
+
+ if (get_bits_left(gb) < 3) {
+ av_log(avctx, AV_LOG_ERROR, overread_err);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+
+ if (!avctx->ch_layout.nb_channels) {
+ *got_frame_ptr = 0;
+ return 0;
+ }
+
+ multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0;
+ samples <<= multiplier;
+
+ spectral_to_sample(ac, samples);
+
+ if (ac->oc[1].status && audio_found) {
+ avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier;
+ avctx->frame_size = samples;
+ ac->oc[1].status = OC_LOCKED;
+ }
+
+ if (!ac->frame->data[0] && samples) {
+ av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ if (samples) {
+ ac->frame->nb_samples = samples;
+ ac->frame->sample_rate = avctx->sample_rate;
+ } else
+ av_frame_unref(ac->frame);
+ *got_frame_ptr = !!samples;
+
+ /* for dual-mono audio (SCE + SCE) */
+ is_dmono = ac->dmono_mode && sce_count == 2 &&
+ !av_channel_layout_compare(&ac->oc[1].ch_layout,
+ &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
+ if (is_dmono) {
+ if (ac->dmono_mode == 1)
+ frame->data[1] = frame->data[0];
+ else if (ac->dmono_mode == 2)
+ frame->data[0] = frame->data[1];
+ }
+
+ return 0;
+fail:
+ pop_output_configuration(ac);
+ return err;
+}
+
+static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ AACDecContext *ac = avctx->priv_data;
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ GetBitContext gb;
+ int buf_consumed;
+ int buf_offset;
+ int err;
+ size_t new_extradata_size;
+ const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
+ AV_PKT_DATA_NEW_EXTRADATA,
+ &new_extradata_size);
+ size_t jp_dualmono_size;
+ const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt,
+ AV_PKT_DATA_JP_DUALMONO,
+ &jp_dualmono_size);
+
+ if (new_extradata) {
+ /* discard previous configuration */
+ ac->oc[1].status = OC_NONE;
+ err = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
+ new_extradata,
+ new_extradata_size * 8LL, 1);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ ac->dmono_mode = 0;
+ if (jp_dualmono && jp_dualmono_size > 0)
+ ac->dmono_mode = 1 + *jp_dualmono;
+ if (ac->force_dmono_mode >= 0)
+ ac->dmono_mode = ac->force_dmono_mode;
+
+ if (INT_MAX / 8 <= buf_size)
+ return AVERROR_INVALIDDATA;
+
+ if ((err = init_get_bits8(&gb, buf, buf_size)) < 0)
+ return err;
+
+ switch (ac->oc[1].m4ac.object_type) {
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_LD:
+ case AOT_ER_AAC_ELD:
+ err = aac_decode_er_frame(avctx, frame, got_frame_ptr, &gb);
+ break;
+ default:
+ err = aac_decode_frame_int(avctx, frame, got_frame_ptr, &gb, avpkt);
+ }
+ if (err < 0)
+ return err;
+
+ buf_consumed = (get_bits_count(&gb) + 7) >> 3;
+ for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++)
+ if (buf[buf_offset])
+ break;
+
+ return buf_size > buf_offset ? buf_consumed : buf_size;
}
+#include "aacdec_latm.h"
+
#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
#define OFF(field) offsetof(AACDecContext, field)
static const AVOption options[] = {
@@ -153,9 +2542,49 @@ static const AVOption options[] = {
{NULL},
};
-const AVClass ff_aac_decoder_class = {
+static const AVClass decoder_class = {
.class_name = "AAC decoder",
.item_name = av_default_item_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
};
+
+const FFCodec ff_aac_decoder = {
+ .p.name = "aac",
+ CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .p.priv_class = &decoder_class,
+ .priv_data_size = sizeof(AACDecContext),
+ .init = aac_decode_init,
+ .close = decode_close,
+ FF_CODEC_DECODE_CB(aac_decode_frame),
+ .p.sample_fmts = (const enum AVSampleFormat[]) {
+ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
+ },
+ .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .p.ch_layouts = ff_aac_ch_layout,
+ .flush = flush,
+ .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
+};
+
+const FFCodec ff_aac_fixed_decoder = {
+ .p.name = "aac_fixed",
+ CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .p.priv_class = &decoder_class,
+ .priv_data_size = sizeof(AACDecContext),
+ .init = aac_decode_init_fixed,
+ .close = decode_close,
+ FF_CODEC_DECODE_CB(aac_decode_frame),
+ .p.sample_fmts = (const enum AVSampleFormat[]) {
+ AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE
+ },
+ .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .p.ch_layouts = ff_aac_ch_layout,
+ .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
+ .flush = flush,
+};
diff --git a/libavcodec/aac/aacdec.h b/libavcodec/aac/aacdec.h
index 3b411e2be6..9674f897b1 100644
--- a/libavcodec/aac/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -339,10 +339,11 @@ struct AACDecContext {
#define fdsp RENAME_FIXED(fdsp)
#endif
-extern const struct AVClass ff_aac_decoder_class;
+extern const AACDecDSP aac_dsp;
+extern const AACDecDSP aac_dsp_fixed;
-int ff_aac_decode_init_common(struct AVCodecContext *avctx);
-int ff_aac_decode_close(struct AVCodecContext *avctx);
+extern const AACDecProc aac_proc;
+extern const AACDecProc aac_proc_fixed;
void ff_aacdec_init_mips(AACDecContext *c);
diff --git a/libavcodec/aac/aacdec_latm.h b/libavcodec/aac/aacdec_latm.h
index 031b392d93..5f106d78e6 100644
--- a/libavcodec/aac/aacdec_latm.h
+++ b/libavcodec/aac/aacdec_latm.h
@@ -332,7 +332,7 @@ const FFCodec ff_aac_latm_decoder = {
.p.id = AV_CODEC_ID_AAC_LATM,
.priv_data_size = sizeof(struct LATMContext),
.init = latm_decode_init,
- .close = ff_aac_decode_close,
+ .close = decode_close,
FF_CODEC_DECODE_CB(latm_decode_frame),
.p.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
deleted file mode 100644
index 666e0c89db..0000000000
--- a/libavcodec/aacdec.c
+++ /dev/null
@@ -1,2495 +0,0 @@
-/*
- * AAC decoder
- * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
- * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
- * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
- *
- * AAC LATM decoder
- * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
- * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
- *
- * 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
- */
-
-/**
- * @file
- * AAC decoder
- * @author Oded Shimon ( ods15 ods15 dyndns org )
- * @author Maxim Gavrilov ( maxim.gavrilov gmail com )
- */
-
-#define USE_FIXED 1 // aacsbr.h breaks without this
-
-#include "libavutil/float_dsp.h"
-#include "avcodec.h"
-#include "codec_internal.h"
-#include "get_bits.h"
-#include "kbdwin.h"
-#include "sinewin.h"
-
-#include "aac.h"
-#include "aac/aacdec.h"
-#include "aactab.h"
-#include "aac/aacdec_tab.h"
-#include "adts_header.h"
-#include "cbrt_data.h"
-#include "aacsbr.h"
-#include "mpeg4audio.h"
-#include "profiles.h"
-#include "libavutil/intfloat.h"
-
-#include <errno.h>
-#include <math.h>
-#include <stdint.h>
-#include <string.h>
-
-#if ARCH_ARM
-# include "arm/aac.h"
-#elif ARCH_MIPS
-# include "mips/aacdec_mips.h"
-#endif
-
-/*
- * supported tools
- *
- * Support? Name
- * N (code in SoC repo) gain control
- * Y block switching
- * Y window shapes - standard
- * N window shapes - Low Delay
- * Y filterbank - standard
- * N (code in SoC repo) filterbank - Scalable Sample Rate
- * Y Temporal Noise Shaping
- * Y Long Term Prediction
- * Y intensity stereo
- * Y channel coupling
- * Y frequency domain prediction
- * Y Perceptual Noise Substitution
- * Y Mid/Side stereo
- * N Scalable Inverse AAC Quantization
- * N Frequency Selective Switch
- * N upsampling filter
- * Y quantization & coding - AAC
- * N quantization & coding - TwinVQ
- * N quantization & coding - BSAC
- * N AAC Error Resilience tools
- * N Error Resilience payload syntax
- * N Error Protection tool
- * N CELP
- * N Silence Compression
- * N HVXC
- * N HVXC 4kbits/s VR
- * N Structured Audio tools
- * N Structured Audio Sample Bank Format
- * N MIDI
- * N Harmonic and Individual Lines plus Noise
- * N Text-To-Speech Interface
- * Y Spectral Band Replication
- * Y (not in this code) Layer-1
- * Y (not in this code) Layer-2
- * Y (not in this code) Layer-3
- * N SinuSoidal Coding (Transient, Sinusoid, Noise)
- * Y Parametric Stereo
- * N Direct Stream Transfer
- * Y (not in fixed point code) Enhanced AAC Low Delay (ER AAC ELD)
- *
- * Note: - HE AAC v1 comprises LC AAC with Spectral Band Replication.
- * - HE AAC v2 comprises LC AAC with Spectral Band Replication and
- Parametric Stereo.
- */
-
-#include "libavutil/channel_layout.h"
-#include "libavutil/thread.h"
-#include "decode.h"
-#include "internal.h"
-#include "lpc_functions.h"
-
-static int output_configure(AACDecContext *ac,
- uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
- enum OCStatus oc_type, int get_new_frame);
-
-#define overread_err "Input buffer exhausted before END element found\n"
-
-static int count_channels(uint8_t (*layout)[3], int tags)
-{
- int i, sum = 0;
- for (i = 0; i < tags; i++) {
- int syn_ele = layout[i][0];
- int pos = layout[i][2];
- sum += (1 + (syn_ele == TYPE_CPE)) *
- (pos != AAC_CHANNEL_OFF && pos != AAC_CHANNEL_CC);
- }
- return sum;
-}
-
-/**
- * Check for the channel element in the current channel position configuration.
- * If it exists, make sure the appropriate element is allocated and map the
- * channel order to match the internal FFmpeg channel layout.
- *
- * @param che_pos current channel position configuration
- * @param type channel element type
- * @param id channel element id
- * @param channels count of the number of channels in the configuration
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static av_cold int che_configure(AACDecContext *ac,
- enum ChannelPosition che_pos,
- int type, int id, int *channels)
-{
- if (*channels >= MAX_CHANNELS)
- return AVERROR_INVALIDDATA;
- if (che_pos) {
- if (!ac->che[type][id]) {
- int ret;
- if (ac->is_fixed)
- ret = ff_aac_sbr_ctx_alloc_init_fixed(ac, &ac->che[type][id], type);
- else
- ret = ff_aac_sbr_ctx_alloc_init(ac, &ac->che[type][id], type);
- if (ret < 0)
- return ret;
- }
- if (type != TYPE_CCE) {
- if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) {
- av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n");
- return AVERROR_INVALIDDATA;
- }
- ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0];
- if (type == TYPE_CPE ||
- (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
- ac->output_element[(*channels)++] = &ac->che[type][id]->ch[1];
- }
- }
- } else {
- if (ac->che[type][id]) {
- if (ac->is_fixed)
- ff_aac_sbr_ctx_close_fixed(ac->che[type][id]);
- else
- ff_aac_sbr_ctx_close(ac->che[type][id]);
- }
- av_freep(&ac->che[type][id]);
- }
- return 0;
-}
-
-static int frame_configure_elements(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- int type, id, ch, ret;
-
- /* set channel pointers to internal buffers by default */
- for (type = 0; type < 4; type++) {
- for (id = 0; id < MAX_ELEM_ID; id++) {
- ChannelElement *che = ac->che[type][id];
- if (che) {
- che->ch[0].AAC_RENAME(output) = che->ch[0].AAC_RENAME(ret_buf);
- che->ch[1].AAC_RENAME(output) = che->ch[1].AAC_RENAME(ret_buf);
- }
- }
- }
-
- /* get output buffer */
- av_frame_unref(ac->frame);
- if (!avctx->ch_layout.nb_channels)
- return 1;
-
- ac->frame->nb_samples = 2048;
- if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
- return ret;
-
- /* map output channel pointers to AVFrame data */
- for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
- if (ac->output_element[ch])
- ac->output_element[ch]->AAC_RENAME(output) = (INTFLOAT *)ac->frame->extended_data[ch];
- }
-
- return 0;
-}
-
-struct elem_to_channel {
- uint64_t av_position;
- uint8_t syn_ele;
- uint8_t elem_id;
- uint8_t aac_position;
-};
-
-static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID],
- uint8_t (*layout_map)[3], int offset, uint64_t left,
- uint64_t right, int pos, uint64_t *layout)
-{
- if (layout_map[offset][0] == TYPE_CPE) {
- e2c_vec[offset] = (struct elem_to_channel) {
- .av_position = left | right,
- .syn_ele = TYPE_CPE,
- .elem_id = layout_map[offset][1],
- .aac_position = pos
- };
- if (e2c_vec[offset].av_position != UINT64_MAX)
- *layout |= e2c_vec[offset].av_position;
-
- return 1;
- } else {
- e2c_vec[offset] = (struct elem_to_channel) {
- .av_position = left,
- .syn_ele = TYPE_SCE,
- .elem_id = layout_map[offset][1],
- .aac_position = pos
- };
- e2c_vec[offset + 1] = (struct elem_to_channel) {
- .av_position = right,
- .syn_ele = TYPE_SCE,
- .elem_id = layout_map[offset + 1][1],
- .aac_position = pos
- };
- if (left != UINT64_MAX)
- *layout |= left;
-
- if (right != UINT64_MAX)
- *layout |= right;
-
- return 2;
- }
-}
-
-static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
- int current)
-{
- int num_pos_channels = 0;
- int first_cpe = 0;
- int sce_parity = 0;
- int i;
- for (i = current; i < tags; i++) {
- if (layout_map[i][2] != pos)
- break;
- if (layout_map[i][0] == TYPE_CPE) {
- if (sce_parity) {
- if (pos == AAC_CHANNEL_FRONT && !first_cpe) {
- sce_parity = 0;
- } else {
- return -1;
- }
- }
- num_pos_channels += 2;
- first_cpe = 1;
- } else {
- num_pos_channels++;
- sce_parity ^= (pos != AAC_CHANNEL_LFE);
- }
- }
- if (sce_parity &&
- (pos == AAC_CHANNEL_FRONT && first_cpe))
- return -1;
-
- return num_pos_channels;
-}
-
-static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t (*layout_map)[3],
- uint64_t *layout, int tags, int layer, int pos, int *current)
-{
- int i = *current, j = 0;
- int nb_channels = count_paired_channels(layout_map, tags, pos, i);
-
- if (nb_channels < 0 || nb_channels > 5)
- return 0;
-
- if (pos == AAC_CHANNEL_LFE) {
- while (nb_channels) {
- if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE)
- return -1;
- e2c_vec[i] = (struct elem_to_channel) {
- .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][j],
- .syn_ele = layout_map[i][0],
- .elem_id = layout_map[i][1],
- .aac_position = pos
- };
- *layout |= e2c_vec[i].av_position;
- i++;
- j++;
- nb_channels--;
- }
- *current = i;
-
- return 0;
- }
-
- while (nb_channels & 1) {
- if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE)
- return -1;
- if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED)
- break;
- e2c_vec[i] = (struct elem_to_channel) {
- .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][0],
- .syn_ele = layout_map[i][0],
- .elem_id = layout_map[i][1],
- .aac_position = pos
- };
- *layout |= e2c_vec[i].av_position;
- i++;
- nb_channels--;
- }
-
- j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1;
- while (nb_channels >= 2) {
- if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE ||
- ff_aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE)
- return -1;
- i += assign_pair(e2c_vec, layout_map, i,
- 1ULL << ff_aac_channel_map[layer][pos - 1][j],
- 1ULL << ff_aac_channel_map[layer][pos - 1][j+1],
- pos, layout);
- j += 2;
- nb_channels -= 2;
- }
- while (nb_channels & 1) {
- if (ff_aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE)
- return -1;
- e2c_vec[i] = (struct elem_to_channel) {
- .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][5],
- .syn_ele = layout_map[i][0],
- .elem_id = layout_map[i][1],
- .aac_position = pos
- };
- *layout |= e2c_vec[i].av_position;
- i++;
- nb_channels--;
- }
- if (nb_channels)
- return -1;
-
- *current = i;
-
- return 0;
-}
-
-static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
-{
- int i, n, total_non_cc_elements;
- struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
- uint64_t layout = 0;
-
- if (FF_ARRAY_ELEMS(e2c_vec) < tags)
- return 0;
-
- for (n = 0, i = 0; n < 3 && i < tags; n++) {
- int ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_FRONT, &i);
- if (ret < 0)
- return 0;
- ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_SIDE, &i);
- if (ret < 0)
- return 0;
- ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_BACK, &i);
- if (ret < 0)
- return 0;
- ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_LFE, &i);
- if (ret < 0)
- return 0;
- }
-
- total_non_cc_elements = n = i;
-
- if (layout == AV_CH_LAYOUT_22POINT2) {
- // For 22.2 reorder the result as needed
- FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[0]); // FL & FR first (final), FC third
- FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[1]); // FC second (final), FLc & FRc third
- FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[2]); // LFE1 third (final), FLc & FRc seventh
- FFSWAP(struct elem_to_channel, e2c_vec[4], e2c_vec[3]); // BL & BR fourth (final), SiL & SiR fifth
- FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[4]); // FLc & FRc fifth (final), SiL & SiR seventh
- FFSWAP(struct elem_to_channel, e2c_vec[7], e2c_vec[6]); // LFE2 seventh (final), SiL & SiR eight (final)
- FFSWAP(struct elem_to_channel, e2c_vec[9], e2c_vec[8]); // TpFL & TpFR ninth (final), TFC tenth (final)
- FFSWAP(struct elem_to_channel, e2c_vec[11], e2c_vec[10]); // TC eleventh (final), TpSiL & TpSiR twelth
- FFSWAP(struct elem_to_channel, e2c_vec[12], e2c_vec[11]); // TpBL & TpBR twelth (final), TpSiL & TpSiR thirteenth (final)
- } else {
- // For everything else, utilize the AV channel position define as a
- // stable sort.
- do {
- int next_n = 0;
- for (i = 1; i < n; i++)
- if (e2c_vec[i - 1].av_position > e2c_vec[i].av_position) {
- FFSWAP(struct elem_to_channel, e2c_vec[i - 1], e2c_vec[i]);
- next_n = i;
- }
- n = next_n;
- } while (n > 0);
-
- }
-
- for (i = 0; i < total_non_cc_elements; i++) {
- layout_map[i][0] = e2c_vec[i].syn_ele;
- layout_map[i][1] = e2c_vec[i].elem_id;
- layout_map[i][2] = e2c_vec[i].aac_position;
- }
-
- return layout;
-}
-
-/**
- * Save current output configuration if and only if it has been locked.
- */
-static int push_output_configuration(AACDecContext *ac)
-{
- int pushed = 0;
-
- if (ac->oc[1].status == OC_LOCKED || ac->oc[0].status == OC_NONE) {
- ac->oc[0] = ac->oc[1];
- pushed = 1;
- }
- ac->oc[1].status = OC_NONE;
- return pushed;
-}
-
-/**
- * Restore the previous output configuration if and only if the current
- * configuration is unlocked.
- */
-static void pop_output_configuration(AACDecContext *ac)
-{
- if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
- ac->oc[1] = ac->oc[0];
- ac->avctx->ch_layout = ac->oc[1].ch_layout;
- output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
- ac->oc[1].status, 0);
- }
-}
-
-/**
- * Configure output channel order based on the current program
- * configuration element.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int output_configure(AACDecContext *ac,
- uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags,
- enum OCStatus oc_type, int get_new_frame)
-{
- AVCodecContext *avctx = ac->avctx;
- int i, channels = 0, ret;
- uint64_t layout = 0;
- uint8_t id_map[TYPE_END][MAX_ELEM_ID] = {{ 0 }};
- uint8_t type_counts[TYPE_END] = { 0 };
-
- if (ac->oc[1].layout_map != layout_map) {
- memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0]));
- ac->oc[1].layout_map_tags = tags;
- }
- for (i = 0; i < tags; i++) {
- int type = layout_map[i][0];
- int id = layout_map[i][1];
- id_map[type][id] = type_counts[type]++;
- if (id_map[type][id] >= MAX_ELEM_ID) {
- avpriv_request_sample(ac->avctx, "Too large remapped id");
- return AVERROR_PATCHWELCOME;
- }
- }
- // Try to sniff a reasonable channel order, otherwise output the
- // channels in the order the PCE declared them.
- if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT)
- layout = sniff_channel_order(layout_map, tags);
- for (i = 0; i < tags; i++) {
- int type = layout_map[i][0];
- int id = layout_map[i][1];
- int iid = id_map[type][id];
- int position = layout_map[i][2];
- // Allocate or free elements depending on if they are in the
- // current program configuration.
- ret = che_configure(ac, position, type, iid, &channels);
- if (ret < 0)
- return ret;
- ac->tag_che_map[type][id] = ac->che[type][iid];
- }
- if (ac->oc[1].m4ac.ps == 1 && channels == 2) {
- if (layout == AV_CH_FRONT_CENTER) {
- layout = AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT;
- } else {
- layout = 0;
- }
- }
-
- av_channel_layout_uninit(&ac->oc[1].ch_layout);
- if (layout)
- av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
- else {
- ac->oc[1].ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
- ac->oc[1].ch_layout.nb_channels = channels;
- }
-
- av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
- ac->oc[1].status = oc_type;
-
- if (get_new_frame) {
- if ((ret = frame_configure_elements(ac->avctx)) < 0)
- return ret;
- }
-
- return 0;
-}
-
-static void flush(AVCodecContext *avctx)
-{
- AACDecContext *ac= avctx->priv_data;
- int type, i, j;
-
- for (type = 3; type >= 0; type--) {
- for (i = 0; i < MAX_ELEM_ID; i++) {
- ChannelElement *che = ac->che[type][i];
- if (che) {
- for (j = 0; j <= 1; j++) {
- memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
- }
- }
- }
- }
-}
-
-/**
- * Set up channel positions based on a default channel configuration
- * as specified in table 1.17.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int set_default_channel_config(AACDecContext *ac, AVCodecContext *avctx,
- uint8_t (*layout_map)[3],
- int *tags,
- int channel_config)
-{
- if (channel_config < 1 || (channel_config > 7 && channel_config < 11) ||
- channel_config > 14) {
- av_log(avctx, AV_LOG_ERROR,
- "invalid default channel configuration (%d)\n",
- channel_config);
- return AVERROR_INVALIDDATA;
- }
- *tags = ff_tags_per_config[channel_config];
- memcpy(layout_map, ff_aac_channel_layout_map[channel_config - 1],
- *tags * sizeof(*layout_map));
-
- /*
- * AAC specification has 7.1(wide) as a default layout for 8-channel streams.
- * However, at least Nero AAC encoder encodes 7.1 streams using the default
- * channel config 7, mapping the side channels of the original audio stream
- * to the second AAC_CHANNEL_FRONT pair in the AAC stream. Similarly, e.g. FAAD
- * decodes the second AAC_CHANNEL_FRONT pair as side channels, therefore decoding
- * the incorrect streams as if they were correct (and as the encoder intended).
- *
- * As actual intended 7.1(wide) streams are very rare, default to assuming a
- * 7.1 layout was intended.
- */
- if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) {
- layout_map[2][2] = AAC_CHANNEL_BACK;
-
- if (!ac || !ac->warned_71_wide++) {
- av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout"
- " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode"
- " according to the specification instead.\n", FF_COMPLIANCE_STRICT);
- }
- }
-
- return 0;
-}
-
-static ChannelElement *get_che(AACDecContext *ac, int type, int elem_id)
-{
- /* For PCE based channel configurations map the channels solely based
- * on tags. */
- if (!ac->oc[1].m4ac.chan_config) {
- return ac->tag_che_map[type][elem_id];
- }
- // Allow single CPE stereo files to be signalled with mono configuration.
- if (!ac->tags_mapped && type == TYPE_CPE &&
- ac->oc[1].m4ac.chan_config == 1) {
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int layout_map_tags;
- push_output_configuration(ac);
-
- av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n");
-
- if (set_default_channel_config(ac, ac->avctx, layout_map,
- &layout_map_tags, 2) < 0)
- return NULL;
- if (output_configure(ac, layout_map, layout_map_tags,
- OC_TRIAL_FRAME, 1) < 0)
- return NULL;
-
- ac->oc[1].m4ac.chan_config = 2;
- ac->oc[1].m4ac.ps = 0;
- }
- // And vice-versa
- if (!ac->tags_mapped && type == TYPE_SCE &&
- ac->oc[1].m4ac.chan_config == 2) {
- uint8_t layout_map[MAX_ELEM_ID * 4][3];
- int layout_map_tags;
- push_output_configuration(ac);
-
- av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n");
-
- layout_map_tags = 2;
- layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
- layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
- layout_map[0][1] = 0;
- layout_map[1][1] = 1;
- if (output_configure(ac, layout_map, layout_map_tags,
- OC_TRIAL_FRAME, 1) < 0)
- return NULL;
-
- if (ac->oc[1].m4ac.sbr)
- ac->oc[1].m4ac.ps = -1;
- }
- /* For indexed channel configurations map the channels solely based
- * on position. */
- switch (ac->oc[1].m4ac.chan_config) {
- case 14:
- if (ac->tags_mapped > 2 && ((type == TYPE_CPE && elem_id < 3) ||
- (type == TYPE_LFE && elem_id < 1))) {
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
- }
- case 13:
- if (ac->tags_mapped > 3 && ((type == TYPE_CPE && elem_id < 8) ||
- (type == TYPE_SCE && elem_id < 6) ||
- (type == TYPE_LFE && elem_id < 2))) {
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
- }
- case 12:
- case 7:
- if (ac->tags_mapped == 3 && type == TYPE_CPE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
- }
- case 11:
- if (ac->tags_mapped == 3 && type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
- }
- case 6:
- /* Some streams incorrectly code 5.1 audio as
- * SCE[0] CPE[0] CPE[1] SCE[1]
- * instead of
- * SCE[0] CPE[0] CPE[1] LFE[0].
- * If we seem to have encountered such a stream, transfer
- * the LFE[0] element to the SCE[1]'s mapping */
- if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
- if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) {
- av_log(ac->avctx, AV_LOG_WARNING,
- "This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n",
- type == TYPE_SCE ? "SCE" : "LFE", elem_id);
- ac->warned_remapping_once++;
- }
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
- }
- case 5:
- if (ac->tags_mapped == 2 && type == TYPE_CPE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
- }
- case 4:
- /* Some streams incorrectly code 4.0 audio as
- * SCE[0] CPE[0] LFE[0]
- * instead of
- * SCE[0] CPE[0] SCE[1].
- * If we seem to have encountered such a stream, transfer
- * the SCE[1] element to the LFE[0]'s mapping */
- if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
- if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) {
- av_log(ac->avctx, AV_LOG_WARNING,
- "This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n",
- type == TYPE_SCE ? "SCE" : "LFE", elem_id);
- ac->warned_remapping_once++;
- }
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[TYPE_SCE][1];
- }
- if (ac->tags_mapped == 2 &&
- ac->oc[1].m4ac.chan_config == 4 &&
- type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
- }
- case 3:
- case 2:
- if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) &&
- type == TYPE_CPE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0];
- } else if (ac->tags_mapped == 1 && ac->oc[1].m4ac.chan_config == 2 &&
- type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
- }
- case 1:
- if (!ac->tags_mapped && type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
- }
- default:
- return NULL;
- }
-}
-
-/**
- * Decode an array of 4 bit element IDs, optionally interleaved with a
- * stereo/mono switching bit.
- *
- * @param type speaker type/position for these channels
- */
-static void decode_channel_map(uint8_t layout_map[][3],
- enum ChannelPosition type,
- GetBitContext *gb, int n)
-{
- while (n--) {
- enum RawDataBlockType syn_ele;
- switch (type) {
- case AAC_CHANNEL_FRONT:
- case AAC_CHANNEL_BACK:
- case AAC_CHANNEL_SIDE:
- syn_ele = get_bits1(gb);
- break;
- case AAC_CHANNEL_CC:
- skip_bits1(gb);
- syn_ele = TYPE_CCE;
- break;
- case AAC_CHANNEL_LFE:
- syn_ele = TYPE_LFE;
- break;
- default:
- // AAC_CHANNEL_OFF has no channel map
- av_assert0(0);
- }
- layout_map[0][0] = syn_ele;
- layout_map[0][1] = get_bits(gb, 4);
- layout_map[0][2] = type;
- layout_map++;
- }
-}
-
-static inline void relative_align_get_bits(GetBitContext *gb,
- int reference_position) {
- int n = (reference_position - get_bits_count(gb) & 7);
- if (n)
- skip_bits(gb, n);
-}
-
-/**
- * Decode program configuration element; reference: table 4.2.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
- uint8_t (*layout_map)[3],
- GetBitContext *gb, int byte_align_ref)
-{
- int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc;
- int sampling_index;
- int comment_len;
- int tags;
-
- skip_bits(gb, 2); // object_type
-
- sampling_index = get_bits(gb, 4);
- if (m4ac->sampling_index != sampling_index)
- av_log(avctx, AV_LOG_WARNING,
- "Sample rate index in program config element does not "
- "match the sample rate index configured by the container.\n");
-
- num_front = get_bits(gb, 4);
- num_side = get_bits(gb, 4);
- num_back = get_bits(gb, 4);
- num_lfe = get_bits(gb, 2);
- num_assoc_data = get_bits(gb, 3);
- num_cc = get_bits(gb, 4);
-
- if (get_bits1(gb))
- skip_bits(gb, 4); // mono_mixdown_tag
- if (get_bits1(gb))
- skip_bits(gb, 4); // stereo_mixdown_tag
-
- if (get_bits1(gb))
- skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
-
- if (get_bits_left(gb) < 5 * (num_front + num_side + num_back + num_cc) + 4 *(num_lfe + num_assoc_data + num_cc)) {
- av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
- return -1;
- }
- decode_channel_map(layout_map , AAC_CHANNEL_FRONT, gb, num_front);
- tags = num_front;
- decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE, gb, num_side);
- tags += num_side;
- decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK, gb, num_back);
- tags += num_back;
- decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE, gb, num_lfe);
- tags += num_lfe;
-
- skip_bits_long(gb, 4 * num_assoc_data);
-
- decode_channel_map(layout_map + tags, AAC_CHANNEL_CC, gb, num_cc);
- tags += num_cc;
-
- relative_align_get_bits(gb, byte_align_ref);
-
- /* comment field, first byte is length */
- comment_len = get_bits(gb, 8) * 8;
- if (get_bits_left(gb) < comment_len) {
- av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
- return AVERROR_INVALIDDATA;
- }
- skip_bits_long(gb, comment_len);
- return tags;
-}
-
-/**
- * Decode GA "General Audio" specific configuration; reference: table 4.1.
- *
- * @param ac pointer to AACDecContext, may be null
- * @param avctx pointer to AVCCodecContext, used for logging
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_ga_specific_config(AACDecContext *ac, AVCodecContext *avctx,
- GetBitContext *gb,
- int get_bit_alignment,
- MPEG4AudioConfig *m4ac,
- int channel_config)
-{
- int extension_flag, ret, ep_config, res_flags;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- 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
- extension_flag = get_bits1(gb);
-
- if (m4ac->object_type == AOT_AAC_SCALABLE ||
- m4ac->object_type == AOT_ER_AAC_SCALABLE)
- skip_bits(gb, 3); // layerNr
-
- if (channel_config == 0) {
- skip_bits(gb, 4); // element_instance_tag
- tags = decode_pce(avctx, m4ac, layout_map, gb, get_bit_alignment);
- if (tags < 0)
- return tags;
- } else {
- if ((ret = set_default_channel_config(ac, avctx, layout_map,
- &tags, channel_config)))
- return ret;
- }
-
- if (count_channels(layout_map, tags) > 1) {
- m4ac->ps = 0;
- } else if (m4ac->sbr == 1 && m4ac->ps == -1)
- m4ac->ps = 1;
-
- if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
- return ret;
-
- if (extension_flag) {
- switch (m4ac->object_type) {
- case AOT_ER_BSAC:
- skip_bits(gb, 5); // numOfSubFrame
- skip_bits(gb, 11); // layer_length
- break;
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_SCALABLE:
- case AOT_ER_AAC_LD:
- res_flags = get_bits(gb, 3);
- if (res_flags) {
- avpriv_report_missing_feature(avctx,
- "AAC data resilience (flags %x)",
- res_flags);
- return AVERROR_PATCHWELCOME;
- }
- break;
- }
- skip_bits1(gb); // extensionFlag3 (TBD in version 3)
- }
- switch (m4ac->object_type) {
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_SCALABLE:
- case AOT_ER_AAC_LD:
- ep_config = get_bits(gb, 2);
- if (ep_config) {
- avpriv_report_missing_feature(avctx,
- "epConfig %d", ep_config);
- return AVERROR_PATCHWELCOME;
- }
- }
- return 0;
-}
-
-static int decode_eld_specific_config(AACDecContext *ac, AVCodecContext *avctx,
- GetBitContext *gb,
- MPEG4AudioConfig *m4ac,
- int channel_config)
-{
- int ret, ep_config, res_flags;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int tags = 0;
- const int ELDEXT_TERM = 0;
-
- m4ac->ps = 0;
- m4ac->sbr = 0;
- m4ac->frame_length_short = get_bits1(gb);
-
- res_flags = get_bits(gb, 3);
- if (res_flags) {
- avpriv_report_missing_feature(avctx,
- "AAC data resilience (flags %x)",
- res_flags);
- return AVERROR_PATCHWELCOME;
- }
-
- if (get_bits1(gb)) { // ldSbrPresentFlag
- avpriv_report_missing_feature(avctx,
- "Low Delay SBR");
- return AVERROR_PATCHWELCOME;
- }
-
- while (get_bits(gb, 4) != ELDEXT_TERM) {
- int len = get_bits(gb, 4);
- if (len == 15)
- len += get_bits(gb, 8);
- if (len == 15 + 255)
- len += get_bits(gb, 16);
- if (get_bits_left(gb) < len * 8 + 4) {
- av_log(avctx, AV_LOG_ERROR, overread_err);
- return AVERROR_INVALIDDATA;
- }
- skip_bits_long(gb, 8 * len);
- }
-
- if ((ret = set_default_channel_config(ac, avctx, layout_map,
- &tags, channel_config)))
- return ret;
-
- if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
- return ret;
-
- ep_config = get_bits(gb, 2);
- if (ep_config) {
- avpriv_report_missing_feature(avctx,
- "epConfig %d", ep_config);
- return AVERROR_PATCHWELCOME;
- }
- return 0;
-}
-
-/**
- * Decode audio specific configuration; reference: table 1.13.
- *
- * @param ac pointer to AACDecContext, may be null
- * @param avctx pointer to AVCCodecContext, used for logging
- * @param m4ac pointer to MPEG4AudioConfig, used for parsing
- * @param gb buffer holding an audio specific config
- * @param get_bit_alignment relative alignment for byte align operations
- * @param sync_extension look for an appended sync extension
- *
- * @return Returns error status or number of consumed bits. <0 - error
- */
-static int decode_audio_specific_config_gb(AACDecContext *ac,
- AVCodecContext *avctx,
- MPEG4AudioConfig *m4ac,
- GetBitContext *gb,
- int get_bit_alignment,
- int sync_extension)
-{
- int i, ret;
- GetBitContext gbc = *gb;
- MPEG4AudioConfig m4ac_bak = *m4ac;
-
- if ((i = ff_mpeg4audio_get_config_gb(m4ac, &gbc, sync_extension, avctx)) < 0) {
- *m4ac = m4ac_bak;
- return AVERROR_INVALIDDATA;
- }
-
- if (m4ac->sampling_index > 12) {
- av_log(avctx, AV_LOG_ERROR,
- "invalid sampling rate index %d\n",
- m4ac->sampling_index);
- *m4ac = m4ac_bak;
- 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);
- *m4ac = m4ac_bak;
- return AVERROR_INVALIDDATA;
- }
-
- skip_bits_long(gb, i);
-
- switch (m4ac->object_type) {
- case AOT_AAC_MAIN:
- case AOT_AAC_LC:
- case AOT_AAC_SSR:
- case AOT_AAC_LTP:
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LD:
- if ((ret = decode_ga_specific_config(ac, avctx, gb, get_bit_alignment,
- m4ac, m4ac->chan_config)) < 0)
- return ret;
- break;
- case AOT_ER_AAC_ELD:
- if ((ret = decode_eld_specific_config(ac, avctx, gb,
- m4ac, m4ac->chan_config)) < 0)
- return ret;
- break;
- default:
- avpriv_report_missing_feature(avctx,
- "Audio object type %s%d",
- m4ac->sbr == 1 ? "SBR+" : "",
- m4ac->object_type);
- return AVERROR(ENOSYS);
- }
-
- ff_dlog(avctx,
- "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
- m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
- m4ac->sample_rate, m4ac->sbr,
- m4ac->ps);
-
- return get_bits_count(gb);
-}
-
-static int decode_audio_specific_config(AACDecContext *ac,
- AVCodecContext *avctx,
- MPEG4AudioConfig *m4ac,
- const uint8_t *data, int64_t bit_size,
- int sync_extension)
-{
- int i, ret;
- GetBitContext gb;
-
- if (bit_size < 0 || bit_size > INT_MAX) {
- av_log(avctx, AV_LOG_ERROR, "Audio specific config size is invalid\n");
- return AVERROR_INVALIDDATA;
- }
-
- ff_dlog(avctx, "audio specific config size %d\n", (int)bit_size >> 3);
- for (i = 0; i < bit_size >> 3; i++)
- ff_dlog(avctx, "%02x ", data[i]);
- ff_dlog(avctx, "\n");
-
- if ((ret = init_get_bits(&gb, data, bit_size)) < 0)
- return ret;
-
- return decode_audio_specific_config_gb(ac, avctx, m4ac, &gb, 0,
- sync_extension);
-}
-
-static int sample_rate_idx (int rate)
-{
- if (92017 <= rate) return 0;
- else if (75132 <= rate) return 1;
- else if (55426 <= rate) return 2;
- else if (46009 <= rate) return 3;
- else if (37566 <= rate) return 4;
- else if (27713 <= rate) return 5;
- else if (23004 <= rate) return 6;
- else if (18783 <= rate) return 7;
- else if (13856 <= rate) return 8;
- else if (11502 <= rate) return 9;
- else if (9391 <= rate) return 10;
- else return 11;
-}
-
-static av_cold void aac_static_table_init(void)
-{
- ff_aac_sbr_init();
- ff_aac_sbr_init_fixed();
-
- ff_aacdec_common_init_once();
-}
-
-static AVOnce aac_table_init = AV_ONCE_INIT;
-
-static av_cold int aac_decode_init_internal(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- int ret;
-
- if (avctx->sample_rate > 96000)
- return AVERROR_INVALIDDATA;
-
- ret = ff_thread_once(&aac_table_init, &aac_static_table_init);
- if (ret != 0)
- return AVERROR_UNKNOWN;
-
- ac->avctx = avctx;
- ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
-
- if (ac->is_fixed)
- avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
- else
- avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
-
- if (avctx->extradata_size > 0) {
- if ((ret = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
- avctx->extradata,
- avctx->extradata_size * 8LL,
- 1)) < 0)
- return ret;
- } else {
- int sr, i;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int layout_map_tags;
-
- sr = sample_rate_idx(avctx->sample_rate);
- ac->oc[1].m4ac.sampling_index = sr;
- ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels;
- ac->oc[1].m4ac.sbr = -1;
- ac->oc[1].m4ac.ps = -1;
-
- for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
- if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels)
- break;
- if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
- i = 0;
- }
- ac->oc[1].m4ac.chan_config = i;
-
- if (ac->oc[1].m4ac.chan_config) {
- int ret = set_default_channel_config(ac, avctx, layout_map,
- &layout_map_tags, ac->oc[1].m4ac.chan_config);
- if (!ret)
- output_configure(ac, layout_map, layout_map_tags,
- OC_GLOBAL_HDR, 0);
- else if (avctx->err_recognition & AV_EF_EXPLODE)
- return AVERROR_INVALIDDATA;
- }
- }
-
- return ff_aac_decode_init_common(avctx);
-}
-
-static av_cold int aac_decode_init(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- ac->is_fixed = 0;
- return aac_decode_init_internal(avctx);
-}
-
-static av_cold int aac_decode_init_fixed(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- ac->is_fixed = 1;
- return aac_decode_init_internal(avctx);
-}
-
-/**
- * Skip data_stream_element; reference: table 4.10.
- */
-static int skip_data_stream_element(AACDecContext *ac, GetBitContext *gb)
-{
- int byte_align = get_bits1(gb);
- int count = get_bits(gb, 8);
- if (count == 255)
- count += get_bits(gb, 8);
- if (byte_align)
- align_get_bits(gb);
-
- if (get_bits_left(gb) < 8 * count) {
- av_log(ac->avctx, AV_LOG_ERROR, "skip_data_stream_element: "overread_err);
- return AVERROR_INVALIDDATA;
- }
- skip_bits_long(gb, 8 * count);
- return 0;
-}
-
-static int decode_prediction(AACDecContext *ac, IndividualChannelStream *ics,
- GetBitContext *gb)
-{
- int sfb;
- if (get_bits1(gb)) {
- ics->predictor_reset_group = get_bits(gb, 5);
- if (ics->predictor_reset_group == 0 ||
- ics->predictor_reset_group > 30) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Invalid Predictor Reset Group.\n");
- return AVERROR_INVALIDDATA;
- }
- }
- for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]); sfb++) {
- ics->prediction_used[sfb] = get_bits1(gb);
- }
- return 0;
-}
-
-/**
- * Decode Long Term Prediction data; reference: table 4.xx.
- */
-static void decode_ltp(AACDecContext *ac, LongTermPrediction *ltp,
- GetBitContext *gb, uint8_t max_sfb)
-{
- int sfb;
-
- ltp->lag = get_bits(gb, 11);
- if (ac->is_fixed)
- ltp->coef_fixed = Q30(ff_ltp_coef[get_bits(gb, 3)]);
- else
- ltp->coef = ff_ltp_coef[get_bits(gb, 3)];
-
- for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
- ltp->used[sfb] = get_bits1(gb);
-}
-
-/**
- * Decode Individual Channel Stream info; reference: table 4.6.
- */
-static int decode_ics_info(AACDecContext *ac, IndividualChannelStream *ics,
- GetBitContext *gb)
-{
- const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
- const int aot = m4ac->object_type;
- const int sampling_index = m4ac->sampling_index;
- int ret_fail = AVERROR_INVALIDDATA;
-
- if (aot != AOT_ER_AAC_ELD) {
- if (get_bits1(gb)) {
- av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n");
- if (ac->avctx->err_recognition & AV_EF_BITSTREAM)
- return AVERROR_INVALIDDATA;
- }
- ics->window_sequence[1] = ics->window_sequence[0];
- ics->window_sequence[0] = get_bits(gb, 2);
- if (aot == 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;
- ics->group_len[0] = 1;
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- int i;
- ics->max_sfb = get_bits(gb, 4);
- for (i = 0; i < 7; i++) {
- if (get_bits1(gb)) {
- ics->group_len[ics->num_window_groups - 1]++;
- } else {
- ics->num_window_groups++;
- ics->group_len[ics->num_window_groups - 1] = 1;
- }
- }
- ics->num_windows = 8;
- 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 {
- ics->max_sfb = get_bits(gb, 6);
- ics->num_windows = 1;
- if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) {
- if (m4ac->frame_length_short) {
- ics->swb_offset = ff_swb_offset_480[sampling_index];
- ics->num_swb = ff_aac_num_swb_480[sampling_index];
- ics->tns_max_bands = ff_tns_max_bands_480[sampling_index];
- } else {
- ics->swb_offset = ff_swb_offset_512[sampling_index];
- ics->num_swb = ff_aac_num_swb_512[sampling_index];
- ics->tns_max_bands = ff_tns_max_bands_512[sampling_index];
- }
- if (!ics->num_swb || !ics->swb_offset) {
- ret_fail = AVERROR_BUG;
- goto fail;
- }
- } else {
- 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) {
- ics->predictor_present = get_bits1(gb);
- ics->predictor_reset_group = 0;
- }
- if (ics->predictor_present) {
- if (aot == AOT_AAC_MAIN) {
- if (decode_prediction(ac, ics, gb)) {
- goto fail;
- }
- } else if (aot == AOT_AAC_LC ||
- aot == AOT_ER_AAC_LC) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Prediction is not allowed in AAC-LC.\n");
- goto fail;
- } else {
- if (aot == AOT_ER_AAC_LD) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "LTP in ER AAC LD not yet implemented.\n");
- ret_fail = AVERROR_PATCHWELCOME;
- goto fail;
- }
- if ((ics->ltp.present = get_bits(gb, 1)))
- decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
- }
- }
- }
-
- if (ics->max_sfb > ics->num_swb) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Number of scalefactor bands in group (%d) "
- "exceeds limit (%d).\n",
- ics->max_sfb, ics->num_swb);
- goto fail;
- }
-
- return 0;
-fail:
- ics->max_sfb = 0;
- return ret_fail;
-}
-
-/**
- * Decode band types (section_data payload); reference: table 4.46.
- *
- * @param band_type array of the used band type
- * @param band_type_run_end array of the last scalefactor band of a band type run
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_band_types(AACDecContext *ac, enum BandType band_type[120],
- int band_type_run_end[120], GetBitContext *gb,
- IndividualChannelStream *ics)
-{
- int g, idx = 0;
- const int bits = (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) ? 3 : 5;
- for (g = 0; g < ics->num_window_groups; g++) {
- int k = 0;
- while (k < ics->max_sfb) {
- uint8_t sect_end = k;
- int sect_len_incr;
- int sect_band_type = get_bits(gb, 4);
- if (sect_band_type == 12) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid band type\n");
- return AVERROR_INVALIDDATA;
- }
- do {
- sect_len_incr = get_bits(gb, bits);
- sect_end += sect_len_incr;
- if (get_bits_left(gb) < 0) {
- av_log(ac->avctx, AV_LOG_ERROR, "decode_band_types: "overread_err);
- return AVERROR_INVALIDDATA;
- }
- if (sect_end > ics->max_sfb) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Number of bands (%d) exceeds limit (%d).\n",
- sect_end, ics->max_sfb);
- return AVERROR_INVALIDDATA;
- }
- } while (sect_len_incr == (1 << bits) - 1);
- for (; k < sect_end; k++) {
- band_type [idx] = sect_band_type;
- band_type_run_end[idx++] = sect_end;
- }
- }
- }
- return 0;
-}
-
-/**
- * Decode scalefactors; reference: table 4.47.
- *
- * @param global_gain first scalefactor value as scalefactors are differentially coded
- * @param band_type array of the used band type
- * @param band_type_run_end array of the last scalefactor band of a band type run
- * @param sf array of scalefactors or intensity stereo positions
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_scalefactors(AACDecContext *ac, int sfo[120],
- GetBitContext *gb,
- unsigned int global_gain,
- IndividualChannelStream *ics,
- enum BandType band_type[120],
- int band_type_run_end[120])
-{
- int g, i, idx = 0;
- int offset[3] = { global_gain, global_gain - NOISE_OFFSET, 0 };
- int clipped_offset;
- int noise_flag = 1;
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb;) {
- int run_end = band_type_run_end[idx];
- switch (band_type[idx]) {
- case ZERO_BT:
- for (; i < run_end; i++, idx++)
- sfo[idx] = 0;
- break;
- case INTENSITY_BT: /* fallthrough */
- case INTENSITY_BT2:
- for (; i < run_end; i++, idx++) {
- offset[2] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
- clipped_offset = av_clip(offset[2], -155, 100);
- if (offset[2] != clipped_offset) {
- avpriv_request_sample(ac->avctx,
- "If you heard an audible artifact, there may be a bug in the decoder. "
- "Clipped intensity stereo position (%d -> %d)",
- offset[2], clipped_offset);
- }
- sfo[idx] = clipped_offset;
- }
- break;
- case NOISE_BT:
- for (; i < run_end; i++, idx++) {
- if (noise_flag-- > 0)
- offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE;
- else
- offset[1] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
- clipped_offset = av_clip(offset[1], -100, 155);
- if (offset[1] != clipped_offset) {
- avpriv_request_sample(ac->avctx,
- "If you heard an audible artifact, there may be a bug in the decoder. "
- "Clipped noise gain (%d -> %d)",
- offset[1], clipped_offset);
- }
- sfo[idx] = clipped_offset;
- }
- break;
- default:
- for (; i < run_end; i++, idx++) {
- offset[0] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
- if (offset[0] > 255U) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Scalefactor (%d) out of range.\n", offset[0]);
- return AVERROR_INVALIDDATA;
- }
- sfo[idx] = offset[0];
- }
- break;
- }
- }
- }
- return 0;
-}
-
-/**
- * Decode pulse data; reference: table 4.7.
- */
-static int decode_pulses(Pulse *pulse, GetBitContext *gb,
- const uint16_t *swb_offset, int num_swb)
-{
- int i, pulse_swb;
- pulse->num_pulse = get_bits(gb, 2) + 1;
- pulse_swb = get_bits(gb, 6);
- if (pulse_swb >= num_swb)
- return -1;
- pulse->pos[0] = swb_offset[pulse_swb];
- pulse->pos[0] += get_bits(gb, 5);
- if (pulse->pos[0] >= swb_offset[num_swb])
- return -1;
- pulse->amp[0] = get_bits(gb, 4);
- for (i = 1; i < pulse->num_pulse; i++) {
- pulse->pos[i] = get_bits(gb, 5) + pulse->pos[i - 1];
- if (pulse->pos[i] >= swb_offset[num_swb])
- return -1;
- pulse->amp[i] = get_bits(gb, 4);
- }
- return 0;
-}
-
-/**
- * Decode Temporal Noise Shaping data; reference: table 4.48.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
- GetBitContext *gb, const IndividualChannelStream *ics)
-{
- int w, filt, i, coef_len, coef_res, coef_compress;
- const int is8 = ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE;
- const int tns_max_order = is8 ? 7 : ac->oc[1].m4ac.object_type == AOT_AAC_MAIN ? 20 : 12;
- for (w = 0; w < ics->num_windows; w++) {
- if ((tns->n_filt[w] = get_bits(gb, 2 - is8))) {
- coef_res = get_bits1(gb);
-
- for (filt = 0; filt < tns->n_filt[w]; filt++) {
- int tmp2_idx;
- tns->length[w][filt] = get_bits(gb, 6 - 2 * is8);
-
- if ((tns->order[w][filt] = get_bits(gb, 5 - 2 * is8)) > tns_max_order) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "TNS filter order %d is greater than maximum %d.\n",
- tns->order[w][filt], tns_max_order);
- tns->order[w][filt] = 0;
- return AVERROR_INVALIDDATA;
- }
- if (tns->order[w][filt]) {
- tns->direction[w][filt] = get_bits1(gb);
- coef_compress = get_bits1(gb);
- coef_len = coef_res + 3 - coef_compress;
- tmp2_idx = 2 * coef_compress + coef_res;
-
- for (i = 0; i < tns->order[w][filt]; i++) {
- if (ac->is_fixed)
- tns->coef_fixed[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
- else
- tns->coef[w][filt][i] = ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)];
- }
- }
- }
- }
- }
- return 0;
-}
-
-/**
- * Decode Mid/Side data; reference: table 4.54.
- *
- * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
- * [1] mask is decoded from bitstream; [2] mask is all 1s;
- * [3] reserved for scalable AAC
- */
-static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
- int ms_present)
-{
- int idx;
- int max_idx = cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb;
- if (ms_present == 1) {
- for (idx = 0; idx < max_idx; idx++)
- cpe->ms_mask[idx] = get_bits1(gb);
- } else if (ms_present == 2) {
- memset(cpe->ms_mask, 1, max_idx * sizeof(cpe->ms_mask[0]));
- }
-}
-
-static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
-{
- // wd_num, wd_test, aloc_size
- static const uint8_t gain_mode[4][3] = {
- {1, 0, 5}, // ONLY_LONG_SEQUENCE = 0,
- {2, 1, 2}, // LONG_START_SEQUENCE,
- {8, 0, 2}, // EIGHT_SHORT_SEQUENCE,
- {2, 1, 5}, // LONG_STOP_SEQUENCE
- };
-
- const int mode = sce->ics.window_sequence[0];
- uint8_t bd, wd, ad;
-
- // FIXME: Store the gain control data on |sce| and do something with it.
- uint8_t max_band = get_bits(gb, 2);
- for (bd = 0; bd < max_band; bd++) {
- for (wd = 0; wd < gain_mode[mode][0]; wd++) {
- uint8_t adjust_num = get_bits(gb, 3);
- for (ad = 0; ad < adjust_num; ad++) {
- skip_bits(gb, 4 + ((wd == 0 && gain_mode[mode][1])
- ? 4
- : gain_mode[mode][2]));
- }
- }
- }
-}
-
-/**
- * Decode an individual_channel_stream payload; reference: table 4.44.
- *
- * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
- * @param scale_flag scalable [1] or non-scalable [0] AAC (Unused until scalable AAC is implemented.)
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
- GetBitContext *gb, int common_window, int scale_flag)
-{
- Pulse pulse;
- TemporalNoiseShaping *tns = &sce->tns;
- IndividualChannelStream *ics = &sce->ics;
- int global_gain, eld_syntax, er_syntax, pulse_present = 0;
- int ret;
-
- eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
- er_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_LC ||
- ac->oc[1].m4ac.object_type == AOT_ER_AAC_LTP ||
- ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD ||
- ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
-
- /* This assignment is to silence a GCC warning about the variable being used
- * uninitialized when in fact it always is.
- */
- pulse.num_pulse = 0;
-
- global_gain = get_bits(gb, 8);
-
- if (!common_window && !scale_flag) {
- ret = decode_ics_info(ac, ics, gb);
- if (ret < 0)
- goto fail;
- }
-
- if ((ret = decode_band_types(ac, sce->band_type,
- sce->band_type_run_end, gb, ics)) < 0)
- goto fail;
- if ((ret = decode_scalefactors(ac, sce->sfo, gb, global_gain, ics,
- sce->band_type, sce->band_type_run_end)) < 0)
- goto fail;
-
- ac->dsp.dequant_scalefactors(sce);
-
- pulse_present = 0;
- if (!scale_flag) {
- if (!eld_syntax && (pulse_present = get_bits1(gb))) {
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Pulse tool not allowed in eight short sequence.\n");
- ret = AVERROR_INVALIDDATA;
- goto fail;
- }
- if (decode_pulses(&pulse, gb, ics->swb_offset, ics->num_swb)) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Pulse data corrupt or invalid.\n");
- ret = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
- tns->present = get_bits1(gb);
- if (tns->present && !er_syntax) {
- ret = decode_tns(ac, tns, gb, ics);
- if (ret < 0)
- goto fail;
- }
- if (!eld_syntax && get_bits1(gb)) {
- decode_gain_control(sce, gb);
- if (!ac->warned_gain_control) {
- avpriv_report_missing_feature(ac->avctx, "Gain control");
- ac->warned_gain_control = 1;
- }
- }
- // I see no textual basis in the spec for this occurring after SSR gain
- // control, but this is what both reference and real implmentations do
- if (tns->present && er_syntax) {
- ret = decode_tns(ac, tns, gb, ics);
- if (ret < 0)
- goto fail;
- }
- }
-
- ret = ac->proc.decode_spectrum_and_dequant(ac, gb,
- pulse_present ? &pulse : NULL,
- sce);
- if (ret < 0)
- goto fail;
-
- if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window)
- ac->dsp.apply_prediction(ac, sce);
-
- return 0;
-fail:
- tns->present = 0;
- return ret;
-}
-
-/**
- * Decode a channel_pair_element; reference: table 4.4.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
-{
- int i, ret, common_window, ms_present = 0;
- int eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
-
- common_window = eld_syntax || get_bits1(gb);
- if (common_window) {
- if (decode_ics_info(ac, &cpe->ch[0].ics, gb))
- return AVERROR_INVALIDDATA;
- i = cpe->ch[1].ics.use_kb_window[0];
- cpe->ch[1].ics = cpe->ch[0].ics;
- cpe->ch[1].ics.use_kb_window[1] = i;
- if (cpe->ch[1].ics.predictor_present &&
- (ac->oc[1].m4ac.object_type != AOT_AAC_MAIN))
- if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
- decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
- ms_present = get_bits(gb, 2);
- if (ms_present == 3) {
- av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
- return AVERROR_INVALIDDATA;
- } else if (ms_present)
- decode_mid_side_stereo(cpe, gb, ms_present);
- }
- if ((ret = ff_aac_decode_ics(ac, &cpe->ch[0], gb, common_window, 0)))
- return ret;
- if ((ret = ff_aac_decode_ics(ac, &cpe->ch[1], gb, common_window, 0)))
- return ret;
-
- if (common_window) {
- if (ms_present)
- ac->dsp.apply_mid_side_stereo(ac, cpe);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) {
- ac->dsp.apply_prediction(ac, &cpe->ch[0]);
- ac->dsp.apply_prediction(ac, &cpe->ch[1]);
- }
- }
-
- ac->dsp.apply_intensity_stereo(ac, cpe, ms_present);
- return 0;
-}
-
-/**
- * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
- *
- * @return Returns number of bytes consumed.
- */
-static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc,
- GetBitContext *gb)
-{
- int i;
- int num_excl_chan = 0;
-
- do {
- for (i = 0; i < 7; i++)
- che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb);
- } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb));
-
- return num_excl_chan / 7;
-}
-
-/**
- * Decode dynamic range information; reference: table 4.52.
- *
- * @return Returns number of bytes consumed.
- */
-static int decode_dynamic_range(DynamicRangeControl *che_drc,
- GetBitContext *gb)
-{
- int n = 1;
- int drc_num_bands = 1;
- int i;
-
- /* pce_tag_present? */
- if (get_bits1(gb)) {
- che_drc->pce_instance_tag = get_bits(gb, 4);
- skip_bits(gb, 4); // tag_reserved_bits
- n++;
- }
-
- /* excluded_chns_present? */
- if (get_bits1(gb)) {
- n += decode_drc_channel_exclusions(che_drc, gb);
- }
-
- /* drc_bands_present? */
- if (get_bits1(gb)) {
- che_drc->band_incr = get_bits(gb, 4);
- che_drc->interpolation_scheme = get_bits(gb, 4);
- n++;
- drc_num_bands += che_drc->band_incr;
- for (i = 0; i < drc_num_bands; i++) {
- che_drc->band_top[i] = get_bits(gb, 8);
- n++;
- }
- }
-
- /* prog_ref_level_present? */
- if (get_bits1(gb)) {
- che_drc->prog_ref_level = get_bits(gb, 7);
- skip_bits1(gb); // prog_ref_level_reserved_bits
- n++;
- }
-
- for (i = 0; i < drc_num_bands; i++) {
- che_drc->dyn_rng_sgn[i] = get_bits1(gb);
- che_drc->dyn_rng_ctl[i] = get_bits(gb, 7);
- n++;
- }
-
- return n;
-}
-
-static int decode_fill(AACDecContext *ac, GetBitContext *gb, int len) {
- uint8_t buf[256];
- int i, major, minor;
-
- if (len < 13+7*8)
- goto unknown;
-
- get_bits(gb, 13); len -= 13;
-
- for(i=0; i+1<sizeof(buf) && len>=8; i++, len-=8)
- buf[i] = get_bits(gb, 8);
-
- buf[i] = 0;
- if (ac->avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(ac->avctx, AV_LOG_DEBUG, "FILL:%s\n", buf);
-
- if (sscanf(buf, "libfaac %d.%d", &major, &minor) == 2){
- ac->avctx->internal->skip_samples = 1024;
- }
-
-unknown:
- skip_bits_long(gb, len);
-
- return 0;
-}
-
-/**
- * Decode extension data (incomplete); reference: table 4.51.
- *
- * @param cnt length of TYPE_FIL syntactic element in bytes
- *
- * @return Returns number of bytes consumed
- */
-static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cnt,
- ChannelElement *che, enum RawDataBlockType elem_type)
-{
- int crc_flag = 0;
- int res = cnt;
- int type = get_bits(gb, 4);
-
- if (ac->avctx->debug & FF_DEBUG_STARTCODE)
- av_log(ac->avctx, AV_LOG_DEBUG, "extension type: %d len:%d\n", type, cnt);
-
- switch (type) { // extension type
- case EXT_SBR_DATA_CRC:
- crc_flag++;
- case EXT_SBR_DATA:
- 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);
- return res;
- } else if (ac->oc[1].m4ac.sbr == -1 && ac->oc[1].status == OC_LOCKED) {
- av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n");
- skip_bits_long(gb, 8 * cnt - 4);
- return res;
- } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED &&
- ac->avctx->ch_layout.nb_channels == 1) {
- ac->oc[1].m4ac.sbr = 1;
- ac->oc[1].m4ac.ps = 1;
- ac->avctx->profile = AV_PROFILE_AAC_HE_V2;
- output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
- ac->oc[1].status, 1);
- } else {
- ac->oc[1].m4ac.sbr = 1;
- ac->avctx->profile = AV_PROFILE_AAC_HE;
- }
-
- if (ac->is_fixed)
- res = ff_aac_sbr_decode_extension_fixed(ac, che, gb, crc_flag, cnt, elem_type);
- else
- res = ff_aac_sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
-
-
- 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");
- ac->warned_he_aac_mono = 1;
- }
- break;
- case EXT_DYNAMIC_RANGE:
- res = decode_dynamic_range(&ac->che_drc, gb);
- break;
- case EXT_FILL:
- decode_fill(ac, gb, 8 * cnt - 4);
- break;
- case EXT_FILL_DATA:
- case EXT_DATA_ELEMENT:
- default:
- skip_bits_long(gb, 8 * cnt - 4);
- break;
- };
- return res;
-}
-
-/**
- * channel coupling transformation interface
- *
- * @param apply_coupling_method pointer to (in)dependent coupling function
- */
-static void apply_channel_coupling(AACDecContext *ac, ChannelElement *cc,
- enum RawDataBlockType type, int elem_id,
- enum CouplingPoint coupling_point,
- void (*apply_coupling_method)(AACDecContext *ac, SingleChannelElement *target, ChannelElement *cce, int index))
-{
- int i, c;
-
- for (i = 0; i < MAX_ELEM_ID; i++) {
- ChannelElement *cce = ac->che[TYPE_CCE][i];
- int index = 0;
-
- if (cce && cce->coup.coupling_point == coupling_point) {
- ChannelCoupling *coup = &cce->coup;
-
- for (c = 0; c <= coup->num_coupled; c++) {
- if (coup->type[c] == type && coup->id_select[c] == elem_id) {
- if (coup->ch_select[c] != 1) {
- apply_coupling_method(ac, &cc->ch[0], cce, index);
- if (coup->ch_select[c] != 0)
- index++;
- }
- if (coup->ch_select[c] != 2)
- apply_coupling_method(ac, &cc->ch[1], cce, index++);
- } else
- index += 1 + (coup->ch_select[c] == 3);
- }
- }
- }
-}
-
-/**
- * Convert spectral data to samples, applying all supported tools as appropriate.
- */
-static void spectral_to_sample(AACDecContext *ac, int samples)
-{
- int i, type;
- void (*imdct_and_window)(AACDecContext *ac, SingleChannelElement *sce);
- switch (ac->oc[1].m4ac.object_type) {
- case AOT_ER_AAC_LD:
- imdct_and_window = ac->dsp.imdct_and_windowing_ld;
- break;
- case AOT_ER_AAC_ELD:
- imdct_and_window = ac->dsp.imdct_and_windowing_eld;
- break;
- default:
- if (ac->oc[1].m4ac.frame_length_short)
- imdct_and_window = ac->dsp.imdct_and_windowing_960;
- else
- imdct_and_window = ac->dsp.imdct_and_windowing;
- }
- for (type = 3; type >= 0; type--) {
- for (i = 0; i < MAX_ELEM_ID; i++) {
- ChannelElement *che = ac->che[type][i];
- if (che && che->present) {
- if (type <= TYPE_CPE)
- apply_channel_coupling(ac, che, type, i, BEFORE_TNS, ac->dsp.apply_dependent_coupling);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
- if (che->ch[0].ics.predictor_present) {
- if (che->ch[0].ics.ltp.present)
- ac->dsp.apply_ltp(ac, &che->ch[0]);
- if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
- ac->dsp.apply_ltp(ac, &che->ch[1]);
- }
- }
- if (che->ch[0].tns.present)
- ac->dsp.apply_tns(che->ch[0].AAC_RENAME(coeffs),
- &che->ch[0].tns, &che->ch[0].ics, 1);
- if (che->ch[1].tns.present)
- ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
- &che->ch[1].tns, &che->ch[1].ics, 1);
- if (type <= TYPE_CPE)
- apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling);
- if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
- imdct_and_window(ac, &che->ch[0]);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
- ac->dsp.update_ltp(ac, &che->ch[0]);
- if (type == TYPE_CPE) {
- imdct_and_window(ac, &che->ch[1]);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
- ac->dsp.update_ltp(ac, &che->ch[1]);
- }
- if (ac->oc[1].m4ac.sbr > 0) {
- if (ac->is_fixed)
- ff_aac_sbr_apply_fixed(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
- else
- ff_aac_sbr_apply(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
- }
- }
- if (type <= TYPE_CCE)
- apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling);
- ac->dsp.clip_output(ac, che, type, samples);
- che->present = 0;
- } else if (che) {
- av_log(ac->avctx, AV_LOG_VERBOSE, "ChannelElement %d.%d missing \n", type, i);
- }
- }
- }
-}
-
-static int parse_adts_frame_header(AACDecContext *ac, GetBitContext *gb)
-{
- int size;
- AACADTSHeaderInfo hdr_info;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int layout_map_tags, ret;
-
- size = ff_adts_header_parse(gb, &hdr_info);
- if (size > 0) {
- if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
- // This is 2 for "VLB " audio in NSV files.
- // See samples/nsv/vlb_audio.
- avpriv_report_missing_feature(ac->avctx,
- "More than one AAC RDB per ADTS frame");
- ac->warned_num_aac_frames = 1;
- }
- push_output_configuration(ac);
- if (hdr_info.chan_config) {
- ac->oc[1].m4ac.chan_config = hdr_info.chan_config;
- if ((ret = set_default_channel_config(ac, ac->avctx,
- layout_map,
- &layout_map_tags,
- hdr_info.chan_config)) < 0)
- return ret;
- if ((ret = output_configure(ac, layout_map, layout_map_tags,
- FFMAX(ac->oc[1].status,
- OC_TRIAL_FRAME), 0)) < 0)
- return ret;
- } else {
- ac->oc[1].m4ac.chan_config = 0;
- /**
- * dual mono frames in Japanese DTV can have chan_config 0
- * WITHOUT specifying PCE.
- * thus, set dual mono as default.
- */
- if (ac->dmono_mode && ac->oc[0].status == OC_NONE) {
- layout_map_tags = 2;
- layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
- layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
- layout_map[0][1] = 0;
- layout_map[1][1] = 1;
- if (output_configure(ac, layout_map, layout_map_tags,
- OC_TRIAL_FRAME, 0))
- return -7;
- }
- }
- ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate;
- ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index;
- ac->oc[1].m4ac.object_type = hdr_info.object_type;
- ac->oc[1].m4ac.frame_length_short = 0;
- if (ac->oc[0].status != OC_LOCKED ||
- ac->oc[0].m4ac.chan_config != hdr_info.chan_config ||
- ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) {
- ac->oc[1].m4ac.sbr = -1;
- ac->oc[1].m4ac.ps = -1;
- }
- if (!hdr_info.crc_absent)
- skip_bits(gb, 16);
- }
- return size;
-}
-
-static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame_ptr, GetBitContext *gb)
-{
- AACDecContext *ac = avctx->priv_data;
- const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
- ChannelElement *che;
- int err, i;
- int samples = m4ac->frame_length_short ? 960 : 1024;
- int chan_config = m4ac->chan_config;
- int aot = m4ac->object_type;
-
- if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD)
- samples >>= 1;
-
- ac->frame = frame;
-
- if ((err = frame_configure_elements(avctx)) < 0)
- return err;
-
- // The AV_PROFILE_AAC_* defines are all object_type - 1
- // This may lead to an undefined profile being signaled
- ac->avctx->profile = aot - 1;
-
- ac->tags_mapped = 0;
-
- if (chan_config < 0 || (chan_config >= 8 && chan_config < 11) || chan_config >= 13) {
- avpriv_request_sample(avctx, "Unknown ER channel configuration %d",
- chan_config);
- return AVERROR_INVALIDDATA;
- }
- for (i = 0; i < ff_tags_per_config[chan_config]; i++) {
- const int elem_type = ff_aac_channel_layout_map[chan_config-1][i][0];
- const int elem_id = ff_aac_channel_layout_map[chan_config-1][i][1];
- if (!(che=get_che(ac, elem_type, elem_id))) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "channel element %d.%d is not allocated\n",
- elem_type, elem_id);
- return AVERROR_INVALIDDATA;
- }
- che->present = 1;
- if (aot != AOT_ER_AAC_ELD)
- skip_bits(gb, 4);
- switch (elem_type) {
- case TYPE_SCE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- break;
- case TYPE_CPE:
- err = decode_cpe(ac, gb, che);
- break;
- case TYPE_LFE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- break;
- }
- if (err < 0)
- return err;
- }
-
- spectral_to_sample(ac, samples);
-
- if (!ac->frame->data[0] && samples) {
- av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
- return AVERROR_INVALIDDATA;
- }
-
- ac->frame->nb_samples = samples;
- ac->frame->sample_rate = avctx->sample_rate;
- *got_frame_ptr = 1;
-
- skip_bits_long(gb, get_bits_left(gb));
- return 0;
-}
-
-static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame_ptr, GetBitContext *gb,
- const AVPacket *avpkt)
-{
- AACDecContext *ac = avctx->priv_data;
- ChannelElement *che = NULL, *che_prev = NULL;
- enum RawDataBlockType elem_type, che_prev_type = TYPE_END;
- int err, elem_id;
- int samples = 0, multiplier, audio_found = 0, pce_found = 0;
- int is_dmono, sce_count = 0;
- int payload_alignment;
- uint8_t che_presence[4][MAX_ELEM_ID] = {{0}};
-
- ac->frame = frame;
-
- if (show_bits(gb, 12) == 0xfff) {
- if ((err = parse_adts_frame_header(ac, gb)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n");
- goto fail;
- }
- if (ac->oc[1].m4ac.sampling_index > 12) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->oc[1].m4ac.sampling_index);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
-
- if ((err = frame_configure_elements(avctx)) < 0)
- goto fail;
-
- // The AV_PROFILE_AAC_* defines are all object_type - 1
- // This may lead to an undefined profile being signaled
- ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
-
- payload_alignment = get_bits_count(gb);
- ac->tags_mapped = 0;
- // parse
- while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
- elem_id = get_bits(gb, 4);
-
- if (avctx->debug & FF_DEBUG_STARTCODE)
- av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id);
-
- if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- if (elem_type < TYPE_DSE) {
- if (che_presence[elem_type][elem_id]) {
- int error = che_presence[elem_type][elem_id] > 1;
- av_log(ac->avctx, error ? AV_LOG_ERROR : AV_LOG_DEBUG, "channel element %d.%d duplicate\n",
- elem_type, elem_id);
- if (error) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
- che_presence[elem_type][elem_id]++;
-
- if (!(che=get_che(ac, elem_type, elem_id))) {
- av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
- elem_type, elem_id);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- samples = ac->oc[1].m4ac.frame_length_short ? 960 : 1024;
- che->present = 1;
- }
-
- switch (elem_type) {
-
- case TYPE_SCE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- audio_found = 1;
- sce_count++;
- break;
-
- case TYPE_CPE:
- err = decode_cpe(ac, gb, che);
- audio_found = 1;
- break;
-
- case TYPE_CCE:
- err = ac->proc.decode_cce(ac, gb, che);
- break;
-
- case TYPE_LFE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- audio_found = 1;
- break;
-
- case TYPE_DSE:
- err = skip_data_stream_element(ac, gb);
- break;
-
- case TYPE_PCE: {
- uint8_t layout_map[MAX_ELEM_ID*4][3] = {{0}};
- int tags;
-
- int pushed = push_output_configuration(ac);
- if (pce_found && !pushed) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- tags = decode_pce(avctx, &ac->oc[1].m4ac, layout_map, gb,
- payload_alignment);
- if (tags < 0) {
- err = tags;
- break;
- }
- if (pce_found) {
- av_log(avctx, AV_LOG_ERROR,
- "Not evaluating a further program_config_element as this construct is dubious at best.\n");
- pop_output_configuration(ac);
- } else {
- err = output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1);
- if (!err)
- ac->oc[1].m4ac.chan_config = 0;
- pce_found = 1;
- }
- break;
- }
-
- case TYPE_FIL:
- if (elem_id == 15)
- elem_id += get_bits(gb, 8) - 1;
- if (get_bits_left(gb) < 8 * elem_id) {
- av_log(avctx, AV_LOG_ERROR, "TYPE_FIL: "overread_err);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- err = 0;
- while (elem_id > 0) {
- int ret = decode_extension_payload(ac, gb, elem_id, che_prev, che_prev_type);
- if (ret < 0) {
- err = ret;
- break;
- }
- elem_id -= ret;
- }
- break;
-
- default:
- err = AVERROR_BUG; /* should not happen, but keeps compiler happy */
- break;
- }
-
- if (elem_type < TYPE_DSE) {
- che_prev = che;
- che_prev_type = elem_type;
- }
-
- if (err)
- goto fail;
-
- if (get_bits_left(gb) < 3) {
- av_log(avctx, AV_LOG_ERROR, overread_err);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
-
- if (!avctx->ch_layout.nb_channels) {
- *got_frame_ptr = 0;
- return 0;
- }
-
- multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0;
- samples <<= multiplier;
-
- spectral_to_sample(ac, samples);
-
- if (ac->oc[1].status && audio_found) {
- avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier;
- avctx->frame_size = samples;
- ac->oc[1].status = OC_LOCKED;
- }
-
- if (!ac->frame->data[0] && samples) {
- av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- if (samples) {
- ac->frame->nb_samples = samples;
- ac->frame->sample_rate = avctx->sample_rate;
- } else
- av_frame_unref(ac->frame);
- *got_frame_ptr = !!samples;
-
- /* for dual-mono audio (SCE + SCE) */
- is_dmono = ac->dmono_mode && sce_count == 2 &&
- !av_channel_layout_compare(&ac->oc[1].ch_layout,
- &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
- if (is_dmono) {
- if (ac->dmono_mode == 1)
- frame->data[1] = frame->data[0];
- else if (ac->dmono_mode == 2)
- frame->data[0] = frame->data[1];
- }
-
- return 0;
-fail:
- pop_output_configuration(ac);
- return err;
-}
-
-static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame_ptr, AVPacket *avpkt)
-{
- AACDecContext *ac = avctx->priv_data;
- const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
- GetBitContext gb;
- int buf_consumed;
- int buf_offset;
- int err;
- size_t new_extradata_size;
- const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
- AV_PKT_DATA_NEW_EXTRADATA,
- &new_extradata_size);
- size_t jp_dualmono_size;
- const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt,
- AV_PKT_DATA_JP_DUALMONO,
- &jp_dualmono_size);
-
- if (new_extradata) {
- /* discard previous configuration */
- ac->oc[1].status = OC_NONE;
- err = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
- new_extradata,
- new_extradata_size * 8LL, 1);
- if (err < 0) {
- return err;
- }
- }
-
- ac->dmono_mode = 0;
- if (jp_dualmono && jp_dualmono_size > 0)
- ac->dmono_mode = 1 + *jp_dualmono;
- if (ac->force_dmono_mode >= 0)
- ac->dmono_mode = ac->force_dmono_mode;
-
- if (INT_MAX / 8 <= buf_size)
- return AVERROR_INVALIDDATA;
-
- if ((err = init_get_bits8(&gb, buf, buf_size)) < 0)
- return err;
-
- switch (ac->oc[1].m4ac.object_type) {
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_LD:
- case AOT_ER_AAC_ELD:
- err = aac_decode_er_frame(avctx, frame, got_frame_ptr, &gb);
- break;
- default:
- err = aac_decode_frame_int(avctx, frame, got_frame_ptr, &gb, avpkt);
- }
- if (err < 0)
- return err;
-
- buf_consumed = (get_bits_count(&gb) + 7) >> 3;
- for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++)
- if (buf[buf_offset])
- break;
-
- return buf_size > buf_offset ? buf_consumed : buf_size;
-}
-
-#include "libavcodec/aac/aacdec_latm.h"
-
-const FFCodec ff_aac_decoder = {
- .p.name = "aac",
- CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
- .p.type = AVMEDIA_TYPE_AUDIO,
- .p.id = AV_CODEC_ID_AAC,
- .p.priv_class = &ff_aac_decoder_class,
- .priv_data_size = sizeof(AACDecContext),
- .init = aac_decode_init,
- .close = ff_aac_decode_close,
- FF_CODEC_DECODE_CB(aac_decode_frame),
- .p.sample_fmts = (const enum AVSampleFormat[]) {
- AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
- },
- .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
- .p.ch_layouts = ff_aac_ch_layout,
- .flush = flush,
- .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
-};
-
-const FFCodec ff_aac_fixed_decoder = {
- .p.name = "aac_fixed",
- CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
- .p.type = AVMEDIA_TYPE_AUDIO,
- .p.id = AV_CODEC_ID_AAC,
- .p.priv_class = &ff_aac_decoder_class,
- .priv_data_size = sizeof(AACDecContext),
- .init = aac_decode_init_fixed,
- .close = ff_aac_decode_close,
- FF_CODEC_DECODE_CB(aac_decode_frame),
- .p.sample_fmts = (const enum AVSampleFormat[]) {
- AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE
- },
- .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
- .p.ch_layouts = ff_aac_ch_layout,
- .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
- .flush = flush,
-};
--
2.43.0.381.gb435a96ce8
[-- Attachment #6: 0034-aacdec-move-aacdec.h-into-libavcodec-aac.patch --]
[-- Type: text/x-diff, Size: 4911 bytes --]
From f3b6a28cc1115d1e5b3fadc3b51be770645144de Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Tue, 19 Mar 2024 20:19:06 +0100
Subject: [PATCH 34/38] aacdec: move aacdec.h into libavcodec/aac
---
libavcodec/aac/aacdec.c | 2 +-
libavcodec/{ => aac}/aacdec.h | 4 ++--
libavcodec/aac/aacdec_dsp_template.c | 2 +-
libavcodec/aac/aacdec_fixed.c | 2 +-
libavcodec/aac/aacdec_fixed_coupling.h | 2 +-
libavcodec/aac/aacdec_float.c | 2 +-
libavcodec/aac/aacdec_float_coupling.h | 2 +-
libavcodec/aacdec.c | 2 +-
libavcodec/aacsbr.h | 2 +-
libavcodec/aacsbr_template.c | 2 +-
10 files changed, 11 insertions(+), 11 deletions(-)
rename libavcodec/{ => aac}/aacdec.h (99%)
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 3af0e808fd..dfbc309583 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -34,7 +34,7 @@
#include "libavcodec/aac.h"
#include "libavcodec/aacsbr.h"
-#include "libavcodec/aacdec.h"
+#include "aacdec.h"
#include "libavcodec/avcodec.h"
#include "libavutil/attributes.h"
#include "libavutil/error.h"
diff --git a/libavcodec/aacdec.h b/libavcodec/aac/aacdec.h
similarity index 99%
rename from libavcodec/aacdec.h
rename to libavcodec/aac/aacdec.h
index 3d15cef453..3b411e2be6 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aac/aacdec.h
@@ -38,8 +38,8 @@
#include "libavutil/mem_internal.h"
#include "libavutil/tx.h"
-#include "aac.h"
-#include "mpeg4audio.h"
+#include "libavcodec/aac.h"
+#include "libavcodec/mpeg4audio.h"
typedef struct AACDecContext AACDecContext;
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index f260d32e4a..a42b40f674 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -29,7 +29,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "libavcodec/aacdec.h"
+#include "aacdec.h"
#include "libavcodec/lpc_functions.h"
#include "libavcodec/aactab.h"
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index d706cfcc92..a65ba19137 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -36,7 +36,7 @@
#include "libavcodec/aac_defines.h"
#include "libavcodec/avcodec.h"
-#include "libavcodec/aacdec.h"
+#include "aacdec.h"
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin_fixed_tablegen.h"
#include "libavcodec/kbdwin.h"
diff --git a/libavcodec/aac/aacdec_fixed_coupling.h b/libavcodec/aac/aacdec_fixed_coupling.h
index 4a3dc3d9b1..1e15e71f0a 100644
--- a/libavcodec/aac/aacdec_fixed_coupling.h
+++ b/libavcodec/aac/aacdec_fixed_coupling.h
@@ -32,7 +32,7 @@
#ifndef AVCODEC_AAC_AACDEC_FIXED_COUPLING
#define AVCODEC_AAC_AACDEC_FIXED_COUPLING
-#include "libavcodec/aacdec.h"
+#include "aacdec.h"
/**
* Apply dependent channel coupling (applied before IMDCT).
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index 6801085098..f0e69579f5 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -36,7 +36,7 @@
#include "libavcodec/aac_defines.h"
#include "libavcodec/avcodec.h"
-#include "libavcodec/aacdec.h"
+#include "aacdec.h"
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin.h"
#include "libavcodec/kbdwin.h"
diff --git a/libavcodec/aac/aacdec_float_coupling.h b/libavcodec/aac/aacdec_float_coupling.h
index 8171750115..1832fa747d 100644
--- a/libavcodec/aac/aacdec_float_coupling.h
+++ b/libavcodec/aac/aacdec_float_coupling.h
@@ -32,7 +32,7 @@
#ifndef AVCODEC_AAC_AACDEC_FLOAT_COUPLING
#define AVCODEC_AAC_AACDEC_FLOAT_COUPLING
-#include "libavcodec/aacdec.h"
+#include "aacdec.h"
/**
* Apply dependent channel coupling (applied before IMDCT).
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 6542f8e527..666e0c89db 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -42,7 +42,7 @@
#include "sinewin.h"
#include "aac.h"
-#include "aacdec.h"
+#include "aac/aacdec.h"
#include "aactab.h"
#include "aac/aacdec_tab.h"
#include "adts_header.h"
diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h
index 41ac53acea..cd030aa801 100644
--- a/libavcodec/aacsbr.h
+++ b/libavcodec/aacsbr.h
@@ -30,7 +30,7 @@
#define AVCODEC_AACSBR_H
#include "get_bits.h"
-#include "aacdec.h"
+#include "aac/aacdec.h"
#include "aac_defines.h"
#include "libavutil/attributes_internal.h"
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index 8bc2605db8..a7469eb92b 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -32,7 +32,7 @@
* @author Zoran Basaric ( zoran.basaric@imgtec.com )
*/
-#include "aacdec.h"
+#include "aac/aacdec.h"
#include "aac/aacdec_tab.h"
#include "avcodec.h"
#include "libavutil/qsort.h"
--
2.43.0.381.gb435a96ce8
[-- Attachment #7: 0033-aacdec-merge-previously-templated-code.patch --]
[-- Type: text/x-diff, Size: 178191 bytes --]
From 01aa46b8abd6c26db0f67a374b681cf35fb5106d Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 23:36:20 +0100
Subject: [PATCH 33/38] aacdec: merge previously-templated code
---
libavcodec/aacdec.c | 2389 ++++++++++++++++++++++++++++++++-
libavcodec/aacdec_template.c | 2430 ----------------------------------
2 files changed, 2388 insertions(+), 2431 deletions(-)
delete mode 100644 libavcodec/aacdec_template.c
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index bf1b1c29c7..6542f8e527 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -63,7 +63,2394 @@
# include "mips/aacdec_mips.h"
#endif
-#include "aacdec_template.c"
+/*
+ * supported tools
+ *
+ * Support? Name
+ * N (code in SoC repo) gain control
+ * Y block switching
+ * Y window shapes - standard
+ * N window shapes - Low Delay
+ * Y filterbank - standard
+ * N (code in SoC repo) filterbank - Scalable Sample Rate
+ * Y Temporal Noise Shaping
+ * Y Long Term Prediction
+ * Y intensity stereo
+ * Y channel coupling
+ * Y frequency domain prediction
+ * Y Perceptual Noise Substitution
+ * Y Mid/Side stereo
+ * N Scalable Inverse AAC Quantization
+ * N Frequency Selective Switch
+ * N upsampling filter
+ * Y quantization & coding - AAC
+ * N quantization & coding - TwinVQ
+ * N quantization & coding - BSAC
+ * N AAC Error Resilience tools
+ * N Error Resilience payload syntax
+ * N Error Protection tool
+ * N CELP
+ * N Silence Compression
+ * N HVXC
+ * N HVXC 4kbits/s VR
+ * N Structured Audio tools
+ * N Structured Audio Sample Bank Format
+ * N MIDI
+ * N Harmonic and Individual Lines plus Noise
+ * N Text-To-Speech Interface
+ * Y Spectral Band Replication
+ * Y (not in this code) Layer-1
+ * Y (not in this code) Layer-2
+ * Y (not in this code) Layer-3
+ * N SinuSoidal Coding (Transient, Sinusoid, Noise)
+ * Y Parametric Stereo
+ * N Direct Stream Transfer
+ * Y (not in fixed point code) Enhanced AAC Low Delay (ER AAC ELD)
+ *
+ * Note: - HE AAC v1 comprises LC AAC with Spectral Band Replication.
+ * - HE AAC v2 comprises LC AAC with Spectral Band Replication and
+ Parametric Stereo.
+ */
+
+#include "libavutil/channel_layout.h"
+#include "libavutil/thread.h"
+#include "decode.h"
+#include "internal.h"
+#include "lpc_functions.h"
+
+static int output_configure(AACDecContext *ac,
+ uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
+ enum OCStatus oc_type, int get_new_frame);
+
+#define overread_err "Input buffer exhausted before END element found\n"
+
+static int count_channels(uint8_t (*layout)[3], int tags)
+{
+ int i, sum = 0;
+ for (i = 0; i < tags; i++) {
+ int syn_ele = layout[i][0];
+ int pos = layout[i][2];
+ sum += (1 + (syn_ele == TYPE_CPE)) *
+ (pos != AAC_CHANNEL_OFF && pos != AAC_CHANNEL_CC);
+ }
+ return sum;
+}
+
+/**
+ * Check for the channel element in the current channel position configuration.
+ * If it exists, make sure the appropriate element is allocated and map the
+ * channel order to match the internal FFmpeg channel layout.
+ *
+ * @param che_pos current channel position configuration
+ * @param type channel element type
+ * @param id channel element id
+ * @param channels count of the number of channels in the configuration
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static av_cold int che_configure(AACDecContext *ac,
+ enum ChannelPosition che_pos,
+ int type, int id, int *channels)
+{
+ if (*channels >= MAX_CHANNELS)
+ return AVERROR_INVALIDDATA;
+ if (che_pos) {
+ if (!ac->che[type][id]) {
+ int ret;
+ if (ac->is_fixed)
+ ret = ff_aac_sbr_ctx_alloc_init_fixed(ac, &ac->che[type][id], type);
+ else
+ ret = ff_aac_sbr_ctx_alloc_init(ac, &ac->che[type][id], type);
+ if (ret < 0)
+ return ret;
+ }
+ if (type != TYPE_CCE) {
+ if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) {
+ av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n");
+ return AVERROR_INVALIDDATA;
+ }
+ ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0];
+ if (type == TYPE_CPE ||
+ (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
+ ac->output_element[(*channels)++] = &ac->che[type][id]->ch[1];
+ }
+ }
+ } else {
+ if (ac->che[type][id]) {
+ if (ac->is_fixed)
+ ff_aac_sbr_ctx_close_fixed(ac->che[type][id]);
+ else
+ ff_aac_sbr_ctx_close(ac->che[type][id]);
+ }
+ av_freep(&ac->che[type][id]);
+ }
+ return 0;
+}
+
+static int frame_configure_elements(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int type, id, ch, ret;
+
+ /* set channel pointers to internal buffers by default */
+ for (type = 0; type < 4; type++) {
+ for (id = 0; id < MAX_ELEM_ID; id++) {
+ ChannelElement *che = ac->che[type][id];
+ if (che) {
+ che->ch[0].AAC_RENAME(output) = che->ch[0].AAC_RENAME(ret_buf);
+ che->ch[1].AAC_RENAME(output) = che->ch[1].AAC_RENAME(ret_buf);
+ }
+ }
+ }
+
+ /* get output buffer */
+ av_frame_unref(ac->frame);
+ if (!avctx->ch_layout.nb_channels)
+ return 1;
+
+ ac->frame->nb_samples = 2048;
+ if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
+ return ret;
+
+ /* map output channel pointers to AVFrame data */
+ for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
+ if (ac->output_element[ch])
+ ac->output_element[ch]->AAC_RENAME(output) = (INTFLOAT *)ac->frame->extended_data[ch];
+ }
+
+ return 0;
+}
+
+struct elem_to_channel {
+ uint64_t av_position;
+ uint8_t syn_ele;
+ uint8_t elem_id;
+ uint8_t aac_position;
+};
+
+static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID],
+ uint8_t (*layout_map)[3], int offset, uint64_t left,
+ uint64_t right, int pos, uint64_t *layout)
+{
+ if (layout_map[offset][0] == TYPE_CPE) {
+ e2c_vec[offset] = (struct elem_to_channel) {
+ .av_position = left | right,
+ .syn_ele = TYPE_CPE,
+ .elem_id = layout_map[offset][1],
+ .aac_position = pos
+ };
+ if (e2c_vec[offset].av_position != UINT64_MAX)
+ *layout |= e2c_vec[offset].av_position;
+
+ return 1;
+ } else {
+ e2c_vec[offset] = (struct elem_to_channel) {
+ .av_position = left,
+ .syn_ele = TYPE_SCE,
+ .elem_id = layout_map[offset][1],
+ .aac_position = pos
+ };
+ e2c_vec[offset + 1] = (struct elem_to_channel) {
+ .av_position = right,
+ .syn_ele = TYPE_SCE,
+ .elem_id = layout_map[offset + 1][1],
+ .aac_position = pos
+ };
+ if (left != UINT64_MAX)
+ *layout |= left;
+
+ if (right != UINT64_MAX)
+ *layout |= right;
+
+ return 2;
+ }
+}
+
+static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
+ int current)
+{
+ int num_pos_channels = 0;
+ int first_cpe = 0;
+ int sce_parity = 0;
+ int i;
+ for (i = current; i < tags; i++) {
+ if (layout_map[i][2] != pos)
+ break;
+ if (layout_map[i][0] == TYPE_CPE) {
+ if (sce_parity) {
+ if (pos == AAC_CHANNEL_FRONT && !first_cpe) {
+ sce_parity = 0;
+ } else {
+ return -1;
+ }
+ }
+ num_pos_channels += 2;
+ first_cpe = 1;
+ } else {
+ num_pos_channels++;
+ sce_parity ^= (pos != AAC_CHANNEL_LFE);
+ }
+ }
+ if (sce_parity &&
+ (pos == AAC_CHANNEL_FRONT && first_cpe))
+ return -1;
+
+ return num_pos_channels;
+}
+
+static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t (*layout_map)[3],
+ uint64_t *layout, int tags, int layer, int pos, int *current)
+{
+ int i = *current, j = 0;
+ int nb_channels = count_paired_channels(layout_map, tags, pos, i);
+
+ if (nb_channels < 0 || nb_channels > 5)
+ return 0;
+
+ if (pos == AAC_CHANNEL_LFE) {
+ while (nb_channels) {
+ if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE)
+ return -1;
+ e2c_vec[i] = (struct elem_to_channel) {
+ .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][j],
+ .syn_ele = layout_map[i][0],
+ .elem_id = layout_map[i][1],
+ .aac_position = pos
+ };
+ *layout |= e2c_vec[i].av_position;
+ i++;
+ j++;
+ nb_channels--;
+ }
+ *current = i;
+
+ return 0;
+ }
+
+ while (nb_channels & 1) {
+ if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE)
+ return -1;
+ if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED)
+ break;
+ e2c_vec[i] = (struct elem_to_channel) {
+ .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][0],
+ .syn_ele = layout_map[i][0],
+ .elem_id = layout_map[i][1],
+ .aac_position = pos
+ };
+ *layout |= e2c_vec[i].av_position;
+ i++;
+ nb_channels--;
+ }
+
+ j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1;
+ while (nb_channels >= 2) {
+ if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE ||
+ ff_aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE)
+ return -1;
+ i += assign_pair(e2c_vec, layout_map, i,
+ 1ULL << ff_aac_channel_map[layer][pos - 1][j],
+ 1ULL << ff_aac_channel_map[layer][pos - 1][j+1],
+ pos, layout);
+ j += 2;
+ nb_channels -= 2;
+ }
+ while (nb_channels & 1) {
+ if (ff_aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE)
+ return -1;
+ e2c_vec[i] = (struct elem_to_channel) {
+ .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][5],
+ .syn_ele = layout_map[i][0],
+ .elem_id = layout_map[i][1],
+ .aac_position = pos
+ };
+ *layout |= e2c_vec[i].av_position;
+ i++;
+ nb_channels--;
+ }
+ if (nb_channels)
+ return -1;
+
+ *current = i;
+
+ return 0;
+}
+
+static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
+{
+ int i, n, total_non_cc_elements;
+ struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
+ uint64_t layout = 0;
+
+ if (FF_ARRAY_ELEMS(e2c_vec) < tags)
+ return 0;
+
+ for (n = 0, i = 0; n < 3 && i < tags; n++) {
+ int ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_FRONT, &i);
+ if (ret < 0)
+ return 0;
+ ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_SIDE, &i);
+ if (ret < 0)
+ return 0;
+ ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_BACK, &i);
+ if (ret < 0)
+ return 0;
+ ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_LFE, &i);
+ if (ret < 0)
+ return 0;
+ }
+
+ total_non_cc_elements = n = i;
+
+ if (layout == AV_CH_LAYOUT_22POINT2) {
+ // For 22.2 reorder the result as needed
+ FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[0]); // FL & FR first (final), FC third
+ FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[1]); // FC second (final), FLc & FRc third
+ FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[2]); // LFE1 third (final), FLc & FRc seventh
+ FFSWAP(struct elem_to_channel, e2c_vec[4], e2c_vec[3]); // BL & BR fourth (final), SiL & SiR fifth
+ FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[4]); // FLc & FRc fifth (final), SiL & SiR seventh
+ FFSWAP(struct elem_to_channel, e2c_vec[7], e2c_vec[6]); // LFE2 seventh (final), SiL & SiR eight (final)
+ FFSWAP(struct elem_to_channel, e2c_vec[9], e2c_vec[8]); // TpFL & TpFR ninth (final), TFC tenth (final)
+ FFSWAP(struct elem_to_channel, e2c_vec[11], e2c_vec[10]); // TC eleventh (final), TpSiL & TpSiR twelth
+ FFSWAP(struct elem_to_channel, e2c_vec[12], e2c_vec[11]); // TpBL & TpBR twelth (final), TpSiL & TpSiR thirteenth (final)
+ } else {
+ // For everything else, utilize the AV channel position define as a
+ // stable sort.
+ do {
+ int next_n = 0;
+ for (i = 1; i < n; i++)
+ if (e2c_vec[i - 1].av_position > e2c_vec[i].av_position) {
+ FFSWAP(struct elem_to_channel, e2c_vec[i - 1], e2c_vec[i]);
+ next_n = i;
+ }
+ n = next_n;
+ } while (n > 0);
+
+ }
+
+ for (i = 0; i < total_non_cc_elements; i++) {
+ layout_map[i][0] = e2c_vec[i].syn_ele;
+ layout_map[i][1] = e2c_vec[i].elem_id;
+ layout_map[i][2] = e2c_vec[i].aac_position;
+ }
+
+ return layout;
+}
+
+/**
+ * Save current output configuration if and only if it has been locked.
+ */
+static int push_output_configuration(AACDecContext *ac)
+{
+ int pushed = 0;
+
+ if (ac->oc[1].status == OC_LOCKED || ac->oc[0].status == OC_NONE) {
+ ac->oc[0] = ac->oc[1];
+ pushed = 1;
+ }
+ ac->oc[1].status = OC_NONE;
+ return pushed;
+}
+
+/**
+ * Restore the previous output configuration if and only if the current
+ * configuration is unlocked.
+ */
+static void pop_output_configuration(AACDecContext *ac)
+{
+ if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
+ ac->oc[1] = ac->oc[0];
+ ac->avctx->ch_layout = ac->oc[1].ch_layout;
+ output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
+ ac->oc[1].status, 0);
+ }
+}
+
+/**
+ * Configure output channel order based on the current program
+ * configuration element.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int output_configure(AACDecContext *ac,
+ uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags,
+ enum OCStatus oc_type, int get_new_frame)
+{
+ AVCodecContext *avctx = ac->avctx;
+ int i, channels = 0, ret;
+ uint64_t layout = 0;
+ uint8_t id_map[TYPE_END][MAX_ELEM_ID] = {{ 0 }};
+ uint8_t type_counts[TYPE_END] = { 0 };
+
+ if (ac->oc[1].layout_map != layout_map) {
+ memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0]));
+ ac->oc[1].layout_map_tags = tags;
+ }
+ for (i = 0; i < tags; i++) {
+ int type = layout_map[i][0];
+ int id = layout_map[i][1];
+ id_map[type][id] = type_counts[type]++;
+ if (id_map[type][id] >= MAX_ELEM_ID) {
+ avpriv_request_sample(ac->avctx, "Too large remapped id");
+ return AVERROR_PATCHWELCOME;
+ }
+ }
+ // Try to sniff a reasonable channel order, otherwise output the
+ // channels in the order the PCE declared them.
+ if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT)
+ layout = sniff_channel_order(layout_map, tags);
+ for (i = 0; i < tags; i++) {
+ int type = layout_map[i][0];
+ int id = layout_map[i][1];
+ int iid = id_map[type][id];
+ int position = layout_map[i][2];
+ // Allocate or free elements depending on if they are in the
+ // current program configuration.
+ ret = che_configure(ac, position, type, iid, &channels);
+ if (ret < 0)
+ return ret;
+ ac->tag_che_map[type][id] = ac->che[type][iid];
+ }
+ if (ac->oc[1].m4ac.ps == 1 && channels == 2) {
+ if (layout == AV_CH_FRONT_CENTER) {
+ layout = AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT;
+ } else {
+ layout = 0;
+ }
+ }
+
+ av_channel_layout_uninit(&ac->oc[1].ch_layout);
+ if (layout)
+ av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
+ else {
+ ac->oc[1].ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
+ ac->oc[1].ch_layout.nb_channels = channels;
+ }
+
+ av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
+ ac->oc[1].status = oc_type;
+
+ if (get_new_frame) {
+ if ((ret = frame_configure_elements(ac->avctx)) < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void flush(AVCodecContext *avctx)
+{
+ AACDecContext *ac= avctx->priv_data;
+ int type, i, j;
+
+ for (type = 3; type >= 0; type--) {
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *che = ac->che[type][i];
+ if (che) {
+ for (j = 0; j <= 1; j++) {
+ memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Set up channel positions based on a default channel configuration
+ * as specified in table 1.17.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int set_default_channel_config(AACDecContext *ac, AVCodecContext *avctx,
+ uint8_t (*layout_map)[3],
+ int *tags,
+ int channel_config)
+{
+ if (channel_config < 1 || (channel_config > 7 && channel_config < 11) ||
+ channel_config > 14) {
+ av_log(avctx, AV_LOG_ERROR,
+ "invalid default channel configuration (%d)\n",
+ channel_config);
+ return AVERROR_INVALIDDATA;
+ }
+ *tags = ff_tags_per_config[channel_config];
+ memcpy(layout_map, ff_aac_channel_layout_map[channel_config - 1],
+ *tags * sizeof(*layout_map));
+
+ /*
+ * AAC specification has 7.1(wide) as a default layout for 8-channel streams.
+ * However, at least Nero AAC encoder encodes 7.1 streams using the default
+ * channel config 7, mapping the side channels of the original audio stream
+ * to the second AAC_CHANNEL_FRONT pair in the AAC stream. Similarly, e.g. FAAD
+ * decodes the second AAC_CHANNEL_FRONT pair as side channels, therefore decoding
+ * the incorrect streams as if they were correct (and as the encoder intended).
+ *
+ * As actual intended 7.1(wide) streams are very rare, default to assuming a
+ * 7.1 layout was intended.
+ */
+ if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) {
+ layout_map[2][2] = AAC_CHANNEL_BACK;
+
+ if (!ac || !ac->warned_71_wide++) {
+ av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout"
+ " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode"
+ " according to the specification instead.\n", FF_COMPLIANCE_STRICT);
+ }
+ }
+
+ return 0;
+}
+
+static ChannelElement *get_che(AACDecContext *ac, int type, int elem_id)
+{
+ /* For PCE based channel configurations map the channels solely based
+ * on tags. */
+ if (!ac->oc[1].m4ac.chan_config) {
+ return ac->tag_che_map[type][elem_id];
+ }
+ // Allow single CPE stereo files to be signalled with mono configuration.
+ if (!ac->tags_mapped && type == TYPE_CPE &&
+ ac->oc[1].m4ac.chan_config == 1) {
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int layout_map_tags;
+ push_output_configuration(ac);
+
+ av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n");
+
+ if (set_default_channel_config(ac, ac->avctx, layout_map,
+ &layout_map_tags, 2) < 0)
+ return NULL;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ OC_TRIAL_FRAME, 1) < 0)
+ return NULL;
+
+ ac->oc[1].m4ac.chan_config = 2;
+ ac->oc[1].m4ac.ps = 0;
+ }
+ // And vice-versa
+ if (!ac->tags_mapped && type == TYPE_SCE &&
+ ac->oc[1].m4ac.chan_config == 2) {
+ uint8_t layout_map[MAX_ELEM_ID * 4][3];
+ int layout_map_tags;
+ push_output_configuration(ac);
+
+ av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n");
+
+ layout_map_tags = 2;
+ layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
+ layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
+ layout_map[0][1] = 0;
+ layout_map[1][1] = 1;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ OC_TRIAL_FRAME, 1) < 0)
+ return NULL;
+
+ if (ac->oc[1].m4ac.sbr)
+ ac->oc[1].m4ac.ps = -1;
+ }
+ /* For indexed channel configurations map the channels solely based
+ * on position. */
+ switch (ac->oc[1].m4ac.chan_config) {
+ case 14:
+ if (ac->tags_mapped > 2 && ((type == TYPE_CPE && elem_id < 3) ||
+ (type == TYPE_LFE && elem_id < 1))) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
+ }
+ case 13:
+ if (ac->tags_mapped > 3 && ((type == TYPE_CPE && elem_id < 8) ||
+ (type == TYPE_SCE && elem_id < 6) ||
+ (type == TYPE_LFE && elem_id < 2))) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
+ }
+ case 12:
+ case 7:
+ if (ac->tags_mapped == 3 && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
+ }
+ case 11:
+ if (ac->tags_mapped == 3 && type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 6:
+ /* Some streams incorrectly code 5.1 audio as
+ * SCE[0] CPE[0] CPE[1] SCE[1]
+ * instead of
+ * SCE[0] CPE[0] CPE[1] LFE[0].
+ * If we seem to have encountered such a stream, transfer
+ * the LFE[0] element to the SCE[1]'s mapping */
+ if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
+ if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) {
+ av_log(ac->avctx, AV_LOG_WARNING,
+ "This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n",
+ type == TYPE_SCE ? "SCE" : "LFE", elem_id);
+ ac->warned_remapping_once++;
+ }
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
+ }
+ case 5:
+ if (ac->tags_mapped == 2 && type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
+ }
+ case 4:
+ /* Some streams incorrectly code 4.0 audio as
+ * SCE[0] CPE[0] LFE[0]
+ * instead of
+ * SCE[0] CPE[0] SCE[1].
+ * If we seem to have encountered such a stream, transfer
+ * the SCE[1] element to the LFE[0]'s mapping */
+ if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
+ if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) {
+ av_log(ac->avctx, AV_LOG_WARNING,
+ "This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n",
+ type == TYPE_SCE ? "SCE" : "LFE", elem_id);
+ ac->warned_remapping_once++;
+ }
+ ac->tags_mapped++;
+ return ac->tag_che_map[type][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ if (ac->tags_mapped == 2 &&
+ ac->oc[1].m4ac.chan_config == 4 &&
+ type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 3:
+ case 2:
+ if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) &&
+ type == TYPE_CPE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0];
+ } else if (ac->tags_mapped == 1 && ac->oc[1].m4ac.chan_config == 2 &&
+ type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
+ }
+ case 1:
+ if (!ac->tags_mapped && type == TYPE_SCE) {
+ ac->tags_mapped++;
+ return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
+ }
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Decode an array of 4 bit element IDs, optionally interleaved with a
+ * stereo/mono switching bit.
+ *
+ * @param type speaker type/position for these channels
+ */
+static void decode_channel_map(uint8_t layout_map[][3],
+ enum ChannelPosition type,
+ GetBitContext *gb, int n)
+{
+ while (n--) {
+ enum RawDataBlockType syn_ele;
+ switch (type) {
+ case AAC_CHANNEL_FRONT:
+ case AAC_CHANNEL_BACK:
+ case AAC_CHANNEL_SIDE:
+ syn_ele = get_bits1(gb);
+ break;
+ case AAC_CHANNEL_CC:
+ skip_bits1(gb);
+ syn_ele = TYPE_CCE;
+ break;
+ case AAC_CHANNEL_LFE:
+ syn_ele = TYPE_LFE;
+ break;
+ default:
+ // AAC_CHANNEL_OFF has no channel map
+ av_assert0(0);
+ }
+ layout_map[0][0] = syn_ele;
+ layout_map[0][1] = get_bits(gb, 4);
+ layout_map[0][2] = type;
+ layout_map++;
+ }
+}
+
+static inline void relative_align_get_bits(GetBitContext *gb,
+ int reference_position) {
+ int n = (reference_position - get_bits_count(gb) & 7);
+ if (n)
+ skip_bits(gb, n);
+}
+
+/**
+ * Decode program configuration element; reference: table 4.2.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
+ uint8_t (*layout_map)[3],
+ GetBitContext *gb, int byte_align_ref)
+{
+ int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc;
+ int sampling_index;
+ int comment_len;
+ int tags;
+
+ skip_bits(gb, 2); // object_type
+
+ sampling_index = get_bits(gb, 4);
+ if (m4ac->sampling_index != sampling_index)
+ av_log(avctx, AV_LOG_WARNING,
+ "Sample rate index in program config element does not "
+ "match the sample rate index configured by the container.\n");
+
+ num_front = get_bits(gb, 4);
+ num_side = get_bits(gb, 4);
+ num_back = get_bits(gb, 4);
+ num_lfe = get_bits(gb, 2);
+ num_assoc_data = get_bits(gb, 3);
+ num_cc = get_bits(gb, 4);
+
+ if (get_bits1(gb))
+ skip_bits(gb, 4); // mono_mixdown_tag
+ if (get_bits1(gb))
+ skip_bits(gb, 4); // stereo_mixdown_tag
+
+ if (get_bits1(gb))
+ skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
+
+ if (get_bits_left(gb) < 5 * (num_front + num_side + num_back + num_cc) + 4 *(num_lfe + num_assoc_data + num_cc)) {
+ av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
+ return -1;
+ }
+ decode_channel_map(layout_map , AAC_CHANNEL_FRONT, gb, num_front);
+ tags = num_front;
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE, gb, num_side);
+ tags += num_side;
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK, gb, num_back);
+ tags += num_back;
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE, gb, num_lfe);
+ tags += num_lfe;
+
+ skip_bits_long(gb, 4 * num_assoc_data);
+
+ decode_channel_map(layout_map + tags, AAC_CHANNEL_CC, gb, num_cc);
+ tags += num_cc;
+
+ relative_align_get_bits(gb, byte_align_ref);
+
+ /* comment field, first byte is length */
+ comment_len = get_bits(gb, 8) * 8;
+ if (get_bits_left(gb) < comment_len) {
+ av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ skip_bits_long(gb, comment_len);
+ return tags;
+}
+
+/**
+ * Decode GA "General Audio" specific configuration; reference: table 4.1.
+ *
+ * @param ac pointer to AACDecContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_ga_specific_config(AACDecContext *ac, AVCodecContext *avctx,
+ GetBitContext *gb,
+ int get_bit_alignment,
+ MPEG4AudioConfig *m4ac,
+ int channel_config)
+{
+ int extension_flag, ret, ep_config, res_flags;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ 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
+ extension_flag = get_bits1(gb);
+
+ if (m4ac->object_type == AOT_AAC_SCALABLE ||
+ m4ac->object_type == AOT_ER_AAC_SCALABLE)
+ skip_bits(gb, 3); // layerNr
+
+ if (channel_config == 0) {
+ skip_bits(gb, 4); // element_instance_tag
+ tags = decode_pce(avctx, m4ac, layout_map, gb, get_bit_alignment);
+ if (tags < 0)
+ return tags;
+ } else {
+ if ((ret = set_default_channel_config(ac, avctx, layout_map,
+ &tags, channel_config)))
+ return ret;
+ }
+
+ if (count_channels(layout_map, tags) > 1) {
+ m4ac->ps = 0;
+ } else if (m4ac->sbr == 1 && m4ac->ps == -1)
+ m4ac->ps = 1;
+
+ if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
+ return ret;
+
+ if (extension_flag) {
+ switch (m4ac->object_type) {
+ case AOT_ER_BSAC:
+ skip_bits(gb, 5); // numOfSubFrame
+ skip_bits(gb, 11); // layer_length
+ break;
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_SCALABLE:
+ case AOT_ER_AAC_LD:
+ res_flags = get_bits(gb, 3);
+ if (res_flags) {
+ avpriv_report_missing_feature(avctx,
+ "AAC data resilience (flags %x)",
+ res_flags);
+ return AVERROR_PATCHWELCOME;
+ }
+ break;
+ }
+ skip_bits1(gb); // extensionFlag3 (TBD in version 3)
+ }
+ switch (m4ac->object_type) {
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_SCALABLE:
+ case AOT_ER_AAC_LD:
+ ep_config = get_bits(gb, 2);
+ if (ep_config) {
+ avpriv_report_missing_feature(avctx,
+ "epConfig %d", ep_config);
+ return AVERROR_PATCHWELCOME;
+ }
+ }
+ return 0;
+}
+
+static int decode_eld_specific_config(AACDecContext *ac, AVCodecContext *avctx,
+ GetBitContext *gb,
+ MPEG4AudioConfig *m4ac,
+ int channel_config)
+{
+ int ret, ep_config, res_flags;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int tags = 0;
+ const int ELDEXT_TERM = 0;
+
+ m4ac->ps = 0;
+ m4ac->sbr = 0;
+ m4ac->frame_length_short = get_bits1(gb);
+
+ res_flags = get_bits(gb, 3);
+ if (res_flags) {
+ avpriv_report_missing_feature(avctx,
+ "AAC data resilience (flags %x)",
+ res_flags);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ if (get_bits1(gb)) { // ldSbrPresentFlag
+ avpriv_report_missing_feature(avctx,
+ "Low Delay SBR");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ while (get_bits(gb, 4) != ELDEXT_TERM) {
+ int len = get_bits(gb, 4);
+ if (len == 15)
+ len += get_bits(gb, 8);
+ if (len == 15 + 255)
+ len += get_bits(gb, 16);
+ if (get_bits_left(gb) < len * 8 + 4) {
+ av_log(avctx, AV_LOG_ERROR, overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ skip_bits_long(gb, 8 * len);
+ }
+
+ if ((ret = set_default_channel_config(ac, avctx, layout_map,
+ &tags, channel_config)))
+ return ret;
+
+ if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
+ return ret;
+
+ ep_config = get_bits(gb, 2);
+ if (ep_config) {
+ avpriv_report_missing_feature(avctx,
+ "epConfig %d", ep_config);
+ return AVERROR_PATCHWELCOME;
+ }
+ return 0;
+}
+
+/**
+ * Decode audio specific configuration; reference: table 1.13.
+ *
+ * @param ac pointer to AACDecContext, may be null
+ * @param avctx pointer to AVCCodecContext, used for logging
+ * @param m4ac pointer to MPEG4AudioConfig, used for parsing
+ * @param gb buffer holding an audio specific config
+ * @param get_bit_alignment relative alignment for byte align operations
+ * @param sync_extension look for an appended sync extension
+ *
+ * @return Returns error status or number of consumed bits. <0 - error
+ */
+static int decode_audio_specific_config_gb(AACDecContext *ac,
+ AVCodecContext *avctx,
+ MPEG4AudioConfig *m4ac,
+ GetBitContext *gb,
+ int get_bit_alignment,
+ int sync_extension)
+{
+ int i, ret;
+ GetBitContext gbc = *gb;
+ MPEG4AudioConfig m4ac_bak = *m4ac;
+
+ if ((i = ff_mpeg4audio_get_config_gb(m4ac, &gbc, sync_extension, avctx)) < 0) {
+ *m4ac = m4ac_bak;
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (m4ac->sampling_index > 12) {
+ av_log(avctx, AV_LOG_ERROR,
+ "invalid sampling rate index %d\n",
+ m4ac->sampling_index);
+ *m4ac = m4ac_bak;
+ 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);
+ *m4ac = m4ac_bak;
+ return AVERROR_INVALIDDATA;
+ }
+
+ skip_bits_long(gb, i);
+
+ switch (m4ac->object_type) {
+ case AOT_AAC_MAIN:
+ case AOT_AAC_LC:
+ case AOT_AAC_SSR:
+ case AOT_AAC_LTP:
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LD:
+ if ((ret = decode_ga_specific_config(ac, avctx, gb, get_bit_alignment,
+ m4ac, m4ac->chan_config)) < 0)
+ return ret;
+ break;
+ case AOT_ER_AAC_ELD:
+ if ((ret = decode_eld_specific_config(ac, avctx, gb,
+ m4ac, m4ac->chan_config)) < 0)
+ return ret;
+ break;
+ default:
+ avpriv_report_missing_feature(avctx,
+ "Audio object type %s%d",
+ m4ac->sbr == 1 ? "SBR+" : "",
+ m4ac->object_type);
+ return AVERROR(ENOSYS);
+ }
+
+ ff_dlog(avctx,
+ "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
+ m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
+ m4ac->sample_rate, m4ac->sbr,
+ m4ac->ps);
+
+ return get_bits_count(gb);
+}
+
+static int decode_audio_specific_config(AACDecContext *ac,
+ AVCodecContext *avctx,
+ MPEG4AudioConfig *m4ac,
+ const uint8_t *data, int64_t bit_size,
+ int sync_extension)
+{
+ int i, ret;
+ GetBitContext gb;
+
+ if (bit_size < 0 || bit_size > INT_MAX) {
+ av_log(avctx, AV_LOG_ERROR, "Audio specific config size is invalid\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ ff_dlog(avctx, "audio specific config size %d\n", (int)bit_size >> 3);
+ for (i = 0; i < bit_size >> 3; i++)
+ ff_dlog(avctx, "%02x ", data[i]);
+ ff_dlog(avctx, "\n");
+
+ if ((ret = init_get_bits(&gb, data, bit_size)) < 0)
+ return ret;
+
+ return decode_audio_specific_config_gb(ac, avctx, m4ac, &gb, 0,
+ sync_extension);
+}
+
+static int sample_rate_idx (int rate)
+{
+ if (92017 <= rate) return 0;
+ else if (75132 <= rate) return 1;
+ else if (55426 <= rate) return 2;
+ else if (46009 <= rate) return 3;
+ else if (37566 <= rate) return 4;
+ else if (27713 <= rate) return 5;
+ else if (23004 <= rate) return 6;
+ else if (18783 <= rate) return 7;
+ else if (13856 <= rate) return 8;
+ else if (11502 <= rate) return 9;
+ else if (9391 <= rate) return 10;
+ else return 11;
+}
+
+static av_cold void aac_static_table_init(void)
+{
+ ff_aac_sbr_init();
+ ff_aac_sbr_init_fixed();
+
+ ff_aacdec_common_init_once();
+}
+
+static AVOnce aac_table_init = AV_ONCE_INIT;
+
+static av_cold int aac_decode_init_internal(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int ret;
+
+ if (avctx->sample_rate > 96000)
+ return AVERROR_INVALIDDATA;
+
+ ret = ff_thread_once(&aac_table_init, &aac_static_table_init);
+ if (ret != 0)
+ return AVERROR_UNKNOWN;
+
+ ac->avctx = avctx;
+ ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
+
+ if (ac->is_fixed)
+ avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
+ else
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
+
+ if (avctx->extradata_size > 0) {
+ if ((ret = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
+ avctx->extradata,
+ avctx->extradata_size * 8LL,
+ 1)) < 0)
+ return ret;
+ } else {
+ int sr, i;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int layout_map_tags;
+
+ sr = sample_rate_idx(avctx->sample_rate);
+ ac->oc[1].m4ac.sampling_index = sr;
+ ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels;
+ ac->oc[1].m4ac.sbr = -1;
+ ac->oc[1].m4ac.ps = -1;
+
+ for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
+ if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels)
+ break;
+ if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
+ i = 0;
+ }
+ ac->oc[1].m4ac.chan_config = i;
+
+ if (ac->oc[1].m4ac.chan_config) {
+ int ret = set_default_channel_config(ac, avctx, layout_map,
+ &layout_map_tags, ac->oc[1].m4ac.chan_config);
+ if (!ret)
+ output_configure(ac, layout_map, layout_map_tags,
+ OC_GLOBAL_HDR, 0);
+ else if (avctx->err_recognition & AV_EF_EXPLODE)
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
+ return ff_aac_decode_init_common(avctx);
+}
+
+static av_cold int aac_decode_init(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ac->is_fixed = 0;
+ return aac_decode_init_internal(avctx);
+}
+
+static av_cold int aac_decode_init_fixed(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ac->is_fixed = 1;
+ return aac_decode_init_internal(avctx);
+}
+
+/**
+ * Skip data_stream_element; reference: table 4.10.
+ */
+static int skip_data_stream_element(AACDecContext *ac, GetBitContext *gb)
+{
+ int byte_align = get_bits1(gb);
+ int count = get_bits(gb, 8);
+ if (count == 255)
+ count += get_bits(gb, 8);
+ if (byte_align)
+ align_get_bits(gb);
+
+ if (get_bits_left(gb) < 8 * count) {
+ av_log(ac->avctx, AV_LOG_ERROR, "skip_data_stream_element: "overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ skip_bits_long(gb, 8 * count);
+ return 0;
+}
+
+static int decode_prediction(AACDecContext *ac, IndividualChannelStream *ics,
+ GetBitContext *gb)
+{
+ int sfb;
+ if (get_bits1(gb)) {
+ ics->predictor_reset_group = get_bits(gb, 5);
+ if (ics->predictor_reset_group == 0 ||
+ ics->predictor_reset_group > 30) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Invalid Predictor Reset Group.\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]); sfb++) {
+ ics->prediction_used[sfb] = get_bits1(gb);
+ }
+ return 0;
+}
+
+/**
+ * Decode Long Term Prediction data; reference: table 4.xx.
+ */
+static void decode_ltp(AACDecContext *ac, LongTermPrediction *ltp,
+ GetBitContext *gb, uint8_t max_sfb)
+{
+ int sfb;
+
+ ltp->lag = get_bits(gb, 11);
+ if (ac->is_fixed)
+ ltp->coef_fixed = Q30(ff_ltp_coef[get_bits(gb, 3)]);
+ else
+ ltp->coef = ff_ltp_coef[get_bits(gb, 3)];
+
+ for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ ltp->used[sfb] = get_bits1(gb);
+}
+
+/**
+ * Decode Individual Channel Stream info; reference: table 4.6.
+ */
+static int decode_ics_info(AACDecContext *ac, IndividualChannelStream *ics,
+ GetBitContext *gb)
+{
+ const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
+ const int aot = m4ac->object_type;
+ const int sampling_index = m4ac->sampling_index;
+ int ret_fail = AVERROR_INVALIDDATA;
+
+ if (aot != AOT_ER_AAC_ELD) {
+ if (get_bits1(gb)) {
+ av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n");
+ if (ac->avctx->err_recognition & AV_EF_BITSTREAM)
+ return AVERROR_INVALIDDATA;
+ }
+ ics->window_sequence[1] = ics->window_sequence[0];
+ ics->window_sequence[0] = get_bits(gb, 2);
+ if (aot == 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;
+ ics->group_len[0] = 1;
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ int i;
+ ics->max_sfb = get_bits(gb, 4);
+ for (i = 0; i < 7; i++) {
+ if (get_bits1(gb)) {
+ ics->group_len[ics->num_window_groups - 1]++;
+ } else {
+ ics->num_window_groups++;
+ ics->group_len[ics->num_window_groups - 1] = 1;
+ }
+ }
+ ics->num_windows = 8;
+ 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 {
+ ics->max_sfb = get_bits(gb, 6);
+ ics->num_windows = 1;
+ if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) {
+ if (m4ac->frame_length_short) {
+ ics->swb_offset = ff_swb_offset_480[sampling_index];
+ ics->num_swb = ff_aac_num_swb_480[sampling_index];
+ ics->tns_max_bands = ff_tns_max_bands_480[sampling_index];
+ } else {
+ ics->swb_offset = ff_swb_offset_512[sampling_index];
+ ics->num_swb = ff_aac_num_swb_512[sampling_index];
+ ics->tns_max_bands = ff_tns_max_bands_512[sampling_index];
+ }
+ if (!ics->num_swb || !ics->swb_offset) {
+ ret_fail = AVERROR_BUG;
+ goto fail;
+ }
+ } else {
+ 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) {
+ ics->predictor_present = get_bits1(gb);
+ ics->predictor_reset_group = 0;
+ }
+ if (ics->predictor_present) {
+ if (aot == AOT_AAC_MAIN) {
+ if (decode_prediction(ac, ics, gb)) {
+ goto fail;
+ }
+ } else if (aot == AOT_AAC_LC ||
+ aot == AOT_ER_AAC_LC) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Prediction is not allowed in AAC-LC.\n");
+ goto fail;
+ } else {
+ if (aot == AOT_ER_AAC_LD) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "LTP in ER AAC LD not yet implemented.\n");
+ ret_fail = AVERROR_PATCHWELCOME;
+ goto fail;
+ }
+ if ((ics->ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
+ }
+ }
+ }
+
+ if (ics->max_sfb > ics->num_swb) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Number of scalefactor bands in group (%d) "
+ "exceeds limit (%d).\n",
+ ics->max_sfb, ics->num_swb);
+ goto fail;
+ }
+
+ return 0;
+fail:
+ ics->max_sfb = 0;
+ return ret_fail;
+}
+
+/**
+ * Decode band types (section_data payload); reference: table 4.46.
+ *
+ * @param band_type array of the used band type
+ * @param band_type_run_end array of the last scalefactor band of a band type run
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_band_types(AACDecContext *ac, enum BandType band_type[120],
+ int band_type_run_end[120], GetBitContext *gb,
+ IndividualChannelStream *ics)
+{
+ int g, idx = 0;
+ const int bits = (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) ? 3 : 5;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ int k = 0;
+ while (k < ics->max_sfb) {
+ uint8_t sect_end = k;
+ int sect_len_incr;
+ int sect_band_type = get_bits(gb, 4);
+ if (sect_band_type == 12) {
+ av_log(ac->avctx, AV_LOG_ERROR, "invalid band type\n");
+ return AVERROR_INVALIDDATA;
+ }
+ do {
+ sect_len_incr = get_bits(gb, bits);
+ sect_end += sect_len_incr;
+ if (get_bits_left(gb) < 0) {
+ av_log(ac->avctx, AV_LOG_ERROR, "decode_band_types: "overread_err);
+ return AVERROR_INVALIDDATA;
+ }
+ if (sect_end > ics->max_sfb) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Number of bands (%d) exceeds limit (%d).\n",
+ sect_end, ics->max_sfb);
+ return AVERROR_INVALIDDATA;
+ }
+ } while (sect_len_incr == (1 << bits) - 1);
+ for (; k < sect_end; k++) {
+ band_type [idx] = sect_band_type;
+ band_type_run_end[idx++] = sect_end;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Decode scalefactors; reference: table 4.47.
+ *
+ * @param global_gain first scalefactor value as scalefactors are differentially coded
+ * @param band_type array of the used band type
+ * @param band_type_run_end array of the last scalefactor band of a band type run
+ * @param sf array of scalefactors or intensity stereo positions
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_scalefactors(AACDecContext *ac, int sfo[120],
+ GetBitContext *gb,
+ unsigned int global_gain,
+ IndividualChannelStream *ics,
+ enum BandType band_type[120],
+ int band_type_run_end[120])
+{
+ int g, i, idx = 0;
+ int offset[3] = { global_gain, global_gain - NOISE_OFFSET, 0 };
+ int clipped_offset;
+ int noise_flag = 1;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb;) {
+ int run_end = band_type_run_end[idx];
+ switch (band_type[idx]) {
+ case ZERO_BT:
+ for (; i < run_end; i++, idx++)
+ sfo[idx] = 0;
+ break;
+ case INTENSITY_BT: /* fallthrough */
+ case INTENSITY_BT2:
+ for (; i < run_end; i++, idx++) {
+ offset[2] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
+ clipped_offset = av_clip(offset[2], -155, 100);
+ if (offset[2] != clipped_offset) {
+ avpriv_request_sample(ac->avctx,
+ "If you heard an audible artifact, there may be a bug in the decoder. "
+ "Clipped intensity stereo position (%d -> %d)",
+ offset[2], clipped_offset);
+ }
+ sfo[idx] = clipped_offset;
+ }
+ break;
+ case NOISE_BT:
+ for (; i < run_end; i++, idx++) {
+ if (noise_flag-- > 0)
+ offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE;
+ else
+ offset[1] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
+ clipped_offset = av_clip(offset[1], -100, 155);
+ if (offset[1] != clipped_offset) {
+ avpriv_request_sample(ac->avctx,
+ "If you heard an audible artifact, there may be a bug in the decoder. "
+ "Clipped noise gain (%d -> %d)",
+ offset[1], clipped_offset);
+ }
+ sfo[idx] = clipped_offset;
+ }
+ break;
+ default:
+ for (; i < run_end; i++, idx++) {
+ offset[0] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
+ if (offset[0] > 255U) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Scalefactor (%d) out of range.\n", offset[0]);
+ return AVERROR_INVALIDDATA;
+ }
+ sfo[idx] = offset[0];
+ }
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Decode pulse data; reference: table 4.7.
+ */
+static int decode_pulses(Pulse *pulse, GetBitContext *gb,
+ const uint16_t *swb_offset, int num_swb)
+{
+ int i, pulse_swb;
+ pulse->num_pulse = get_bits(gb, 2) + 1;
+ pulse_swb = get_bits(gb, 6);
+ if (pulse_swb >= num_swb)
+ return -1;
+ pulse->pos[0] = swb_offset[pulse_swb];
+ pulse->pos[0] += get_bits(gb, 5);
+ if (pulse->pos[0] >= swb_offset[num_swb])
+ return -1;
+ pulse->amp[0] = get_bits(gb, 4);
+ for (i = 1; i < pulse->num_pulse; i++) {
+ pulse->pos[i] = get_bits(gb, 5) + pulse->pos[i - 1];
+ if (pulse->pos[i] >= swb_offset[num_swb])
+ return -1;
+ pulse->amp[i] = get_bits(gb, 4);
+ }
+ return 0;
+}
+
+/**
+ * Decode Temporal Noise Shaping data; reference: table 4.48.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
+ GetBitContext *gb, const IndividualChannelStream *ics)
+{
+ int w, filt, i, coef_len, coef_res, coef_compress;
+ const int is8 = ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE;
+ const int tns_max_order = is8 ? 7 : ac->oc[1].m4ac.object_type == AOT_AAC_MAIN ? 20 : 12;
+ for (w = 0; w < ics->num_windows; w++) {
+ if ((tns->n_filt[w] = get_bits(gb, 2 - is8))) {
+ coef_res = get_bits1(gb);
+
+ for (filt = 0; filt < tns->n_filt[w]; filt++) {
+ int tmp2_idx;
+ tns->length[w][filt] = get_bits(gb, 6 - 2 * is8);
+
+ if ((tns->order[w][filt] = get_bits(gb, 5 - 2 * is8)) > tns_max_order) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "TNS filter order %d is greater than maximum %d.\n",
+ tns->order[w][filt], tns_max_order);
+ tns->order[w][filt] = 0;
+ return AVERROR_INVALIDDATA;
+ }
+ if (tns->order[w][filt]) {
+ tns->direction[w][filt] = get_bits1(gb);
+ coef_compress = get_bits1(gb);
+ coef_len = coef_res + 3 - coef_compress;
+ tmp2_idx = 2 * coef_compress + coef_res;
+
+ for (i = 0; i < tns->order[w][filt]; i++) {
+ if (ac->is_fixed)
+ tns->coef_fixed[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
+ else
+ tns->coef[w][filt][i] = ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)];
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Decode Mid/Side data; reference: table 4.54.
+ *
+ * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
+ * [1] mask is decoded from bitstream; [2] mask is all 1s;
+ * [3] reserved for scalable AAC
+ */
+static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
+ int ms_present)
+{
+ int idx;
+ int max_idx = cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb;
+ if (ms_present == 1) {
+ for (idx = 0; idx < max_idx; idx++)
+ cpe->ms_mask[idx] = get_bits1(gb);
+ } else if (ms_present == 2) {
+ memset(cpe->ms_mask, 1, max_idx * sizeof(cpe->ms_mask[0]));
+ }
+}
+
+static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
+{
+ // wd_num, wd_test, aloc_size
+ static const uint8_t gain_mode[4][3] = {
+ {1, 0, 5}, // ONLY_LONG_SEQUENCE = 0,
+ {2, 1, 2}, // LONG_START_SEQUENCE,
+ {8, 0, 2}, // EIGHT_SHORT_SEQUENCE,
+ {2, 1, 5}, // LONG_STOP_SEQUENCE
+ };
+
+ const int mode = sce->ics.window_sequence[0];
+ uint8_t bd, wd, ad;
+
+ // FIXME: Store the gain control data on |sce| and do something with it.
+ uint8_t max_band = get_bits(gb, 2);
+ for (bd = 0; bd < max_band; bd++) {
+ for (wd = 0; wd < gain_mode[mode][0]; wd++) {
+ uint8_t adjust_num = get_bits(gb, 3);
+ for (ad = 0; ad < adjust_num; ad++) {
+ skip_bits(gb, 4 + ((wd == 0 && gain_mode[mode][1])
+ ? 4
+ : gain_mode[mode][2]));
+ }
+ }
+ }
+}
+
+/**
+ * Decode an individual_channel_stream payload; reference: table 4.44.
+ *
+ * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
+ * @param scale_flag scalable [1] or non-scalable [0] AAC (Unused until scalable AAC is implemented.)
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
+ GetBitContext *gb, int common_window, int scale_flag)
+{
+ Pulse pulse;
+ TemporalNoiseShaping *tns = &sce->tns;
+ IndividualChannelStream *ics = &sce->ics;
+ int global_gain, eld_syntax, er_syntax, pulse_present = 0;
+ int ret;
+
+ eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
+ er_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_LC ||
+ ac->oc[1].m4ac.object_type == AOT_ER_AAC_LTP ||
+ ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD ||
+ ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
+
+ /* This assignment is to silence a GCC warning about the variable being used
+ * uninitialized when in fact it always is.
+ */
+ pulse.num_pulse = 0;
+
+ global_gain = get_bits(gb, 8);
+
+ if (!common_window && !scale_flag) {
+ ret = decode_ics_info(ac, ics, gb);
+ if (ret < 0)
+ goto fail;
+ }
+
+ if ((ret = decode_band_types(ac, sce->band_type,
+ sce->band_type_run_end, gb, ics)) < 0)
+ goto fail;
+ if ((ret = decode_scalefactors(ac, sce->sfo, gb, global_gain, ics,
+ sce->band_type, sce->band_type_run_end)) < 0)
+ goto fail;
+
+ ac->dsp.dequant_scalefactors(sce);
+
+ pulse_present = 0;
+ if (!scale_flag) {
+ if (!eld_syntax && (pulse_present = get_bits1(gb))) {
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Pulse tool not allowed in eight short sequence.\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ if (decode_pulses(&pulse, gb, ics->swb_offset, ics->num_swb)) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Pulse data corrupt or invalid.\n");
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ tns->present = get_bits1(gb);
+ if (tns->present && !er_syntax) {
+ ret = decode_tns(ac, tns, gb, ics);
+ if (ret < 0)
+ goto fail;
+ }
+ if (!eld_syntax && get_bits1(gb)) {
+ decode_gain_control(sce, gb);
+ if (!ac->warned_gain_control) {
+ avpriv_report_missing_feature(ac->avctx, "Gain control");
+ ac->warned_gain_control = 1;
+ }
+ }
+ // I see no textual basis in the spec for this occurring after SSR gain
+ // control, but this is what both reference and real implmentations do
+ if (tns->present && er_syntax) {
+ ret = decode_tns(ac, tns, gb, ics);
+ if (ret < 0)
+ goto fail;
+ }
+ }
+
+ ret = ac->proc.decode_spectrum_and_dequant(ac, gb,
+ pulse_present ? &pulse : NULL,
+ sce);
+ if (ret < 0)
+ goto fail;
+
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window)
+ ac->dsp.apply_prediction(ac, sce);
+
+ return 0;
+fail:
+ tns->present = 0;
+ return ret;
+}
+
+/**
+ * Decode a channel_pair_element; reference: table 4.4.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
+{
+ int i, ret, common_window, ms_present = 0;
+ int eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
+
+ common_window = eld_syntax || get_bits1(gb);
+ if (common_window) {
+ if (decode_ics_info(ac, &cpe->ch[0].ics, gb))
+ return AVERROR_INVALIDDATA;
+ i = cpe->ch[1].ics.use_kb_window[0];
+ cpe->ch[1].ics = cpe->ch[0].ics;
+ cpe->ch[1].ics.use_kb_window[1] = i;
+ if (cpe->ch[1].ics.predictor_present &&
+ (ac->oc[1].m4ac.object_type != AOT_AAC_MAIN))
+ if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
+ decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
+ ms_present = get_bits(gb, 2);
+ if (ms_present == 3) {
+ av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
+ return AVERROR_INVALIDDATA;
+ } else if (ms_present)
+ decode_mid_side_stereo(cpe, gb, ms_present);
+ }
+ if ((ret = ff_aac_decode_ics(ac, &cpe->ch[0], gb, common_window, 0)))
+ return ret;
+ if ((ret = ff_aac_decode_ics(ac, &cpe->ch[1], gb, common_window, 0)))
+ return ret;
+
+ if (common_window) {
+ if (ms_present)
+ ac->dsp.apply_mid_side_stereo(ac, cpe);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) {
+ ac->dsp.apply_prediction(ac, &cpe->ch[0]);
+ ac->dsp.apply_prediction(ac, &cpe->ch[1]);
+ }
+ }
+
+ ac->dsp.apply_intensity_stereo(ac, cpe, ms_present);
+ return 0;
+}
+
+/**
+ * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
+ *
+ * @return Returns number of bytes consumed.
+ */
+static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc,
+ GetBitContext *gb)
+{
+ int i;
+ int num_excl_chan = 0;
+
+ do {
+ for (i = 0; i < 7; i++)
+ che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb);
+ } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb));
+
+ return num_excl_chan / 7;
+}
+
+/**
+ * Decode dynamic range information; reference: table 4.52.
+ *
+ * @return Returns number of bytes consumed.
+ */
+static int decode_dynamic_range(DynamicRangeControl *che_drc,
+ GetBitContext *gb)
+{
+ int n = 1;
+ int drc_num_bands = 1;
+ int i;
+
+ /* pce_tag_present? */
+ if (get_bits1(gb)) {
+ che_drc->pce_instance_tag = get_bits(gb, 4);
+ skip_bits(gb, 4); // tag_reserved_bits
+ n++;
+ }
+
+ /* excluded_chns_present? */
+ if (get_bits1(gb)) {
+ n += decode_drc_channel_exclusions(che_drc, gb);
+ }
+
+ /* drc_bands_present? */
+ if (get_bits1(gb)) {
+ che_drc->band_incr = get_bits(gb, 4);
+ che_drc->interpolation_scheme = get_bits(gb, 4);
+ n++;
+ drc_num_bands += che_drc->band_incr;
+ for (i = 0; i < drc_num_bands; i++) {
+ che_drc->band_top[i] = get_bits(gb, 8);
+ n++;
+ }
+ }
+
+ /* prog_ref_level_present? */
+ if (get_bits1(gb)) {
+ che_drc->prog_ref_level = get_bits(gb, 7);
+ skip_bits1(gb); // prog_ref_level_reserved_bits
+ n++;
+ }
+
+ for (i = 0; i < drc_num_bands; i++) {
+ che_drc->dyn_rng_sgn[i] = get_bits1(gb);
+ che_drc->dyn_rng_ctl[i] = get_bits(gb, 7);
+ n++;
+ }
+
+ return n;
+}
+
+static int decode_fill(AACDecContext *ac, GetBitContext *gb, int len) {
+ uint8_t buf[256];
+ int i, major, minor;
+
+ if (len < 13+7*8)
+ goto unknown;
+
+ get_bits(gb, 13); len -= 13;
+
+ for(i=0; i+1<sizeof(buf) && len>=8; i++, len-=8)
+ buf[i] = get_bits(gb, 8);
+
+ buf[i] = 0;
+ if (ac->avctx->debug & FF_DEBUG_PICT_INFO)
+ av_log(ac->avctx, AV_LOG_DEBUG, "FILL:%s\n", buf);
+
+ if (sscanf(buf, "libfaac %d.%d", &major, &minor) == 2){
+ ac->avctx->internal->skip_samples = 1024;
+ }
+
+unknown:
+ skip_bits_long(gb, len);
+
+ return 0;
+}
+
+/**
+ * Decode extension data (incomplete); reference: table 4.51.
+ *
+ * @param cnt length of TYPE_FIL syntactic element in bytes
+ *
+ * @return Returns number of bytes consumed
+ */
+static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cnt,
+ ChannelElement *che, enum RawDataBlockType elem_type)
+{
+ int crc_flag = 0;
+ int res = cnt;
+ int type = get_bits(gb, 4);
+
+ if (ac->avctx->debug & FF_DEBUG_STARTCODE)
+ av_log(ac->avctx, AV_LOG_DEBUG, "extension type: %d len:%d\n", type, cnt);
+
+ switch (type) { // extension type
+ case EXT_SBR_DATA_CRC:
+ crc_flag++;
+ case EXT_SBR_DATA:
+ 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);
+ return res;
+ } else if (ac->oc[1].m4ac.sbr == -1 && ac->oc[1].status == OC_LOCKED) {
+ av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n");
+ skip_bits_long(gb, 8 * cnt - 4);
+ return res;
+ } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED &&
+ ac->avctx->ch_layout.nb_channels == 1) {
+ ac->oc[1].m4ac.sbr = 1;
+ ac->oc[1].m4ac.ps = 1;
+ ac->avctx->profile = AV_PROFILE_AAC_HE_V2;
+ output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
+ ac->oc[1].status, 1);
+ } else {
+ ac->oc[1].m4ac.sbr = 1;
+ ac->avctx->profile = AV_PROFILE_AAC_HE;
+ }
+
+ if (ac->is_fixed)
+ res = ff_aac_sbr_decode_extension_fixed(ac, che, gb, crc_flag, cnt, elem_type);
+ else
+ res = ff_aac_sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
+
+
+ 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");
+ ac->warned_he_aac_mono = 1;
+ }
+ break;
+ case EXT_DYNAMIC_RANGE:
+ res = decode_dynamic_range(&ac->che_drc, gb);
+ break;
+ case EXT_FILL:
+ decode_fill(ac, gb, 8 * cnt - 4);
+ break;
+ case EXT_FILL_DATA:
+ case EXT_DATA_ELEMENT:
+ default:
+ skip_bits_long(gb, 8 * cnt - 4);
+ break;
+ };
+ return res;
+}
+
+/**
+ * channel coupling transformation interface
+ *
+ * @param apply_coupling_method pointer to (in)dependent coupling function
+ */
+static void apply_channel_coupling(AACDecContext *ac, ChannelElement *cc,
+ enum RawDataBlockType type, int elem_id,
+ enum CouplingPoint coupling_point,
+ void (*apply_coupling_method)(AACDecContext *ac, SingleChannelElement *target, ChannelElement *cce, int index))
+{
+ int i, c;
+
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *cce = ac->che[TYPE_CCE][i];
+ int index = 0;
+
+ if (cce && cce->coup.coupling_point == coupling_point) {
+ ChannelCoupling *coup = &cce->coup;
+
+ for (c = 0; c <= coup->num_coupled; c++) {
+ if (coup->type[c] == type && coup->id_select[c] == elem_id) {
+ if (coup->ch_select[c] != 1) {
+ apply_coupling_method(ac, &cc->ch[0], cce, index);
+ if (coup->ch_select[c] != 0)
+ index++;
+ }
+ if (coup->ch_select[c] != 2)
+ apply_coupling_method(ac, &cc->ch[1], cce, index++);
+ } else
+ index += 1 + (coup->ch_select[c] == 3);
+ }
+ }
+ }
+}
+
+/**
+ * Convert spectral data to samples, applying all supported tools as appropriate.
+ */
+static void spectral_to_sample(AACDecContext *ac, int samples)
+{
+ int i, type;
+ void (*imdct_and_window)(AACDecContext *ac, SingleChannelElement *sce);
+ switch (ac->oc[1].m4ac.object_type) {
+ case AOT_ER_AAC_LD:
+ imdct_and_window = ac->dsp.imdct_and_windowing_ld;
+ break;
+ case AOT_ER_AAC_ELD:
+ imdct_and_window = ac->dsp.imdct_and_windowing_eld;
+ break;
+ default:
+ if (ac->oc[1].m4ac.frame_length_short)
+ imdct_and_window = ac->dsp.imdct_and_windowing_960;
+ else
+ imdct_and_window = ac->dsp.imdct_and_windowing;
+ }
+ for (type = 3; type >= 0; type--) {
+ for (i = 0; i < MAX_ELEM_ID; i++) {
+ ChannelElement *che = ac->che[type][i];
+ if (che && che->present) {
+ if (type <= TYPE_CPE)
+ apply_channel_coupling(ac, che, type, i, BEFORE_TNS, ac->dsp.apply_dependent_coupling);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
+ if (che->ch[0].ics.predictor_present) {
+ if (che->ch[0].ics.ltp.present)
+ ac->dsp.apply_ltp(ac, &che->ch[0]);
+ if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
+ ac->dsp.apply_ltp(ac, &che->ch[1]);
+ }
+ }
+ if (che->ch[0].tns.present)
+ ac->dsp.apply_tns(che->ch[0].AAC_RENAME(coeffs),
+ &che->ch[0].tns, &che->ch[0].ics, 1);
+ if (che->ch[1].tns.present)
+ ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
+ &che->ch[1].tns, &che->ch[1].ics, 1);
+ if (type <= TYPE_CPE)
+ apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling);
+ if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
+ imdct_and_window(ac, &che->ch[0]);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
+ ac->dsp.update_ltp(ac, &che->ch[0]);
+ if (type == TYPE_CPE) {
+ imdct_and_window(ac, &che->ch[1]);
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
+ ac->dsp.update_ltp(ac, &che->ch[1]);
+ }
+ if (ac->oc[1].m4ac.sbr > 0) {
+ if (ac->is_fixed)
+ ff_aac_sbr_apply_fixed(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
+ else
+ ff_aac_sbr_apply(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
+ }
+ }
+ if (type <= TYPE_CCE)
+ apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling);
+ ac->dsp.clip_output(ac, che, type, samples);
+ che->present = 0;
+ } else if (che) {
+ av_log(ac->avctx, AV_LOG_VERBOSE, "ChannelElement %d.%d missing \n", type, i);
+ }
+ }
+ }
+}
+
+static int parse_adts_frame_header(AACDecContext *ac, GetBitContext *gb)
+{
+ int size;
+ AACADTSHeaderInfo hdr_info;
+ uint8_t layout_map[MAX_ELEM_ID*4][3];
+ int layout_map_tags, ret;
+
+ size = ff_adts_header_parse(gb, &hdr_info);
+ if (size > 0) {
+ if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
+ // This is 2 for "VLB " audio in NSV files.
+ // See samples/nsv/vlb_audio.
+ avpriv_report_missing_feature(ac->avctx,
+ "More than one AAC RDB per ADTS frame");
+ ac->warned_num_aac_frames = 1;
+ }
+ push_output_configuration(ac);
+ if (hdr_info.chan_config) {
+ ac->oc[1].m4ac.chan_config = hdr_info.chan_config;
+ if ((ret = set_default_channel_config(ac, ac->avctx,
+ layout_map,
+ &layout_map_tags,
+ hdr_info.chan_config)) < 0)
+ return ret;
+ if ((ret = output_configure(ac, layout_map, layout_map_tags,
+ FFMAX(ac->oc[1].status,
+ OC_TRIAL_FRAME), 0)) < 0)
+ return ret;
+ } else {
+ ac->oc[1].m4ac.chan_config = 0;
+ /**
+ * dual mono frames in Japanese DTV can have chan_config 0
+ * WITHOUT specifying PCE.
+ * thus, set dual mono as default.
+ */
+ if (ac->dmono_mode && ac->oc[0].status == OC_NONE) {
+ layout_map_tags = 2;
+ layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
+ layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
+ layout_map[0][1] = 0;
+ layout_map[1][1] = 1;
+ if (output_configure(ac, layout_map, layout_map_tags,
+ OC_TRIAL_FRAME, 0))
+ return -7;
+ }
+ }
+ ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate;
+ ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index;
+ ac->oc[1].m4ac.object_type = hdr_info.object_type;
+ ac->oc[1].m4ac.frame_length_short = 0;
+ if (ac->oc[0].status != OC_LOCKED ||
+ ac->oc[0].m4ac.chan_config != hdr_info.chan_config ||
+ ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) {
+ ac->oc[1].m4ac.sbr = -1;
+ ac->oc[1].m4ac.ps = -1;
+ }
+ if (!hdr_info.crc_absent)
+ skip_bits(gb, 16);
+ }
+ return size;
+}
+
+static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, GetBitContext *gb)
+{
+ AACDecContext *ac = avctx->priv_data;
+ const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
+ ChannelElement *che;
+ int err, i;
+ int samples = m4ac->frame_length_short ? 960 : 1024;
+ int chan_config = m4ac->chan_config;
+ int aot = m4ac->object_type;
+
+ if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD)
+ samples >>= 1;
+
+ ac->frame = frame;
+
+ if ((err = frame_configure_elements(avctx)) < 0)
+ return err;
+
+ // The AV_PROFILE_AAC_* defines are all object_type - 1
+ // This may lead to an undefined profile being signaled
+ ac->avctx->profile = aot - 1;
+
+ ac->tags_mapped = 0;
+
+ if (chan_config < 0 || (chan_config >= 8 && chan_config < 11) || chan_config >= 13) {
+ avpriv_request_sample(avctx, "Unknown ER channel configuration %d",
+ chan_config);
+ return AVERROR_INVALIDDATA;
+ }
+ for (i = 0; i < ff_tags_per_config[chan_config]; i++) {
+ const int elem_type = ff_aac_channel_layout_map[chan_config-1][i][0];
+ const int elem_id = ff_aac_channel_layout_map[chan_config-1][i][1];
+ if (!(che=get_che(ac, elem_type, elem_id))) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "channel element %d.%d is not allocated\n",
+ elem_type, elem_id);
+ return AVERROR_INVALIDDATA;
+ }
+ che->present = 1;
+ if (aot != AOT_ER_AAC_ELD)
+ skip_bits(gb, 4);
+ switch (elem_type) {
+ case TYPE_SCE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ break;
+ case TYPE_CPE:
+ err = decode_cpe(ac, gb, che);
+ break;
+ case TYPE_LFE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ break;
+ }
+ if (err < 0)
+ return err;
+ }
+
+ spectral_to_sample(ac, samples);
+
+ if (!ac->frame->data[0] && samples) {
+ av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ ac->frame->nb_samples = samples;
+ ac->frame->sample_rate = avctx->sample_rate;
+ *got_frame_ptr = 1;
+
+ skip_bits_long(gb, get_bits_left(gb));
+ return 0;
+}
+
+static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, GetBitContext *gb,
+ const AVPacket *avpkt)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ChannelElement *che = NULL, *che_prev = NULL;
+ enum RawDataBlockType elem_type, che_prev_type = TYPE_END;
+ int err, elem_id;
+ int samples = 0, multiplier, audio_found = 0, pce_found = 0;
+ int is_dmono, sce_count = 0;
+ int payload_alignment;
+ uint8_t che_presence[4][MAX_ELEM_ID] = {{0}};
+
+ ac->frame = frame;
+
+ if (show_bits(gb, 12) == 0xfff) {
+ if ((err = parse_adts_frame_header(ac, gb)) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n");
+ goto fail;
+ }
+ if (ac->oc[1].m4ac.sampling_index > 12) {
+ av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->oc[1].m4ac.sampling_index);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+
+ if ((err = frame_configure_elements(avctx)) < 0)
+ goto fail;
+
+ // The AV_PROFILE_AAC_* defines are all object_type - 1
+ // This may lead to an undefined profile being signaled
+ ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
+
+ payload_alignment = get_bits_count(gb);
+ ac->tags_mapped = 0;
+ // parse
+ while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
+ elem_id = get_bits(gb, 4);
+
+ if (avctx->debug & FF_DEBUG_STARTCODE)
+ av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id);
+
+ if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ if (elem_type < TYPE_DSE) {
+ if (che_presence[elem_type][elem_id]) {
+ int error = che_presence[elem_type][elem_id] > 1;
+ av_log(ac->avctx, error ? AV_LOG_ERROR : AV_LOG_DEBUG, "channel element %d.%d duplicate\n",
+ elem_type, elem_id);
+ if (error) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+ che_presence[elem_type][elem_id]++;
+
+ if (!(che=get_che(ac, elem_type, elem_id))) {
+ av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
+ elem_type, elem_id);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ samples = ac->oc[1].m4ac.frame_length_short ? 960 : 1024;
+ che->present = 1;
+ }
+
+ switch (elem_type) {
+
+ case TYPE_SCE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ audio_found = 1;
+ sce_count++;
+ break;
+
+ case TYPE_CPE:
+ err = decode_cpe(ac, gb, che);
+ audio_found = 1;
+ break;
+
+ case TYPE_CCE:
+ err = ac->proc.decode_cce(ac, gb, che);
+ break;
+
+ case TYPE_LFE:
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
+ audio_found = 1;
+ break;
+
+ case TYPE_DSE:
+ err = skip_data_stream_element(ac, gb);
+ break;
+
+ case TYPE_PCE: {
+ uint8_t layout_map[MAX_ELEM_ID*4][3] = {{0}};
+ int tags;
+
+ int pushed = push_output_configuration(ac);
+ if (pce_found && !pushed) {
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ tags = decode_pce(avctx, &ac->oc[1].m4ac, layout_map, gb,
+ payload_alignment);
+ if (tags < 0) {
+ err = tags;
+ break;
+ }
+ if (pce_found) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Not evaluating a further program_config_element as this construct is dubious at best.\n");
+ pop_output_configuration(ac);
+ } else {
+ err = output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1);
+ if (!err)
+ ac->oc[1].m4ac.chan_config = 0;
+ pce_found = 1;
+ }
+ break;
+ }
+
+ case TYPE_FIL:
+ if (elem_id == 15)
+ elem_id += get_bits(gb, 8) - 1;
+ if (get_bits_left(gb) < 8 * elem_id) {
+ av_log(avctx, AV_LOG_ERROR, "TYPE_FIL: "overread_err);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ err = 0;
+ while (elem_id > 0) {
+ int ret = decode_extension_payload(ac, gb, elem_id, che_prev, che_prev_type);
+ if (ret < 0) {
+ err = ret;
+ break;
+ }
+ elem_id -= ret;
+ }
+ break;
+
+ default:
+ err = AVERROR_BUG; /* should not happen, but keeps compiler happy */
+ break;
+ }
+
+ if (elem_type < TYPE_DSE) {
+ che_prev = che;
+ che_prev_type = elem_type;
+ }
+
+ if (err)
+ goto fail;
+
+ if (get_bits_left(gb) < 3) {
+ av_log(avctx, AV_LOG_ERROR, overread_err);
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ }
+
+ if (!avctx->ch_layout.nb_channels) {
+ *got_frame_ptr = 0;
+ return 0;
+ }
+
+ multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0;
+ samples <<= multiplier;
+
+ spectral_to_sample(ac, samples);
+
+ if (ac->oc[1].status && audio_found) {
+ avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier;
+ avctx->frame_size = samples;
+ ac->oc[1].status = OC_LOCKED;
+ }
+
+ if (!ac->frame->data[0] && samples) {
+ av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
+ err = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ if (samples) {
+ ac->frame->nb_samples = samples;
+ ac->frame->sample_rate = avctx->sample_rate;
+ } else
+ av_frame_unref(ac->frame);
+ *got_frame_ptr = !!samples;
+
+ /* for dual-mono audio (SCE + SCE) */
+ is_dmono = ac->dmono_mode && sce_count == 2 &&
+ !av_channel_layout_compare(&ac->oc[1].ch_layout,
+ &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
+ if (is_dmono) {
+ if (ac->dmono_mode == 1)
+ frame->data[1] = frame->data[0];
+ else if (ac->dmono_mode == 2)
+ frame->data[0] = frame->data[1];
+ }
+
+ return 0;
+fail:
+ pop_output_configuration(ac);
+ return err;
+}
+
+static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ AACDecContext *ac = avctx->priv_data;
+ const uint8_t *buf = avpkt->data;
+ int buf_size = avpkt->size;
+ GetBitContext gb;
+ int buf_consumed;
+ int buf_offset;
+ int err;
+ size_t new_extradata_size;
+ const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
+ AV_PKT_DATA_NEW_EXTRADATA,
+ &new_extradata_size);
+ size_t jp_dualmono_size;
+ const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt,
+ AV_PKT_DATA_JP_DUALMONO,
+ &jp_dualmono_size);
+
+ if (new_extradata) {
+ /* discard previous configuration */
+ ac->oc[1].status = OC_NONE;
+ err = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
+ new_extradata,
+ new_extradata_size * 8LL, 1);
+ if (err < 0) {
+ return err;
+ }
+ }
+
+ ac->dmono_mode = 0;
+ if (jp_dualmono && jp_dualmono_size > 0)
+ ac->dmono_mode = 1 + *jp_dualmono;
+ if (ac->force_dmono_mode >= 0)
+ ac->dmono_mode = ac->force_dmono_mode;
+
+ if (INT_MAX / 8 <= buf_size)
+ return AVERROR_INVALIDDATA;
+
+ if ((err = init_get_bits8(&gb, buf, buf_size)) < 0)
+ return err;
+
+ switch (ac->oc[1].m4ac.object_type) {
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_LD:
+ case AOT_ER_AAC_ELD:
+ err = aac_decode_er_frame(avctx, frame, got_frame_ptr, &gb);
+ break;
+ default:
+ err = aac_decode_frame_int(avctx, frame, got_frame_ptr, &gb, avpkt);
+ }
+ if (err < 0)
+ return err;
+
+ buf_consumed = (get_bits_count(&gb) + 7) >> 3;
+ for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++)
+ if (buf[buf_offset])
+ break;
+
+ return buf_size > buf_offset ? buf_consumed : buf_size;
+}
#include "libavcodec/aac/aacdec_latm.h"
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
deleted file mode 100644
index e90c3edff2..0000000000
--- a/libavcodec/aacdec_template.c
+++ /dev/null
@@ -1,2430 +0,0 @@
-/*
- * AAC decoder
- * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
- * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
- * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
- *
- * AAC LATM decoder
- * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
- * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
- *
- * AAC decoder fixed-point implementation
- * Copyright (c) 2013
- * MIPS Technologies, Inc., California.
- *
- * 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
- */
-
-/**
- * @file
- * AAC decoder
- * @author Oded Shimon ( ods15 ods15 dyndns org )
- * @author Maxim Gavrilov ( maxim.gavrilov gmail com )
- *
- * AAC decoder fixed-point implementation
- * @author Stanislav Ocovaj ( stanislav.ocovaj imgtec com )
- * @author Nedeljko Babic ( nedeljko.babic imgtec com )
- */
-
-/*
- * supported tools
- *
- * Support? Name
- * N (code in SoC repo) gain control
- * Y block switching
- * Y window shapes - standard
- * N window shapes - Low Delay
- * Y filterbank - standard
- * N (code in SoC repo) filterbank - Scalable Sample Rate
- * Y Temporal Noise Shaping
- * Y Long Term Prediction
- * Y intensity stereo
- * Y channel coupling
- * Y frequency domain prediction
- * Y Perceptual Noise Substitution
- * Y Mid/Side stereo
- * N Scalable Inverse AAC Quantization
- * N Frequency Selective Switch
- * N upsampling filter
- * Y quantization & coding - AAC
- * N quantization & coding - TwinVQ
- * N quantization & coding - BSAC
- * N AAC Error Resilience tools
- * N Error Resilience payload syntax
- * N Error Protection tool
- * N CELP
- * N Silence Compression
- * N HVXC
- * N HVXC 4kbits/s VR
- * N Structured Audio tools
- * N Structured Audio Sample Bank Format
- * N MIDI
- * N Harmonic and Individual Lines plus Noise
- * N Text-To-Speech Interface
- * Y Spectral Band Replication
- * Y (not in this code) Layer-1
- * Y (not in this code) Layer-2
- * Y (not in this code) Layer-3
- * N SinuSoidal Coding (Transient, Sinusoid, Noise)
- * Y Parametric Stereo
- * N Direct Stream Transfer
- * Y (not in fixed point code) Enhanced AAC Low Delay (ER AAC ELD)
- *
- * Note: - HE AAC v1 comprises LC AAC with Spectral Band Replication.
- * - HE AAC v2 comprises LC AAC with Spectral Band Replication and
- Parametric Stereo.
- */
-
-#include "libavutil/channel_layout.h"
-#include "libavutil/thread.h"
-#include "decode.h"
-#include "internal.h"
-#include "lpc_functions.h"
-
-static int output_configure(AACDecContext *ac,
- uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
- enum OCStatus oc_type, int get_new_frame);
-
-#define overread_err "Input buffer exhausted before END element found\n"
-
-static int count_channels(uint8_t (*layout)[3], int tags)
-{
- int i, sum = 0;
- for (i = 0; i < tags; i++) {
- int syn_ele = layout[i][0];
- int pos = layout[i][2];
- sum += (1 + (syn_ele == TYPE_CPE)) *
- (pos != AAC_CHANNEL_OFF && pos != AAC_CHANNEL_CC);
- }
- return sum;
-}
-
-/**
- * Check for the channel element in the current channel position configuration.
- * If it exists, make sure the appropriate element is allocated and map the
- * channel order to match the internal FFmpeg channel layout.
- *
- * @param che_pos current channel position configuration
- * @param type channel element type
- * @param id channel element id
- * @param channels count of the number of channels in the configuration
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static av_cold int che_configure(AACDecContext *ac,
- enum ChannelPosition che_pos,
- int type, int id, int *channels)
-{
- if (*channels >= MAX_CHANNELS)
- return AVERROR_INVALIDDATA;
- if (che_pos) {
- if (!ac->che[type][id]) {
- int ret;
- if (ac->is_fixed)
- ret = ff_aac_sbr_ctx_alloc_init_fixed(ac, &ac->che[type][id], type);
- else
- ret = ff_aac_sbr_ctx_alloc_init(ac, &ac->che[type][id], type);
- if (ret < 0)
- return ret;
- }
- if (type != TYPE_CCE) {
- if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) {
- av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n");
- return AVERROR_INVALIDDATA;
- }
- ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0];
- if (type == TYPE_CPE ||
- (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
- ac->output_element[(*channels)++] = &ac->che[type][id]->ch[1];
- }
- }
- } else {
- if (ac->che[type][id]) {
- if (ac->is_fixed)
- ff_aac_sbr_ctx_close_fixed(ac->che[type][id]);
- else
- ff_aac_sbr_ctx_close(ac->che[type][id]);
- }
- av_freep(&ac->che[type][id]);
- }
- return 0;
-}
-
-static int frame_configure_elements(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- int type, id, ch, ret;
-
- /* set channel pointers to internal buffers by default */
- for (type = 0; type < 4; type++) {
- for (id = 0; id < MAX_ELEM_ID; id++) {
- ChannelElement *che = ac->che[type][id];
- if (che) {
- che->ch[0].AAC_RENAME(output) = che->ch[0].AAC_RENAME(ret_buf);
- che->ch[1].AAC_RENAME(output) = che->ch[1].AAC_RENAME(ret_buf);
- }
- }
- }
-
- /* get output buffer */
- av_frame_unref(ac->frame);
- if (!avctx->ch_layout.nb_channels)
- return 1;
-
- ac->frame->nb_samples = 2048;
- if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
- return ret;
-
- /* map output channel pointers to AVFrame data */
- for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
- if (ac->output_element[ch])
- ac->output_element[ch]->AAC_RENAME(output) = (INTFLOAT *)ac->frame->extended_data[ch];
- }
-
- return 0;
-}
-
-struct elem_to_channel {
- uint64_t av_position;
- uint8_t syn_ele;
- uint8_t elem_id;
- uint8_t aac_position;
-};
-
-static int assign_pair(struct elem_to_channel e2c_vec[MAX_ELEM_ID],
- uint8_t (*layout_map)[3], int offset, uint64_t left,
- uint64_t right, int pos, uint64_t *layout)
-{
- if (layout_map[offset][0] == TYPE_CPE) {
- e2c_vec[offset] = (struct elem_to_channel) {
- .av_position = left | right,
- .syn_ele = TYPE_CPE,
- .elem_id = layout_map[offset][1],
- .aac_position = pos
- };
- if (e2c_vec[offset].av_position != UINT64_MAX)
- *layout |= e2c_vec[offset].av_position;
-
- return 1;
- } else {
- e2c_vec[offset] = (struct elem_to_channel) {
- .av_position = left,
- .syn_ele = TYPE_SCE,
- .elem_id = layout_map[offset][1],
- .aac_position = pos
- };
- e2c_vec[offset + 1] = (struct elem_to_channel) {
- .av_position = right,
- .syn_ele = TYPE_SCE,
- .elem_id = layout_map[offset + 1][1],
- .aac_position = pos
- };
- if (left != UINT64_MAX)
- *layout |= left;
-
- if (right != UINT64_MAX)
- *layout |= right;
-
- return 2;
- }
-}
-
-static int count_paired_channels(uint8_t (*layout_map)[3], int tags, int pos,
- int current)
-{
- int num_pos_channels = 0;
- int first_cpe = 0;
- int sce_parity = 0;
- int i;
- for (i = current; i < tags; i++) {
- if (layout_map[i][2] != pos)
- break;
- if (layout_map[i][0] == TYPE_CPE) {
- if (sce_parity) {
- if (pos == AAC_CHANNEL_FRONT && !first_cpe) {
- sce_parity = 0;
- } else {
- return -1;
- }
- }
- num_pos_channels += 2;
- first_cpe = 1;
- } else {
- num_pos_channels++;
- sce_parity ^= (pos != AAC_CHANNEL_LFE);
- }
- }
- if (sce_parity &&
- (pos == AAC_CHANNEL_FRONT && first_cpe))
- return -1;
-
- return num_pos_channels;
-}
-
-static int assign_channels(struct elem_to_channel e2c_vec[MAX_ELEM_ID], uint8_t (*layout_map)[3],
- uint64_t *layout, int tags, int layer, int pos, int *current)
-{
- int i = *current, j = 0;
- int nb_channels = count_paired_channels(layout_map, tags, pos, i);
-
- if (nb_channels < 0 || nb_channels > 5)
- return 0;
-
- if (pos == AAC_CHANNEL_LFE) {
- while (nb_channels) {
- if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE)
- return -1;
- e2c_vec[i] = (struct elem_to_channel) {
- .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][j],
- .syn_ele = layout_map[i][0],
- .elem_id = layout_map[i][1],
- .aac_position = pos
- };
- *layout |= e2c_vec[i].av_position;
- i++;
- j++;
- nb_channels--;
- }
- *current = i;
-
- return 0;
- }
-
- while (nb_channels & 1) {
- if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_NONE)
- return -1;
- if (ff_aac_channel_map[layer][pos - 1][0] == AV_CHAN_UNUSED)
- break;
- e2c_vec[i] = (struct elem_to_channel) {
- .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][0],
- .syn_ele = layout_map[i][0],
- .elem_id = layout_map[i][1],
- .aac_position = pos
- };
- *layout |= e2c_vec[i].av_position;
- i++;
- nb_channels--;
- }
-
- j = (pos != AAC_CHANNEL_SIDE) && nb_channels <= 3 ? 3 : 1;
- while (nb_channels >= 2) {
- if (ff_aac_channel_map[layer][pos - 1][j] == AV_CHAN_NONE ||
- ff_aac_channel_map[layer][pos - 1][j+1] == AV_CHAN_NONE)
- return -1;
- i += assign_pair(e2c_vec, layout_map, i,
- 1ULL << ff_aac_channel_map[layer][pos - 1][j],
- 1ULL << ff_aac_channel_map[layer][pos - 1][j+1],
- pos, layout);
- j += 2;
- nb_channels -= 2;
- }
- while (nb_channels & 1) {
- if (ff_aac_channel_map[layer][pos - 1][5] == AV_CHAN_NONE)
- return -1;
- e2c_vec[i] = (struct elem_to_channel) {
- .av_position = 1ULL << ff_aac_channel_map[layer][pos - 1][5],
- .syn_ele = layout_map[i][0],
- .elem_id = layout_map[i][1],
- .aac_position = pos
- };
- *layout |= e2c_vec[i].av_position;
- i++;
- nb_channels--;
- }
- if (nb_channels)
- return -1;
-
- *current = i;
-
- return 0;
-}
-
-static uint64_t sniff_channel_order(uint8_t (*layout_map)[3], int tags)
-{
- int i, n, total_non_cc_elements;
- struct elem_to_channel e2c_vec[4 * MAX_ELEM_ID] = { { 0 } };
- uint64_t layout = 0;
-
- if (FF_ARRAY_ELEMS(e2c_vec) < tags)
- return 0;
-
- for (n = 0, i = 0; n < 3 && i < tags; n++) {
- int ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_FRONT, &i);
- if (ret < 0)
- return 0;
- ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_SIDE, &i);
- if (ret < 0)
- return 0;
- ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_BACK, &i);
- if (ret < 0)
- return 0;
- ret = assign_channels(e2c_vec, layout_map, &layout, tags, n, AAC_CHANNEL_LFE, &i);
- if (ret < 0)
- return 0;
- }
-
- total_non_cc_elements = n = i;
-
- if (layout == AV_CH_LAYOUT_22POINT2) {
- // For 22.2 reorder the result as needed
- FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[0]); // FL & FR first (final), FC third
- FFSWAP(struct elem_to_channel, e2c_vec[2], e2c_vec[1]); // FC second (final), FLc & FRc third
- FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[2]); // LFE1 third (final), FLc & FRc seventh
- FFSWAP(struct elem_to_channel, e2c_vec[4], e2c_vec[3]); // BL & BR fourth (final), SiL & SiR fifth
- FFSWAP(struct elem_to_channel, e2c_vec[6], e2c_vec[4]); // FLc & FRc fifth (final), SiL & SiR seventh
- FFSWAP(struct elem_to_channel, e2c_vec[7], e2c_vec[6]); // LFE2 seventh (final), SiL & SiR eight (final)
- FFSWAP(struct elem_to_channel, e2c_vec[9], e2c_vec[8]); // TpFL & TpFR ninth (final), TFC tenth (final)
- FFSWAP(struct elem_to_channel, e2c_vec[11], e2c_vec[10]); // TC eleventh (final), TpSiL & TpSiR twelth
- FFSWAP(struct elem_to_channel, e2c_vec[12], e2c_vec[11]); // TpBL & TpBR twelth (final), TpSiL & TpSiR thirteenth (final)
- } else {
- // For everything else, utilize the AV channel position define as a
- // stable sort.
- do {
- int next_n = 0;
- for (i = 1; i < n; i++)
- if (e2c_vec[i - 1].av_position > e2c_vec[i].av_position) {
- FFSWAP(struct elem_to_channel, e2c_vec[i - 1], e2c_vec[i]);
- next_n = i;
- }
- n = next_n;
- } while (n > 0);
-
- }
-
- for (i = 0; i < total_non_cc_elements; i++) {
- layout_map[i][0] = e2c_vec[i].syn_ele;
- layout_map[i][1] = e2c_vec[i].elem_id;
- layout_map[i][2] = e2c_vec[i].aac_position;
- }
-
- return layout;
-}
-
-/**
- * Save current output configuration if and only if it has been locked.
- */
-static int push_output_configuration(AACDecContext *ac)
-{
- int pushed = 0;
-
- if (ac->oc[1].status == OC_LOCKED || ac->oc[0].status == OC_NONE) {
- ac->oc[0] = ac->oc[1];
- pushed = 1;
- }
- ac->oc[1].status = OC_NONE;
- return pushed;
-}
-
-/**
- * Restore the previous output configuration if and only if the current
- * configuration is unlocked.
- */
-static void pop_output_configuration(AACDecContext *ac)
-{
- if (ac->oc[1].status != OC_LOCKED && ac->oc[0].status != OC_NONE) {
- ac->oc[1] = ac->oc[0];
- ac->avctx->ch_layout = ac->oc[1].ch_layout;
- output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
- ac->oc[1].status, 0);
- }
-}
-
-/**
- * Configure output channel order based on the current program
- * configuration element.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int output_configure(AACDecContext *ac,
- uint8_t layout_map[MAX_ELEM_ID * 4][3], int tags,
- enum OCStatus oc_type, int get_new_frame)
-{
- AVCodecContext *avctx = ac->avctx;
- int i, channels = 0, ret;
- uint64_t layout = 0;
- uint8_t id_map[TYPE_END][MAX_ELEM_ID] = {{ 0 }};
- uint8_t type_counts[TYPE_END] = { 0 };
-
- if (ac->oc[1].layout_map != layout_map) {
- memcpy(ac->oc[1].layout_map, layout_map, tags * sizeof(layout_map[0]));
- ac->oc[1].layout_map_tags = tags;
- }
- for (i = 0; i < tags; i++) {
- int type = layout_map[i][0];
- int id = layout_map[i][1];
- id_map[type][id] = type_counts[type]++;
- if (id_map[type][id] >= MAX_ELEM_ID) {
- avpriv_request_sample(ac->avctx, "Too large remapped id");
- return AVERROR_PATCHWELCOME;
- }
- }
- // Try to sniff a reasonable channel order, otherwise output the
- // channels in the order the PCE declared them.
- if (ac->output_channel_order == CHANNEL_ORDER_DEFAULT)
- layout = sniff_channel_order(layout_map, tags);
- for (i = 0; i < tags; i++) {
- int type = layout_map[i][0];
- int id = layout_map[i][1];
- int iid = id_map[type][id];
- int position = layout_map[i][2];
- // Allocate or free elements depending on if they are in the
- // current program configuration.
- ret = che_configure(ac, position, type, iid, &channels);
- if (ret < 0)
- return ret;
- ac->tag_che_map[type][id] = ac->che[type][iid];
- }
- if (ac->oc[1].m4ac.ps == 1 && channels == 2) {
- if (layout == AV_CH_FRONT_CENTER) {
- layout = AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT;
- } else {
- layout = 0;
- }
- }
-
- av_channel_layout_uninit(&ac->oc[1].ch_layout);
- if (layout)
- av_channel_layout_from_mask(&ac->oc[1].ch_layout, layout);
- else {
- ac->oc[1].ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
- ac->oc[1].ch_layout.nb_channels = channels;
- }
-
- av_channel_layout_copy(&avctx->ch_layout, &ac->oc[1].ch_layout);
- ac->oc[1].status = oc_type;
-
- if (get_new_frame) {
- if ((ret = frame_configure_elements(ac->avctx)) < 0)
- return ret;
- }
-
- return 0;
-}
-
-static void flush(AVCodecContext *avctx)
-{
- AACDecContext *ac= avctx->priv_data;
- int type, i, j;
-
- for (type = 3; type >= 0; type--) {
- for (i = 0; i < MAX_ELEM_ID; i++) {
- ChannelElement *che = ac->che[type][i];
- if (che) {
- for (j = 0; j <= 1; j++) {
- memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
- }
- }
- }
- }
-}
-
-/**
- * Set up channel positions based on a default channel configuration
- * as specified in table 1.17.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int set_default_channel_config(AACDecContext *ac, AVCodecContext *avctx,
- uint8_t (*layout_map)[3],
- int *tags,
- int channel_config)
-{
- if (channel_config < 1 || (channel_config > 7 && channel_config < 11) ||
- channel_config > 14) {
- av_log(avctx, AV_LOG_ERROR,
- "invalid default channel configuration (%d)\n",
- channel_config);
- return AVERROR_INVALIDDATA;
- }
- *tags = ff_tags_per_config[channel_config];
- memcpy(layout_map, ff_aac_channel_layout_map[channel_config - 1],
- *tags * sizeof(*layout_map));
-
- /*
- * AAC specification has 7.1(wide) as a default layout for 8-channel streams.
- * However, at least Nero AAC encoder encodes 7.1 streams using the default
- * channel config 7, mapping the side channels of the original audio stream
- * to the second AAC_CHANNEL_FRONT pair in the AAC stream. Similarly, e.g. FAAD
- * decodes the second AAC_CHANNEL_FRONT pair as side channels, therefore decoding
- * the incorrect streams as if they were correct (and as the encoder intended).
- *
- * As actual intended 7.1(wide) streams are very rare, default to assuming a
- * 7.1 layout was intended.
- */
- if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) {
- layout_map[2][2] = AAC_CHANNEL_BACK;
-
- if (!ac || !ac->warned_71_wide++) {
- av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout"
- " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode"
- " according to the specification instead.\n", FF_COMPLIANCE_STRICT);
- }
- }
-
- return 0;
-}
-
-static ChannelElement *get_che(AACDecContext *ac, int type, int elem_id)
-{
- /* For PCE based channel configurations map the channels solely based
- * on tags. */
- if (!ac->oc[1].m4ac.chan_config) {
- return ac->tag_che_map[type][elem_id];
- }
- // Allow single CPE stereo files to be signalled with mono configuration.
- if (!ac->tags_mapped && type == TYPE_CPE &&
- ac->oc[1].m4ac.chan_config == 1) {
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int layout_map_tags;
- push_output_configuration(ac);
-
- av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n");
-
- if (set_default_channel_config(ac, ac->avctx, layout_map,
- &layout_map_tags, 2) < 0)
- return NULL;
- if (output_configure(ac, layout_map, layout_map_tags,
- OC_TRIAL_FRAME, 1) < 0)
- return NULL;
-
- ac->oc[1].m4ac.chan_config = 2;
- ac->oc[1].m4ac.ps = 0;
- }
- // And vice-versa
- if (!ac->tags_mapped && type == TYPE_SCE &&
- ac->oc[1].m4ac.chan_config == 2) {
- uint8_t layout_map[MAX_ELEM_ID * 4][3];
- int layout_map_tags;
- push_output_configuration(ac);
-
- av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n");
-
- layout_map_tags = 2;
- layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
- layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
- layout_map[0][1] = 0;
- layout_map[1][1] = 1;
- if (output_configure(ac, layout_map, layout_map_tags,
- OC_TRIAL_FRAME, 1) < 0)
- return NULL;
-
- if (ac->oc[1].m4ac.sbr)
- ac->oc[1].m4ac.ps = -1;
- }
- /* For indexed channel configurations map the channels solely based
- * on position. */
- switch (ac->oc[1].m4ac.chan_config) {
- case 14:
- if (ac->tags_mapped > 2 && ((type == TYPE_CPE && elem_id < 3) ||
- (type == TYPE_LFE && elem_id < 1))) {
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
- }
- case 13:
- if (ac->tags_mapped > 3 && ((type == TYPE_CPE && elem_id < 8) ||
- (type == TYPE_SCE && elem_id < 6) ||
- (type == TYPE_LFE && elem_id < 2))) {
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[type][elem_id];
- }
- case 12:
- case 7:
- if (ac->tags_mapped == 3 && type == TYPE_CPE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][2];
- }
- case 11:
- if (ac->tags_mapped == 3 && type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
- }
- case 6:
- /* Some streams incorrectly code 5.1 audio as
- * SCE[0] CPE[0] CPE[1] SCE[1]
- * instead of
- * SCE[0] CPE[0] CPE[1] LFE[0].
- * If we seem to have encountered such a stream, transfer
- * the LFE[0] element to the SCE[1]'s mapping */
- if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
- if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) {
- av_log(ac->avctx, AV_LOG_WARNING,
- "This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n",
- type == TYPE_SCE ? "SCE" : "LFE", elem_id);
- ac->warned_remapping_once++;
- }
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
- }
- case 5:
- if (ac->tags_mapped == 2 && type == TYPE_CPE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
- }
- case 4:
- /* Some streams incorrectly code 4.0 audio as
- * SCE[0] CPE[0] LFE[0]
- * instead of
- * SCE[0] CPE[0] SCE[1].
- * If we seem to have encountered such a stream, transfer
- * the SCE[1] element to the LFE[0]'s mapping */
- if (ac->tags_mapped == ff_tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
- if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) {
- av_log(ac->avctx, AV_LOG_WARNING,
- "This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n",
- type == TYPE_SCE ? "SCE" : "LFE", elem_id);
- ac->warned_remapping_once++;
- }
- ac->tags_mapped++;
- return ac->tag_che_map[type][elem_id] = ac->che[TYPE_SCE][1];
- }
- if (ac->tags_mapped == 2 &&
- ac->oc[1].m4ac.chan_config == 4 &&
- type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
- }
- case 3:
- case 2:
- if (ac->tags_mapped == (ac->oc[1].m4ac.chan_config != 2) &&
- type == TYPE_CPE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][0];
- } else if (ac->tags_mapped == 1 && ac->oc[1].m4ac.chan_config == 2 &&
- type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][1];
- }
- case 1:
- if (!ac->tags_mapped && type == TYPE_SCE) {
- ac->tags_mapped++;
- return ac->tag_che_map[TYPE_SCE][elem_id] = ac->che[TYPE_SCE][0];
- }
- default:
- return NULL;
- }
-}
-
-/**
- * Decode an array of 4 bit element IDs, optionally interleaved with a
- * stereo/mono switching bit.
- *
- * @param type speaker type/position for these channels
- */
-static void decode_channel_map(uint8_t layout_map[][3],
- enum ChannelPosition type,
- GetBitContext *gb, int n)
-{
- while (n--) {
- enum RawDataBlockType syn_ele;
- switch (type) {
- case AAC_CHANNEL_FRONT:
- case AAC_CHANNEL_BACK:
- case AAC_CHANNEL_SIDE:
- syn_ele = get_bits1(gb);
- break;
- case AAC_CHANNEL_CC:
- skip_bits1(gb);
- syn_ele = TYPE_CCE;
- break;
- case AAC_CHANNEL_LFE:
- syn_ele = TYPE_LFE;
- break;
- default:
- // AAC_CHANNEL_OFF has no channel map
- av_assert0(0);
- }
- layout_map[0][0] = syn_ele;
- layout_map[0][1] = get_bits(gb, 4);
- layout_map[0][2] = type;
- layout_map++;
- }
-}
-
-static inline void relative_align_get_bits(GetBitContext *gb,
- int reference_position) {
- int n = (reference_position - get_bits_count(gb) & 7);
- if (n)
- skip_bits(gb, n);
-}
-
-/**
- * Decode program configuration element; reference: table 4.2.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac,
- uint8_t (*layout_map)[3],
- GetBitContext *gb, int byte_align_ref)
-{
- int num_front, num_side, num_back, num_lfe, num_assoc_data, num_cc;
- int sampling_index;
- int comment_len;
- int tags;
-
- skip_bits(gb, 2); // object_type
-
- sampling_index = get_bits(gb, 4);
- if (m4ac->sampling_index != sampling_index)
- av_log(avctx, AV_LOG_WARNING,
- "Sample rate index in program config element does not "
- "match the sample rate index configured by the container.\n");
-
- num_front = get_bits(gb, 4);
- num_side = get_bits(gb, 4);
- num_back = get_bits(gb, 4);
- num_lfe = get_bits(gb, 2);
- num_assoc_data = get_bits(gb, 3);
- num_cc = get_bits(gb, 4);
-
- if (get_bits1(gb))
- skip_bits(gb, 4); // mono_mixdown_tag
- if (get_bits1(gb))
- skip_bits(gb, 4); // stereo_mixdown_tag
-
- if (get_bits1(gb))
- skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
-
- if (get_bits_left(gb) < 5 * (num_front + num_side + num_back + num_cc) + 4 *(num_lfe + num_assoc_data + num_cc)) {
- av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
- return -1;
- }
- decode_channel_map(layout_map , AAC_CHANNEL_FRONT, gb, num_front);
- tags = num_front;
- decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE, gb, num_side);
- tags += num_side;
- decode_channel_map(layout_map + tags, AAC_CHANNEL_BACK, gb, num_back);
- tags += num_back;
- decode_channel_map(layout_map + tags, AAC_CHANNEL_LFE, gb, num_lfe);
- tags += num_lfe;
-
- skip_bits_long(gb, 4 * num_assoc_data);
-
- decode_channel_map(layout_map + tags, AAC_CHANNEL_CC, gb, num_cc);
- tags += num_cc;
-
- relative_align_get_bits(gb, byte_align_ref);
-
- /* comment field, first byte is length */
- comment_len = get_bits(gb, 8) * 8;
- if (get_bits_left(gb) < comment_len) {
- av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
- return AVERROR_INVALIDDATA;
- }
- skip_bits_long(gb, comment_len);
- return tags;
-}
-
-/**
- * Decode GA "General Audio" specific configuration; reference: table 4.1.
- *
- * @param ac pointer to AACDecContext, may be null
- * @param avctx pointer to AVCCodecContext, used for logging
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_ga_specific_config(AACDecContext *ac, AVCodecContext *avctx,
- GetBitContext *gb,
- int get_bit_alignment,
- MPEG4AudioConfig *m4ac,
- int channel_config)
-{
- int extension_flag, ret, ep_config, res_flags;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- 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
- extension_flag = get_bits1(gb);
-
- if (m4ac->object_type == AOT_AAC_SCALABLE ||
- m4ac->object_type == AOT_ER_AAC_SCALABLE)
- skip_bits(gb, 3); // layerNr
-
- if (channel_config == 0) {
- skip_bits(gb, 4); // element_instance_tag
- tags = decode_pce(avctx, m4ac, layout_map, gb, get_bit_alignment);
- if (tags < 0)
- return tags;
- } else {
- if ((ret = set_default_channel_config(ac, avctx, layout_map,
- &tags, channel_config)))
- return ret;
- }
-
- if (count_channels(layout_map, tags) > 1) {
- m4ac->ps = 0;
- } else if (m4ac->sbr == 1 && m4ac->ps == -1)
- m4ac->ps = 1;
-
- if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
- return ret;
-
- if (extension_flag) {
- switch (m4ac->object_type) {
- case AOT_ER_BSAC:
- skip_bits(gb, 5); // numOfSubFrame
- skip_bits(gb, 11); // layer_length
- break;
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_SCALABLE:
- case AOT_ER_AAC_LD:
- res_flags = get_bits(gb, 3);
- if (res_flags) {
- avpriv_report_missing_feature(avctx,
- "AAC data resilience (flags %x)",
- res_flags);
- return AVERROR_PATCHWELCOME;
- }
- break;
- }
- skip_bits1(gb); // extensionFlag3 (TBD in version 3)
- }
- switch (m4ac->object_type) {
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_SCALABLE:
- case AOT_ER_AAC_LD:
- ep_config = get_bits(gb, 2);
- if (ep_config) {
- avpriv_report_missing_feature(avctx,
- "epConfig %d", ep_config);
- return AVERROR_PATCHWELCOME;
- }
- }
- return 0;
-}
-
-static int decode_eld_specific_config(AACDecContext *ac, AVCodecContext *avctx,
- GetBitContext *gb,
- MPEG4AudioConfig *m4ac,
- int channel_config)
-{
- int ret, ep_config, res_flags;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int tags = 0;
- const int ELDEXT_TERM = 0;
-
- m4ac->ps = 0;
- m4ac->sbr = 0;
- m4ac->frame_length_short = get_bits1(gb);
-
- res_flags = get_bits(gb, 3);
- if (res_flags) {
- avpriv_report_missing_feature(avctx,
- "AAC data resilience (flags %x)",
- res_flags);
- return AVERROR_PATCHWELCOME;
- }
-
- if (get_bits1(gb)) { // ldSbrPresentFlag
- avpriv_report_missing_feature(avctx,
- "Low Delay SBR");
- return AVERROR_PATCHWELCOME;
- }
-
- while (get_bits(gb, 4) != ELDEXT_TERM) {
- int len = get_bits(gb, 4);
- if (len == 15)
- len += get_bits(gb, 8);
- if (len == 15 + 255)
- len += get_bits(gb, 16);
- if (get_bits_left(gb) < len * 8 + 4) {
- av_log(avctx, AV_LOG_ERROR, overread_err);
- return AVERROR_INVALIDDATA;
- }
- skip_bits_long(gb, 8 * len);
- }
-
- if ((ret = set_default_channel_config(ac, avctx, layout_map,
- &tags, channel_config)))
- return ret;
-
- if (ac && (ret = output_configure(ac, layout_map, tags, OC_GLOBAL_HDR, 0)))
- return ret;
-
- ep_config = get_bits(gb, 2);
- if (ep_config) {
- avpriv_report_missing_feature(avctx,
- "epConfig %d", ep_config);
- return AVERROR_PATCHWELCOME;
- }
- return 0;
-}
-
-/**
- * Decode audio specific configuration; reference: table 1.13.
- *
- * @param ac pointer to AACDecContext, may be null
- * @param avctx pointer to AVCCodecContext, used for logging
- * @param m4ac pointer to MPEG4AudioConfig, used for parsing
- * @param gb buffer holding an audio specific config
- * @param get_bit_alignment relative alignment for byte align operations
- * @param sync_extension look for an appended sync extension
- *
- * @return Returns error status or number of consumed bits. <0 - error
- */
-static int decode_audio_specific_config_gb(AACDecContext *ac,
- AVCodecContext *avctx,
- MPEG4AudioConfig *m4ac,
- GetBitContext *gb,
- int get_bit_alignment,
- int sync_extension)
-{
- int i, ret;
- GetBitContext gbc = *gb;
- MPEG4AudioConfig m4ac_bak = *m4ac;
-
- if ((i = ff_mpeg4audio_get_config_gb(m4ac, &gbc, sync_extension, avctx)) < 0) {
- *m4ac = m4ac_bak;
- return AVERROR_INVALIDDATA;
- }
-
- if (m4ac->sampling_index > 12) {
- av_log(avctx, AV_LOG_ERROR,
- "invalid sampling rate index %d\n",
- m4ac->sampling_index);
- *m4ac = m4ac_bak;
- 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);
- *m4ac = m4ac_bak;
- return AVERROR_INVALIDDATA;
- }
-
- skip_bits_long(gb, i);
-
- switch (m4ac->object_type) {
- case AOT_AAC_MAIN:
- case AOT_AAC_LC:
- case AOT_AAC_SSR:
- case AOT_AAC_LTP:
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LD:
- if ((ret = decode_ga_specific_config(ac, avctx, gb, get_bit_alignment,
- m4ac, m4ac->chan_config)) < 0)
- return ret;
- break;
- case AOT_ER_AAC_ELD:
- if ((ret = decode_eld_specific_config(ac, avctx, gb,
- m4ac, m4ac->chan_config)) < 0)
- return ret;
- break;
- default:
- avpriv_report_missing_feature(avctx,
- "Audio object type %s%d",
- m4ac->sbr == 1 ? "SBR+" : "",
- m4ac->object_type);
- return AVERROR(ENOSYS);
- }
-
- ff_dlog(avctx,
- "AOT %d chan config %d sampling index %d (%d) SBR %d PS %d\n",
- m4ac->object_type, m4ac->chan_config, m4ac->sampling_index,
- m4ac->sample_rate, m4ac->sbr,
- m4ac->ps);
-
- return get_bits_count(gb);
-}
-
-static int decode_audio_specific_config(AACDecContext *ac,
- AVCodecContext *avctx,
- MPEG4AudioConfig *m4ac,
- const uint8_t *data, int64_t bit_size,
- int sync_extension)
-{
- int i, ret;
- GetBitContext gb;
-
- if (bit_size < 0 || bit_size > INT_MAX) {
- av_log(avctx, AV_LOG_ERROR, "Audio specific config size is invalid\n");
- return AVERROR_INVALIDDATA;
- }
-
- ff_dlog(avctx, "audio specific config size %d\n", (int)bit_size >> 3);
- for (i = 0; i < bit_size >> 3; i++)
- ff_dlog(avctx, "%02x ", data[i]);
- ff_dlog(avctx, "\n");
-
- if ((ret = init_get_bits(&gb, data, bit_size)) < 0)
- return ret;
-
- return decode_audio_specific_config_gb(ac, avctx, m4ac, &gb, 0,
- sync_extension);
-}
-
-static int sample_rate_idx (int rate)
-{
- if (92017 <= rate) return 0;
- else if (75132 <= rate) return 1;
- else if (55426 <= rate) return 2;
- else if (46009 <= rate) return 3;
- else if (37566 <= rate) return 4;
- else if (27713 <= rate) return 5;
- else if (23004 <= rate) return 6;
- else if (18783 <= rate) return 7;
- else if (13856 <= rate) return 8;
- else if (11502 <= rate) return 9;
- else if (9391 <= rate) return 10;
- else return 11;
-}
-
-static av_cold void aac_static_table_init(void)
-{
- ff_aac_sbr_init();
- ff_aac_sbr_init_fixed();
-
- ff_aacdec_common_init_once();
-}
-
-static AVOnce aac_table_init = AV_ONCE_INIT;
-
-static av_cold int aac_decode_init_internal(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- int ret;
-
- if (avctx->sample_rate > 96000)
- return AVERROR_INVALIDDATA;
-
- ret = ff_thread_once(&aac_table_init, &aac_static_table_init);
- if (ret != 0)
- return AVERROR_UNKNOWN;
-
- ac->avctx = avctx;
- ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
-
- if (ac->is_fixed)
- avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
- else
- avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
-
- if (avctx->extradata_size > 0) {
- if ((ret = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
- avctx->extradata,
- avctx->extradata_size * 8LL,
- 1)) < 0)
- return ret;
- } else {
- int sr, i;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int layout_map_tags;
-
- sr = sample_rate_idx(avctx->sample_rate);
- ac->oc[1].m4ac.sampling_index = sr;
- ac->oc[1].m4ac.channels = avctx->ch_layout.nb_channels;
- ac->oc[1].m4ac.sbr = -1;
- ac->oc[1].m4ac.ps = -1;
-
- for (i = 0; i < FF_ARRAY_ELEMS(ff_mpeg4audio_channels); i++)
- if (ff_mpeg4audio_channels[i] == avctx->ch_layout.nb_channels)
- break;
- if (i == FF_ARRAY_ELEMS(ff_mpeg4audio_channels)) {
- i = 0;
- }
- ac->oc[1].m4ac.chan_config = i;
-
- if (ac->oc[1].m4ac.chan_config) {
- int ret = set_default_channel_config(ac, avctx, layout_map,
- &layout_map_tags, ac->oc[1].m4ac.chan_config);
- if (!ret)
- output_configure(ac, layout_map, layout_map_tags,
- OC_GLOBAL_HDR, 0);
- else if (avctx->err_recognition & AV_EF_EXPLODE)
- return AVERROR_INVALIDDATA;
- }
- }
-
- return ff_aac_decode_init_common(avctx);
-}
-
-static av_cold int aac_decode_init(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- ac->is_fixed = 0;
- return aac_decode_init_internal(avctx);
-}
-
-static av_cold int aac_decode_init_fixed(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- ac->is_fixed = 1;
- return aac_decode_init_internal(avctx);
-}
-
-/**
- * Skip data_stream_element; reference: table 4.10.
- */
-static int skip_data_stream_element(AACDecContext *ac, GetBitContext *gb)
-{
- int byte_align = get_bits1(gb);
- int count = get_bits(gb, 8);
- if (count == 255)
- count += get_bits(gb, 8);
- if (byte_align)
- align_get_bits(gb);
-
- if (get_bits_left(gb) < 8 * count) {
- av_log(ac->avctx, AV_LOG_ERROR, "skip_data_stream_element: "overread_err);
- return AVERROR_INVALIDDATA;
- }
- skip_bits_long(gb, 8 * count);
- return 0;
-}
-
-static int decode_prediction(AACDecContext *ac, IndividualChannelStream *ics,
- GetBitContext *gb)
-{
- int sfb;
- if (get_bits1(gb)) {
- ics->predictor_reset_group = get_bits(gb, 5);
- if (ics->predictor_reset_group == 0 ||
- ics->predictor_reset_group > 30) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Invalid Predictor Reset Group.\n");
- return AVERROR_INVALIDDATA;
- }
- }
- for (sfb = 0; sfb < FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index]); sfb++) {
- ics->prediction_used[sfb] = get_bits1(gb);
- }
- return 0;
-}
-
-/**
- * Decode Long Term Prediction data; reference: table 4.xx.
- */
-static void decode_ltp(AACDecContext *ac, LongTermPrediction *ltp,
- GetBitContext *gb, uint8_t max_sfb)
-{
- int sfb;
-
- ltp->lag = get_bits(gb, 11);
- if (ac->is_fixed)
- ltp->coef_fixed = Q30(ff_ltp_coef[get_bits(gb, 3)]);
- else
- ltp->coef = ff_ltp_coef[get_bits(gb, 3)];
-
- for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
- ltp->used[sfb] = get_bits1(gb);
-}
-
-/**
- * Decode Individual Channel Stream info; reference: table 4.6.
- */
-static int decode_ics_info(AACDecContext *ac, IndividualChannelStream *ics,
- GetBitContext *gb)
-{
- const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
- const int aot = m4ac->object_type;
- const int sampling_index = m4ac->sampling_index;
- int ret_fail = AVERROR_INVALIDDATA;
-
- if (aot != AOT_ER_AAC_ELD) {
- if (get_bits1(gb)) {
- av_log(ac->avctx, AV_LOG_ERROR, "Reserved bit set.\n");
- if (ac->avctx->err_recognition & AV_EF_BITSTREAM)
- return AVERROR_INVALIDDATA;
- }
- ics->window_sequence[1] = ics->window_sequence[0];
- ics->window_sequence[0] = get_bits(gb, 2);
- if (aot == 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;
- ics->group_len[0] = 1;
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- int i;
- ics->max_sfb = get_bits(gb, 4);
- for (i = 0; i < 7; i++) {
- if (get_bits1(gb)) {
- ics->group_len[ics->num_window_groups - 1]++;
- } else {
- ics->num_window_groups++;
- ics->group_len[ics->num_window_groups - 1] = 1;
- }
- }
- ics->num_windows = 8;
- 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 {
- ics->max_sfb = get_bits(gb, 6);
- ics->num_windows = 1;
- if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD) {
- if (m4ac->frame_length_short) {
- ics->swb_offset = ff_swb_offset_480[sampling_index];
- ics->num_swb = ff_aac_num_swb_480[sampling_index];
- ics->tns_max_bands = ff_tns_max_bands_480[sampling_index];
- } else {
- ics->swb_offset = ff_swb_offset_512[sampling_index];
- ics->num_swb = ff_aac_num_swb_512[sampling_index];
- ics->tns_max_bands = ff_tns_max_bands_512[sampling_index];
- }
- if (!ics->num_swb || !ics->swb_offset) {
- ret_fail = AVERROR_BUG;
- goto fail;
- }
- } else {
- 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) {
- ics->predictor_present = get_bits1(gb);
- ics->predictor_reset_group = 0;
- }
- if (ics->predictor_present) {
- if (aot == AOT_AAC_MAIN) {
- if (decode_prediction(ac, ics, gb)) {
- goto fail;
- }
- } else if (aot == AOT_AAC_LC ||
- aot == AOT_ER_AAC_LC) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Prediction is not allowed in AAC-LC.\n");
- goto fail;
- } else {
- if (aot == AOT_ER_AAC_LD) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "LTP in ER AAC LD not yet implemented.\n");
- ret_fail = AVERROR_PATCHWELCOME;
- goto fail;
- }
- if ((ics->ltp.present = get_bits(gb, 1)))
- decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
- }
- }
- }
-
- if (ics->max_sfb > ics->num_swb) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Number of scalefactor bands in group (%d) "
- "exceeds limit (%d).\n",
- ics->max_sfb, ics->num_swb);
- goto fail;
- }
-
- return 0;
-fail:
- ics->max_sfb = 0;
- return ret_fail;
-}
-
-/**
- * Decode band types (section_data payload); reference: table 4.46.
- *
- * @param band_type array of the used band type
- * @param band_type_run_end array of the last scalefactor band of a band type run
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_band_types(AACDecContext *ac, enum BandType band_type[120],
- int band_type_run_end[120], GetBitContext *gb,
- IndividualChannelStream *ics)
-{
- int g, idx = 0;
- const int bits = (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) ? 3 : 5;
- for (g = 0; g < ics->num_window_groups; g++) {
- int k = 0;
- while (k < ics->max_sfb) {
- uint8_t sect_end = k;
- int sect_len_incr;
- int sect_band_type = get_bits(gb, 4);
- if (sect_band_type == 12) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid band type\n");
- return AVERROR_INVALIDDATA;
- }
- do {
- sect_len_incr = get_bits(gb, bits);
- sect_end += sect_len_incr;
- if (get_bits_left(gb) < 0) {
- av_log(ac->avctx, AV_LOG_ERROR, "decode_band_types: "overread_err);
- return AVERROR_INVALIDDATA;
- }
- if (sect_end > ics->max_sfb) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Number of bands (%d) exceeds limit (%d).\n",
- sect_end, ics->max_sfb);
- return AVERROR_INVALIDDATA;
- }
- } while (sect_len_incr == (1 << bits) - 1);
- for (; k < sect_end; k++) {
- band_type [idx] = sect_band_type;
- band_type_run_end[idx++] = sect_end;
- }
- }
- }
- return 0;
-}
-
-/**
- * Decode scalefactors; reference: table 4.47.
- *
- * @param global_gain first scalefactor value as scalefactors are differentially coded
- * @param band_type array of the used band type
- * @param band_type_run_end array of the last scalefactor band of a band type run
- * @param sf array of scalefactors or intensity stereo positions
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_scalefactors(AACDecContext *ac, int sfo[120],
- GetBitContext *gb,
- unsigned int global_gain,
- IndividualChannelStream *ics,
- enum BandType band_type[120],
- int band_type_run_end[120])
-{
- int g, i, idx = 0;
- int offset[3] = { global_gain, global_gain - NOISE_OFFSET, 0 };
- int clipped_offset;
- int noise_flag = 1;
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb;) {
- int run_end = band_type_run_end[idx];
- switch (band_type[idx]) {
- case ZERO_BT:
- for (; i < run_end; i++, idx++)
- sfo[idx] = 0;
- break;
- case INTENSITY_BT: /* fallthrough */
- case INTENSITY_BT2:
- for (; i < run_end; i++, idx++) {
- offset[2] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
- clipped_offset = av_clip(offset[2], -155, 100);
- if (offset[2] != clipped_offset) {
- avpriv_request_sample(ac->avctx,
- "If you heard an audible artifact, there may be a bug in the decoder. "
- "Clipped intensity stereo position (%d -> %d)",
- offset[2], clipped_offset);
- }
- sfo[idx] = clipped_offset;
- }
- break;
- case NOISE_BT:
- for (; i < run_end; i++, idx++) {
- if (noise_flag-- > 0)
- offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE;
- else
- offset[1] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
- clipped_offset = av_clip(offset[1], -100, 155);
- if (offset[1] != clipped_offset) {
- avpriv_request_sample(ac->avctx,
- "If you heard an audible artifact, there may be a bug in the decoder. "
- "Clipped noise gain (%d -> %d)",
- offset[1], clipped_offset);
- }
- sfo[idx] = clipped_offset;
- }
- break;
- default:
- for (; i < run_end; i++, idx++) {
- offset[0] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
- if (offset[0] > 255U) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Scalefactor (%d) out of range.\n", offset[0]);
- return AVERROR_INVALIDDATA;
- }
- sfo[idx] = offset[0];
- }
- break;
- }
- }
- }
- return 0;
-}
-
-/**
- * Decode pulse data; reference: table 4.7.
- */
-static int decode_pulses(Pulse *pulse, GetBitContext *gb,
- const uint16_t *swb_offset, int num_swb)
-{
- int i, pulse_swb;
- pulse->num_pulse = get_bits(gb, 2) + 1;
- pulse_swb = get_bits(gb, 6);
- if (pulse_swb >= num_swb)
- return -1;
- pulse->pos[0] = swb_offset[pulse_swb];
- pulse->pos[0] += get_bits(gb, 5);
- if (pulse->pos[0] >= swb_offset[num_swb])
- return -1;
- pulse->amp[0] = get_bits(gb, 4);
- for (i = 1; i < pulse->num_pulse; i++) {
- pulse->pos[i] = get_bits(gb, 5) + pulse->pos[i - 1];
- if (pulse->pos[i] >= swb_offset[num_swb])
- return -1;
- pulse->amp[i] = get_bits(gb, 4);
- }
- return 0;
-}
-
-/**
- * Decode Temporal Noise Shaping data; reference: table 4.48.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
- GetBitContext *gb, const IndividualChannelStream *ics)
-{
- int w, filt, i, coef_len, coef_res, coef_compress;
- const int is8 = ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE;
- const int tns_max_order = is8 ? 7 : ac->oc[1].m4ac.object_type == AOT_AAC_MAIN ? 20 : 12;
- for (w = 0; w < ics->num_windows; w++) {
- if ((tns->n_filt[w] = get_bits(gb, 2 - is8))) {
- coef_res = get_bits1(gb);
-
- for (filt = 0; filt < tns->n_filt[w]; filt++) {
- int tmp2_idx;
- tns->length[w][filt] = get_bits(gb, 6 - 2 * is8);
-
- if ((tns->order[w][filt] = get_bits(gb, 5 - 2 * is8)) > tns_max_order) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "TNS filter order %d is greater than maximum %d.\n",
- tns->order[w][filt], tns_max_order);
- tns->order[w][filt] = 0;
- return AVERROR_INVALIDDATA;
- }
- if (tns->order[w][filt]) {
- tns->direction[w][filt] = get_bits1(gb);
- coef_compress = get_bits1(gb);
- coef_len = coef_res + 3 - coef_compress;
- tmp2_idx = 2 * coef_compress + coef_res;
-
- for (i = 0; i < tns->order[w][filt]; i++) {
- if (ac->is_fixed)
- tns->coef_fixed[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
- else
- tns->coef[w][filt][i] = ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)];
- }
- }
- }
- }
- }
- return 0;
-}
-
-/**
- * Decode Mid/Side data; reference: table 4.54.
- *
- * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
- * [1] mask is decoded from bitstream; [2] mask is all 1s;
- * [3] reserved for scalable AAC
- */
-static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
- int ms_present)
-{
- int idx;
- int max_idx = cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb;
- if (ms_present == 1) {
- for (idx = 0; idx < max_idx; idx++)
- cpe->ms_mask[idx] = get_bits1(gb);
- } else if (ms_present == 2) {
- memset(cpe->ms_mask, 1, max_idx * sizeof(cpe->ms_mask[0]));
- }
-}
-
-static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
-{
- // wd_num, wd_test, aloc_size
- static const uint8_t gain_mode[4][3] = {
- {1, 0, 5}, // ONLY_LONG_SEQUENCE = 0,
- {2, 1, 2}, // LONG_START_SEQUENCE,
- {8, 0, 2}, // EIGHT_SHORT_SEQUENCE,
- {2, 1, 5}, // LONG_STOP_SEQUENCE
- };
-
- const int mode = sce->ics.window_sequence[0];
- uint8_t bd, wd, ad;
-
- // FIXME: Store the gain control data on |sce| and do something with it.
- uint8_t max_band = get_bits(gb, 2);
- for (bd = 0; bd < max_band; bd++) {
- for (wd = 0; wd < gain_mode[mode][0]; wd++) {
- uint8_t adjust_num = get_bits(gb, 3);
- for (ad = 0; ad < adjust_num; ad++) {
- skip_bits(gb, 4 + ((wd == 0 && gain_mode[mode][1])
- ? 4
- : gain_mode[mode][2]));
- }
- }
- }
-}
-
-/**
- * Decode an individual_channel_stream payload; reference: table 4.44.
- *
- * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
- * @param scale_flag scalable [1] or non-scalable [0] AAC (Unused until scalable AAC is implemented.)
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
- GetBitContext *gb, int common_window, int scale_flag)
-{
- Pulse pulse;
- TemporalNoiseShaping *tns = &sce->tns;
- IndividualChannelStream *ics = &sce->ics;
- int global_gain, eld_syntax, er_syntax, pulse_present = 0;
- int ret;
-
- eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
- er_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_LC ||
- ac->oc[1].m4ac.object_type == AOT_ER_AAC_LTP ||
- ac->oc[1].m4ac.object_type == AOT_ER_AAC_LD ||
- ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
-
- /* This assignment is to silence a GCC warning about the variable being used
- * uninitialized when in fact it always is.
- */
- pulse.num_pulse = 0;
-
- global_gain = get_bits(gb, 8);
-
- if (!common_window && !scale_flag) {
- ret = decode_ics_info(ac, ics, gb);
- if (ret < 0)
- goto fail;
- }
-
- if ((ret = decode_band_types(ac, sce->band_type,
- sce->band_type_run_end, gb, ics)) < 0)
- goto fail;
- if ((ret = decode_scalefactors(ac, sce->sfo, gb, global_gain, ics,
- sce->band_type, sce->band_type_run_end)) < 0)
- goto fail;
-
- ac->dsp.dequant_scalefactors(sce);
-
- pulse_present = 0;
- if (!scale_flag) {
- if (!eld_syntax && (pulse_present = get_bits1(gb))) {
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Pulse tool not allowed in eight short sequence.\n");
- ret = AVERROR_INVALIDDATA;
- goto fail;
- }
- if (decode_pulses(&pulse, gb, ics->swb_offset, ics->num_swb)) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Pulse data corrupt or invalid.\n");
- ret = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
- tns->present = get_bits1(gb);
- if (tns->present && !er_syntax) {
- ret = decode_tns(ac, tns, gb, ics);
- if (ret < 0)
- goto fail;
- }
- if (!eld_syntax && get_bits1(gb)) {
- decode_gain_control(sce, gb);
- if (!ac->warned_gain_control) {
- avpriv_report_missing_feature(ac->avctx, "Gain control");
- ac->warned_gain_control = 1;
- }
- }
- // I see no textual basis in the spec for this occurring after SSR gain
- // control, but this is what both reference and real implmentations do
- if (tns->present && er_syntax) {
- ret = decode_tns(ac, tns, gb, ics);
- if (ret < 0)
- goto fail;
- }
- }
-
- ret = ac->proc.decode_spectrum_and_dequant(ac, gb,
- pulse_present ? &pulse : NULL,
- sce);
- if (ret < 0)
- goto fail;
-
- if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window)
- ac->dsp.apply_prediction(ac, sce);
-
- return 0;
-fail:
- tns->present = 0;
- return ret;
-}
-
-/**
- * Decode a channel_pair_element; reference: table 4.4.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
-{
- int i, ret, common_window, ms_present = 0;
- int eld_syntax = ac->oc[1].m4ac.object_type == AOT_ER_AAC_ELD;
-
- common_window = eld_syntax || get_bits1(gb);
- if (common_window) {
- if (decode_ics_info(ac, &cpe->ch[0].ics, gb))
- return AVERROR_INVALIDDATA;
- i = cpe->ch[1].ics.use_kb_window[0];
- cpe->ch[1].ics = cpe->ch[0].ics;
- cpe->ch[1].ics.use_kb_window[1] = i;
- if (cpe->ch[1].ics.predictor_present &&
- (ac->oc[1].m4ac.object_type != AOT_AAC_MAIN))
- if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
- decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
- ms_present = get_bits(gb, 2);
- if (ms_present == 3) {
- av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
- return AVERROR_INVALIDDATA;
- } else if (ms_present)
- decode_mid_side_stereo(cpe, gb, ms_present);
- }
- if ((ret = ff_aac_decode_ics(ac, &cpe->ch[0], gb, common_window, 0)))
- return ret;
- if ((ret = ff_aac_decode_ics(ac, &cpe->ch[1], gb, common_window, 0)))
- return ret;
-
- if (common_window) {
- if (ms_present)
- ac->dsp.apply_mid_side_stereo(ac, cpe);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) {
- ac->dsp.apply_prediction(ac, &cpe->ch[0]);
- ac->dsp.apply_prediction(ac, &cpe->ch[1]);
- }
- }
-
- ac->dsp.apply_intensity_stereo(ac, cpe, ms_present);
- return 0;
-}
-
-/**
- * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
- *
- * @return Returns number of bytes consumed.
- */
-static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc,
- GetBitContext *gb)
-{
- int i;
- int num_excl_chan = 0;
-
- do {
- for (i = 0; i < 7; i++)
- che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb);
- } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb));
-
- return num_excl_chan / 7;
-}
-
-/**
- * Decode dynamic range information; reference: table 4.52.
- *
- * @return Returns number of bytes consumed.
- */
-static int decode_dynamic_range(DynamicRangeControl *che_drc,
- GetBitContext *gb)
-{
- int n = 1;
- int drc_num_bands = 1;
- int i;
-
- /* pce_tag_present? */
- if (get_bits1(gb)) {
- che_drc->pce_instance_tag = get_bits(gb, 4);
- skip_bits(gb, 4); // tag_reserved_bits
- n++;
- }
-
- /* excluded_chns_present? */
- if (get_bits1(gb)) {
- n += decode_drc_channel_exclusions(che_drc, gb);
- }
-
- /* drc_bands_present? */
- if (get_bits1(gb)) {
- che_drc->band_incr = get_bits(gb, 4);
- che_drc->interpolation_scheme = get_bits(gb, 4);
- n++;
- drc_num_bands += che_drc->band_incr;
- for (i = 0; i < drc_num_bands; i++) {
- che_drc->band_top[i] = get_bits(gb, 8);
- n++;
- }
- }
-
- /* prog_ref_level_present? */
- if (get_bits1(gb)) {
- che_drc->prog_ref_level = get_bits(gb, 7);
- skip_bits1(gb); // prog_ref_level_reserved_bits
- n++;
- }
-
- for (i = 0; i < drc_num_bands; i++) {
- che_drc->dyn_rng_sgn[i] = get_bits1(gb);
- che_drc->dyn_rng_ctl[i] = get_bits(gb, 7);
- n++;
- }
-
- return n;
-}
-
-static int decode_fill(AACDecContext *ac, GetBitContext *gb, int len) {
- uint8_t buf[256];
- int i, major, minor;
-
- if (len < 13+7*8)
- goto unknown;
-
- get_bits(gb, 13); len -= 13;
-
- for(i=0; i+1<sizeof(buf) && len>=8; i++, len-=8)
- buf[i] = get_bits(gb, 8);
-
- buf[i] = 0;
- if (ac->avctx->debug & FF_DEBUG_PICT_INFO)
- av_log(ac->avctx, AV_LOG_DEBUG, "FILL:%s\n", buf);
-
- if (sscanf(buf, "libfaac %d.%d", &major, &minor) == 2){
- ac->avctx->internal->skip_samples = 1024;
- }
-
-unknown:
- skip_bits_long(gb, len);
-
- return 0;
-}
-
-/**
- * Decode extension data (incomplete); reference: table 4.51.
- *
- * @param cnt length of TYPE_FIL syntactic element in bytes
- *
- * @return Returns number of bytes consumed
- */
-static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cnt,
- ChannelElement *che, enum RawDataBlockType elem_type)
-{
- int crc_flag = 0;
- int res = cnt;
- int type = get_bits(gb, 4);
-
- if (ac->avctx->debug & FF_DEBUG_STARTCODE)
- av_log(ac->avctx, AV_LOG_DEBUG, "extension type: %d len:%d\n", type, cnt);
-
- switch (type) { // extension type
- case EXT_SBR_DATA_CRC:
- crc_flag++;
- case EXT_SBR_DATA:
- 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);
- return res;
- } else if (ac->oc[1].m4ac.sbr == -1 && ac->oc[1].status == OC_LOCKED) {
- av_log(ac->avctx, AV_LOG_ERROR, "Implicit SBR was found with a first occurrence after the first frame.\n");
- skip_bits_long(gb, 8 * cnt - 4);
- return res;
- } else if (ac->oc[1].m4ac.ps == -1 && ac->oc[1].status < OC_LOCKED &&
- ac->avctx->ch_layout.nb_channels == 1) {
- ac->oc[1].m4ac.sbr = 1;
- ac->oc[1].m4ac.ps = 1;
- ac->avctx->profile = AV_PROFILE_AAC_HE_V2;
- output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
- ac->oc[1].status, 1);
- } else {
- ac->oc[1].m4ac.sbr = 1;
- ac->avctx->profile = AV_PROFILE_AAC_HE;
- }
-
- if (ac->is_fixed)
- res = ff_aac_sbr_decode_extension_fixed(ac, che, gb, crc_flag, cnt, elem_type);
- else
- res = ff_aac_sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
-
-
- 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");
- ac->warned_he_aac_mono = 1;
- }
- break;
- case EXT_DYNAMIC_RANGE:
- res = decode_dynamic_range(&ac->che_drc, gb);
- break;
- case EXT_FILL:
- decode_fill(ac, gb, 8 * cnt - 4);
- break;
- case EXT_FILL_DATA:
- case EXT_DATA_ELEMENT:
- default:
- skip_bits_long(gb, 8 * cnt - 4);
- break;
- };
- return res;
-}
-
-/**
- * channel coupling transformation interface
- *
- * @param apply_coupling_method pointer to (in)dependent coupling function
- */
-static void apply_channel_coupling(AACDecContext *ac, ChannelElement *cc,
- enum RawDataBlockType type, int elem_id,
- enum CouplingPoint coupling_point,
- void (*apply_coupling_method)(AACDecContext *ac, SingleChannelElement *target, ChannelElement *cce, int index))
-{
- int i, c;
-
- for (i = 0; i < MAX_ELEM_ID; i++) {
- ChannelElement *cce = ac->che[TYPE_CCE][i];
- int index = 0;
-
- if (cce && cce->coup.coupling_point == coupling_point) {
- ChannelCoupling *coup = &cce->coup;
-
- for (c = 0; c <= coup->num_coupled; c++) {
- if (coup->type[c] == type && coup->id_select[c] == elem_id) {
- if (coup->ch_select[c] != 1) {
- apply_coupling_method(ac, &cc->ch[0], cce, index);
- if (coup->ch_select[c] != 0)
- index++;
- }
- if (coup->ch_select[c] != 2)
- apply_coupling_method(ac, &cc->ch[1], cce, index++);
- } else
- index += 1 + (coup->ch_select[c] == 3);
- }
- }
- }
-}
-
-/**
- * Convert spectral data to samples, applying all supported tools as appropriate.
- */
-static void spectral_to_sample(AACDecContext *ac, int samples)
-{
- int i, type;
- void (*imdct_and_window)(AACDecContext *ac, SingleChannelElement *sce);
- switch (ac->oc[1].m4ac.object_type) {
- case AOT_ER_AAC_LD:
- imdct_and_window = ac->dsp.imdct_and_windowing_ld;
- break;
- case AOT_ER_AAC_ELD:
- imdct_and_window = ac->dsp.imdct_and_windowing_eld;
- break;
- default:
- if (ac->oc[1].m4ac.frame_length_short)
- imdct_and_window = ac->dsp.imdct_and_windowing_960;
- else
- imdct_and_window = ac->dsp.imdct_and_windowing;
- }
- for (type = 3; type >= 0; type--) {
- for (i = 0; i < MAX_ELEM_ID; i++) {
- ChannelElement *che = ac->che[type][i];
- if (che && che->present) {
- if (type <= TYPE_CPE)
- apply_channel_coupling(ac, che, type, i, BEFORE_TNS, ac->dsp.apply_dependent_coupling);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
- if (che->ch[0].ics.predictor_present) {
- if (che->ch[0].ics.ltp.present)
- ac->dsp.apply_ltp(ac, &che->ch[0]);
- if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
- ac->dsp.apply_ltp(ac, &che->ch[1]);
- }
- }
- if (che->ch[0].tns.present)
- ac->dsp.apply_tns(che->ch[0].AAC_RENAME(coeffs),
- &che->ch[0].tns, &che->ch[0].ics, 1);
- if (che->ch[1].tns.present)
- ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
- &che->ch[1].tns, &che->ch[1].ics, 1);
- if (type <= TYPE_CPE)
- apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling);
- if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
- imdct_and_window(ac, &che->ch[0]);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
- ac->dsp.update_ltp(ac, &che->ch[0]);
- if (type == TYPE_CPE) {
- imdct_and_window(ac, &che->ch[1]);
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
- ac->dsp.update_ltp(ac, &che->ch[1]);
- }
- if (ac->oc[1].m4ac.sbr > 0) {
- if (ac->is_fixed)
- ff_aac_sbr_apply_fixed(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
- else
- ff_aac_sbr_apply(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
- }
- }
- if (type <= TYPE_CCE)
- apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling);
- ac->dsp.clip_output(ac, che, type, samples);
- che->present = 0;
- } else if (che) {
- av_log(ac->avctx, AV_LOG_VERBOSE, "ChannelElement %d.%d missing \n", type, i);
- }
- }
- }
-}
-
-static int parse_adts_frame_header(AACDecContext *ac, GetBitContext *gb)
-{
- int size;
- AACADTSHeaderInfo hdr_info;
- uint8_t layout_map[MAX_ELEM_ID*4][3];
- int layout_map_tags, ret;
-
- size = ff_adts_header_parse(gb, &hdr_info);
- if (size > 0) {
- if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
- // This is 2 for "VLB " audio in NSV files.
- // See samples/nsv/vlb_audio.
- avpriv_report_missing_feature(ac->avctx,
- "More than one AAC RDB per ADTS frame");
- ac->warned_num_aac_frames = 1;
- }
- push_output_configuration(ac);
- if (hdr_info.chan_config) {
- ac->oc[1].m4ac.chan_config = hdr_info.chan_config;
- if ((ret = set_default_channel_config(ac, ac->avctx,
- layout_map,
- &layout_map_tags,
- hdr_info.chan_config)) < 0)
- return ret;
- if ((ret = output_configure(ac, layout_map, layout_map_tags,
- FFMAX(ac->oc[1].status,
- OC_TRIAL_FRAME), 0)) < 0)
- return ret;
- } else {
- ac->oc[1].m4ac.chan_config = 0;
- /**
- * dual mono frames in Japanese DTV can have chan_config 0
- * WITHOUT specifying PCE.
- * thus, set dual mono as default.
- */
- if (ac->dmono_mode && ac->oc[0].status == OC_NONE) {
- layout_map_tags = 2;
- layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
- layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
- layout_map[0][1] = 0;
- layout_map[1][1] = 1;
- if (output_configure(ac, layout_map, layout_map_tags,
- OC_TRIAL_FRAME, 0))
- return -7;
- }
- }
- ac->oc[1].m4ac.sample_rate = hdr_info.sample_rate;
- ac->oc[1].m4ac.sampling_index = hdr_info.sampling_index;
- ac->oc[1].m4ac.object_type = hdr_info.object_type;
- ac->oc[1].m4ac.frame_length_short = 0;
- if (ac->oc[0].status != OC_LOCKED ||
- ac->oc[0].m4ac.chan_config != hdr_info.chan_config ||
- ac->oc[0].m4ac.sample_rate != hdr_info.sample_rate) {
- ac->oc[1].m4ac.sbr = -1;
- ac->oc[1].m4ac.ps = -1;
- }
- if (!hdr_info.crc_absent)
- skip_bits(gb, 16);
- }
- return size;
-}
-
-static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame_ptr, GetBitContext *gb)
-{
- AACDecContext *ac = avctx->priv_data;
- const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
- ChannelElement *che;
- int err, i;
- int samples = m4ac->frame_length_short ? 960 : 1024;
- int chan_config = m4ac->chan_config;
- int aot = m4ac->object_type;
-
- if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD)
- samples >>= 1;
-
- ac->frame = frame;
-
- if ((err = frame_configure_elements(avctx)) < 0)
- return err;
-
- // The AV_PROFILE_AAC_* defines are all object_type - 1
- // This may lead to an undefined profile being signaled
- ac->avctx->profile = aot - 1;
-
- ac->tags_mapped = 0;
-
- if (chan_config < 0 || (chan_config >= 8 && chan_config < 11) || chan_config >= 13) {
- avpriv_request_sample(avctx, "Unknown ER channel configuration %d",
- chan_config);
- return AVERROR_INVALIDDATA;
- }
- for (i = 0; i < ff_tags_per_config[chan_config]; i++) {
- const int elem_type = ff_aac_channel_layout_map[chan_config-1][i][0];
- const int elem_id = ff_aac_channel_layout_map[chan_config-1][i][1];
- if (!(che=get_che(ac, elem_type, elem_id))) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "channel element %d.%d is not allocated\n",
- elem_type, elem_id);
- return AVERROR_INVALIDDATA;
- }
- che->present = 1;
- if (aot != AOT_ER_AAC_ELD)
- skip_bits(gb, 4);
- switch (elem_type) {
- case TYPE_SCE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- break;
- case TYPE_CPE:
- err = decode_cpe(ac, gb, che);
- break;
- case TYPE_LFE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- break;
- }
- if (err < 0)
- return err;
- }
-
- spectral_to_sample(ac, samples);
-
- if (!ac->frame->data[0] && samples) {
- av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
- return AVERROR_INVALIDDATA;
- }
-
- ac->frame->nb_samples = samples;
- ac->frame->sample_rate = avctx->sample_rate;
- *got_frame_ptr = 1;
-
- skip_bits_long(gb, get_bits_left(gb));
- return 0;
-}
-
-static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame_ptr, GetBitContext *gb,
- const AVPacket *avpkt)
-{
- AACDecContext *ac = avctx->priv_data;
- ChannelElement *che = NULL, *che_prev = NULL;
- enum RawDataBlockType elem_type, che_prev_type = TYPE_END;
- int err, elem_id;
- int samples = 0, multiplier, audio_found = 0, pce_found = 0;
- int is_dmono, sce_count = 0;
- int payload_alignment;
- uint8_t che_presence[4][MAX_ELEM_ID] = {{0}};
-
- ac->frame = frame;
-
- if (show_bits(gb, 12) == 0xfff) {
- if ((err = parse_adts_frame_header(ac, gb)) < 0) {
- av_log(avctx, AV_LOG_ERROR, "Error decoding AAC frame header.\n");
- goto fail;
- }
- if (ac->oc[1].m4ac.sampling_index > 12) {
- av_log(ac->avctx, AV_LOG_ERROR, "invalid sampling rate index %d\n", ac->oc[1].m4ac.sampling_index);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
-
- if ((err = frame_configure_elements(avctx)) < 0)
- goto fail;
-
- // The AV_PROFILE_AAC_* defines are all object_type - 1
- // This may lead to an undefined profile being signaled
- ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
-
- payload_alignment = get_bits_count(gb);
- ac->tags_mapped = 0;
- // parse
- while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
- elem_id = get_bits(gb, 4);
-
- if (avctx->debug & FF_DEBUG_STARTCODE)
- av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id);
-
- if (!avctx->ch_layout.nb_channels && elem_type != TYPE_PCE) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- if (elem_type < TYPE_DSE) {
- if (che_presence[elem_type][elem_id]) {
- int error = che_presence[elem_type][elem_id] > 1;
- av_log(ac->avctx, error ? AV_LOG_ERROR : AV_LOG_DEBUG, "channel element %d.%d duplicate\n",
- elem_type, elem_id);
- if (error) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
- che_presence[elem_type][elem_id]++;
-
- if (!(che=get_che(ac, elem_type, elem_id))) {
- av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
- elem_type, elem_id);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- samples = ac->oc[1].m4ac.frame_length_short ? 960 : 1024;
- che->present = 1;
- }
-
- switch (elem_type) {
-
- case TYPE_SCE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- audio_found = 1;
- sce_count++;
- break;
-
- case TYPE_CPE:
- err = decode_cpe(ac, gb, che);
- audio_found = 1;
- break;
-
- case TYPE_CCE:
- err = ac->proc.decode_cce(ac, gb, che);
- break;
-
- case TYPE_LFE:
- err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
- audio_found = 1;
- break;
-
- case TYPE_DSE:
- err = skip_data_stream_element(ac, gb);
- break;
-
- case TYPE_PCE: {
- uint8_t layout_map[MAX_ELEM_ID*4][3] = {{0}};
- int tags;
-
- int pushed = push_output_configuration(ac);
- if (pce_found && !pushed) {
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- tags = decode_pce(avctx, &ac->oc[1].m4ac, layout_map, gb,
- payload_alignment);
- if (tags < 0) {
- err = tags;
- break;
- }
- if (pce_found) {
- av_log(avctx, AV_LOG_ERROR,
- "Not evaluating a further program_config_element as this construct is dubious at best.\n");
- pop_output_configuration(ac);
- } else {
- err = output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1);
- if (!err)
- ac->oc[1].m4ac.chan_config = 0;
- pce_found = 1;
- }
- break;
- }
-
- case TYPE_FIL:
- if (elem_id == 15)
- elem_id += get_bits(gb, 8) - 1;
- if (get_bits_left(gb) < 8 * elem_id) {
- av_log(avctx, AV_LOG_ERROR, "TYPE_FIL: "overread_err);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- err = 0;
- while (elem_id > 0) {
- int ret = decode_extension_payload(ac, gb, elem_id, che_prev, che_prev_type);
- if (ret < 0) {
- err = ret;
- break;
- }
- elem_id -= ret;
- }
- break;
-
- default:
- err = AVERROR_BUG; /* should not happen, but keeps compiler happy */
- break;
- }
-
- if (elem_type < TYPE_DSE) {
- che_prev = che;
- che_prev_type = elem_type;
- }
-
- if (err)
- goto fail;
-
- if (get_bits_left(gb) < 3) {
- av_log(avctx, AV_LOG_ERROR, overread_err);
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
- }
-
- if (!avctx->ch_layout.nb_channels) {
- *got_frame_ptr = 0;
- return 0;
- }
-
- multiplier = (ac->oc[1].m4ac.sbr == 1) ? ac->oc[1].m4ac.ext_sample_rate > ac->oc[1].m4ac.sample_rate : 0;
- samples <<= multiplier;
-
- spectral_to_sample(ac, samples);
-
- if (ac->oc[1].status && audio_found) {
- avctx->sample_rate = ac->oc[1].m4ac.sample_rate << multiplier;
- avctx->frame_size = samples;
- ac->oc[1].status = OC_LOCKED;
- }
-
- if (!ac->frame->data[0] && samples) {
- av_log(avctx, AV_LOG_ERROR, "no frame data found\n");
- err = AVERROR_INVALIDDATA;
- goto fail;
- }
-
- if (samples) {
- ac->frame->nb_samples = samples;
- ac->frame->sample_rate = avctx->sample_rate;
- } else
- av_frame_unref(ac->frame);
- *got_frame_ptr = !!samples;
-
- /* for dual-mono audio (SCE + SCE) */
- is_dmono = ac->dmono_mode && sce_count == 2 &&
- !av_channel_layout_compare(&ac->oc[1].ch_layout,
- &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
- if (is_dmono) {
- if (ac->dmono_mode == 1)
- frame->data[1] = frame->data[0];
- else if (ac->dmono_mode == 2)
- frame->data[0] = frame->data[1];
- }
-
- return 0;
-fail:
- pop_output_configuration(ac);
- return err;
-}
-
-static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame_ptr, AVPacket *avpkt)
-{
- AACDecContext *ac = avctx->priv_data;
- const uint8_t *buf = avpkt->data;
- int buf_size = avpkt->size;
- GetBitContext gb;
- int buf_consumed;
- int buf_offset;
- int err;
- size_t new_extradata_size;
- const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
- AV_PKT_DATA_NEW_EXTRADATA,
- &new_extradata_size);
- size_t jp_dualmono_size;
- const uint8_t *jp_dualmono = av_packet_get_side_data(avpkt,
- AV_PKT_DATA_JP_DUALMONO,
- &jp_dualmono_size);
-
- if (new_extradata) {
- /* discard previous configuration */
- ac->oc[1].status = OC_NONE;
- err = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
- new_extradata,
- new_extradata_size * 8LL, 1);
- if (err < 0) {
- return err;
- }
- }
-
- ac->dmono_mode = 0;
- if (jp_dualmono && jp_dualmono_size > 0)
- ac->dmono_mode = 1 + *jp_dualmono;
- if (ac->force_dmono_mode >= 0)
- ac->dmono_mode = ac->force_dmono_mode;
-
- if (INT_MAX / 8 <= buf_size)
- return AVERROR_INVALIDDATA;
-
- if ((err = init_get_bits8(&gb, buf, buf_size)) < 0)
- return err;
-
- switch (ac->oc[1].m4ac.object_type) {
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_LD:
- case AOT_ER_AAC_ELD:
- err = aac_decode_er_frame(avctx, frame, got_frame_ptr, &gb);
- break;
- default:
- err = aac_decode_frame_int(avctx, frame, got_frame_ptr, &gb, avpkt);
- }
- if (err < 0)
- return err;
-
- buf_consumed = (get_bits_count(&gb) + 7) >> 3;
- for (buf_offset = buf_consumed; buf_offset < buf_size; buf_offset++)
- if (buf[buf_offset])
- break;
-
- return buf_size > buf_offset ? buf_consumed : buf_size;
-}
--
2.43.0.381.gb435a96ce8
[-- Attachment #8: 0032-aacdec-move-LATM-decode-functions-into-a-separate-fi.patch --]
[-- Type: text/x-diff, Size: 24021 bytes --]
From 63bb2db6611156b9ed4ce051ae08f4e7272b870c Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 23:34:46 +0100
Subject: [PATCH 32/38] aacdec: move LATM decode functions into a separate file
---
libavcodec/aac/aacdec_latm.h | 345 +++++++++++++++++++++++++++++++++++
libavcodec/aacdec.c | 315 +-------------------------------
2 files changed, 346 insertions(+), 314 deletions(-)
create mode 100644 libavcodec/aac/aacdec_latm.h
diff --git a/libavcodec/aac/aacdec_latm.h b/libavcodec/aac/aacdec_latm.h
new file mode 100644
index 0000000000..031b392d93
--- /dev/null
+++ b/libavcodec/aac/aacdec_latm.h
@@ -0,0 +1,345 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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 LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
+
+struct LATMContext {
+ AACDecContext aac_ctx; ///< containing AACContext
+ int initialized; ///< initialized after a valid extradata was seen
+
+ // parser data
+ int audio_mux_version_A; ///< LATM syntax version
+ int frame_length_type; ///< 0/1 variable/fixed frame length
+ int frame_length; ///< frame length for fixed frame length
+};
+
+static inline uint32_t latm_get_value(GetBitContext *b)
+{
+ int length = get_bits(b, 2);
+
+ return get_bits_long(b, (length+1)*8);
+}
+
+static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
+ GetBitContext *gb, int asclen)
+{
+ AACDecContext *ac = &latmctx->aac_ctx;
+ AVCodecContext *avctx = ac->avctx;
+ MPEG4AudioConfig m4ac = { 0 };
+ GetBitContext gbc;
+ int config_start_bit = get_bits_count(gb);
+ int sync_extension = 0;
+ int bits_consumed, esize, i;
+
+ if (asclen > 0) {
+ sync_extension = 1;
+ asclen = FFMIN(asclen, get_bits_left(gb));
+ init_get_bits(&gbc, gb->buffer, config_start_bit + asclen);
+ skip_bits_long(&gbc, config_start_bit);
+ } else if (asclen == 0) {
+ gbc = *gb;
+ } else {
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (get_bits_left(gb) <= 0)
+ return AVERROR_INVALIDDATA;
+
+ bits_consumed = decode_audio_specific_config_gb(NULL, avctx, &m4ac,
+ &gbc, config_start_bit,
+ sync_extension);
+
+ if (bits_consumed < config_start_bit)
+ return AVERROR_INVALIDDATA;
+ bits_consumed -= config_start_bit;
+
+ if (asclen == 0)
+ asclen = bits_consumed;
+
+ if (!latmctx->initialized ||
+ ac->oc[1].m4ac.sample_rate != m4ac.sample_rate ||
+ ac->oc[1].m4ac.chan_config != m4ac.chan_config) {
+
+ if (latmctx->initialized) {
+ av_log(avctx, AV_LOG_INFO, "audio config changed (sample_rate=%d, chan_config=%d)\n", m4ac.sample_rate, m4ac.chan_config);
+ } else {
+ av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n");
+ }
+ latmctx->initialized = 0;
+
+ esize = (asclen + 7) / 8;
+
+ if (avctx->extradata_size < esize) {
+ av_free(avctx->extradata);
+ avctx->extradata = av_malloc(esize + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!avctx->extradata)
+ return AVERROR(ENOMEM);
+ }
+
+ avctx->extradata_size = esize;
+ gbc = *gb;
+ for (i = 0; i < esize; i++) {
+ avctx->extradata[i] = get_bits(&gbc, 8);
+ }
+ memset(avctx->extradata+esize, 0, AV_INPUT_BUFFER_PADDING_SIZE);
+ }
+ skip_bits_long(gb, asclen);
+
+ return 0;
+}
+
+static int read_stream_mux_config(struct LATMContext *latmctx,
+ GetBitContext *gb)
+{
+ int ret, audio_mux_version = get_bits(gb, 1);
+
+ latmctx->audio_mux_version_A = 0;
+ if (audio_mux_version)
+ latmctx->audio_mux_version_A = get_bits(gb, 1);
+
+ if (!latmctx->audio_mux_version_A) {
+
+ if (audio_mux_version)
+ latm_get_value(gb); // taraFullness
+
+ skip_bits(gb, 1); // allStreamSameTimeFraming
+ skip_bits(gb, 6); // numSubFrames
+ // numPrograms
+ if (get_bits(gb, 4)) { // numPrograms
+ avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple programs");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // for each program (which there is only one in DVB)
+
+ // for each layer (which there is only one in DVB)
+ if (get_bits(gb, 3)) { // numLayer
+ avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple layers");
+ return AVERROR_PATCHWELCOME;
+ }
+
+ // for all but first stream: use_same_config = get_bits(gb, 1);
+ if (!audio_mux_version) {
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb, 0)) < 0)
+ return ret;
+ } else {
+ int ascLen = latm_get_value(gb);
+ if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0)
+ return ret;
+ }
+
+ latmctx->frame_length_type = get_bits(gb, 3);
+ switch (latmctx->frame_length_type) {
+ case 0:
+ skip_bits(gb, 8); // latmBufferFullness
+ break;
+ case 1:
+ latmctx->frame_length = get_bits(gb, 9);
+ break;
+ case 3:
+ case 4:
+ case 5:
+ skip_bits(gb, 6); // CELP frame length table index
+ break;
+ case 6:
+ case 7:
+ skip_bits(gb, 1); // HVXC frame length table index
+ break;
+ }
+
+ if (get_bits(gb, 1)) { // other data
+ if (audio_mux_version) {
+ latm_get_value(gb); // other_data_bits
+ } else {
+ int esc;
+ do {
+ if (get_bits_left(gb) < 9)
+ return AVERROR_INVALIDDATA;
+ esc = get_bits(gb, 1);
+ skip_bits(gb, 8);
+ } while (esc);
+ }
+ }
+
+ if (get_bits(gb, 1)) // crc present
+ skip_bits(gb, 8); // config_crc
+ }
+
+ return 0;
+}
+
+static int read_payload_length_info(struct LATMContext *ctx, GetBitContext *gb)
+{
+ uint8_t tmp;
+
+ if (ctx->frame_length_type == 0) {
+ int mux_slot_length = 0;
+ do {
+ if (get_bits_left(gb) < 8)
+ return AVERROR_INVALIDDATA;
+ tmp = get_bits(gb, 8);
+ mux_slot_length += tmp;
+ } while (tmp == 255);
+ return mux_slot_length;
+ } else if (ctx->frame_length_type == 1) {
+ return ctx->frame_length;
+ } else if (ctx->frame_length_type == 3 ||
+ ctx->frame_length_type == 5 ||
+ ctx->frame_length_type == 7) {
+ skip_bits(gb, 2); // mux_slot_length_coded
+ }
+ return 0;
+}
+
+static int read_audio_mux_element(struct LATMContext *latmctx,
+ GetBitContext *gb)
+{
+ int err;
+ uint8_t use_same_mux = get_bits(gb, 1);
+ if (!use_same_mux) {
+ if ((err = read_stream_mux_config(latmctx, gb)) < 0)
+ return err;
+ } else if (!latmctx->aac_ctx.avctx->extradata) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG,
+ "no decoder config found\n");
+ return 1;
+ }
+ if (latmctx->audio_mux_version_A == 0) {
+ int mux_slot_length_bytes = read_payload_length_info(latmctx, gb);
+ if (mux_slot_length_bytes < 0 || mux_slot_length_bytes * 8LL > get_bits_left(gb)) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, "incomplete frame\n");
+ return AVERROR_INVALIDDATA;
+ } else if (mux_slot_length_bytes * 8 + 256 < get_bits_left(gb)) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
+ "frame length mismatch %d << %d\n",
+ mux_slot_length_bytes * 8, get_bits_left(gb));
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ return 0;
+}
+
+
+static int latm_decode_frame(AVCodecContext *avctx, AVFrame *out,
+ int *got_frame_ptr, AVPacket *avpkt)
+{
+ struct LATMContext *latmctx = avctx->priv_data;
+ int muxlength, err;
+ GetBitContext gb;
+
+ if ((err = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
+ return err;
+
+ // check for LOAS sync word
+ if (get_bits(&gb, 11) != LOAS_SYNC_WORD)
+ return AVERROR_INVALIDDATA;
+
+ muxlength = get_bits(&gb, 13) + 3;
+ // not enough data, the parser should have sorted this out
+ if (muxlength > avpkt->size)
+ return AVERROR_INVALIDDATA;
+
+ if ((err = read_audio_mux_element(latmctx, &gb)))
+ return (err < 0) ? err : avpkt->size;
+
+ if (!latmctx->initialized) {
+ if (!avctx->extradata) {
+ *got_frame_ptr = 0;
+ return avpkt->size;
+ } else {
+ push_output_configuration(&latmctx->aac_ctx);
+ if ((err = decode_audio_specific_config(
+ &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.oc[1].m4ac,
+ avctx->extradata, avctx->extradata_size*8LL, 1)) < 0) {
+ pop_output_configuration(&latmctx->aac_ctx);
+ return err;
+ }
+ latmctx->initialized = 1;
+ }
+ }
+
+ if (show_bits(&gb, 12) == 0xfff) {
+ av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
+ "ADTS header detected, probably as result of configuration "
+ "misparsing\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ switch (latmctx->aac_ctx.oc[1].m4ac.object_type) {
+ case AOT_ER_AAC_LC:
+ case AOT_ER_AAC_LTP:
+ case AOT_ER_AAC_LD:
+ case AOT_ER_AAC_ELD:
+ err = aac_decode_er_frame(avctx, out, got_frame_ptr, &gb);
+ break;
+ default:
+ err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb, avpkt);
+ }
+ if (err < 0)
+ return err;
+
+ return muxlength;
+}
+
+static av_cold int latm_decode_init(AVCodecContext *avctx)
+{
+ struct LATMContext *latmctx = avctx->priv_data;
+ int ret = aac_decode_init(avctx);
+
+ if (avctx->extradata_size > 0)
+ latmctx->initialized = !ret;
+
+ return ret;
+}
+
+/*
+ Note: This decoder filter is intended to decode LATM streams transferred
+ in MPEG transport streams which only contain one program.
+ To do a more complex LATM demuxing a separate LATM demuxer should be used.
+*/
+const FFCodec ff_aac_latm_decoder = {
+ .p.name = "aac_latm",
+ CODEC_LONG_NAME("AAC LATM (Advanced Audio Coding LATM syntax)"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC_LATM,
+ .priv_data_size = sizeof(struct LATMContext),
+ .init = latm_decode_init,
+ .close = ff_aac_decode_close,
+ FF_CODEC_DECODE_CB(latm_decode_frame),
+ .p.sample_fmts = (const enum AVSampleFormat[]) {
+ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
+ },
+ .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .p.ch_layouts = ff_aac_ch_layout,
+ .flush = flush,
+ .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
+};
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 1e7bdb6416..bf1b1c29c7 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -65,296 +65,7 @@
#include "aacdec_template.c"
-#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
-
-struct LATMContext {
- AACDecContext aac_ctx; ///< containing AACContext
- int initialized; ///< initialized after a valid extradata was seen
-
- // parser data
- int audio_mux_version_A; ///< LATM syntax version
- int frame_length_type; ///< 0/1 variable/fixed frame length
- int frame_length; ///< frame length for fixed frame length
-};
-
-static inline uint32_t latm_get_value(GetBitContext *b)
-{
- int length = get_bits(b, 2);
-
- return get_bits_long(b, (length+1)*8);
-}
-
-static int latm_decode_audio_specific_config(struct LATMContext *latmctx,
- GetBitContext *gb, int asclen)
-{
- AACDecContext *ac = &latmctx->aac_ctx;
- AVCodecContext *avctx = ac->avctx;
- MPEG4AudioConfig m4ac = { 0 };
- GetBitContext gbc;
- int config_start_bit = get_bits_count(gb);
- int sync_extension = 0;
- int bits_consumed, esize, i;
-
- if (asclen > 0) {
- sync_extension = 1;
- asclen = FFMIN(asclen, get_bits_left(gb));
- init_get_bits(&gbc, gb->buffer, config_start_bit + asclen);
- skip_bits_long(&gbc, config_start_bit);
- } else if (asclen == 0) {
- gbc = *gb;
- } else {
- return AVERROR_INVALIDDATA;
- }
-
- if (get_bits_left(gb) <= 0)
- return AVERROR_INVALIDDATA;
-
- bits_consumed = decode_audio_specific_config_gb(NULL, avctx, &m4ac,
- &gbc, config_start_bit,
- sync_extension);
-
- if (bits_consumed < config_start_bit)
- return AVERROR_INVALIDDATA;
- bits_consumed -= config_start_bit;
-
- if (asclen == 0)
- asclen = bits_consumed;
-
- if (!latmctx->initialized ||
- ac->oc[1].m4ac.sample_rate != m4ac.sample_rate ||
- ac->oc[1].m4ac.chan_config != m4ac.chan_config) {
-
- if (latmctx->initialized) {
- av_log(avctx, AV_LOG_INFO, "audio config changed (sample_rate=%d, chan_config=%d)\n", m4ac.sample_rate, m4ac.chan_config);
- } else {
- av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n");
- }
- latmctx->initialized = 0;
-
- esize = (asclen + 7) / 8;
-
- if (avctx->extradata_size < esize) {
- av_free(avctx->extradata);
- avctx->extradata = av_malloc(esize + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!avctx->extradata)
- return AVERROR(ENOMEM);
- }
-
- avctx->extradata_size = esize;
- gbc = *gb;
- for (i = 0; i < esize; i++) {
- avctx->extradata[i] = get_bits(&gbc, 8);
- }
- memset(avctx->extradata+esize, 0, AV_INPUT_BUFFER_PADDING_SIZE);
- }
- skip_bits_long(gb, asclen);
-
- return 0;
-}
-
-static int read_stream_mux_config(struct LATMContext *latmctx,
- GetBitContext *gb)
-{
- int ret, audio_mux_version = get_bits(gb, 1);
-
- latmctx->audio_mux_version_A = 0;
- if (audio_mux_version)
- latmctx->audio_mux_version_A = get_bits(gb, 1);
-
- if (!latmctx->audio_mux_version_A) {
-
- if (audio_mux_version)
- latm_get_value(gb); // taraFullness
-
- skip_bits(gb, 1); // allStreamSameTimeFraming
- skip_bits(gb, 6); // numSubFrames
- // numPrograms
- if (get_bits(gb, 4)) { // numPrograms
- avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple programs");
- return AVERROR_PATCHWELCOME;
- }
-
- // for each program (which there is only one in DVB)
-
- // for each layer (which there is only one in DVB)
- if (get_bits(gb, 3)) { // numLayer
- avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple layers");
- return AVERROR_PATCHWELCOME;
- }
-
- // for all but first stream: use_same_config = get_bits(gb, 1);
- if (!audio_mux_version) {
- if ((ret = latm_decode_audio_specific_config(latmctx, gb, 0)) < 0)
- return ret;
- } else {
- int ascLen = latm_get_value(gb);
- if ((ret = latm_decode_audio_specific_config(latmctx, gb, ascLen)) < 0)
- return ret;
- }
-
- latmctx->frame_length_type = get_bits(gb, 3);
- switch (latmctx->frame_length_type) {
- case 0:
- skip_bits(gb, 8); // latmBufferFullness
- break;
- case 1:
- latmctx->frame_length = get_bits(gb, 9);
- break;
- case 3:
- case 4:
- case 5:
- skip_bits(gb, 6); // CELP frame length table index
- break;
- case 6:
- case 7:
- skip_bits(gb, 1); // HVXC frame length table index
- break;
- }
-
- if (get_bits(gb, 1)) { // other data
- if (audio_mux_version) {
- latm_get_value(gb); // other_data_bits
- } else {
- int esc;
- do {
- if (get_bits_left(gb) < 9)
- return AVERROR_INVALIDDATA;
- esc = get_bits(gb, 1);
- skip_bits(gb, 8);
- } while (esc);
- }
- }
-
- if (get_bits(gb, 1)) // crc present
- skip_bits(gb, 8); // config_crc
- }
-
- return 0;
-}
-
-static int read_payload_length_info(struct LATMContext *ctx, GetBitContext *gb)
-{
- uint8_t tmp;
-
- if (ctx->frame_length_type == 0) {
- int mux_slot_length = 0;
- do {
- if (get_bits_left(gb) < 8)
- return AVERROR_INVALIDDATA;
- tmp = get_bits(gb, 8);
- mux_slot_length += tmp;
- } while (tmp == 255);
- return mux_slot_length;
- } else if (ctx->frame_length_type == 1) {
- return ctx->frame_length;
- } else if (ctx->frame_length_type == 3 ||
- ctx->frame_length_type == 5 ||
- ctx->frame_length_type == 7) {
- skip_bits(gb, 2); // mux_slot_length_coded
- }
- return 0;
-}
-
-static int read_audio_mux_element(struct LATMContext *latmctx,
- GetBitContext *gb)
-{
- int err;
- uint8_t use_same_mux = get_bits(gb, 1);
- if (!use_same_mux) {
- if ((err = read_stream_mux_config(latmctx, gb)) < 0)
- return err;
- } else if (!latmctx->aac_ctx.avctx->extradata) {
- av_log(latmctx->aac_ctx.avctx, AV_LOG_DEBUG,
- "no decoder config found\n");
- return 1;
- }
- if (latmctx->audio_mux_version_A == 0) {
- int mux_slot_length_bytes = read_payload_length_info(latmctx, gb);
- if (mux_slot_length_bytes < 0 || mux_slot_length_bytes * 8LL > get_bits_left(gb)) {
- av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR, "incomplete frame\n");
- return AVERROR_INVALIDDATA;
- } else if (mux_slot_length_bytes * 8 + 256 < get_bits_left(gb)) {
- av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
- "frame length mismatch %d << %d\n",
- mux_slot_length_bytes * 8, get_bits_left(gb));
- return AVERROR_INVALIDDATA;
- }
- }
- return 0;
-}
-
-
-static int latm_decode_frame(AVCodecContext *avctx, AVFrame *out,
- int *got_frame_ptr, AVPacket *avpkt)
-{
- struct LATMContext *latmctx = avctx->priv_data;
- int muxlength, err;
- GetBitContext gb;
-
- if ((err = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
- return err;
-
- // check for LOAS sync word
- if (get_bits(&gb, 11) != LOAS_SYNC_WORD)
- return AVERROR_INVALIDDATA;
-
- muxlength = get_bits(&gb, 13) + 3;
- // not enough data, the parser should have sorted this out
- if (muxlength > avpkt->size)
- return AVERROR_INVALIDDATA;
-
- if ((err = read_audio_mux_element(latmctx, &gb)))
- return (err < 0) ? err : avpkt->size;
-
- if (!latmctx->initialized) {
- if (!avctx->extradata) {
- *got_frame_ptr = 0;
- return avpkt->size;
- } else {
- push_output_configuration(&latmctx->aac_ctx);
- if ((err = decode_audio_specific_config(
- &latmctx->aac_ctx, avctx, &latmctx->aac_ctx.oc[1].m4ac,
- avctx->extradata, avctx->extradata_size*8LL, 1)) < 0) {
- pop_output_configuration(&latmctx->aac_ctx);
- return err;
- }
- latmctx->initialized = 1;
- }
- }
-
- if (show_bits(&gb, 12) == 0xfff) {
- av_log(latmctx->aac_ctx.avctx, AV_LOG_ERROR,
- "ADTS header detected, probably as result of configuration "
- "misparsing\n");
- return AVERROR_INVALIDDATA;
- }
-
- switch (latmctx->aac_ctx.oc[1].m4ac.object_type) {
- case AOT_ER_AAC_LC:
- case AOT_ER_AAC_LTP:
- case AOT_ER_AAC_LD:
- case AOT_ER_AAC_ELD:
- err = aac_decode_er_frame(avctx, out, got_frame_ptr, &gb);
- break;
- default:
- err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb, avpkt);
- }
- if (err < 0)
- return err;
-
- return muxlength;
-}
-
-static av_cold int latm_decode_init(AVCodecContext *avctx)
-{
- struct LATMContext *latmctx = avctx->priv_data;
- int ret = aac_decode_init(avctx);
-
- if (avctx->extradata_size > 0)
- latmctx->initialized = !ret;
-
- return ret;
-}
+#include "libavcodec/aac/aacdec_latm.h"
const FFCodec ff_aac_decoder = {
.p.name = "aac",
@@ -376,30 +87,6 @@ const FFCodec ff_aac_decoder = {
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
};
-/*
- Note: This decoder filter is intended to decode LATM streams transferred
- in MPEG transport streams which only contain one program.
- To do a more complex LATM demuxing a separate LATM demuxer should be used.
-*/
-const FFCodec ff_aac_latm_decoder = {
- .p.name = "aac_latm",
- CODEC_LONG_NAME("AAC LATM (Advanced Audio Coding LATM syntax)"),
- .p.type = AVMEDIA_TYPE_AUDIO,
- .p.id = AV_CODEC_ID_AAC_LATM,
- .priv_data_size = sizeof(struct LATMContext),
- .init = latm_decode_init,
- .close = ff_aac_decode_close,
- FF_CODEC_DECODE_CB(latm_decode_frame),
- .p.sample_fmts = (const enum AVSampleFormat[]) {
- AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
- },
- .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
- .p.ch_layouts = ff_aac_ch_layout,
- .flush = flush,
- .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
-};
-
const FFCodec ff_aac_fixed_decoder = {
.p.name = "aac_fixed",
CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
--
2.43.0.381.gb435a96ce8
[-- Attachment #9: 0031-aacdec-fully-detemplate-decoder-core.patch --]
[-- Type: text/x-diff, Size: 17663 bytes --]
From 382b47dc38ae4933ade2a8c31b478def0b81c515 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 06:27:39 +0100
Subject: [PATCH 31/38] aacdec: fully detemplate decoder core
---
libavcodec/Makefile | 2 +-
libavcodec/aac/aacdec_proc_template.c | 2 +-
libavcodec/aacdec.c | 22 +++++-
libavcodec/aacdec.h | 2 -
libavcodec/aacdec_fixed.c | 102 --------------------------
libavcodec/aacdec_template.c | 78 ++++++++++++++------
libavcodec/aacsbr.h | 22 ++++--
7 files changed, 95 insertions(+), 135 deletions(-)
delete mode 100644 libavcodec/aacdec_fixed.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 71bef865f5..6ba4a4140e 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -182,7 +182,7 @@ OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o \
aacsbr.o aacps_common.o aacps_float.o \
kbdwin.o \
sbrdsp.o aacpsdsp_float.o cbrt_data.o
-OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o \
+OBJS-$(CONFIG_AAC_FIXED_DECODER) += aactab.o \
aacsbr_fixed.o aacps_common.o aacps_fixed.o \
kbdwin.o \
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
diff --git a/libavcodec/aac/aacdec_proc_template.c b/libavcodec/aac/aacdec_proc_template.c
index 609aa2fcc5..319bf61993 100644
--- a/libavcodec/aac/aacdec_proc_template.c
+++ b/libavcodec/aac/aacdec_proc_template.c
@@ -385,7 +385,7 @@ static int AAC_RENAME(decode_cce)(AACDecContext *ac, GetBitContext *gb, ChannelE
scale = cce_scale[get_bits(gb, 2)];
#endif
- if ((ret = AAC_RENAME(ff_aac_decode_ics)(ac, sce, gb, 0, 0)))
+ if ((ret = ff_aac_decode_ics(ac, sce, gb, 0, 0)))
return ret;
for (c = 0; c < num_gain; c++) {
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index cc2b9bedfb..1e7bdb6416 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -32,7 +32,7 @@
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
*/
-#define USE_FIXED 0
+#define USE_FIXED 1 // aacsbr.h breaks without this
#include "libavutil/float_dsp.h"
#include "avcodec.h"
@@ -399,3 +399,23 @@ const FFCodec ff_aac_latm_decoder = {
.flush = flush,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
};
+
+const FFCodec ff_aac_fixed_decoder = {
+ .p.name = "aac_fixed",
+ CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
+ .p.type = AVMEDIA_TYPE_AUDIO,
+ .p.id = AV_CODEC_ID_AAC,
+ .p.priv_class = &ff_aac_decoder_class,
+ .priv_data_size = sizeof(AACDecContext),
+ .init = aac_decode_init_fixed,
+ .close = ff_aac_decode_close,
+ FF_CODEC_DECODE_CB(aac_decode_frame),
+ .p.sample_fmts = (const enum AVSampleFormat[]) {
+ AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE
+ },
+ .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .p.ch_layouts = ff_aac_ch_layout,
+ .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
+ .flush = flush,
+};
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 2e3ee961b0..3d15cef453 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -348,7 +348,5 @@ void ff_aacdec_init_mips(AACDecContext *c);
int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
GetBitContext *gb, int common_window, int scale_flag);
-int ff_aac_decode_ics_fixed(AACDecContext *ac, SingleChannelElement *sce,
- GetBitContext *gb, int common_window, int scale_flag);
#endif /* AVCODEC_AACDEC_H */
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
deleted file mode 100644
index 91ec616644..0000000000
--- a/libavcodec/aacdec_fixed.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2013
- * 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.
- *
- * AAC decoder fixed-point implementation
- *
- * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
- * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov 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
- */
-
-/**
- * @file
- * AAC decoder
- * @author Oded Shimon ( ods15 ods15 dyndns org )
- * @author Maxim Gavrilov ( maxim.gavrilov gmail com )
- *
- * Fixed point implementation
- * @author Stanislav Ocovaj ( stanislav.ocovaj imgtec com )
- */
-
-#define USE_FIXED 1
-
-#include "libavutil/fixed_dsp.h"
-#include "avcodec.h"
-#include "codec_internal.h"
-#include "get_bits.h"
-
-#include "aac.h"
-#include "aacdec.h"
-#include "aactab.h"
-#include "aac/aacdec_tab.h"
-#include "adts_header.h"
-#include "cbrt_data.h"
-#include "aacsbr.h"
-#include "mpeg4audio.h"
-#include "profiles.h"
-#include "libavutil/intfloat.h"
-
-#include <math.h>
-#include <string.h>
-
-#include "aacdec_template.c"
-
-const FFCodec ff_aac_fixed_decoder = {
- .p.name = "aac_fixed",
- CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
- .p.type = AVMEDIA_TYPE_AUDIO,
- .p.id = AV_CODEC_ID_AAC,
- .p.priv_class = &ff_aac_decoder_class,
- .priv_data_size = sizeof(AACDecContext),
- .init = aac_decode_init,
- .close = ff_aac_decode_close,
- FF_CODEC_DECODE_CB(aac_decode_frame),
- .p.sample_fmts = (const enum AVSampleFormat[]) {
- AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE
- },
- .p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
- .p.ch_layouts = ff_aac_ch_layout,
- .p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
- .flush = flush,
-};
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 76bc28e3d5..e90c3edff2 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -133,7 +133,11 @@ static av_cold int che_configure(AACDecContext *ac,
return AVERROR_INVALIDDATA;
if (che_pos) {
if (!ac->che[type][id]) {
- int ret = AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(ac, &ac->che[type][id], type);
+ int ret;
+ if (ac->is_fixed)
+ ret = ff_aac_sbr_ctx_alloc_init_fixed(ac, &ac->che[type][id], type);
+ else
+ ret = ff_aac_sbr_ctx_alloc_init(ac, &ac->che[type][id], type);
if (ret < 0)
return ret;
}
@@ -149,8 +153,12 @@ static av_cold int che_configure(AACDecContext *ac,
}
}
} else {
- if (ac->che[type][id])
- AAC_RENAME(ff_aac_sbr_ctx_close)(ac->che[type][id]);
+ if (ac->che[type][id]) {
+ if (ac->is_fixed)
+ ff_aac_sbr_ctx_close_fixed(ac->che[type][id]);
+ else
+ ff_aac_sbr_ctx_close(ac->che[type][id]);
+ }
av_freep(&ac->che[type][id]);
}
return 0;
@@ -1089,20 +1097,19 @@ static int sample_rate_idx (int rate)
static av_cold void aac_static_table_init(void)
{
- AAC_RENAME(ff_aac_sbr_init)();
+ ff_aac_sbr_init();
+ ff_aac_sbr_init_fixed();
ff_aacdec_common_init_once();
}
static AVOnce aac_table_init = AV_ONCE_INIT;
-static av_cold int aac_decode_init(AVCodecContext *avctx)
+static av_cold int aac_decode_init_internal(AVCodecContext *avctx)
{
AACDecContext *ac = avctx->priv_data;
int ret;
- ac->is_fixed = USE_FIXED;
-
if (avctx->sample_rate > 96000)
return AVERROR_INVALIDDATA;
@@ -1157,6 +1164,20 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
return ff_aac_decode_init_common(avctx);
}
+static av_cold int aac_decode_init(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ac->is_fixed = 0;
+ return aac_decode_init_internal(avctx);
+}
+
+static av_cold int aac_decode_init_fixed(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ ac->is_fixed = 1;
+ return aac_decode_init_internal(avctx);
+}
+
/**
* Skip data_stream_element; reference: table 4.10.
*/
@@ -1515,8 +1536,12 @@ static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
coef_len = coef_res + 3 - coef_compress;
tmp2_idx = 2 * coef_compress + coef_res;
- for (i = 0; i < tns->order[w][filt]; i++)
- tns->AAC_RENAME(coef)[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
+ for (i = 0; i < tns->order[w][filt]; i++) {
+ if (ac->is_fixed)
+ tns->coef_fixed[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
+ else
+ tns->coef[w][filt][i] = ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)];
+ }
}
}
}
@@ -1579,8 +1604,8 @@ static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
*
* @return Returns error status. 0 - OK, !0 - error
*/
-int AAC_RENAME(ff_aac_decode_ics)(AACDecContext *ac, SingleChannelElement *sce,
- GetBitContext *gb, int common_window, int scale_flag)
+int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
+ GetBitContext *gb, int common_window, int scale_flag)
{
Pulse pulse;
TemporalNoiseShaping *tns = &sce->tns;
@@ -1697,9 +1722,9 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
} else if (ms_present)
decode_mid_side_stereo(cpe, gb, ms_present);
}
- if ((ret = AAC_RENAME(ff_aac_decode_ics)(ac, &cpe->ch[0], gb, common_window, 0)))
+ if ((ret = ff_aac_decode_ics(ac, &cpe->ch[0], gb, common_window, 0)))
return ret;
- if ((ret = AAC_RENAME(ff_aac_decode_ics)(ac, &cpe->ch[1], gb, common_window, 0)))
+ if ((ret = ff_aac_decode_ics(ac, &cpe->ch[1], gb, common_window, 0)))
return ret;
if (common_window) {
@@ -1862,7 +1887,13 @@ static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cn
ac->oc[1].m4ac.sbr = 1;
ac->avctx->profile = AV_PROFILE_AAC_HE;
}
- res = AAC_RENAME(ff_aac_sbr_decode_extension)(ac, che, gb, crc_flag, cnt, elem_type);
+
+ if (ac->is_fixed)
+ res = ff_aac_sbr_decode_extension_fixed(ac, che, gb, crc_flag, cnt, elem_type);
+ else
+ res = ff_aac_sbr_decode_extension(ac, che, gb, crc_flag, cnt, elem_type);
+
+
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");
ac->warned_he_aac_mono = 1;
@@ -1970,9 +2001,14 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
ac->dsp.update_ltp(ac, &che->ch[1]);
}
if (ac->oc[1].m4ac.sbr > 0) {
- AAC_RENAME(ff_aac_sbr_apply)(ac, che, type,
- che->ch[0].AAC_RENAME(output),
- che->ch[1].AAC_RENAME(output));
+ if (ac->is_fixed)
+ ff_aac_sbr_apply_fixed(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
+ else
+ ff_aac_sbr_apply(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
}
}
if (type <= TYPE_CCE)
@@ -2092,13 +2128,13 @@ static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
skip_bits(gb, 4);
switch (elem_type) {
case TYPE_SCE:
- err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
break;
case TYPE_CPE:
err = decode_cpe(ac, gb, che);
break;
case TYPE_LFE:
- err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
break;
}
if (err < 0)
@@ -2193,7 +2229,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
switch (elem_type) {
case TYPE_SCE:
- err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
audio_found = 1;
sce_count++;
break;
@@ -2208,7 +2244,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
break;
case TYPE_LFE:
- err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
+ err = ff_aac_decode_ics(ac, &che->ch[0], gb, 0, 0);
audio_found = 1;
break;
diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h
index 4ace1e04d4..41ac53acea 100644
--- a/libavcodec/aacsbr.h
+++ b/libavcodec/aacsbr.h
@@ -70,23 +70,31 @@ enum {
FF_VISIBILITY_PUSH_HIDDEN
/** Initialize SBR. */
-void AAC_RENAME(ff_aac_sbr_init)(void);
+void ff_aac_sbr_init(void);
+void ff_aac_sbr_init_fixed(void);
/**
* Allocate an ExtChannelElement (if necessary) and
* initialize the SBR context contained in it.
*/
-int AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac, ChannelElement **che, int id_aac);
+int ff_aac_sbr_ctx_alloc_init(AACDecContext *ac, ChannelElement **che, int id_aac);
+int ff_aac_sbr_ctx_alloc_init_fixed(AACDecContext *ac, ChannelElement **che, int id_aac);
/** Close the SBR context implicitly contained in a ChannelElement. */
-void RENAME_FIXED(ff_aac_sbr_ctx_close)(ChannelElement *che);
void ff_aac_sbr_ctx_close(ChannelElement *che);
+void ff_aac_sbr_ctx_close_fixed(ChannelElement *che);
/** Decode one SBR element. */
-int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
- GetBitContext *gb, int crc, int cnt, int id_aac);
+int ff_aac_sbr_decode_extension(AACDecContext *ac, ChannelElement *che,
+ GetBitContext *gb, int crc, int cnt, int id_aac);
+int ff_aac_sbr_decode_extension_fixed(AACDecContext *ac, ChannelElement *che,
+ GetBitContext *gb, int crc, int cnt, int id_aac);
+
/** Apply one SBR element to one AAC element. */
-void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, ChannelElement *che,
- int id_aac, INTFLOAT* L, INTFLOAT* R);
+void ff_aac_sbr_apply(AACDecContext *ac, ChannelElement *che,
+ int id_aac, INTFLOAT* L, INTFLOAT* R);
+void ff_aac_sbr_apply_fixed(AACDecContext *ac, ChannelElement *che,
+ int id_aac, INTFLOAT* L, INTFLOAT* R);
+
FF_VISIBILITY_POP_HIDDEN
#endif /* AVCODEC_AACSBR_H */
--
2.43.0.381.gb435a96ce8
[-- Attachment #10: 0030-aacdec-move-fixed-float-DSP-initialization-to-templa.patch --]
[-- Type: text/x-diff, Size: 5854 bytes --]
From 8f232c307727e915d12531736cf959a3abcc445c Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 06:05:45 +0100
Subject: [PATCH 30/38] aacdec: move fixed/float DSP initialization to
templated init functions
---
libavcodec/aac/aacdec.c | 4 +---
libavcodec/aac/aacdec_dsp_template.c | 2 +-
libavcodec/aac/aacdec_fixed.c | 10 +++++++-
libavcodec/aac/aacdec_float.c | 16 ++++++++++++-
libavcodec/aacdec.h | 2 +-
libavcodec/aacdec_template.c | 35 ++++------------------------
6 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index d31c64d08d..3af0e808fd 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -124,9 +124,7 @@ av_cold int ff_aac_decode_init_common(AVCodecContext *avctx)
ac->dsp = is_fixed ? aac_dsp_fixed : aac_dsp;
ac->proc = is_fixed ? aac_proc_fixed : aac_proc;
- ac->dsp.init_tables();
-
- return 0;
+ return ac->dsp.init(ac);
}
#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 338e512ed2..f260d32e4a 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -616,7 +616,7 @@ static void AAC_RENAME(apply_prediction)(AACDecContext *ac, SingleChannelElement
}
const AACDecDSP AAC_RENAME(aac_dsp) = {
- .init_tables = &AAC_RENAME(init_tables),
+ .init = &AAC_RENAME(init),
.dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
.apply_mid_side_stereo = &AAC_RENAME(apply_mid_side_stereo),
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index 41f25d8148..d706cfcc92 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -35,6 +35,8 @@
#include "libavcodec/aac_defines.h"
+#include "libavcodec/avcodec.h"
+#include "libavcodec/aacdec.h"
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin_fixed_tablegen.h"
#include "libavcodec/kbdwin.h"
@@ -58,10 +60,16 @@ static void init_tables_fixed_fn(void)
init_sine_windows_fixed();
}
-static void init_tables_fixed(void)
+static int init_fixed(AACDecContext *ac)
{
static AVOnce init_fixed_once = AV_ONCE_INIT;
ff_thread_once(&init_fixed_once, init_tables_fixed_fn);
+
+ ac->fdsp = avpriv_alloc_fixed_dsp(ac->avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ if (!ac->fdsp)
+ return AVERROR(ENOMEM);
+
+ return 0;
}
static const int cce_scale_fixed[8] = {
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index 73aaa72f68..6801085098 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -35,6 +35,8 @@
#include "libavcodec/aac_defines.h"
+#include "libavcodec/avcodec.h"
+#include "libavcodec/aacdec.h"
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin.h"
#include "libavcodec/kbdwin.h"
@@ -61,10 +63,22 @@ static void init_tables_float_fn(void)
AAC_RENAME(ff_init_ff_sine_windows)(9);
}
-static void init_tables(void)
+static int init(AACDecContext *ac)
{
static AVOnce init_float_once = AV_ONCE_INIT;
ff_thread_once(&init_float_once, init_tables_float_fn);
+
+ ac->fdsp = avpriv_float_dsp_alloc(ac->avctx->flags & AV_CODEC_FLAG_BITEXACT);
+ if (!ac->fdsp)
+ return AVERROR(ENOMEM);
+
+ ff_aac_float_common_init();
+
+#if ARCH_MIPS
+ ff_aacdec_init_mips(ac);
+#endif
+
+ return 0;
}
static const float cce_scale[] = {
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 2a997823ee..2e3ee961b0 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -216,7 +216,7 @@ typedef struct AACDecProc {
* DSP-specific primitives
*/
typedef struct AACDecDSP {
- void (*init_tables)(void);
+ int (*init)(AACDecContext *ac);
void (*dequant_scalefactors)(SingleChannelElement *sce);
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 6894de7325..76bc28e3d5 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1087,18 +1087,11 @@ static int sample_rate_idx (int rate)
else return 11;
}
-static void aacdec_init(AACDecContext *ac);
-
static av_cold void aac_static_table_init(void)
{
AAC_RENAME(ff_aac_sbr_init)();
ff_aacdec_common_init_once();
-
-#if !USE_FIXED
- ff_aac_float_common_init();
-#else
-#endif
}
static AVOnce aac_table_init = AV_ONCE_INIT;
@@ -1120,12 +1113,10 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
ac->avctx = avctx;
ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
- aacdec_init(ac);
-#if USE_FIXED
- avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
-#else
- avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
-#endif /* USE_FIXED */
+ if (ac->is_fixed)
+ avctx->sample_fmt = AV_SAMPLE_FMT_S32P;
+ else
+ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
if (avctx->extradata_size > 0) {
if ((ret = decode_audio_specific_config(ac, ac->avctx, &ac->oc[1].m4ac,
@@ -1163,15 +1154,6 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
}
}
-#if USE_FIXED
- ac->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT);
-#else
- ac->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
-#endif /* USE_FIXED */
- if (!ac->fdsp) {
- return AVERROR(ENOMEM);
- }
-
return ff_aac_decode_init_common(avctx);
}
@@ -2410,12 +2392,3 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
return buf_size > buf_offset ? buf_consumed : buf_size;
}
-
-static void aacdec_init(AACDecContext *c)
-{
-#if !USE_FIXED
-#if ARCH_MIPS
- ff_aacdec_init_mips(c);
-#endif
-#endif /* !USE_FIXED */
-}
--
2.43.0.381.gb435a96ce8
[-- Attachment #11: 0029-aacdec-reuse-TNS-and-LTP-tables-between-fixed-and-fl.patch --]
[-- Type: text/x-diff, Size: 5024 bytes --]
From bf2d405e99718553106ab75dfc17ad9a6305b1c9 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 05:55:13 +0100
Subject: [PATCH 29/38] aacdec: reuse TNS and LTP tables between fixed and
float decoders
The fixed decoder derives the values from floats anyway.
---
libavcodec/aacdec_fixed.c | 50 ------------------------------------
libavcodec/aacdec_template.c | 14 ++++++----
2 files changed, 9 insertions(+), 55 deletions(-)
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 880c18b0f8..91ec616644 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -79,56 +79,6 @@
#include <math.h>
#include <string.h>
-DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_long_1024))[1024];
-DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_short_128))[128];
-DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_long_960))[960];
-DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_short_120))[120];
-
-/* @name ltp_coef
- * Table of the LTP coefficients
- */
-static const int ltp_coef_fixed[8] = {
- Q30(0.570829), Q30(0.696616), Q30(0.813004), Q30(0.911304),
- Q30(0.984900), Q30(1.067894), Q30(1.194601), Q30(1.369533),
-};
-
-/* @name tns_tmp2_map
- * Tables of the tmp2[] arrays of LPC coefficients used for TNS.
- * The suffix _M_N[] indicate the values of coef_compress and coef_res
- * respectively.
- * @{
- */
-static const int tns_tmp2_map_1_3[4] = {
- Q31(0.00000000), Q31(-0.43388373), Q31(0.64278758), Q31(0.34202015),
-};
-
-static const int tns_tmp2_map_0_3[8] = {
- Q31(0.00000000), Q31(-0.43388373), Q31(-0.78183150), Q31(-0.97492790),
- Q31(0.98480773), Q31( 0.86602539), Q31( 0.64278758), Q31( 0.34202015),
-};
-
-static const int tns_tmp2_map_1_4[8] = {
- Q31(0.00000000), Q31(-0.20791170), Q31(-0.40673664), Q31(-0.58778524),
- Q31(0.67369562), Q31( 0.52643216), Q31( 0.36124167), Q31( 0.18374951),
-};
-
-static const int tns_tmp2_map_0_4[16] = {
- Q31( 0.00000000), Q31(-0.20791170), Q31(-0.40673664), Q31(-0.58778524),
- Q31(-0.74314481), Q31(-0.86602539), Q31(-0.95105654), Q31(-0.99452192),
- Q31( 0.99573416), Q31( 0.96182561), Q31( 0.89516330), Q31( 0.79801720),
- Q31( 0.67369562), Q31( 0.52643216), Q31( 0.36124167), Q31( 0.18374951),
-};
-
-static const int * const tns_tmp2_map_fixed[4] = {
- tns_tmp2_map_0_3,
- tns_tmp2_map_0_4,
- tns_tmp2_map_1_3,
- tns_tmp2_map_1_4
-};
-// @}
-
-static const int exp2tab[4] = { Q31(1.0000000000/2), Q31(1.1892071150/2), Q31(1.4142135624/2), Q31(1.6817928305/2) }; // 2^0, 2^0.25, 2^0.5, 2^0.75
-
#include "aacdec_template.c"
const FFCodec ff_aac_fixed_decoder = {
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 27629676bb..6894de7325 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1217,13 +1217,17 @@ static int decode_prediction(AACDecContext *ac, IndividualChannelStream *ics,
/**
* Decode Long Term Prediction data; reference: table 4.xx.
*/
-static void decode_ltp(LongTermPrediction *ltp,
+static void decode_ltp(AACDecContext *ac, LongTermPrediction *ltp,
GetBitContext *gb, uint8_t max_sfb)
{
int sfb;
ltp->lag = get_bits(gb, 11);
- ltp->AAC_RENAME(coef) = AAC_RENAME2(ltp_coef)[get_bits(gb, 3)];
+ if (ac->is_fixed)
+ ltp->coef_fixed = Q30(ff_ltp_coef[get_bits(gb, 3)]);
+ else
+ ltp->coef = ff_ltp_coef[get_bits(gb, 3)];
+
for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
ltp->used[sfb] = get_bits1(gb);
}
@@ -1330,7 +1334,7 @@ static int decode_ics_info(AACDecContext *ac, IndividualChannelStream *ics,
goto fail;
}
if ((ics->ltp.present = get_bits(gb, 1)))
- decode_ltp(&ics->ltp, gb, ics->max_sfb);
+ decode_ltp(ac, &ics->ltp, gb, ics->max_sfb);
}
}
}
@@ -1530,7 +1534,7 @@ static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
tmp2_idx = 2 * coef_compress + coef_res;
for (i = 0; i < tns->order[w][filt]; i++)
- tns->AAC_RENAME(coef)[w][filt][i] = AAC_RENAME2(tns_tmp2_map)[tmp2_idx][get_bits(gb, coef_len)];
+ tns->AAC_RENAME(coef)[w][filt][i] = Q31(ff_tns_tmp2_map[tmp2_idx][get_bits(gb, coef_len)]);
}
}
}
@@ -1703,7 +1707,7 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
if (cpe->ch[1].ics.predictor_present &&
(ac->oc[1].m4ac.object_type != AOT_AAC_MAIN))
if ((cpe->ch[1].ics.ltp.present = get_bits(gb, 1)))
- decode_ltp(&cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
+ decode_ltp(ac, &cpe->ch[1].ics.ltp, gb, cpe->ch[1].ics.max_sfb);
ms_present = get_bits(gb, 2);
if (ms_present == 3) {
av_log(ac->avctx, AV_LOG_ERROR, "ms_present = 3 is reserved.\n");
--
2.43.0.381.gb435a96ce8
[-- Attachment #12: 0028-aacdec-move-prediction-to-separate-files.patch --]
[-- Type: text/x-diff, Size: 21779 bytes --]
From 87bece5780a8d0ce57ee324c4aa0f7d15aee4005 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 05:16:50 +0100
Subject: [PATCH 28/38] aacdec: move prediction to separate files
---
libavcodec/aac/aacdec_dsp_template.c | 48 +++++++
libavcodec/aac/aacdec_fixed.c | 1 +
libavcodec/aac/aacdec_fixed_prediction.h | 151 +++++++++++++++++++++++
libavcodec/aac/aacdec_float.c | 1 +
libavcodec/aac/aacdec_float_prediction.h | 100 +++++++++++++++
libavcodec/aacdec.c | 65 ----------
libavcodec/aacdec.h | 2 +
libavcodec/aacdec_fixed.c | 116 -----------------
libavcodec/aacdec_template.c | 52 +-------
9 files changed, 306 insertions(+), 230 deletions(-)
create mode 100644 libavcodec/aac/aacdec_fixed_prediction.h
create mode 100644 libavcodec/aac/aacdec_float_prediction.h
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index adcafa10e7..338e512ed2 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -569,6 +569,52 @@ static void AAC_RENAME(clip_output)(AACDecContext *ac, ChannelElement *che,
#endif
}
+static inline void reset_all_predictors(PredictorState *ps)
+{
+ int i;
+ for (i = 0; i < MAX_PREDICTORS; i++)
+ reset_predict_state(&ps[i]);
+}
+
+static inline void reset_predictor_group(PredictorState *ps, int group_num)
+{
+ int i;
+ for (i = group_num - 1; i < MAX_PREDICTORS; i += 30)
+ reset_predict_state(&ps[i]);
+}
+
+/**
+ * Apply AAC-Main style frequency domain prediction.
+ */
+static void AAC_RENAME(apply_prediction)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ int sfb, k;
+
+ if (!sce->ics.predictor_initialized) {
+ reset_all_predictors(sce->AAC_RENAME(predictor_state));
+ sce->ics.predictor_initialized = 1;
+ }
+
+ if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
+ for (sfb = 0;
+ sfb < ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index];
+ sfb++) {
+ for (k = sce->ics.swb_offset[sfb];
+ k < sce->ics.swb_offset[sfb + 1];
+ k++) {
+ predict(&sce->AAC_RENAME(predictor_state)[k],
+ &sce->AAC_RENAME(coeffs)[k],
+ sce->ics.predictor_present &&
+ sce->ics.prediction_used[sfb]);
+ }
+ }
+ if (sce->ics.predictor_reset_group)
+ reset_predictor_group(sce->AAC_RENAME(predictor_state),
+ sce->ics.predictor_reset_group);
+ } else
+ reset_all_predictors(sce->AAC_RENAME(predictor_state));
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.init_tables = &AAC_RENAME(init_tables),
@@ -579,6 +625,8 @@ const AACDecDSP AAC_RENAME(aac_dsp) = {
.apply_ltp = &AAC_RENAME(apply_ltp),
.update_ltp = &AAC_RENAME(update_ltp),
+ .apply_prediction = AAC_RENAME(apply_prediction),
+
.imdct_and_windowing = AAC_RENAME(imdct_and_windowing),
.imdct_and_windowing_960 = AAC_RENAME(imdct_and_windowing_960),
.imdct_and_windowing_ld = AAC_RENAME(imdct_and_windowing_ld),
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index dc3e8eaab6..41f25d8148 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -79,5 +79,6 @@ static const int cce_scale_fixed[8] = {
#include "aacdec_fixed_dequant.h"
#include "aacdec_fixed_coupling.h"
+#include "aacdec_fixed_prediction.h"
#include "aacdec_dsp_template.c"
#include "aacdec_proc_template.c"
diff --git a/libavcodec/aac/aacdec_fixed_prediction.h b/libavcodec/aac/aacdec_fixed_prediction.h
new file mode 100644
index 0000000000..008b50a4c1
--- /dev/null
+++ b/libavcodec/aac/aacdec_fixed_prediction.h
@@ -0,0 +1,151 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_AAC_AACDEC_FIXED_PREDICTION
+#define AVCODEC_AAC_AACDEC_FIXED_PREDICTION
+
+static av_always_inline SoftFloat flt16_round(SoftFloat pf)
+{
+ SoftFloat tmp;
+ int s;
+
+ tmp.exp = pf.exp;
+ s = pf.mant >> 31;
+ tmp.mant = (pf.mant ^ s) - s;
+ tmp.mant = (tmp.mant + 0x00200000U) & 0xFFC00000U;
+ tmp.mant = (tmp.mant ^ s) - s;
+
+ return tmp;
+}
+
+static av_always_inline SoftFloat flt16_even(SoftFloat pf)
+{
+ SoftFloat tmp;
+ int s;
+
+ tmp.exp = pf.exp;
+ s = pf.mant >> 31;
+ tmp.mant = (pf.mant ^ s) - s;
+ tmp.mant = (tmp.mant + 0x001FFFFFU + (tmp.mant & 0x00400000U >> 16)) & 0xFFC00000U;
+ tmp.mant = (tmp.mant ^ s) - s;
+
+ return tmp;
+}
+
+static av_always_inline SoftFloat flt16_trunc(SoftFloat pf)
+{
+ SoftFloat pun;
+ int s;
+
+ pun.exp = pf.exp;
+ s = pf.mant >> 31;
+ pun.mant = (pf.mant ^ s) - s;
+ pun.mant = pun.mant & 0xFFC00000U;
+ pun.mant = (pun.mant ^ s) - s;
+
+ return pun;
+}
+
+static av_always_inline void predict(PredictorState *ps, int *coef,
+ int output_enable)
+{
+ const SoftFloat a = { 1023410176, 0 }; // 61.0 / 64
+ const SoftFloat alpha = { 973078528, 0 }; // 29.0 / 32
+ SoftFloat e0, e1;
+ SoftFloat pv;
+ SoftFloat k1, k2;
+ SoftFloat r0 = ps->r0, r1 = ps->r1;
+ SoftFloat cor0 = ps->cor0, cor1 = ps->cor1;
+ SoftFloat var0 = ps->var0, var1 = ps->var1;
+ SoftFloat tmp;
+
+ if (var0.exp > 1 || (var0.exp == 1 && var0.mant > 0x20000000)) {
+ k1 = av_mul_sf(cor0, flt16_even(av_div_sf(a, var0)));
+ }
+ else {
+ k1.mant = 0;
+ k1.exp = 0;
+ }
+
+ if (var1.exp > 1 || (var1.exp == 1 && var1.mant > 0x20000000)) {
+ k2 = av_mul_sf(cor1, flt16_even(av_div_sf(a, var1)));
+ }
+ else {
+ k2.mant = 0;
+ k2.exp = 0;
+ }
+
+ tmp = av_mul_sf(k1, r0);
+ pv = flt16_round(av_add_sf(tmp, av_mul_sf(k2, r1)));
+ if (output_enable) {
+ int shift = 28 - pv.exp;
+
+ if (shift < 31) {
+ if (shift > 0) {
+ *coef += (unsigned)((pv.mant + (1 << (shift - 1))) >> shift);
+ } else
+ *coef += (unsigned)pv.mant << -shift;
+ }
+ }
+
+ e0 = av_int2sf(*coef, 2);
+ e1 = av_sub_sf(e0, tmp);
+
+ ps->cor1 = flt16_trunc(av_add_sf(av_mul_sf(alpha, cor1), av_mul_sf(r1, e1)));
+ tmp = av_add_sf(av_mul_sf(r1, r1), av_mul_sf(e1, e1));
+ tmp.exp--;
+ ps->var1 = flt16_trunc(av_add_sf(av_mul_sf(alpha, var1), tmp));
+ ps->cor0 = flt16_trunc(av_add_sf(av_mul_sf(alpha, cor0), av_mul_sf(r0, e0)));
+ tmp = av_add_sf(av_mul_sf(r0, r0), av_mul_sf(e0, e0));
+ tmp.exp--;
+ ps->var0 = flt16_trunc(av_add_sf(av_mul_sf(alpha, var0), tmp));
+
+ ps->r1 = flt16_trunc(av_mul_sf(a, av_sub_sf(r0, av_mul_sf(k1, e0))));
+ ps->r0 = flt16_trunc(av_mul_sf(a, e0));
+}
+
+static av_always_inline void reset_predict_state(PredictorState *ps)
+{
+ ps->r0.mant = 0;
+ ps->r0.exp = 0;
+ ps->r1.mant = 0;
+ ps->r1.exp = 0;
+ ps->cor0.mant = 0;
+ ps->cor0.exp = 0;
+ ps->cor1.mant = 0;
+ ps->cor1.exp = 0;
+ ps->var0.mant = 0x20000000;
+ ps->var0.exp = 1;
+ ps->var1.mant = 0x20000000;
+ ps->var1.exp = 1;
+}
+
+#endif /* AVCODEC_AAC_AACDEC_FIXED_PREDICTION */
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index bbb4aec0a2..73aaa72f68 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -147,5 +147,6 @@ static inline float *VMUL4S(float *dst, const float *v, unsigned idx,
#endif
#include "aacdec_float_coupling.h"
+#include "aacdec_float_prediction.h"
#include "aacdec_dsp_template.c"
#include "aacdec_proc_template.c"
diff --git a/libavcodec/aac/aacdec_float_prediction.h b/libavcodec/aac/aacdec_float_prediction.h
new file mode 100644
index 0000000000..338e59bc11
--- /dev/null
+++ b/libavcodec/aac/aacdec_float_prediction.h
@@ -0,0 +1,100 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_AAC_AACDEC_FLOAT_PREDICTION
+#define AVCODEC_AAC_AACDEC_FLOAT_PREDICTION
+
+static av_always_inline float flt16_round(float pf)
+{
+ union av_intfloat32 tmp;
+ tmp.f = pf;
+ tmp.i = (tmp.i + 0x00008000U) & 0xFFFF0000U;
+ return tmp.f;
+}
+
+static av_always_inline float flt16_even(float pf)
+{
+ union av_intfloat32 tmp;
+ tmp.f = pf;
+ tmp.i = (tmp.i + 0x00007FFFU + (tmp.i & 0x00010000U >> 16)) & 0xFFFF0000U;
+ return tmp.f;
+}
+
+static av_always_inline float flt16_trunc(float pf)
+{
+ union av_intfloat32 pun;
+ pun.f = pf;
+ pun.i &= 0xFFFF0000U;
+ return pun.f;
+}
+
+static av_always_inline void predict(PredictorState *ps, float *coef,
+ int output_enable)
+{
+ const float a = 0.953125; // 61.0 / 64
+ const float alpha = 0.90625; // 29.0 / 32
+ float e0, e1;
+ float pv;
+ float k1, k2;
+ float r0 = ps->r0, r1 = ps->r1;
+ float cor0 = ps->cor0, cor1 = ps->cor1;
+ float var0 = ps->var0, var1 = ps->var1;
+
+ k1 = var0 > 1 ? cor0 * flt16_even(a / var0) : 0;
+ k2 = var1 > 1 ? cor1 * flt16_even(a / var1) : 0;
+
+ pv = flt16_round(k1 * r0 + k2 * r1);
+ if (output_enable)
+ *coef += pv;
+
+ e0 = *coef;
+ e1 = e0 - k1 * r0;
+
+ ps->cor1 = flt16_trunc(alpha * cor1 + r1 * e1);
+ ps->var1 = flt16_trunc(alpha * var1 + 0.5f * (r1 * r1 + e1 * e1));
+ ps->cor0 = flt16_trunc(alpha * cor0 + r0 * e0);
+ ps->var0 = flt16_trunc(alpha * var0 + 0.5f * (r0 * r0 + e0 * e0));
+
+ ps->r1 = flt16_trunc(a * (r0 - k1 * e0));
+ ps->r0 = flt16_trunc(a * e0);
+}
+
+static av_always_inline void reset_predict_state(PredictorState *ps)
+{
+ ps->r0 = 0.0f;
+ ps->r1 = 0.0f;
+ ps->cor0 = 0.0f;
+ ps->cor1 = 0.0f;
+ ps->var0 = 1.0f;
+ ps->var1 = 1.0f;
+}
+
+#endif /* AVCODEC_AAC_AACDEC_FLOAT_PREDICTION */
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index d269b93564..cc2b9bedfb 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -63,71 +63,6 @@
# include "mips/aacdec_mips.h"
#endif
-static av_always_inline void reset_predict_state(PredictorState *ps)
-{
- ps->r0 = 0.0f;
- ps->r1 = 0.0f;
- ps->cor0 = 0.0f;
- ps->cor1 = 0.0f;
- ps->var0 = 1.0f;
- ps->var1 = 1.0f;
-}
-
-static av_always_inline float flt16_round(float pf)
-{
- union av_intfloat32 tmp;
- tmp.f = pf;
- tmp.i = (tmp.i + 0x00008000U) & 0xFFFF0000U;
- return tmp.f;
-}
-
-static av_always_inline float flt16_even(float pf)
-{
- union av_intfloat32 tmp;
- tmp.f = pf;
- tmp.i = (tmp.i + 0x00007FFFU + (tmp.i & 0x00010000U >> 16)) & 0xFFFF0000U;
- return tmp.f;
-}
-
-static av_always_inline float flt16_trunc(float pf)
-{
- union av_intfloat32 pun;
- pun.f = pf;
- pun.i &= 0xFFFF0000U;
- return pun.f;
-}
-
-static av_always_inline void predict(PredictorState *ps, float *coef,
- int output_enable)
-{
- const float a = 0.953125; // 61.0 / 64
- const float alpha = 0.90625; // 29.0 / 32
- float e0, e1;
- float pv;
- float k1, k2;
- float r0 = ps->r0, r1 = ps->r1;
- float cor0 = ps->cor0, cor1 = ps->cor1;
- float var0 = ps->var0, var1 = ps->var1;
-
- k1 = var0 > 1 ? cor0 * flt16_even(a / var0) : 0;
- k2 = var1 > 1 ? cor1 * flt16_even(a / var1) : 0;
-
- pv = flt16_round(k1 * r0 + k2 * r1);
- if (output_enable)
- *coef += pv;
-
- e0 = *coef;
- e1 = e0 - k1 * r0;
-
- ps->cor1 = flt16_trunc(alpha * cor1 + r1 * e1);
- ps->var1 = flt16_trunc(alpha * var1 + 0.5f * (r1 * r1 + e1 * e1));
- ps->cor0 = flt16_trunc(alpha * cor0 + r0 * e0);
- ps->var0 = flt16_trunc(alpha * var0 + 0.5f * (r0 * r0 + e0 * e0));
-
- ps->r1 = flt16_trunc(a * (r0 - k1 * e0));
- ps->r0 = flt16_trunc(a * e0);
-}
-
#include "aacdec_template.c"
#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index b78368d69f..2a997823ee 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -230,6 +230,8 @@ typedef struct AACDecDSP {
void (*apply_ltp)(AACDecContext *ac, SingleChannelElement *sce);
void (*update_ltp)(AACDecContext *ac, SingleChannelElement *sce);
+ void (*apply_prediction)(AACDecContext *ac, SingleChannelElement *sce);
+
void (*apply_dependent_coupling)(AACDecContext *ac,
SingleChannelElement *target,
ChannelElement *cce, int index);
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 03b39854f8..880c18b0f8 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -127,124 +127,8 @@ static const int * const tns_tmp2_map_fixed[4] = {
};
// @}
-static av_always_inline void reset_predict_state(PredictorState *ps)
-{
- ps->r0.mant = 0;
- ps->r0.exp = 0;
- ps->r1.mant = 0;
- ps->r1.exp = 0;
- ps->cor0.mant = 0;
- ps->cor0.exp = 0;
- ps->cor1.mant = 0;
- ps->cor1.exp = 0;
- ps->var0.mant = 0x20000000;
- ps->var0.exp = 1;
- ps->var1.mant = 0x20000000;
- ps->var1.exp = 1;
-}
-
static const int exp2tab[4] = { Q31(1.0000000000/2), Q31(1.1892071150/2), Q31(1.4142135624/2), Q31(1.6817928305/2) }; // 2^0, 2^0.25, 2^0.5, 2^0.75
-static av_always_inline SoftFloat flt16_round(SoftFloat pf)
-{
- SoftFloat tmp;
- int s;
-
- tmp.exp = pf.exp;
- s = pf.mant >> 31;
- tmp.mant = (pf.mant ^ s) - s;
- tmp.mant = (tmp.mant + 0x00200000U) & 0xFFC00000U;
- tmp.mant = (tmp.mant ^ s) - s;
-
- return tmp;
-}
-
-static av_always_inline SoftFloat flt16_even(SoftFloat pf)
-{
- SoftFloat tmp;
- int s;
-
- tmp.exp = pf.exp;
- s = pf.mant >> 31;
- tmp.mant = (pf.mant ^ s) - s;
- tmp.mant = (tmp.mant + 0x001FFFFFU + (tmp.mant & 0x00400000U >> 16)) & 0xFFC00000U;
- tmp.mant = (tmp.mant ^ s) - s;
-
- return tmp;
-}
-
-static av_always_inline SoftFloat flt16_trunc(SoftFloat pf)
-{
- SoftFloat pun;
- int s;
-
- pun.exp = pf.exp;
- s = pf.mant >> 31;
- pun.mant = (pf.mant ^ s) - s;
- pun.mant = pun.mant & 0xFFC00000U;
- pun.mant = (pun.mant ^ s) - s;
-
- return pun;
-}
-
-static av_always_inline void predict(PredictorState *ps, int *coef,
- int output_enable)
-{
- const SoftFloat a = { 1023410176, 0 }; // 61.0 / 64
- const SoftFloat alpha = { 973078528, 0 }; // 29.0 / 32
- SoftFloat e0, e1;
- SoftFloat pv;
- SoftFloat k1, k2;
- SoftFloat r0 = ps->r0, r1 = ps->r1;
- SoftFloat cor0 = ps->cor0, cor1 = ps->cor1;
- SoftFloat var0 = ps->var0, var1 = ps->var1;
- SoftFloat tmp;
-
- if (var0.exp > 1 || (var0.exp == 1 && var0.mant > 0x20000000)) {
- k1 = av_mul_sf(cor0, flt16_even(av_div_sf(a, var0)));
- }
- else {
- k1.mant = 0;
- k1.exp = 0;
- }
-
- if (var1.exp > 1 || (var1.exp == 1 && var1.mant > 0x20000000)) {
- k2 = av_mul_sf(cor1, flt16_even(av_div_sf(a, var1)));
- }
- else {
- k2.mant = 0;
- k2.exp = 0;
- }
-
- tmp = av_mul_sf(k1, r0);
- pv = flt16_round(av_add_sf(tmp, av_mul_sf(k2, r1)));
- if (output_enable) {
- int shift = 28 - pv.exp;
-
- if (shift < 31) {
- if (shift > 0) {
- *coef += (unsigned)((pv.mant + (1 << (shift - 1))) >> shift);
- } else
- *coef += (unsigned)pv.mant << -shift;
- }
- }
-
- e0 = av_int2sf(*coef, 2);
- e1 = av_sub_sf(e0, tmp);
-
- ps->cor1 = flt16_trunc(av_add_sf(av_mul_sf(alpha, cor1), av_mul_sf(r1, e1)));
- tmp = av_add_sf(av_mul_sf(r1, r1), av_mul_sf(e1, e1));
- tmp.exp--;
- ps->var1 = flt16_trunc(av_add_sf(av_mul_sf(alpha, var1), tmp));
- ps->cor0 = flt16_trunc(av_add_sf(av_mul_sf(alpha, cor0), av_mul_sf(r0, e0)));
- tmp = av_add_sf(av_mul_sf(r0, r0), av_mul_sf(e0, e0));
- tmp.exp--;
- ps->var0 = flt16_trunc(av_add_sf(av_mul_sf(alpha, var0), tmp));
-
- ps->r1 = flt16_trunc(av_mul_sf(a, av_sub_sf(r0, av_mul_sf(k1, e0))));
- ps->r0 = flt16_trunc(av_mul_sf(a, e0));
-}
-
#include "aacdec_template.c"
const FFCodec ff_aac_fixed_decoder = {
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index e6965df2ca..27629676bb 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1071,13 +1071,6 @@ static int decode_audio_specific_config(AACDecContext *ac,
sync_extension);
}
-static void reset_all_predictors(PredictorState *ps)
-{
- int i;
- for (i = 0; i < MAX_PREDICTORS; i++)
- reset_predict_state(&ps[i]);
-}
-
static int sample_rate_idx (int rate)
{
if (92017 <= rate) return 0;
@@ -1094,13 +1087,6 @@ static int sample_rate_idx (int rate)
else return 11;
}
-static void reset_predictor_group(PredictorState *ps, int group_num)
-{
- int i;
- for (i = group_num - 1; i < MAX_PREDICTORS; i += 30)
- reset_predict_state(&ps[i]);
-}
-
static void aacdec_init(AACDecContext *ac);
static av_cold void aac_static_table_init(void)
@@ -1572,38 +1558,6 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
}
}
-/**
- * Apply AAC-Main style frequency domain prediction.
- */
-static void apply_prediction(AACDecContext *ac, SingleChannelElement *sce)
-{
- int sfb, k;
-
- if (!sce->ics.predictor_initialized) {
- reset_all_predictors(sce->AAC_RENAME(predictor_state));
- sce->ics.predictor_initialized = 1;
- }
-
- if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
- for (sfb = 0;
- sfb < ff_aac_pred_sfb_max[ac->oc[1].m4ac.sampling_index];
- sfb++) {
- for (k = sce->ics.swb_offset[sfb];
- k < sce->ics.swb_offset[sfb + 1];
- k++) {
- predict(&sce->AAC_RENAME(predictor_state)[k],
- &sce->AAC_RENAME(coeffs)[k],
- sce->ics.predictor_present &&
- sce->ics.prediction_used[sfb]);
- }
- }
- if (sce->ics.predictor_reset_group)
- reset_predictor_group(sce->AAC_RENAME(predictor_state),
- sce->ics.predictor_reset_group);
- } else
- reset_all_predictors(sce->AAC_RENAME(predictor_state));
-}
-
static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
{
// wd_num, wd_test, aloc_size
@@ -1721,7 +1675,7 @@ int AAC_RENAME(ff_aac_decode_ics)(AACDecContext *ac, SingleChannelElement *sce,
goto fail;
if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN && !common_window)
- apply_prediction(ac, sce);
+ ac->dsp.apply_prediction(ac, sce);
return 0;
fail:
@@ -1766,8 +1720,8 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
if (ms_present)
ac->dsp.apply_mid_side_stereo(ac, cpe);
if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) {
- apply_prediction(ac, &cpe->ch[0]);
- apply_prediction(ac, &cpe->ch[1]);
+ ac->dsp.apply_prediction(ac, &cpe->ch[0]);
+ ac->dsp.apply_prediction(ac, &cpe->ch[1]);
}
}
--
2.43.0.381.gb435a96ce8
[-- Attachment #13: 0027-aacdec-move-CCE-decoding-to-a-separate-templated-fil.patch --]
[-- Type: text/x-diff, Size: 11696 bytes --]
From f027275552464369ebaaeafd396b356f124fce91 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 05:06:58 +0100
Subject: [PATCH 27/38] aacdec: move CCE decoding to a separate templated file
Unfortunately, although it's a purely decode function, it does
need to be templated.
---
libavcodec/aac/aacdec_float.c | 8 ++
libavcodec/aac/aacdec_proc_template.c | 85 ++++++++++++++++++++
libavcodec/aacdec.h | 7 ++
libavcodec/aacdec_template.c | 109 +++-----------------------
4 files changed, 109 insertions(+), 100 deletions(-)
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index 865a57deb1..bbb4aec0a2 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -39,6 +39,7 @@
#include "libavcodec/sinewin.h"
#include "libavcodec/kbdwin.h"
#include "libavcodec/cbrt_data.h"
+#include "libavutil/mathematics.h"
DECLARE_ALIGNED(32, static float, sine_120)[120];
DECLARE_ALIGNED(32, static float, sine_960)[960];
@@ -66,6 +67,13 @@ static void init_tables(void)
ff_thread_once(&init_float_once, init_tables_float_fn);
}
+static const float cce_scale[] = {
+ 1.09050773266525765921, //2^(1/8)
+ 1.18920711500272106672, //2^(1/4)
+ M_SQRT2,
+ 2,
+};
+
/** Dequantization-related **/
#include "aacdec_tab.h"
#include "libavutil/intfloat.h"
diff --git a/libavcodec/aac/aacdec_proc_template.c b/libavcodec/aac/aacdec_proc_template.c
index c3d607b4d3..609aa2fcc5 100644
--- a/libavcodec/aac/aacdec_proc_template.c
+++ b/libavcodec/aac/aacdec_proc_template.c
@@ -349,6 +349,91 @@ static int AAC_RENAME(decode_spectrum_and_dequant)(AACDecContext *ac,
return 0;
}
+/**
+ * Decode coupling_channel_element; reference: table 4.8.
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int AAC_RENAME(decode_cce)(AACDecContext *ac, GetBitContext *gb, ChannelElement *che)
+{
+ int num_gain = 0;
+ int c, g, sfb, ret;
+ int sign;
+ INTFLOAT scale;
+ SingleChannelElement *sce = &che->ch[0];
+ ChannelCoupling *coup = &che->coup;
+
+ coup->coupling_point = 2 * get_bits1(gb);
+ coup->num_coupled = get_bits(gb, 3);
+ for (c = 0; c <= coup->num_coupled; c++) {
+ num_gain++;
+ coup->type[c] = get_bits1(gb) ? TYPE_CPE : TYPE_SCE;
+ coup->id_select[c] = get_bits(gb, 4);
+ if (coup->type[c] == TYPE_CPE) {
+ coup->ch_select[c] = get_bits(gb, 2);
+ if (coup->ch_select[c] == 3)
+ num_gain++;
+ } else
+ coup->ch_select[c] = 2;
+ }
+ coup->coupling_point += get_bits1(gb) || (coup->coupling_point >> 1);
+
+ sign = get_bits(gb, 1);
+#if USE_FIXED
+ scale = get_bits(gb, 2);
+#else
+ scale = cce_scale[get_bits(gb, 2)];
+#endif
+
+ if ((ret = AAC_RENAME(ff_aac_decode_ics)(ac, sce, gb, 0, 0)))
+ return ret;
+
+ for (c = 0; c < num_gain; c++) {
+ int idx = 0;
+ int cge = 1;
+ int gain = 0;
+ INTFLOAT gain_cache = FIXR10(1.);
+ if (c) {
+ cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
+ gain = cge ? get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - 60: 0;
+ gain_cache = GET_GAIN(scale, gain);
+#if USE_FIXED
+ if ((abs(gain_cache)-1024) >> 3 > 30)
+ return AVERROR(ERANGE);
+#endif
+ }
+ if (coup->coupling_point == AFTER_IMDCT) {
+ coup->gain[c][0] = gain_cache;
+ } else {
+ for (g = 0; g < sce->ics.num_window_groups; g++) {
+ for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) {
+ if (sce->band_type[idx] != ZERO_BT) {
+ if (!cge) {
+ int t = get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - 60;
+ if (t) {
+ int s = 1;
+ t = gain += t;
+ if (sign) {
+ s -= 2 * (t & 0x1);
+ t >>= 1;
+ }
+ gain_cache = GET_GAIN(scale, t) * s;
+#if USE_FIXED
+ if ((abs(gain_cache)-1024) >> 3 > 30)
+ return AVERROR(ERANGE);
+#endif
+ }
+ }
+ coup->gain[c][idx] = gain_cache;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
const AACDecProc AAC_RENAME(aac_proc) = {
.decode_spectrum_and_dequant = AAC_RENAME(decode_spectrum_and_dequant),
+ .decode_cce = AAC_RENAME(decode_cce),
};
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index c8bcae4c4f..b78368d69f 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -208,6 +208,8 @@ typedef struct AACDecProc {
GetBitContext *gb,
const Pulse *pulse,
SingleChannelElement *sce);
+
+ int (*decode_cce)(AACDecContext *ac, GetBitContext *gb, ChannelElement *che);
} AACDecProc;
/**
@@ -342,4 +344,9 @@ int ff_aac_decode_close(struct AVCodecContext *avctx);
void ff_aacdec_init_mips(AACDecContext *c);
+int ff_aac_decode_ics(AACDecContext *ac, SingleChannelElement *sce,
+ GetBitContext *gb, int common_window, int scale_flag);
+int ff_aac_decode_ics_fixed(AACDecContext *ac, SingleChannelElement *sce,
+ GetBitContext *gb, int common_window, int scale_flag);
+
#endif /* AVCODEC_AACDEC_H */
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 76c80e28b5..e6965df2ca 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1639,8 +1639,8 @@ static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
- GetBitContext *gb, int common_window, int scale_flag)
+int AAC_RENAME(ff_aac_decode_ics)(AACDecContext *ac, SingleChannelElement *sce,
+ GetBitContext *gb, int common_window, int scale_flag)
{
Pulse pulse;
TemporalNoiseShaping *tns = &sce->tns;
@@ -1757,9 +1757,9 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
} else if (ms_present)
decode_mid_side_stereo(cpe, gb, ms_present);
}
- if ((ret = decode_ics(ac, &cpe->ch[0], gb, common_window, 0)))
+ if ((ret = AAC_RENAME(ff_aac_decode_ics)(ac, &cpe->ch[0], gb, common_window, 0)))
return ret;
- if ((ret = decode_ics(ac, &cpe->ch[1], gb, common_window, 0)))
+ if ((ret = AAC_RENAME(ff_aac_decode_ics)(ac, &cpe->ch[1], gb, common_window, 0)))
return ret;
if (common_window) {
@@ -1775,97 +1775,6 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
return 0;
}
-static const float cce_scale[] = {
- 1.09050773266525765921, //2^(1/8)
- 1.18920711500272106672, //2^(1/4)
- M_SQRT2,
- 2,
-};
-
-/**
- * Decode coupling_channel_element; reference: table 4.8.
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_cce(AACDecContext *ac, GetBitContext *gb, ChannelElement *che)
-{
- int num_gain = 0;
- int c, g, sfb, ret;
- int sign;
- INTFLOAT scale;
- SingleChannelElement *sce = &che->ch[0];
- ChannelCoupling *coup = &che->coup;
-
- coup->coupling_point = 2 * get_bits1(gb);
- coup->num_coupled = get_bits(gb, 3);
- for (c = 0; c <= coup->num_coupled; c++) {
- num_gain++;
- coup->type[c] = get_bits1(gb) ? TYPE_CPE : TYPE_SCE;
- coup->id_select[c] = get_bits(gb, 4);
- if (coup->type[c] == TYPE_CPE) {
- coup->ch_select[c] = get_bits(gb, 2);
- if (coup->ch_select[c] == 3)
- num_gain++;
- } else
- coup->ch_select[c] = 2;
- }
- coup->coupling_point += get_bits1(gb) || (coup->coupling_point >> 1);
-
- sign = get_bits(gb, 1);
-#if USE_FIXED
- scale = get_bits(gb, 2);
-#else
- scale = cce_scale[get_bits(gb, 2)];
-#endif
-
- if ((ret = decode_ics(ac, sce, gb, 0, 0)))
- return ret;
-
- for (c = 0; c < num_gain; c++) {
- int idx = 0;
- int cge = 1;
- int gain = 0;
- INTFLOAT gain_cache = FIXR10(1.);
- if (c) {
- cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
- gain = cge ? get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - 60: 0;
- gain_cache = GET_GAIN(scale, gain);
-#if USE_FIXED
- if ((abs(gain_cache)-1024) >> 3 > 30)
- return AVERROR(ERANGE);
-#endif
- }
- if (coup->coupling_point == AFTER_IMDCT) {
- coup->gain[c][0] = gain_cache;
- } else {
- for (g = 0; g < sce->ics.num_window_groups; g++) {
- for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++) {
- if (sce->band_type[idx] != ZERO_BT) {
- if (!cge) {
- int t = get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - 60;
- if (t) {
- int s = 1;
- t = gain += t;
- if (sign) {
- s -= 2 * (t & 0x1);
- t >>= 1;
- }
- gain_cache = GET_GAIN(scale, t) * s;
-#if USE_FIXED
- if ((abs(gain_cache)-1024) >> 3 > 30)
- return AVERROR(ERANGE);
-#endif
- }
- }
- coup->gain[c][idx] = gain_cache;
- }
- }
- }
- }
- }
- return 0;
-}
-
/**
* Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
*
@@ -2243,13 +2152,13 @@ static int aac_decode_er_frame(AVCodecContext *avctx, AVFrame *frame,
skip_bits(gb, 4);
switch (elem_type) {
case TYPE_SCE:
- err = decode_ics(ac, &che->ch[0], gb, 0, 0);
+ err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
break;
case TYPE_CPE:
err = decode_cpe(ac, gb, che);
break;
case TYPE_LFE:
- err = decode_ics(ac, &che->ch[0], gb, 0, 0);
+ err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
break;
}
if (err < 0)
@@ -2344,7 +2253,7 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
switch (elem_type) {
case TYPE_SCE:
- err = decode_ics(ac, &che->ch[0], gb, 0, 0);
+ err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
audio_found = 1;
sce_count++;
break;
@@ -2355,11 +2264,11 @@ static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,
break;
case TYPE_CCE:
- err = decode_cce(ac, gb, che);
+ err = ac->proc.decode_cce(ac, gb, che);
break;
case TYPE_LFE:
- err = decode_ics(ac, &che->ch[0], gb, 0, 0);
+ err = AAC_RENAME(ff_aac_decode_ics)(ac, &che->ch[0], gb, 0, 0);
audio_found = 1;
break;
--
2.43.0.381.gb435a96ce8
[-- Attachment #14: 0026-aacdec-move-fixed-point-clipping-to-a-separate-funct.patch --]
[-- Type: text/x-diff, Size: 3893 bytes --]
From 0e7455e5003868a1c242b6a6dff771f735d117b2 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 04:29:07 +0100
Subject: [PATCH 26/38] aacdec: move fixed-point clipping to a separate
function
---
libavcodec/aac/aacdec_dsp_template.c | 17 +++++++++++++++++
libavcodec/aacdec.h | 2 ++
libavcodec/aacdec_template.c | 15 +--------------
3 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index a72ccf891c..adcafa10e7 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -554,6 +554,21 @@ static void AAC_RENAME(imdct_and_windowing_eld)(AACDecContext *ac, SingleChannel
memcpy( saved, buf, n * sizeof(*saved));
}
+static void AAC_RENAME(clip_output)(AACDecContext *ac, ChannelElement *che,
+ int type, int samples)
+{
+#if USE_FIXED
+ /* preparation for resampler */
+ for (int j = 0; j < samples; j++){
+ che->ch[0].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[0].output_fixed[j]*128,
+ INT32_MIN, INT32_MAX-0x8000)+0x8000;
+ if (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))
+ che->ch[1].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[1].output_fixed[j]*128,
+ INT32_MIN, INT32_MAX-0x8000)+0x8000;
+ }
+#endif
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.init_tables = &AAC_RENAME(init_tables),
@@ -571,4 +586,6 @@ const AACDecDSP AAC_RENAME(aac_dsp) = {
.apply_dependent_coupling = AAC_RENAME(apply_dependent_coupling),
.apply_independent_coupling = AAC_RENAME(apply_independent_coupling),
+
+ .clip_output = AAC_RENAME(clip_output),
};
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 91ffb877da..c8bcae4c4f 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -239,6 +239,8 @@ typedef struct AACDecDSP {
void (*imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce);
void (*imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce);
void (*imdct_and_windowing_eld)(AACDecContext *ac, SingleChannelElement *sce);
+
+ void (*clip_output)(AACDecContext *ac, ChannelElement *che, int type, int samples);
} AACDecDSP;
/**
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index dc28a0e2e0..76c80e28b5 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2128,20 +2128,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
}
if (type <= TYPE_CCE)
apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling);
-
-#if USE_FIXED
- {
- int j;
- /* preparation for resampler */
- for(j = 0; j<samples; j++){
- che->ch[0].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[0].output_fixed[j]*128,
- INT32_MIN, INT32_MAX-0x8000)+0x8000;
- if (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))
- che->ch[1].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[1].output_fixed[j]*128,
- INT32_MIN, INT32_MAX-0x8000)+0x8000;
- }
- }
-#endif /* USE_FIXED */
+ ac->dsp.clip_output(ac, che, type, samples);
che->present = 0;
} else if (che) {
av_log(ac->avctx, AV_LOG_VERBOSE, "ChannelElement %d.%d missing \n", type, i);
--
2.43.0.381.gb435a96ce8
[-- Attachment #15: 0025-aacdec-split-off-channel-coupling-into-a-new-file.patch --]
[-- Type: text/x-diff, Size: 21541 bytes --]
From 4d825208996981e0df73653ff0da2ab8f1362e86 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 04:17:30 +0100
Subject: [PATCH 25/38] aacdec: split off channel coupling into a new file
---
libavcodec/aac/aacdec_dsp_template.c | 3 +
libavcodec/aac/aacdec_fixed.c | 12 +++
libavcodec/aac/aacdec_fixed_coupling.h | 137 +++++++++++++++++++++++++
libavcodec/aac/aacdec_float.c | 1 +
libavcodec/aac/aacdec_float_coupling.h | 90 ++++++++++++++++
libavcodec/aacdec.c | 53 ----------
libavcodec/aacdec.h | 7 ++
libavcodec/aacdec_fixed.c | 112 --------------------
libavcodec/aacdec_template.c | 6 +-
9 files changed, 253 insertions(+), 168 deletions(-)
create mode 100644 libavcodec/aac/aacdec_fixed_coupling.h
create mode 100644 libavcodec/aac/aacdec_float_coupling.h
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index a04d358883..a72ccf891c 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -568,4 +568,7 @@ const AACDecDSP AAC_RENAME(aac_dsp) = {
.imdct_and_windowing_960 = AAC_RENAME(imdct_and_windowing_960),
.imdct_and_windowing_ld = AAC_RENAME(imdct_and_windowing_ld),
.imdct_and_windowing_eld = AAC_RENAME(imdct_and_windowing_eld),
+
+ .apply_dependent_coupling = AAC_RENAME(apply_dependent_coupling),
+ .apply_independent_coupling = AAC_RENAME(apply_independent_coupling),
};
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index 08e9c3a03f..dc3e8eaab6 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -64,8 +64,20 @@ static void init_tables_fixed(void)
ff_thread_once(&init_fixed_once, init_tables_fixed_fn);
}
+static const int cce_scale_fixed[8] = {
+ Q30(1.0), //2^(0/8)
+ Q30(1.0905077327), //2^(1/8)
+ Q30(1.1892071150), //2^(2/8)
+ Q30(1.2968395547), //2^(3/8)
+ Q30(1.4142135624), //2^(4/8)
+ Q30(1.5422108254), //2^(5/8)
+ Q30(1.6817928305), //2^(6/8)
+ Q30(1.8340080864), //2^(7/8)
+};
+
/** Dequantization-related */
#include "aacdec_fixed_dequant.h"
+#include "aacdec_fixed_coupling.h"
#include "aacdec_dsp_template.c"
#include "aacdec_proc_template.c"
diff --git a/libavcodec/aac/aacdec_fixed_coupling.h b/libavcodec/aac/aacdec_fixed_coupling.h
new file mode 100644
index 0000000000..4a3dc3d9b1
--- /dev/null
+++ b/libavcodec/aac/aacdec_fixed_coupling.h
@@ -0,0 +1,137 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_AAC_AACDEC_FIXED_COUPLING
+#define AVCODEC_AAC_AACDEC_FIXED_COUPLING
+
+#include "libavcodec/aacdec.h"
+
+/**
+ * Apply dependent channel coupling (applied before IMDCT).
+ *
+ * @param index index into coupling gain array
+ */
+static void AAC_RENAME(apply_dependent_coupling)(AACDecContext *ac,
+ SingleChannelElement *target,
+ ChannelElement *cce, int index)
+{
+ IndividualChannelStream *ics = &cce->ch[0].ics;
+ const uint16_t *offsets = ics->swb_offset;
+ int *dest = target->coeffs_fixed;
+ const int *src = cce->ch[0].coeffs_fixed;
+ int g, i, group, k, idx = 0;
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Dependent coupling is not supported together with LTP\n");
+ return;
+ }
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb; i++, idx++) {
+ if (cce->ch[0].band_type[idx] != ZERO_BT) {
+ const int gain = cce->coup.gain[index][idx];
+ int shift, round, c, tmp;
+
+ if (gain < 0) {
+ c = -cce_scale_fixed[-gain & 7];
+ shift = (-gain-1024) >> 3;
+ }
+ else {
+ c = cce_scale_fixed[gain & 7];
+ shift = (gain-1024) >> 3;
+ }
+
+ if (shift < -31) {
+ // Nothing to do
+ } else if (shift < 0) {
+ shift = -shift;
+ round = 1 << (shift - 1);
+
+ for (group = 0; group < ics->group_len[g]; group++) {
+ for (k = offsets[i]; k < offsets[i + 1]; k++) {
+ tmp = (int)(((int64_t)src[group * 128 + k] * c + \
+ (int64_t)0x1000000000) >> 37);
+ dest[group * 128 + k] += (tmp + (int64_t)round) >> shift;
+ }
+ }
+ }
+ else {
+ for (group = 0; group < ics->group_len[g]; group++) {
+ for (k = offsets[i]; k < offsets[i + 1]; k++) {
+ tmp = (int)(((int64_t)src[group * 128 + k] * c + \
+ (int64_t)0x1000000000) >> 37);
+ dest[group * 128 + k] += tmp * (1U << shift);
+ }
+ }
+ }
+ }
+ }
+ dest += ics->group_len[g] * 128;
+ src += ics->group_len[g] * 128;
+ }
+}
+
+/**
+ * Apply independent channel coupling (applied after IMDCT).
+ *
+ * @param index index into coupling gain array
+ */
+static void AAC_RENAME(apply_independent_coupling)(AACDecContext *ac,
+ SingleChannelElement *target,
+ ChannelElement *cce, int index)
+{
+ int i, c, shift, round, tmp;
+ const int gain = cce->coup.gain[index][0];
+ const int *src = cce->ch[0].output_fixed;
+ unsigned int *dest = target->output_fixed;
+ const int len = 1024 << (ac->oc[1].m4ac.sbr == 1);
+
+ c = cce_scale_fixed[gain & 7];
+ shift = (gain-1024) >> 3;
+ if (shift < -31) {
+ return;
+ } else if (shift < 0) {
+ shift = -shift;
+ round = 1 << (shift - 1);
+
+ for (i = 0; i < len; i++) {
+ tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37);
+ dest[i] += (tmp + round) >> shift;
+ }
+ }
+ else {
+ for (i = 0; i < len; i++) {
+ tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37);
+ dest[i] += tmp * (1U << shift);
+ }
+ }
+}
+
+#endif /* AVCODEC_AAC_AACDEC_FIXED_COUPLING */
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index d1cc5ce929..865a57deb1 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -138,5 +138,6 @@ static inline float *VMUL4S(float *dst, const float *v, unsigned idx,
}
#endif
+#include "aacdec_float_coupling.h"
#include "aacdec_dsp_template.c"
#include "aacdec_proc_template.c"
diff --git a/libavcodec/aac/aacdec_float_coupling.h b/libavcodec/aac/aacdec_float_coupling.h
new file mode 100644
index 0000000000..8171750115
--- /dev/null
+++ b/libavcodec/aac/aacdec_float_coupling.h
@@ -0,0 +1,90 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_AAC_AACDEC_FLOAT_COUPLING
+#define AVCODEC_AAC_AACDEC_FLOAT_COUPLING
+
+#include "libavcodec/aacdec.h"
+
+/**
+ * Apply dependent channel coupling (applied before IMDCT).
+ *
+ * @param index index into coupling gain array
+ */
+static void AAC_RENAME(apply_dependent_coupling)(AACDecContext *ac,
+ SingleChannelElement *target,
+ ChannelElement *cce, int index)
+{
+ IndividualChannelStream *ics = &cce->ch[0].ics;
+ const uint16_t *offsets = ics->swb_offset;
+ float *dest = target->coeffs;
+ const float *src = cce->ch[0].coeffs;
+ int g, i, group, k, idx = 0;
+ if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
+ av_log(ac->avctx, AV_LOG_ERROR,
+ "Dependent coupling is not supported together with LTP\n");
+ return;
+ }
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb; i++, idx++) {
+ if (cce->ch[0].band_type[idx] != ZERO_BT) {
+ const float gain = cce->coup.gain[index][idx];
+ for (group = 0; group < ics->group_len[g]; group++) {
+ for (k = offsets[i]; k < offsets[i + 1]; k++) {
+ // FIXME: SIMDify
+ dest[group * 128 + k] += gain * src[group * 128 + k];
+ }
+ }
+ }
+ }
+ dest += ics->group_len[g] * 128;
+ src += ics->group_len[g] * 128;
+ }
+}
+
+/**
+ * Apply independent channel coupling (applied after IMDCT).
+ *
+ * @param index index into coupling gain array
+ */
+static void AAC_RENAME(apply_independent_coupling)(AACDecContext *ac,
+ SingleChannelElement *target,
+ ChannelElement *cce, int index)
+{
+ const float gain = cce->coup.gain[index][0];
+ const float *src = cce->ch[0].output;
+ float *dest = target->output;
+ const int len = 1024 << (ac->oc[1].m4ac.sbr == 1);
+
+ ac->fdsp->vector_fmac_scalar(dest, src, gain, len);
+}
+
+#endif /* AVCODEC_AAC_AACDEC_FLOAT_COUPLING */
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 13d53c6cfc..d269b93564 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -128,59 +128,6 @@ static av_always_inline void predict(PredictorState *ps, float *coef,
ps->r0 = flt16_trunc(a * e0);
}
-/**
- * Apply dependent channel coupling (applied before IMDCT).
- *
- * @param index index into coupling gain array
- */
-static void apply_dependent_coupling(AACDecContext *ac,
- SingleChannelElement *target,
- ChannelElement *cce, int index)
-{
- IndividualChannelStream *ics = &cce->ch[0].ics;
- const uint16_t *offsets = ics->swb_offset;
- float *dest = target->coeffs;
- const float *src = cce->ch[0].coeffs;
- int g, i, group, k, idx = 0;
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Dependent coupling is not supported together with LTP\n");
- return;
- }
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb; i++, idx++) {
- if (cce->ch[0].band_type[idx] != ZERO_BT) {
- const float gain = cce->coup.gain[index][idx];
- for (group = 0; group < ics->group_len[g]; group++) {
- for (k = offsets[i]; k < offsets[i + 1]; k++) {
- // FIXME: SIMDify
- dest[group * 128 + k] += gain * src[group * 128 + k];
- }
- }
- }
- }
- dest += ics->group_len[g] * 128;
- src += ics->group_len[g] * 128;
- }
-}
-
-/**
- * Apply independent channel coupling (applied after IMDCT).
- *
- * @param index index into coupling gain array
- */
-static void apply_independent_coupling(AACDecContext *ac,
- SingleChannelElement *target,
- ChannelElement *cce, int index)
-{
- const float gain = cce->coup.gain[index][0];
- const float *src = cce->ch[0].output;
- float *dest = target->output;
- const int len = 1024 << (ac->oc[1].m4ac.sbr == 1);
-
- ac->fdsp->vector_fmac_scalar(dest, src, gain, len);
-}
-
#include "aacdec_template.c"
#define LOAS_SYNC_WORD 0x2b7 ///< 11 bits LOAS sync word
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 811beb77f2..91ffb877da 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -228,6 +228,13 @@ typedef struct AACDecDSP {
void (*apply_ltp)(AACDecContext *ac, SingleChannelElement *sce);
void (*update_ltp)(AACDecContext *ac, SingleChannelElement *sce);
+ void (*apply_dependent_coupling)(AACDecContext *ac,
+ SingleChannelElement *target,
+ ChannelElement *cce, int index);
+ void (*apply_independent_coupling)(AACDecContext *ac,
+ SingleChannelElement *target,
+ ChannelElement *cce, int index);
+
void (*imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce);
void (*imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce);
void (*imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce);
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index f1eb072103..03b39854f8 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -245,118 +245,6 @@ static av_always_inline void predict(PredictorState *ps, int *coef,
ps->r0 = flt16_trunc(av_mul_sf(a, e0));
}
-
-static const int cce_scale_fixed[8] = {
- Q30(1.0), //2^(0/8)
- Q30(1.0905077327), //2^(1/8)
- Q30(1.1892071150), //2^(2/8)
- Q30(1.2968395547), //2^(3/8)
- Q30(1.4142135624), //2^(4/8)
- Q30(1.5422108254), //2^(5/8)
- Q30(1.6817928305), //2^(6/8)
- Q30(1.8340080864), //2^(7/8)
-};
-
-/**
- * Apply dependent channel coupling (applied before IMDCT).
- *
- * @param index index into coupling gain array
- */
-static void apply_dependent_coupling_fixed(AACDecContext *ac,
- SingleChannelElement *target,
- ChannelElement *cce, int index)
-{
- IndividualChannelStream *ics = &cce->ch[0].ics;
- const uint16_t *offsets = ics->swb_offset;
- int *dest = target->coeffs_fixed;
- const int *src = cce->ch[0].coeffs_fixed;
- int g, i, group, k, idx = 0;
- if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
- av_log(ac->avctx, AV_LOG_ERROR,
- "Dependent coupling is not supported together with LTP\n");
- return;
- }
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb; i++, idx++) {
- if (cce->ch[0].band_type[idx] != ZERO_BT) {
- const int gain = cce->coup.gain[index][idx];
- int shift, round, c, tmp;
-
- if (gain < 0) {
- c = -cce_scale_fixed[-gain & 7];
- shift = (-gain-1024) >> 3;
- }
- else {
- c = cce_scale_fixed[gain & 7];
- shift = (gain-1024) >> 3;
- }
-
- if (shift < -31) {
- // Nothing to do
- } else if (shift < 0) {
- shift = -shift;
- round = 1 << (shift - 1);
-
- for (group = 0; group < ics->group_len[g]; group++) {
- for (k = offsets[i]; k < offsets[i + 1]; k++) {
- tmp = (int)(((int64_t)src[group * 128 + k] * c + \
- (int64_t)0x1000000000) >> 37);
- dest[group * 128 + k] += (tmp + (int64_t)round) >> shift;
- }
- }
- }
- else {
- for (group = 0; group < ics->group_len[g]; group++) {
- for (k = offsets[i]; k < offsets[i + 1]; k++) {
- tmp = (int)(((int64_t)src[group * 128 + k] * c + \
- (int64_t)0x1000000000) >> 37);
- dest[group * 128 + k] += tmp * (1U << shift);
- }
- }
- }
- }
- }
- dest += ics->group_len[g] * 128;
- src += ics->group_len[g] * 128;
- }
-}
-
-/**
- * Apply independent channel coupling (applied after IMDCT).
- *
- * @param index index into coupling gain array
- */
-static void apply_independent_coupling_fixed(AACDecContext *ac,
- SingleChannelElement *target,
- ChannelElement *cce, int index)
-{
- int i, c, shift, round, tmp;
- const int gain = cce->coup.gain[index][0];
- const int *src = cce->ch[0].output_fixed;
- unsigned int *dest = target->output_fixed;
- const int len = 1024 << (ac->oc[1].m4ac.sbr == 1);
-
- c = cce_scale_fixed[gain & 7];
- shift = (gain-1024) >> 3;
- if (shift < -31) {
- return;
- } else if (shift < 0) {
- shift = -shift;
- round = 1 << (shift - 1);
-
- for (i = 0; i < len; i++) {
- tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37);
- dest[i] += (tmp + round) >> shift;
- }
- }
- else {
- for (i = 0; i < len; i++) {
- tmp = (int)(((int64_t)src[i] * c + (int64_t)0x1000000000) >> 37);
- dest[i] += tmp * (1U << shift);
- }
- }
-}
-
#include "aacdec_template.c"
const FFCodec ff_aac_fixed_decoder = {
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 8a77d2b627..dc28a0e2e0 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2094,7 +2094,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
ChannelElement *che = ac->che[type][i];
if (che && che->present) {
if (type <= TYPE_CPE)
- apply_channel_coupling(ac, che, type, i, BEFORE_TNS, AAC_RENAME(apply_dependent_coupling));
+ apply_channel_coupling(ac, che, type, i, BEFORE_TNS, ac->dsp.apply_dependent_coupling);
if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
if (che->ch[0].ics.predictor_present) {
if (che->ch[0].ics.ltp.present)
@@ -2110,7 +2110,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
&che->ch[1].tns, &che->ch[1].ics, 1);
if (type <= TYPE_CPE)
- apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, AAC_RENAME(apply_dependent_coupling));
+ apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, ac->dsp.apply_dependent_coupling);
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
imdct_and_window(ac, &che->ch[0]);
if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
@@ -2127,7 +2127,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
}
}
if (type <= TYPE_CCE)
- apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, AAC_RENAME(apply_independent_coupling));
+ apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, ac->dsp.apply_independent_coupling);
#if USE_FIXED
{
--
2.43.0.381.gb435a96ce8
[-- Attachment #16: 0024-aacdec-deduplicate-table-initizalization.patch --]
[-- Type: text/x-diff, Size: 3514 bytes --]
From edba0861b540d53217646ea0337651c14df1f342 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 04:03:12 +0100
Subject: [PATCH 24/38] aacdec: deduplicate table initizalization
All tables now initialized by aac/aacdec_fixed|float
---
libavcodec/aac/aacdec_fixed.c | 2 ++
libavcodec/aac/aacdec_float.c | 2 ++
libavcodec/aacdec.c | 5 -----
libavcodec/aacdec_fixed.c | 2 --
libavcodec/aacdec_template.c | 12 ------------
5 files changed, 4 insertions(+), 19 deletions(-)
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index a2ddc5aac2..08e9c3a03f 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -47,6 +47,8 @@ DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_short_120))[120];
static void init_tables_fixed_fn(void)
{
+ AAC_RENAME(ff_cbrt_tableinit)();
+
AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024);
AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128);
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index 355980d169..d1cc5ce929 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -47,6 +47,8 @@ DECLARE_ALIGNED(32, static float, aac_kbd_short_120)[120];
static void init_tables_float_fn(void)
{
+ AAC_RENAME(ff_cbrt_tableinit)();
+
AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024);
AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128);
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 9642c45015..13d53c6cfc 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -63,11 +63,6 @@
# include "mips/aacdec_mips.h"
#endif
-DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(sine_120))[120];
-DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(sine_960))[960];
-DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_long_960))[960];
-DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_short_120))[120];
-
static av_always_inline void reset_predict_state(PredictorState *ps)
{
ps->r0 = 0.0f;
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index efc666a6ce..f1eb072103 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -64,8 +64,6 @@
#include "avcodec.h"
#include "codec_internal.h"
#include "get_bits.h"
-#include "kbdwin.h"
-#include "sinewin_fixed_tablegen.h"
#include "aac.h"
#include "aacdec.h"
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 0dec7bc626..8a77d2b627 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1109,22 +1109,10 @@ static av_cold void aac_static_table_init(void)
ff_aacdec_common_init_once();
- // window initialization
- AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960);
- AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120);
-
#if !USE_FIXED
- AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_960), 960);
- AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_120), 120);
- AAC_RENAME(ff_init_ff_sine_windows)(9);
ff_aac_float_common_init();
#else
- AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024);
- AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128);
- init_sine_windows_fixed();
#endif
-
- AAC_RENAME(ff_cbrt_tableinit)();
}
static AVOnce aac_table_init = AV_ONCE_INIT;
--
2.43.0.381.gb435a96ce8
[-- Attachment #17: 0023-aacdec-move-spectrum-decode-and-dequantization-to-a-.patch --]
[-- Type: text/x-diff, Size: 45485 bytes --]
From c533909e4d5adfb481b868a96bee5d20e66c19d2 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 02:43:33 +0100
Subject: [PATCH 23/38] aacdec: move spectrum decode and dequantization to a
new file
---
libavcodec/aac/aacdec.c | 4 +
libavcodec/aac/aacdec_dsp_template.c | 2 +-
libavcodec/aac/aacdec_fixed.c | 5 +
libavcodec/aac/aacdec_fixed_dequant.h | 174 +++++++++++++
libavcodec/aac/aacdec_float.c | 74 ++++++
libavcodec/aac/aacdec_proc_template.c | 354 ++++++++++++++++++++++++++
libavcodec/aacdec.c | 68 -----
libavcodec/aacdec.h | 15 +-
libavcodec/aacdec_fixed.c | 130 ----------
libavcodec/aacdec_template.c | 331 +-----------------------
10 files changed, 626 insertions(+), 531 deletions(-)
create mode 100644 libavcodec/aac/aacdec_fixed_dequant.h
create mode 100644 libavcodec/aac/aacdec_proc_template.c
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 26612f4a14..d31c64d08d 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -48,6 +48,9 @@
extern const AACDecDSP aac_dsp;
extern const AACDecDSP aac_dsp_fixed;
+extern const AACDecProc aac_proc;
+extern const AACDecProc aac_proc_fixed;
+
av_cold int ff_aac_decode_close(AVCodecContext *avctx)
{
AACDecContext *ac = avctx->priv_data;
@@ -119,6 +122,7 @@ av_cold int ff_aac_decode_init_common(AVCodecContext *avctx)
return ret;
ac->dsp = is_fixed ? aac_dsp_fixed : aac_dsp;
+ ac->proc = is_fixed ? aac_proc_fixed : aac_proc;
ac->dsp.init_tables();
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 56c51c3e07..a04d358883 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -151,7 +151,7 @@ static void AAC_RENAME(apply_intensity_stereo)(AACDecContext *ac,
scale = c * sce1->AAC_RENAME(sf)[idx];
for (group = 0; group < ics->group_len[g]; group++)
#if USE_FIXED
- ac->subband_scale(coef1 + group * 128 + offsets[i],
+ subband_scale(coef1 + group * 128 + offsets[i],
coef0 + group * 128 + offsets[i],
scale,
23,
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index 9dd8f34f55..a2ddc5aac2 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -38,6 +38,7 @@
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin_fixed_tablegen.h"
#include "libavcodec/kbdwin.h"
+#include "libavcodec/cbrt_data.h"
DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME2(aac_kbd_long_1024))[1024];
DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME2(aac_kbd_short_128))[128];
@@ -61,4 +62,8 @@ static void init_tables_fixed(void)
ff_thread_once(&init_fixed_once, init_tables_fixed_fn);
}
+/** Dequantization-related */
+#include "aacdec_fixed_dequant.h"
+
#include "aacdec_dsp_template.c"
+#include "aacdec_proc_template.c"
diff --git a/libavcodec/aac/aacdec_fixed_dequant.h b/libavcodec/aac/aacdec_fixed_dequant.h
new file mode 100644
index 0000000000..08b48a887d
--- /dev/null
+++ b/libavcodec/aac/aacdec_fixed_dequant.h
@@ -0,0 +1,174 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_AAC_AACDEC_FIXED_DEQUANT
+#define AVCODEC_AAC_AACDEC_FIXED_DEQUANT
+
+#include "aacdec_tab.h"
+
+static void inline vector_pow43(int *coefs, int len)
+{
+ int i, coef;
+
+ for (i=0; i<len; i++) {
+ coef = coefs[i];
+ if (coef < 0)
+ coef = -(int)ff_cbrt_tab_fixed[(-coef) & 8191];
+ else
+ coef = (int)ff_cbrt_tab_fixed[ coef & 8191];
+ coefs[i] = coef;
+ }
+}
+
+/* 2^0, 2^0.25, 2^0.5, 2^0.75 */
+static const int exp2tab[4] = {
+ Q31(1.0000000000/2), Q31(1.1892071150/2),
+ Q31(1.4142135624/2), Q31(1.6817928305/2)
+};
+
+static void inline subband_scale(int *dst, int *src, int scale,
+ int offset, int len, void *log_context)
+{
+ int ssign = scale < 0 ? -1 : 1;
+ int s = FFABS(scale);
+ unsigned int round;
+ int i, out, c = exp2tab[s & 3];
+
+ s = offset - (s >> 2);
+
+ if (s > 31) {
+ for (i=0; i<len; i++) {
+ dst[i] = 0;
+ }
+ } else if (s > 0) {
+ round = 1 << (s-1);
+ for (i=0; i<len; i++) {
+ out = (int)(((int64_t)src[i] * c) >> 32);
+ dst[i] = ((int)(out+round) >> s) * ssign;
+ }
+ } else if (s > -32) {
+ s = s + 32;
+ round = 1U << (s-1);
+ for (i=0; i<len; i++) {
+ out = (int)((int64_t)((int64_t)src[i] * c + round) >> s);
+ dst[i] = out * (unsigned)ssign;
+ }
+ } else {
+ av_log(log_context, AV_LOG_ERROR, "Overflow in subband_scale()\n");
+ }
+}
+
+static void noise_scale(int *coefs, int scale, int band_energy, int len)
+{
+ int s = -scale;
+ unsigned int round;
+ int i, out, c = exp2tab[s & 3];
+ int nlz = 0;
+
+ av_assert0(s >= 0);
+ while (band_energy > 0x7fff) {
+ band_energy >>= 1;
+ nlz++;
+ }
+ c /= band_energy;
+ s = 21 + nlz - (s >> 2);
+
+ if (s > 31) {
+ for (i=0; i<len; i++) {
+ coefs[i] = 0;
+ }
+ } else if (s >= 0) {
+ round = s ? 1 << (s-1) : 0;
+ for (i=0; i<len; i++) {
+ out = (int)(((int64_t)coefs[i] * c) >> 32);
+ coefs[i] = -((int)(out+round) >> s);
+ }
+ }
+ else {
+ s = s + 32;
+ if (s > 0) {
+ round = 1 << (s-1);
+ for (i=0; i<len; i++) {
+ out = (int)((int64_t)((int64_t)coefs[i] * c + round) >> s);
+ coefs[i] = -out;
+ }
+ } else {
+ for (i=0; i<len; i++)
+ coefs[i] = -(int64_t)coefs[i] * c * (1 << -s);
+ }
+ }
+}
+
+static inline int *DEC_SPAIR(int *dst, unsigned idx)
+{
+ dst[0] = (idx & 15) - 4;
+ dst[1] = (idx >> 4 & 15) - 4;
+
+ return dst + 2;
+}
+
+static inline int *DEC_SQUAD(int *dst, unsigned idx)
+{
+ dst[0] = (idx & 3) - 1;
+ dst[1] = (idx >> 2 & 3) - 1;
+ dst[2] = (idx >> 4 & 3) - 1;
+ dst[3] = (idx >> 6 & 3) - 1;
+
+ return dst + 4;
+}
+
+static inline int *DEC_UPAIR(int *dst, unsigned idx, unsigned sign)
+{
+ dst[0] = (idx & 15) * (1 - (sign & 0xFFFFFFFE));
+ dst[1] = (idx >> 4 & 15) * (1 - ((sign & 1) * 2));
+
+ return dst + 2;
+}
+
+static inline int *DEC_UQUAD(int *dst, unsigned idx, unsigned sign)
+{
+ unsigned nz = idx >> 12;
+
+ dst[0] = (idx & 3) * (1 + (((int)sign >> 31) * 2));
+ sign <<= nz & 1;
+ nz >>= 1;
+ dst[1] = (idx >> 2 & 3) * (1 + (((int)sign >> 31) * 2));
+ sign <<= nz & 1;
+ nz >>= 1;
+ dst[2] = (idx >> 4 & 3) * (1 + (((int)sign >> 31) * 2));
+ sign <<= nz & 1;
+ nz >>= 1;
+ dst[3] = (idx >> 6 & 3) * (1 + (((int)sign >> 31) * 2));
+
+ return dst + 4;
+}
+
+#endif /* AVCODEC_AAC_AACDEC_FIXED_DEQUANT */
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index 6a5e8483b0..355980d169 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -38,6 +38,7 @@
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin.h"
#include "libavcodec/kbdwin.h"
+#include "libavcodec/cbrt_data.h"
DECLARE_ALIGNED(32, static float, sine_120)[120];
DECLARE_ALIGNED(32, static float, sine_960)[960];
@@ -63,4 +64,77 @@ static void init_tables(void)
ff_thread_once(&init_float_once, init_tables_float_fn);
}
+/** Dequantization-related **/
+#include "aacdec_tab.h"
+#include "libavutil/intfloat.h"
+
+#ifndef VMUL2
+static inline float *VMUL2(float *dst, const float *v, unsigned idx,
+ const float *scale)
+{
+ float s = *scale;
+ *dst++ = v[idx & 15] * s;
+ *dst++ = v[idx>>4 & 15] * s;
+ return dst;
+}
+#endif
+
+#ifndef VMUL4
+static inline float *VMUL4(float *dst, const float *v, unsigned idx,
+ const float *scale)
+{
+ float s = *scale;
+ *dst++ = v[idx & 3] * s;
+ *dst++ = v[idx>>2 & 3] * s;
+ *dst++ = v[idx>>4 & 3] * s;
+ *dst++ = v[idx>>6 & 3] * s;
+ return dst;
+}
+#endif
+
+#ifndef VMUL2S
+static inline float *VMUL2S(float *dst, const float *v, unsigned idx,
+ unsigned sign, const float *scale)
+{
+ union av_intfloat32 s0, s1;
+
+ s0.f = s1.f = *scale;
+ s0.i ^= sign >> 1 << 31;
+ s1.i ^= sign << 31;
+
+ *dst++ = v[idx & 15] * s0.f;
+ *dst++ = v[idx>>4 & 15] * s1.f;
+
+ return dst;
+}
+#endif
+
+#ifndef VMUL4S
+static inline float *VMUL4S(float *dst, const float *v, unsigned idx,
+ unsigned sign, const float *scale)
+{
+ unsigned nz = idx >> 12;
+ union av_intfloat32 s = { .f = *scale };
+ union av_intfloat32 t;
+
+ t.i = s.i ^ (sign & 1U<<31);
+ *dst++ = v[idx & 3] * t.f;
+
+ sign <<= nz & 1; nz >>= 1;
+ t.i = s.i ^ (sign & 1U<<31);
+ *dst++ = v[idx>>2 & 3] * t.f;
+
+ sign <<= nz & 1; nz >>= 1;
+ t.i = s.i ^ (sign & 1U<<31);
+ *dst++ = v[idx>>4 & 3] * t.f;
+
+ sign <<= nz & 1;
+ t.i = s.i ^ (sign & 1U<<31);
+ *dst++ = v[idx>>6 & 3] * t.f;
+
+ return dst;
+}
+#endif
+
#include "aacdec_dsp_template.c"
+#include "aacdec_proc_template.c"
diff --git a/libavcodec/aac/aacdec_proc_template.c b/libavcodec/aac/aacdec_proc_template.c
new file mode 100644
index 0000000000..c3d607b4d3
--- /dev/null
+++ b/libavcodec/aac/aacdec_proc_template.c
@@ -0,0 +1,354 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+/**
+ * linear congruential pseudorandom number generator
+ *
+ * @param previous_val pointer to the current state of the generator
+ *
+ * @return Returns a 32-bit pseudorandom integer
+ */
+static av_always_inline int lcg_random(unsigned previous_val)
+{
+ union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 };
+ return v.s;
+}
+
+/**
+ * Decode spectral data; reference: table 4.50.
+ * Dequantize and scale spectral data; reference: 4.6.3.3.
+ *
+ * @param coef array of dequantized, scaled spectral data
+ * @param sf array of scalefactors or intensity stereo positions
+ * @param pulse_present set if pulses are present
+ * @param pulse pointer to pulse data struct
+ * @param band_type array of the used band type
+ *
+ * @return Returns error status. 0 - OK, !0 - error
+ */
+static int AAC_RENAME(decode_spectrum_and_dequant)(AACDecContext *ac,
+ GetBitContext *gb,
+ const Pulse *pulse,
+ SingleChannelElement *sce)
+{
+ int i, k, g, idx = 0;
+ INTFLOAT *coef = sce->AAC_RENAME(coeffs);
+ IndividualChannelStream *ics = &sce->ics;
+ const int c = 1024 / ics->num_windows;
+ const uint16_t *offsets = ics->swb_offset;
+ const INTFLOAT *sf = sce->AAC_RENAME(sf);
+ const enum BandType *band_type = sce->band_type;
+ INTFLOAT *coef_base = coef;
+
+ for (g = 0; g < ics->num_windows; g++)
+ memset(coef + g * 128 + offsets[ics->max_sfb], 0,
+ sizeof(INTFLOAT) * (c - offsets[ics->max_sfb]));
+
+ for (g = 0; g < ics->num_window_groups; g++) {
+ unsigned g_len = ics->group_len[g];
+
+ for (i = 0; i < ics->max_sfb; i++, idx++) {
+ const unsigned cbt_m1 = band_type[idx] - 1;
+ INTFLOAT *cfo = coef + offsets[i];
+ int off_len = offsets[i + 1] - offsets[i];
+ int group;
+
+ if (cbt_m1 >= INTENSITY_BT2 - 1) {
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+ memset(cfo, 0, off_len * sizeof(*cfo));
+ }
+ } else if (cbt_m1 == NOISE_BT - 1) {
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+ INTFLOAT band_energy;
+#if USE_FIXED
+ for (k = 0; k < off_len; k++) {
+ ac->random_state = lcg_random(ac->random_state);
+ cfo[k] = ac->random_state >> 3;
+ }
+
+ band_energy = ac->fdsp->scalarproduct_fixed(cfo, cfo, off_len);
+ band_energy = fixed_sqrt(band_energy, 31);
+ noise_scale(cfo, sf[idx], band_energy, off_len);
+#else
+ float scale;
+
+ for (k = 0; k < off_len; k++) {
+ ac->random_state = lcg_random(ac->random_state);
+ cfo[k] = ac->random_state;
+ }
+
+ band_energy = ac->fdsp->scalarproduct_float(cfo, cfo, off_len);
+ scale = sf[idx] / sqrtf(band_energy);
+ ac->fdsp->vector_fmul_scalar(cfo, cfo, scale, off_len);
+#endif /* USE_FIXED */
+ }
+ } else {
+#if !USE_FIXED
+ const float *vq = ff_aac_codebook_vector_vals[cbt_m1];
+#endif /* !USE_FIXED */
+ const VLCElem *vlc_tab = ff_vlc_spectral[cbt_m1];
+ OPEN_READER(re, gb);
+
+ switch (cbt_m1 >> 1) {
+ case 0:
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+ INTFLOAT *cf = cfo;
+ int len = off_len;
+
+ do {
+ int code;
+ unsigned cb_idx;
+
+ UPDATE_CACHE(re, gb);
+ GET_VLC(code, re, gb, vlc_tab, 8, 2);
+ cb_idx = code;
+#if USE_FIXED
+ cf = DEC_SQUAD(cf, cb_idx);
+#else
+ cf = VMUL4(cf, vq, cb_idx, sf + idx);
+#endif /* USE_FIXED */
+ } while (len -= 4);
+ }
+ break;
+
+ case 1:
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+ INTFLOAT *cf = cfo;
+ int len = off_len;
+
+ do {
+ int code;
+ unsigned nnz;
+ unsigned cb_idx;
+ uint32_t bits;
+
+ UPDATE_CACHE(re, gb);
+ GET_VLC(code, re, gb, vlc_tab, 8, 2);
+ cb_idx = code;
+ nnz = cb_idx >> 8 & 15;
+ bits = nnz ? GET_CACHE(re, gb) : 0;
+ LAST_SKIP_BITS(re, gb, nnz);
+#if USE_FIXED
+ cf = DEC_UQUAD(cf, cb_idx, bits);
+#else
+ cf = VMUL4S(cf, vq, cb_idx, bits, sf + idx);
+#endif /* USE_FIXED */
+ } while (len -= 4);
+ }
+ break;
+
+ case 2:
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+ INTFLOAT *cf = cfo;
+ int len = off_len;
+
+ do {
+ int code;
+ unsigned cb_idx;
+
+ UPDATE_CACHE(re, gb);
+ GET_VLC(code, re, gb, vlc_tab, 8, 2);
+ cb_idx = code;
+#if USE_FIXED
+ cf = DEC_SPAIR(cf, cb_idx);
+#else
+ cf = VMUL2(cf, vq, cb_idx, sf + idx);
+#endif /* USE_FIXED */
+ } while (len -= 2);
+ }
+ break;
+
+ case 3:
+ case 4:
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+ INTFLOAT *cf = cfo;
+ int len = off_len;
+
+ do {
+ int code;
+ unsigned nnz;
+ unsigned cb_idx;
+ unsigned sign;
+
+ UPDATE_CACHE(re, gb);
+ GET_VLC(code, re, gb, vlc_tab, 8, 2);
+ cb_idx = code;
+ nnz = cb_idx >> 8 & 15;
+ sign = nnz ? SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12) : 0;
+ LAST_SKIP_BITS(re, gb, nnz);
+#if USE_FIXED
+ cf = DEC_UPAIR(cf, cb_idx, sign);
+#else
+ cf = VMUL2S(cf, vq, cb_idx, sign, sf + idx);
+#endif /* USE_FIXED */
+ } while (len -= 2);
+ }
+ break;
+
+ default:
+ for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
+#if USE_FIXED
+ int *icf = cfo;
+ int v;
+#else
+ float *cf = cfo;
+ uint32_t *icf = (uint32_t *) cf;
+#endif /* USE_FIXED */
+ int len = off_len;
+
+ do {
+ int code;
+ unsigned nzt, nnz;
+ unsigned cb_idx;
+ uint32_t bits;
+ int j;
+
+ UPDATE_CACHE(re, gb);
+ GET_VLC(code, re, gb, vlc_tab, 8, 2);
+ cb_idx = code;
+
+ if (cb_idx == 0x0000) {
+ *icf++ = 0;
+ *icf++ = 0;
+ continue;
+ }
+
+ nnz = cb_idx >> 12;
+ nzt = cb_idx >> 8;
+ bits = SHOW_UBITS(re, gb, nnz) << (32-nnz);
+ LAST_SKIP_BITS(re, gb, nnz);
+
+ for (j = 0; j < 2; j++) {
+ if (nzt & 1<<j) {
+ uint32_t b;
+ int n;
+ /* The total length of escape_sequence must be < 22 bits according
+ to the specification (i.e. max is 111111110xxxxxxxxxxxx). */
+ UPDATE_CACHE(re, gb);
+ b = GET_CACHE(re, gb);
+ b = 31 - av_log2(~b);
+
+ if (b > 8) {
+ av_log(ac->avctx, AV_LOG_ERROR, "error in spectral data, ESC overflow\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ SKIP_BITS(re, gb, b + 1);
+ b += 4;
+ n = (1 << b) + SHOW_UBITS(re, gb, b);
+ LAST_SKIP_BITS(re, gb, b);
+#if USE_FIXED
+ v = n;
+ if (bits & 1U<<31)
+ v = -v;
+ *icf++ = v;
+#else
+ *icf++ = ff_cbrt_tab[n] | (bits & 1U<<31);
+#endif /* USE_FIXED */
+ bits <<= 1;
+ } else {
+#if USE_FIXED
+ v = cb_idx & 15;
+ if (bits & 1U<<31)
+ v = -v;
+ *icf++ = v;
+#else
+ unsigned v = ((const uint32_t*)vq)[cb_idx & 15];
+ *icf++ = (bits & 1U<<31) | v;
+#endif /* USE_FIXED */
+ bits <<= !!v;
+ }
+ cb_idx >>= 4;
+ }
+ } while (len -= 2);
+#if !USE_FIXED
+ ac->fdsp->vector_fmul_scalar(cfo, cfo, sf[idx], off_len);
+#endif /* !USE_FIXED */
+ }
+ }
+
+ CLOSE_READER(re, gb);
+ }
+ }
+ coef += g_len << 7;
+ }
+
+ if (pulse) {
+ idx = 0;
+ for (i = 0; i < pulse->num_pulse; i++) {
+ INTFLOAT co = coef_base[ pulse->pos[i] ];
+ while (offsets[idx + 1] <= pulse->pos[i])
+ idx++;
+ if (band_type[idx] != NOISE_BT && sf[idx]) {
+ INTFLOAT ico = -pulse->amp[i];
+#if USE_FIXED
+ if (co) {
+ ico = co + (co > 0 ? -ico : ico);
+ }
+ coef_base[ pulse->pos[i] ] = ico;
+#else
+ if (co) {
+ co /= sf[idx];
+ ico = co / sqrtf(sqrtf(fabsf(co))) + (co > 0 ? -ico : ico);
+ }
+ coef_base[ pulse->pos[i] ] = cbrtf(fabsf(ico)) * ico * sf[idx];
+#endif /* USE_FIXED */
+ }
+ }
+ }
+#if USE_FIXED
+ coef = coef_base;
+ idx = 0;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ unsigned g_len = ics->group_len[g];
+
+ for (i = 0; i < ics->max_sfb; i++, idx++) {
+ const unsigned cbt_m1 = band_type[idx] - 1;
+ int *cfo = coef + offsets[i];
+ int off_len = offsets[i + 1] - offsets[i];
+ int group;
+
+ if (cbt_m1 < NOISE_BT - 1) {
+ for (group = 0; group < (int)g_len; group++, cfo+=128) {
+ vector_pow43(cfo, off_len);
+ subband_scale(cfo, cfo, sf[idx], 34, off_len, ac->avctx);
+ }
+ }
+ }
+ coef += g_len << 7;
+ }
+#endif /* USE_FIXED */
+ return 0;
+}
+
+const AACDecProc AAC_RENAME(aac_proc) = {
+ .decode_spectrum_and_dequant = AAC_RENAME(decode_spectrum_and_dequant),
+};
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 67cdda8cde..9642c45015 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -78,74 +78,6 @@ static av_always_inline void reset_predict_state(PredictorState *ps)
ps->var1 = 1.0f;
}
-#ifndef VMUL2
-static inline float *VMUL2(float *dst, const float *v, unsigned idx,
- const float *scale)
-{
- float s = *scale;
- *dst++ = v[idx & 15] * s;
- *dst++ = v[idx>>4 & 15] * s;
- return dst;
-}
-#endif
-
-#ifndef VMUL4
-static inline float *VMUL4(float *dst, const float *v, unsigned idx,
- const float *scale)
-{
- float s = *scale;
- *dst++ = v[idx & 3] * s;
- *dst++ = v[idx>>2 & 3] * s;
- *dst++ = v[idx>>4 & 3] * s;
- *dst++ = v[idx>>6 & 3] * s;
- return dst;
-}
-#endif
-
-#ifndef VMUL2S
-static inline float *VMUL2S(float *dst, const float *v, unsigned idx,
- unsigned sign, const float *scale)
-{
- union av_intfloat32 s0, s1;
-
- s0.f = s1.f = *scale;
- s0.i ^= sign >> 1 << 31;
- s1.i ^= sign << 31;
-
- *dst++ = v[idx & 15] * s0.f;
- *dst++ = v[idx>>4 & 15] * s1.f;
-
- return dst;
-}
-#endif
-
-#ifndef VMUL4S
-static inline float *VMUL4S(float *dst, const float *v, unsigned idx,
- unsigned sign, const float *scale)
-{
- unsigned nz = idx >> 12;
- union av_intfloat32 s = { .f = *scale };
- union av_intfloat32 t;
-
- t.i = s.i ^ (sign & 1U<<31);
- *dst++ = v[idx & 3] * t.f;
-
- sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1U<<31);
- *dst++ = v[idx>>2 & 3] * t.f;
-
- sign <<= nz & 1; nz >>= 1;
- t.i = s.i ^ (sign & 1U<<31);
- *dst++ = v[idx>>4 & 3] * t.f;
-
- sign <<= nz & 1;
- t.i = s.i ^ (sign & 1U<<31);
- *dst++ = v[idx>>6 & 3] * t.f;
-
- return dst;
-}
-#endif
-
static av_always_inline float flt16_round(float pf)
{
union av_intfloat32 tmp;
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 87462adb02..811beb77f2 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -200,6 +200,16 @@ typedef struct DynamicRangeControl {
*/
} DynamicRangeControl;
+/**
+ * Decode-specific primitives
+ */
+typedef struct AACDecProc {
+ int (*decode_spectrum_and_dequant)(AACDecContext *ac,
+ GetBitContext *gb,
+ const Pulse *pulse,
+ SingleChannelElement *sce);
+} AACDecProc;
+
/**
* DSP-specific primitives
*/
@@ -232,6 +242,7 @@ struct AACDecContext {
struct AVCodecContext *avctx;
AACDecDSP dsp;
+ AACDecProc proc;
struct AVFrame *frame;
@@ -309,10 +320,6 @@ struct AACDecContext {
int warned_he_aac_mono;
int is_fixed;
-
- /* aacdec functions pointers */
- void (*vector_pow43)(int *coefs, int len);
- void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
};
#if defined(USE_FIXED) && USE_FIXED
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 7633f4adb0..efc666a6ce 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -147,136 +147,6 @@ static av_always_inline void reset_predict_state(PredictorState *ps)
static const int exp2tab[4] = { Q31(1.0000000000/2), Q31(1.1892071150/2), Q31(1.4142135624/2), Q31(1.6817928305/2) }; // 2^0, 2^0.25, 2^0.5, 2^0.75
-static inline int *DEC_SPAIR(int *dst, unsigned idx)
-{
- dst[0] = (idx & 15) - 4;
- dst[1] = (idx >> 4 & 15) - 4;
-
- return dst + 2;
-}
-
-static inline int *DEC_SQUAD(int *dst, unsigned idx)
-{
- dst[0] = (idx & 3) - 1;
- dst[1] = (idx >> 2 & 3) - 1;
- dst[2] = (idx >> 4 & 3) - 1;
- dst[3] = (idx >> 6 & 3) - 1;
-
- return dst + 4;
-}
-
-static inline int *DEC_UPAIR(int *dst, unsigned idx, unsigned sign)
-{
- dst[0] = (idx & 15) * (1 - (sign & 0xFFFFFFFE));
- dst[1] = (idx >> 4 & 15) * (1 - ((sign & 1) * 2));
-
- return dst + 2;
-}
-
-static inline int *DEC_UQUAD(int *dst, unsigned idx, unsigned sign)
-{
- unsigned nz = idx >> 12;
-
- dst[0] = (idx & 3) * (1 + (((int)sign >> 31) * 2));
- sign <<= nz & 1;
- nz >>= 1;
- dst[1] = (idx >> 2 & 3) * (1 + (((int)sign >> 31) * 2));
- sign <<= nz & 1;
- nz >>= 1;
- dst[2] = (idx >> 4 & 3) * (1 + (((int)sign >> 31) * 2));
- sign <<= nz & 1;
- nz >>= 1;
- dst[3] = (idx >> 6 & 3) * (1 + (((int)sign >> 31) * 2));
-
- return dst + 4;
-}
-
-static void vector_pow43(int *coefs, int len)
-{
- int i, coef;
-
- for (i=0; i<len; i++) {
- coef = coefs[i];
- if (coef < 0)
- coef = -(int)ff_cbrt_tab_fixed[(-coef) & 8191];
- else
- coef = (int)ff_cbrt_tab_fixed[ coef & 8191];
- coefs[i] = coef;
- }
-}
-
-static void subband_scale(int *dst, int *src, int scale, int offset, int len, void *log_context)
-{
- int ssign = scale < 0 ? -1 : 1;
- int s = FFABS(scale);
- unsigned int round;
- int i, out, c = exp2tab[s & 3];
-
- s = offset - (s >> 2);
-
- if (s > 31) {
- for (i=0; i<len; i++) {
- dst[i] = 0;
- }
- } else if (s > 0) {
- round = 1 << (s-1);
- for (i=0; i<len; i++) {
- out = (int)(((int64_t)src[i] * c) >> 32);
- dst[i] = ((int)(out+round) >> s) * ssign;
- }
- } else if (s > -32) {
- s = s + 32;
- round = 1U << (s-1);
- for (i=0; i<len; i++) {
- out = (int)((int64_t)((int64_t)src[i] * c + round) >> s);
- dst[i] = out * (unsigned)ssign;
- }
- } else {
- av_log(log_context, AV_LOG_ERROR, "Overflow in subband_scale()\n");
- }
-}
-
-static void noise_scale(int *coefs, int scale, int band_energy, int len)
-{
- int s = -scale;
- unsigned int round;
- int i, out, c = exp2tab[s & 3];
- int nlz = 0;
-
- av_assert0(s >= 0);
- while (band_energy > 0x7fff) {
- band_energy >>= 1;
- nlz++;
- }
- c /= band_energy;
- s = 21 + nlz - (s >> 2);
-
- if (s > 31) {
- for (i=0; i<len; i++) {
- coefs[i] = 0;
- }
- } else if (s >= 0) {
- round = s ? 1 << (s-1) : 0;
- for (i=0; i<len; i++) {
- out = (int)(((int64_t)coefs[i] * c) >> 32);
- coefs[i] = -((int)(out+round) >> s);
- }
- }
- else {
- s = s + 32;
- if (s > 0) {
- round = 1 << (s-1);
- for (i=0; i<len; i++) {
- out = (int)((int64_t)((int64_t)coefs[i] * c + round) >> s);
- coefs[i] = -out;
- }
- } else {
- for (i=0; i<len; i++)
- coefs[i] = -(int64_t)coefs[i] * c * (1 << -s);
- }
- }
-}
-
static av_always_inline SoftFloat flt16_round(SoftFloat pf)
{
SoftFloat tmp;
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 4c9869f143..0dec7bc626 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1071,19 +1071,6 @@ static int decode_audio_specific_config(AACDecContext *ac,
sync_extension);
}
-/**
- * linear congruential pseudorandom number generator
- *
- * @param previous_val pointer to the current state of the generator
- *
- * @return Returns a 32-bit pseudorandom integer
- */
-static av_always_inline int lcg_random(unsigned previous_val)
-{
- union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 };
- return v.s;
-}
-
static void reset_all_predictors(PredictorState *ps)
{
int i;
@@ -1597,313 +1584,6 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
}
}
-/**
- * Decode spectral data; reference: table 4.50.
- * Dequantize and scale spectral data; reference: 4.6.3.3.
- *
- * @param coef array of dequantized, scaled spectral data
- * @param sf array of scalefactors or intensity stereo positions
- * @param pulse_present set if pulses are present
- * @param pulse pointer to pulse data struct
- * @param band_type array of the used band type
- *
- * @return Returns error status. 0 - OK, !0 - error
- */
-static int decode_spectrum_and_dequant(AACDecContext *ac,
- GetBitContext *gb,
- const Pulse *pulse,
- SingleChannelElement *sce)
-{
- int i, k, g, idx = 0;
- INTFLOAT *coef = sce->AAC_RENAME(coeffs);
- IndividualChannelStream *ics = &sce->ics;
- const int c = 1024 / ics->num_windows;
- const uint16_t *offsets = ics->swb_offset;
- const INTFLOAT *sf = sce->AAC_RENAME(sf);
- const enum BandType *band_type = sce->band_type;
- INTFLOAT *coef_base = coef;
-
- for (g = 0; g < ics->num_windows; g++)
- memset(coef + g * 128 + offsets[ics->max_sfb], 0,
- sizeof(INTFLOAT) * (c - offsets[ics->max_sfb]));
-
- for (g = 0; g < ics->num_window_groups; g++) {
- unsigned g_len = ics->group_len[g];
-
- for (i = 0; i < ics->max_sfb; i++, idx++) {
- const unsigned cbt_m1 = band_type[idx] - 1;
- INTFLOAT *cfo = coef + offsets[i];
- int off_len = offsets[i + 1] - offsets[i];
- int group;
-
- if (cbt_m1 >= INTENSITY_BT2 - 1) {
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
- memset(cfo, 0, off_len * sizeof(*cfo));
- }
- } else if (cbt_m1 == NOISE_BT - 1) {
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
- INTFLOAT band_energy;
-#if USE_FIXED
- for (k = 0; k < off_len; k++) {
- ac->random_state = lcg_random(ac->random_state);
- cfo[k] = ac->random_state >> 3;
- }
-
- band_energy = ac->fdsp->scalarproduct_fixed(cfo, cfo, off_len);
- band_energy = fixed_sqrt(band_energy, 31);
- noise_scale(cfo, sf[idx], band_energy, off_len);
-#else
- float scale;
-
- for (k = 0; k < off_len; k++) {
- ac->random_state = lcg_random(ac->random_state);
- cfo[k] = ac->random_state;
- }
-
- band_energy = ac->fdsp->scalarproduct_float(cfo, cfo, off_len);
- scale = sf[idx] / sqrtf(band_energy);
- ac->fdsp->vector_fmul_scalar(cfo, cfo, scale, off_len);
-#endif /* USE_FIXED */
- }
- } else {
-#if !USE_FIXED
- const float *vq = ff_aac_codebook_vector_vals[cbt_m1];
-#endif /* !USE_FIXED */
- const VLCElem *vlc_tab = ff_vlc_spectral[cbt_m1];
- OPEN_READER(re, gb);
-
- switch (cbt_m1 >> 1) {
- case 0:
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
- INTFLOAT *cf = cfo;
- int len = off_len;
-
- do {
- int code;
- unsigned cb_idx;
-
- UPDATE_CACHE(re, gb);
- GET_VLC(code, re, gb, vlc_tab, 8, 2);
- cb_idx = code;
-#if USE_FIXED
- cf = DEC_SQUAD(cf, cb_idx);
-#else
- cf = VMUL4(cf, vq, cb_idx, sf + idx);
-#endif /* USE_FIXED */
- } while (len -= 4);
- }
- break;
-
- case 1:
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
- INTFLOAT *cf = cfo;
- int len = off_len;
-
- do {
- int code;
- unsigned nnz;
- unsigned cb_idx;
- uint32_t bits;
-
- UPDATE_CACHE(re, gb);
- GET_VLC(code, re, gb, vlc_tab, 8, 2);
- cb_idx = code;
- nnz = cb_idx >> 8 & 15;
- bits = nnz ? GET_CACHE(re, gb) : 0;
- LAST_SKIP_BITS(re, gb, nnz);
-#if USE_FIXED
- cf = DEC_UQUAD(cf, cb_idx, bits);
-#else
- cf = VMUL4S(cf, vq, cb_idx, bits, sf + idx);
-#endif /* USE_FIXED */
- } while (len -= 4);
- }
- break;
-
- case 2:
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
- INTFLOAT *cf = cfo;
- int len = off_len;
-
- do {
- int code;
- unsigned cb_idx;
-
- UPDATE_CACHE(re, gb);
- GET_VLC(code, re, gb, vlc_tab, 8, 2);
- cb_idx = code;
-#if USE_FIXED
- cf = DEC_SPAIR(cf, cb_idx);
-#else
- cf = VMUL2(cf, vq, cb_idx, sf + idx);
-#endif /* USE_FIXED */
- } while (len -= 2);
- }
- break;
-
- case 3:
- case 4:
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
- INTFLOAT *cf = cfo;
- int len = off_len;
-
- do {
- int code;
- unsigned nnz;
- unsigned cb_idx;
- unsigned sign;
-
- UPDATE_CACHE(re, gb);
- GET_VLC(code, re, gb, vlc_tab, 8, 2);
- cb_idx = code;
- nnz = cb_idx >> 8 & 15;
- sign = nnz ? SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12) : 0;
- LAST_SKIP_BITS(re, gb, nnz);
-#if USE_FIXED
- cf = DEC_UPAIR(cf, cb_idx, sign);
-#else
- cf = VMUL2S(cf, vq, cb_idx, sign, sf + idx);
-#endif /* USE_FIXED */
- } while (len -= 2);
- }
- break;
-
- default:
- for (group = 0; group < (AAC_SIGNE)g_len; group++, cfo+=128) {
-#if USE_FIXED
- int *icf = cfo;
- int v;
-#else
- float *cf = cfo;
- uint32_t *icf = (uint32_t *) cf;
-#endif /* USE_FIXED */
- int len = off_len;
-
- do {
- int code;
- unsigned nzt, nnz;
- unsigned cb_idx;
- uint32_t bits;
- int j;
-
- UPDATE_CACHE(re, gb);
- GET_VLC(code, re, gb, vlc_tab, 8, 2);
- cb_idx = code;
-
- if (cb_idx == 0x0000) {
- *icf++ = 0;
- *icf++ = 0;
- continue;
- }
-
- nnz = cb_idx >> 12;
- nzt = cb_idx >> 8;
- bits = SHOW_UBITS(re, gb, nnz) << (32-nnz);
- LAST_SKIP_BITS(re, gb, nnz);
-
- for (j = 0; j < 2; j++) {
- if (nzt & 1<<j) {
- uint32_t b;
- int n;
- /* The total length of escape_sequence must be < 22 bits according
- to the specification (i.e. max is 111111110xxxxxxxxxxxx). */
- UPDATE_CACHE(re, gb);
- b = GET_CACHE(re, gb);
- b = 31 - av_log2(~b);
-
- if (b > 8) {
- av_log(ac->avctx, AV_LOG_ERROR, "error in spectral data, ESC overflow\n");
- return AVERROR_INVALIDDATA;
- }
-
- SKIP_BITS(re, gb, b + 1);
- b += 4;
- n = (1 << b) + SHOW_UBITS(re, gb, b);
- LAST_SKIP_BITS(re, gb, b);
-#if USE_FIXED
- v = n;
- if (bits & 1U<<31)
- v = -v;
- *icf++ = v;
-#else
- *icf++ = ff_cbrt_tab[n] | (bits & 1U<<31);
-#endif /* USE_FIXED */
- bits <<= 1;
- } else {
-#if USE_FIXED
- v = cb_idx & 15;
- if (bits & 1U<<31)
- v = -v;
- *icf++ = v;
-#else
- unsigned v = ((const uint32_t*)vq)[cb_idx & 15];
- *icf++ = (bits & 1U<<31) | v;
-#endif /* USE_FIXED */
- bits <<= !!v;
- }
- cb_idx >>= 4;
- }
- } while (len -= 2);
-#if !USE_FIXED
- ac->fdsp->vector_fmul_scalar(cfo, cfo, sf[idx], off_len);
-#endif /* !USE_FIXED */
- }
- }
-
- CLOSE_READER(re, gb);
- }
- }
- coef += g_len << 7;
- }
-
- if (pulse) {
- idx = 0;
- for (i = 0; i < pulse->num_pulse; i++) {
- INTFLOAT co = coef_base[ pulse->pos[i] ];
- while (offsets[idx + 1] <= pulse->pos[i])
- idx++;
- if (band_type[idx] != NOISE_BT && sf[idx]) {
- INTFLOAT ico = -pulse->amp[i];
-#if USE_FIXED
- if (co) {
- ico = co + (co > 0 ? -ico : ico);
- }
- coef_base[ pulse->pos[i] ] = ico;
-#else
- if (co) {
- co /= sf[idx];
- ico = co / sqrtf(sqrtf(fabsf(co))) + (co > 0 ? -ico : ico);
- }
- coef_base[ pulse->pos[i] ] = cbrtf(fabsf(ico)) * ico * sf[idx];
-#endif /* USE_FIXED */
- }
- }
- }
-#if USE_FIXED
- coef = coef_base;
- idx = 0;
- for (g = 0; g < ics->num_window_groups; g++) {
- unsigned g_len = ics->group_len[g];
-
- for (i = 0; i < ics->max_sfb; i++, idx++) {
- const unsigned cbt_m1 = band_type[idx] - 1;
- int *cfo = coef + offsets[i];
- int off_len = offsets[i + 1] - offsets[i];
- int group;
-
- if (cbt_m1 < NOISE_BT - 1) {
- for (group = 0; group < (int)g_len; group++, cfo+=128) {
- ac->vector_pow43(cfo, off_len);
- ac->subband_scale(cfo, cfo, sf[idx], 34, off_len, ac->avctx);
- }
- }
- }
- coef += g_len << 7;
- }
-#endif /* USE_FIXED */
- return 0;
-}
-
/**
* Apply AAC-Main style frequency domain prediction.
*/
@@ -2046,9 +1726,9 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
}
}
- ret = decode_spectrum_and_dequant(ac, gb,
- pulse_present ? &pulse : NULL,
- sce);
+ ret = ac->proc.decode_spectrum_and_dequant(ac, gb,
+ pulse_present ? &pulse : NULL,
+ sce);
if (ret < 0)
goto fail;
@@ -2891,11 +2571,6 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
static void aacdec_init(AACDecContext *c)
{
-#if USE_FIXED
- c->vector_pow43 = vector_pow43;
- c->subband_scale = subband_scale;
-#endif
-
#if !USE_FIXED
#if ARCH_MIPS
ff_aacdec_init_mips(c);
--
2.43.0.381.gb435a96ce8
[-- Attachment #18: 0022-aacdec-remove-unnecessary-decode_spectrum_and_dequan.patch --]
[-- Type: text/x-diff, Size: 2469 bytes --]
From 606fb6c03e9797b6bff1df5100e2038b9cf55688 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 02:19:35 +0100
Subject: [PATCH 22/38] aacdec: remove unnecessary decode_spectrum_and_dequant
arguments
Small cleanup to reduce number of arguments.
---
libavcodec/aacdec_template.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 28b2213416..4c9869f143 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1609,12 +1609,13 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_spectrum_and_dequant(AACDecContext *ac, INTFLOAT coef[1024],
+static int decode_spectrum_and_dequant(AACDecContext *ac,
GetBitContext *gb,
- int pulse_present, const Pulse *pulse,
+ const Pulse *pulse,
SingleChannelElement *sce)
{
int i, k, g, idx = 0;
+ INTFLOAT *coef = sce->AAC_RENAME(coeffs);
IndividualChannelStream *ics = &sce->ics;
const int c = 1024 / ics->num_windows;
const uint16_t *offsets = ics->swb_offset;
@@ -1855,7 +1856,7 @@ static int decode_spectrum_and_dequant(AACDecContext *ac, INTFLOAT coef[1024],
coef += g_len << 7;
}
- if (pulse_present) {
+ if (pulse) {
idx = 0;
for (i = 0; i < pulse->num_pulse; i++) {
INTFLOAT co = coef_base[ pulse->pos[i] ];
@@ -1976,7 +1977,6 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
Pulse pulse;
TemporalNoiseShaping *tns = &sce->tns;
IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *out = sce->AAC_RENAME(coeffs);
int global_gain, eld_syntax, er_syntax, pulse_present = 0;
int ret;
@@ -2046,9 +2046,9 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
}
}
- ret = decode_spectrum_and_dequant(ac, out, gb,
- pulse_present,
- &pulse, sce);
+ ret = decode_spectrum_and_dequant(ac, gb,
+ pulse_present ? &pulse : NULL,
+ sce);
if (ret < 0)
goto fail;
--
2.43.0.381.gb435a96ce8
[-- Attachment #19: 0021-aacdec-template-LTP-windowing-separately.patch --]
[-- Type: text/x-diff, Size: 8061 bytes --]
From eb742aa5e221d5fb8240969b836c04864181e125 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 01:28:41 +0100
Subject: [PATCH 21/38] aacdec: template LTP windowing separately
The function is called only internally in DSP, so we do not
need to expose it.
apply_ltp on MIPS uses this function, but due to the function
being just a glue function with no real optimizations,
duplicate it there.
---
libavcodec/aac/aacdec_dsp_template.c | 30 +++++++++++++++++++++++++++-
libavcodec/aacdec.h | 6 ------
libavcodec/aacdec_template.c | 28 --------------------------
libavcodec/mips/aacdec_mips.c | 30 +++++++++++++++++++++++++++-
4 files changed, 58 insertions(+), 36 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index c607383d67..56c51c3e07 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -237,6 +237,34 @@ static void AAC_RENAME(apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
}
}
+/**
+ * Apply windowing and MDCT to obtain the spectral
+ * coefficient from the predicted sample by LTP.
+ */
+static inline void AAC_RENAME(windowing_and_mdct_ltp)(AACDecContext *ac,
+ INTFLOAT *out, INTFLOAT *in,
+ IndividualChannelStream *ics)
+{
+ const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
+ const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
+ const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
+ const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
+
+ if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
+ ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
+ } else {
+ memset(in, 0, 448 * sizeof(*in));
+ ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
+ }
+ if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
+ ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
+ } else {
+ ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
+ memset(in + 1024 + 576, 0, 448 * sizeof(*in));
+ }
+ ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
+}
+
/**
* Apply the long term prediction
*/
@@ -257,7 +285,7 @@ static void AAC_RENAME(apply_ltp)(AACDecContext *ac, SingleChannelElement *sce)
predTime[i] = AAC_MUL30(sce->AAC_RENAME(ltp_state)[i + 2048 - ltp->lag], ltp->AAC_RENAME(coef));
memset(&predTime[i], 0, (2048 - i) * sizeof(*predTime));
- ac->AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
+ AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
if (sce->tns.present)
AAC_RENAME(apply_tns)(predFreq, &sce->tns, &sce->ics, 0);
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index a0f8790e17..87462adb02 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -311,12 +311,6 @@ struct AACDecContext {
int is_fixed;
/* aacdec functions pointers */
- union {
- void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, float *out,
- float *in, IndividualChannelStream *ics);
- void (*windowing_and_mdct_ltp_fixed)(struct AACDecContext *ac, int *out,
- int *in, IndividualChannelStream *ics);
- };
void (*vector_pow43)(int *coefs, int len);
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
};
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 91abd4f393..28b2213416 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2366,33 +2366,6 @@ static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cn
return res;
}
-/**
- * Apply windowing and MDCT to obtain the spectral
- * coefficient from the predicted sample by LTP.
- */
-static void windowing_and_mdct_ltp(AACDecContext *ac, INTFLOAT *out,
- INTFLOAT *in, IndividualChannelStream *ics)
-{
- const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
- const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
- const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
- const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
-
- if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
- ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
- } else {
- memset(in, 0, 448 * sizeof(*in));
- ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
- }
- if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
- ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
- } else {
- ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
- memset(in + 1024 + 576, 0, 448 * sizeof(*in));
- }
- ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
-}
-
/**
* channel coupling transformation interface
*
@@ -2918,7 +2891,6 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
static void aacdec_init(AACDecContext *c)
{
- c->AAC_RENAME(windowing_and_mdct_ltp) = windowing_and_mdct_ltp;
#if USE_FIXED
c->vector_pow43 = vector_pow43;
c->subband_scale = subband_scale;
diff --git a/libavcodec/mips/aacdec_mips.c b/libavcodec/mips/aacdec_mips.c
index b9848baaaa..dee135b032 100644
--- a/libavcodec/mips/aacdec_mips.c
+++ b/libavcodec/mips/aacdec_mips.c
@@ -224,6 +224,34 @@ static void imdct_and_windowing_mips(AACDecContext *ac, SingleChannelElement *sc
}
}
+/**
+ * Apply windowing and MDCT to obtain the spectral
+ * coefficient from the predicted sample by LTP.
+ */
+static inline void windowing_and_mdct_ltp(AACDecContext *ac,
+ float *out, float *in,
+ IndividualChannelStream *ics)
+{
+ const float *lwindow = ics->use_kb_window[0] ? ff_aac_kbd_long_1024) : ff_sine_1024;
+ const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128) : ff_sine_128;
+ const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024) : ff_sine_1024;
+ const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128) : ff_sine_128;
+
+ if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
+ ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
+ } else {
+ memset(in, 0, 448 * sizeof(*in));
+ ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
+ }
+ if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
+ ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
+ } else {
+ ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
+ memset(in + 1024 + 576, 0, 448 * sizeof(*in));
+ }
+ ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
+}
+
static void apply_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
{
const LongTermPrediction *ltp = &sce->ics.ltp;
@@ -272,7 +300,7 @@ static void apply_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
);
}
- ac->windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
+ windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
if (sce->tns.present)
ac->dsp.apply_tns(predFreq, &sce->tns, &sce->ics, 0);
--
2.43.0.381.gb435a96ce8
[-- Attachment #20: 0020-aacdec-template-windowing-and-transforms-separately.patch --]
[-- Type: text/x-diff, Size: 27079 bytes --]
From b330fc2e9c24c93398c7833c0756f77e71a48be6 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 00:14:32 +0100
Subject: [PATCH 20/38] aacdec: template windowing and transforms separately
---
libavcodec/aac/aacdec_dsp_template.c | 221 ++++++++++++++++++++++++++
libavcodec/aacdec.h | 1 -
libavcodec/aacdec_template.c | 225 +--------------------------
libavcodec/mips/aacdec_mips.c | 2 +-
4 files changed, 226 insertions(+), 223 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 30151604c2..c607383d67 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -310,6 +310,222 @@ static void AAC_RENAME(update_ltp)(AACDecContext *ac, SingleChannelElement *sce)
1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
}
+/**
+ * Conduct IMDCT and windowing.
+ */
+static void AAC_RENAME(imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ INTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
+ const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
+ const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
+ INTFLOAT *temp = ac->AAC_RENAME(temp);
+ int i;
+
+ // imdct
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ for (i = 0; i < 1024; i += 128)
+ ac->mdct128_fn(ac->mdct128, buf + i, in + i, sizeof(INTFLOAT));
+ } else {
+ ac->mdct1024_fn(ac->mdct1024, buf, in, sizeof(INTFLOAT));
+ }
+
+ /* 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, 512);
+ } else {
+ memcpy( out, saved, 448 * sizeof(*out));
+
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ ac->fdsp->vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 64);
+ ac->fdsp->vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 64);
+ ac->fdsp->vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 64);
+ ac->fdsp->vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 64);
+ ac->fdsp->vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 64);
+ memcpy( out + 448 + 4*128, temp, 64 * sizeof(*out));
+ } else {
+ ac->fdsp->vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64);
+ memcpy( out + 576, buf + 64, 448 * sizeof(*out));
+ }
+ }
+
+ // buffer update
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ memcpy( saved, temp + 64, 64 * sizeof(*saved));
+ ac->fdsp->vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64);
+ ac->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
+ ac->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
+ memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
+ } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
+ memcpy( saved, buf + 512, 448 * sizeof(*saved));
+ memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
+ } else { // LONG_STOP or ONLY_LONG
+ memcpy( saved, buf + 512, 512 * sizeof(*saved));
+ }
+}
+
+/**
+ * Conduct IMDCT and windowing.
+ */
+static void AAC_RENAME(imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ INTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
+ const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_960) : AAC_RENAME(sine_960);
+ const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
+ INTFLOAT *temp = ac->AAC_RENAME(temp);
+ int i;
+
+ // imdct
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ for (i = 0; i < 8; i++)
+ ac->mdct120_fn(ac->mdct120, buf + i * 120, in + i * 128, sizeof(INTFLOAT));
+ } else {
+ ac->mdct960_fn(ac->mdct960, buf, in, sizeof(INTFLOAT));
+ }
+
+ /* 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));
+ }
+}
+static void AAC_RENAME(imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ INTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
+
+ // imdct
+ ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
+
+ // window overlapping
+ if (ics->use_kb_window[1]) {
+ // AAC LD uses a low overlap sine window instead of a KBD window
+ memcpy(out, saved, 192 * sizeof(*out));
+ ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, AAC_RENAME2(sine_128), 64);
+ memcpy( out + 320, buf + 64, 192 * sizeof(*out));
+ } else {
+ ac->fdsp->vector_fmul_window(out, saved, buf, AAC_RENAME2(sine_512), 256);
+ }
+
+ // buffer update
+ memcpy(saved, buf + 256, 256 * sizeof(*saved));
+}
+
+static void AAC_RENAME(imdct_and_windowing_eld)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ UINTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
+ int i;
+ const int n = ac->oc[1].m4ac.frame_length_short ? 480 : 512;
+ const int n2 = n >> 1;
+ const int n4 = n >> 2;
+ const INTFLOAT *const window = n == 480 ? AAC_RENAME(ff_aac_eld_window_480) :
+ AAC_RENAME(ff_aac_eld_window_512);
+
+ // Inverse transform, mapped to the conventional IMDCT by
+ // Chivukula, R.K.; Reznik, Y.A.; Devarajan, V.,
+ // "Efficient algorithms for MPEG-4 AAC-ELD, AAC-LD and AAC-LC filterbanks,"
+ // International Conference on Audio, Language and Image Processing, ICALIP 2008.
+ // URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4590245&isnumber=4589950
+ for (i = 0; i < n2; i+=2) {
+ INTFLOAT temp;
+ temp = in[i ]; in[i ] = -in[n - 1 - i]; in[n - 1 - i] = temp;
+ temp = -in[i + 1]; in[i + 1] = in[n - 2 - i]; in[n - 2 - i] = temp;
+ }
+
+ if (n == 480)
+ ac->mdct480_fn(ac->mdct480, buf, in, sizeof(INTFLOAT));
+ else
+ ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
+
+ for (i = 0; i < n; i+=2) {
+ buf[i + 0] = -(UINTFLOAT)(USE_FIXED + 1)*buf[i + 0];
+ buf[i + 1] = (UINTFLOAT)(USE_FIXED + 1)*buf[i + 1];
+ }
+ // Like with the regular IMDCT at this point we still have the middle half
+ // of a transform but with even symmetry on the left and odd symmetry on
+ // the right
+
+ // window overlapping
+ // The spec says to use samples [0..511] but the reference decoder uses
+ // samples [128..639].
+ for (i = n4; i < n2; i ++) {
+ out[i - n4] = AAC_MUL31( buf[ n2 - 1 - i] , window[i - n4]) +
+ AAC_MUL31( saved[ i + n2] , window[i + n - n4]) +
+ AAC_MUL31(-saved[n + n2 - 1 - i] , window[i + 2*n - n4]) +
+ AAC_MUL31(-saved[ 2*n + n2 + i] , window[i + 3*n - n4]);
+ }
+ for (i = 0; i < n2; i ++) {
+ out[n4 + i] = AAC_MUL31( buf[ i] , window[i + n2 - n4]) +
+ AAC_MUL31(-saved[ n - 1 - i] , window[i + n2 + n - n4]) +
+ AAC_MUL31(-saved[ n + i] , window[i + n2 + 2*n - n4]) +
+ AAC_MUL31( saved[2*n + n - 1 - i] , window[i + n2 + 3*n - n4]);
+ }
+ for (i = 0; i < n4; i ++) {
+ out[n2 + n4 + i] = AAC_MUL31( buf[ i + n2] , window[i + n - n4]) +
+ AAC_MUL31(-saved[n2 - 1 - i] , window[i + 2*n - n4]) +
+ AAC_MUL31(-saved[n + n2 + i] , window[i + 3*n - n4]);
+ }
+
+ // buffer update
+ memmove(saved + n, saved, 2 * n * sizeof(*saved));
+ memcpy( saved, buf, n * sizeof(*saved));
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.init_tables = &AAC_RENAME(init_tables),
@@ -319,4 +535,9 @@ const AACDecDSP AAC_RENAME(aac_dsp) = {
.apply_tns = &AAC_RENAME(apply_tns),
.apply_ltp = &AAC_RENAME(apply_ltp),
.update_ltp = &AAC_RENAME(update_ltp),
+
+ .imdct_and_windowing = AAC_RENAME(imdct_and_windowing),
+ .imdct_and_windowing_960 = AAC_RENAME(imdct_and_windowing_960),
+ .imdct_and_windowing_ld = AAC_RENAME(imdct_and_windowing_ld),
+ .imdct_and_windowing_eld = AAC_RENAME(imdct_and_windowing_eld),
};
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 30da1fc198..a0f8790e17 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -311,7 +311,6 @@ struct AACDecContext {
int is_fixed;
/* aacdec functions pointers */
- void (*imdct_and_windowing)(struct AACDecContext *ac, SingleChannelElement *sce);
union {
void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, float *out,
float *in, IndividualChannelStream *ics);
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 041ac0a90e..91abd4f393 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2393,222 +2393,6 @@ static void windowing_and_mdct_ltp(AACDecContext *ac, INTFLOAT *out,
ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
}
-/**
- * Conduct IMDCT and windowing.
- */
-static void imdct_and_windowing(AACDecContext *ac, SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *in = sce->AAC_RENAME(coeffs);
- INTFLOAT *out = sce->AAC_RENAME(output);
- INTFLOAT *saved = sce->AAC_RENAME(saved);
- const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
- const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
- const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
- INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
- INTFLOAT *temp = ac->AAC_RENAME(temp);
- int i;
-
- // imdct
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- for (i = 0; i < 1024; i += 128)
- ac->mdct128_fn(ac->mdct128, buf + i, in + i, sizeof(INTFLOAT));
- } else {
- ac->mdct1024_fn(ac->mdct1024, buf, in, sizeof(INTFLOAT));
- }
-
- /* 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, 512);
- } else {
- memcpy( out, saved, 448 * sizeof(*out));
-
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- ac->fdsp->vector_fmul_window(out + 448 + 0*128, saved + 448, buf + 0*128, swindow_prev, 64);
- ac->fdsp->vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow, 64);
- ac->fdsp->vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow, 64);
- ac->fdsp->vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow, 64);
- ac->fdsp->vector_fmul_window(temp, buf + 3*128 + 64, buf + 4*128, swindow, 64);
- memcpy( out + 448 + 4*128, temp, 64 * sizeof(*out));
- } else {
- ac->fdsp->vector_fmul_window(out + 448, saved + 448, buf, swindow_prev, 64);
- memcpy( out + 576, buf + 64, 448 * sizeof(*out));
- }
- }
-
- // buffer update
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- memcpy( saved, temp + 64, 64 * sizeof(*saved));
- ac->fdsp->vector_fmul_window(saved + 64, buf + 4*128 + 64, buf + 5*128, swindow, 64);
- ac->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
- ac->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
- memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
- } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
- memcpy( saved, buf + 512, 448 * sizeof(*saved));
- memcpy( saved + 448, buf + 7*128 + 64, 64 * sizeof(*saved));
- } else { // LONG_STOP or ONLY_LONG
- memcpy( saved, buf + 512, 512 * sizeof(*saved));
- }
-}
-
-/**
- * Conduct IMDCT and windowing.
- */
-static void imdct_and_windowing_960(AACDecContext *ac, SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *in = sce->AAC_RENAME(coeffs);
- INTFLOAT *out = sce->AAC_RENAME(output);
- INTFLOAT *saved = sce->AAC_RENAME(saved);
- const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
- const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_960) : AAC_RENAME(sine_960);
- const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
- INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
- INTFLOAT *temp = ac->AAC_RENAME(temp);
- int i;
-
- // imdct
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- for (i = 0; i < 8; i++)
- ac->mdct120_fn(ac->mdct120, buf + i * 120, in + i * 128, sizeof(INTFLOAT));
- } else {
- ac->mdct960_fn(ac->mdct960, buf, in, sizeof(INTFLOAT));
- }
-
- /* 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));
- }
-}
-static void imdct_and_windowing_ld(AACDecContext *ac, SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *in = sce->AAC_RENAME(coeffs);
- INTFLOAT *out = sce->AAC_RENAME(output);
- INTFLOAT *saved = sce->AAC_RENAME(saved);
- INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
-
- // imdct
- ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
-
- // window overlapping
- if (ics->use_kb_window[1]) {
- // AAC LD uses a low overlap sine window instead of a KBD window
- memcpy(out, saved, 192 * sizeof(*out));
- ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, AAC_RENAME2(sine_128), 64);
- memcpy( out + 320, buf + 64, 192 * sizeof(*out));
- } else {
- ac->fdsp->vector_fmul_window(out, saved, buf, AAC_RENAME2(sine_512), 256);
- }
-
- // buffer update
- memcpy(saved, buf + 256, 256 * sizeof(*saved));
-}
-
-static void imdct_and_windowing_eld(AACDecContext *ac, SingleChannelElement *sce)
-{
- UINTFLOAT *in = sce->AAC_RENAME(coeffs);
- INTFLOAT *out = sce->AAC_RENAME(output);
- INTFLOAT *saved = sce->AAC_RENAME(saved);
- INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
- int i;
- const int n = ac->oc[1].m4ac.frame_length_short ? 480 : 512;
- const int n2 = n >> 1;
- const int n4 = n >> 2;
- const INTFLOAT *const window = n == 480 ? AAC_RENAME(ff_aac_eld_window_480) :
- AAC_RENAME(ff_aac_eld_window_512);
-
- // Inverse transform, mapped to the conventional IMDCT by
- // Chivukula, R.K.; Reznik, Y.A.; Devarajan, V.,
- // "Efficient algorithms for MPEG-4 AAC-ELD, AAC-LD and AAC-LC filterbanks,"
- // International Conference on Audio, Language and Image Processing, ICALIP 2008.
- // URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4590245&isnumber=4589950
- for (i = 0; i < n2; i+=2) {
- INTFLOAT temp;
- temp = in[i ]; in[i ] = -in[n - 1 - i]; in[n - 1 - i] = temp;
- temp = -in[i + 1]; in[i + 1] = in[n - 2 - i]; in[n - 2 - i] = temp;
- }
-
- if (n == 480)
- ac->mdct480_fn(ac->mdct480, buf, in, sizeof(INTFLOAT));
- else
- ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
-
- for (i = 0; i < n; i+=2) {
- buf[i + 0] = -(UINTFLOAT)(USE_FIXED + 1)*buf[i + 0];
- buf[i + 1] = (UINTFLOAT)(USE_FIXED + 1)*buf[i + 1];
- }
- // Like with the regular IMDCT at this point we still have the middle half
- // of a transform but with even symmetry on the left and odd symmetry on
- // the right
-
- // window overlapping
- // The spec says to use samples [0..511] but the reference decoder uses
- // samples [128..639].
- for (i = n4; i < n2; i ++) {
- out[i - n4] = AAC_MUL31( buf[ n2 - 1 - i] , window[i - n4]) +
- AAC_MUL31( saved[ i + n2] , window[i + n - n4]) +
- AAC_MUL31(-saved[n + n2 - 1 - i] , window[i + 2*n - n4]) +
- AAC_MUL31(-saved[ 2*n + n2 + i] , window[i + 3*n - n4]);
- }
- for (i = 0; i < n2; i ++) {
- out[n4 + i] = AAC_MUL31( buf[ i] , window[i + n2 - n4]) +
- AAC_MUL31(-saved[ n - 1 - i] , window[i + n2 + n - n4]) +
- AAC_MUL31(-saved[ n + i] , window[i + n2 + 2*n - n4]) +
- AAC_MUL31( saved[2*n + n - 1 - i] , window[i + n2 + 3*n - n4]);
- }
- for (i = 0; i < n4; i ++) {
- out[n2 + n4 + i] = AAC_MUL31( buf[ i + n2] , window[i + n - n4]) +
- AAC_MUL31(-saved[n2 - 1 - i] , window[i + 2*n - n4]) +
- AAC_MUL31(-saved[n + n2 + i] , window[i + 3*n - n4]);
- }
-
- // buffer update
- memmove(saved + n, saved, 2 * n * sizeof(*saved));
- memcpy( saved, buf, n * sizeof(*saved));
-}
-
/**
* channel coupling transformation interface
*
@@ -2653,16 +2437,16 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
void (*imdct_and_window)(AACDecContext *ac, SingleChannelElement *sce);
switch (ac->oc[1].m4ac.object_type) {
case AOT_ER_AAC_LD:
- imdct_and_window = imdct_and_windowing_ld;
+ imdct_and_window = ac->dsp.imdct_and_windowing_ld;
break;
case AOT_ER_AAC_ELD:
- imdct_and_window = imdct_and_windowing_eld;
+ imdct_and_window = ac->dsp.imdct_and_windowing_eld;
break;
default:
if (ac->oc[1].m4ac.frame_length_short)
- imdct_and_window = imdct_and_windowing_960;
+ imdct_and_window = ac->dsp.imdct_and_windowing_960;
else
- imdct_and_window = ac->imdct_and_windowing;
+ imdct_and_window = ac->dsp.imdct_and_windowing;
}
for (type = 3; type >= 0; type--) {
for (i = 0; i < MAX_ELEM_ID; i++) {
@@ -3134,7 +2918,6 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
static void aacdec_init(AACDecContext *c)
{
- c->imdct_and_windowing = imdct_and_windowing;
c->AAC_RENAME(windowing_and_mdct_ltp) = windowing_and_mdct_ltp;
#if USE_FIXED
c->vector_pow43 = vector_pow43;
diff --git a/libavcodec/mips/aacdec_mips.c b/libavcodec/mips/aacdec_mips.c
index 5b71bb97ab..b9848baaaa 100644
--- a/libavcodec/mips/aacdec_mips.c
+++ b/libavcodec/mips/aacdec_mips.c
@@ -435,7 +435,7 @@ void ff_aacdec_init_mips(AACDecContext *c)
{
#if HAVE_INLINE_ASM
#if HAVE_MIPSFPU
- c->imdct_and_windowing = imdct_and_windowing_mips;
+ c->dsp.imdct_and_windowing = imdct_and_windowing_mips;
c->dsp.apply_ltp = apply_ltp_mips;
c->update_ltp = update_ltp_mips;
#endif /* HAVE_MIPSFPU */
--
2.43.0.381.gb435a96ce8
[-- Attachment #21: 0019-aacdec-duplicate-table-initialization.patch --]
[-- Type: text/x-diff, Size: 4811 bytes --]
From c88897ef5f53b796e6769208cd79de1accd2966a Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Sat, 16 Mar 2024 00:12:56 +0100
Subject: [PATCH 19/38] aacdec: duplicate table initialization
Preparation to move all table init and support windowing functions.
---
libavcodec/aac/aacdec.c | 2 ++
libavcodec/aac/aacdec_dsp_template.c | 2 ++
libavcodec/aac/aacdec_fixed.c | 26 ++++++++++++++++++++++++--
libavcodec/aac/aacdec_float.c | 27 +++++++++++++++++++++++++++
libavcodec/aacdec.h | 2 ++
5 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 00353bddc7..26612f4a14 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -120,6 +120,8 @@ av_cold int ff_aac_decode_init_common(AVCodecContext *avctx)
ac->dsp = is_fixed ? aac_dsp_fixed : aac_dsp;
+ ac->dsp.init_tables();
+
return 0;
}
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 5e18b30d99..30151604c2 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -311,6 +311,8 @@ static void AAC_RENAME(update_ltp)(AACDecContext *ac, SingleChannelElement *sce)
}
const AACDecDSP AAC_RENAME(aac_dsp) = {
+ .init_tables = &AAC_RENAME(init_tables),
+
.dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
.apply_mid_side_stereo = &AAC_RENAME(apply_mid_side_stereo),
.apply_intensity_stereo = &AAC_RENAME(apply_intensity_stereo),
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index 9b66f22d2f..9dd8f34f55 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -31,12 +31,34 @@
#define USE_FIXED 1
+#include "libavutil/thread.h"
+
#include "libavcodec/aac_defines.h"
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin_fixed_tablegen.h"
+#include "libavcodec/kbdwin.h"
+
+DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME2(aac_kbd_long_1024))[1024];
+DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME2(aac_kbd_short_128))[128];
+DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_long_960))[960];
+DECLARE_ALIGNED(32, static INTFLOAT, AAC_RENAME(aac_kbd_short_120))[120];
+
+static void init_tables_fixed_fn(void)
+{
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024);
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128);
+
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960);
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120);
+
+ init_sine_windows_fixed();
+}
-DECLARE_ALIGNED(32, extern int, AAC_RENAME2(aac_kbd_long_1024))[1024];
-DECLARE_ALIGNED(32, extern int, AAC_RENAME2(aac_kbd_short_128))[128];
+static void init_tables_fixed(void)
+{
+ static AVOnce init_fixed_once = AV_ONCE_INIT;
+ ff_thread_once(&init_fixed_once, init_tables_fixed_fn);
+}
#include "aacdec_dsp_template.c"
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index ba1b06cc21..6a5e8483b0 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -31,9 +31,36 @@
#define USE_FIXED 0
+#include "libavutil/thread.h"
+
#include "libavcodec/aac_defines.h"
#include "libavcodec/aactab.h"
#include "libavcodec/sinewin.h"
+#include "libavcodec/kbdwin.h"
+
+DECLARE_ALIGNED(32, static float, sine_120)[120];
+DECLARE_ALIGNED(32, static float, sine_960)[960];
+DECLARE_ALIGNED(32, static float, aac_kbd_long_960)[960];
+DECLARE_ALIGNED(32, static float, aac_kbd_short_120)[120];
+
+static void init_tables_float_fn(void)
+{
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_long_1024), 4.0, 1024);
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME2(aac_kbd_short_128), 6.0, 128);
+
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_long_960), 4.0, 960);
+ AAC_RENAME(ff_kbd_window_init)(AAC_RENAME(aac_kbd_short_120), 6.0, 120);
+
+ AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_960), 960);
+ AAC_RENAME(ff_sine_window_init)(AAC_RENAME(sine_120), 120);
+ AAC_RENAME(ff_init_ff_sine_windows)(9);
+}
+
+static void init_tables(void)
+{
+ static AVOnce init_float_once = AV_ONCE_INIT;
+ ff_thread_once(&init_float_once, init_tables_float_fn);
+}
#include "aacdec_dsp_template.c"
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 109c38d8e2..30da1fc198 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -204,6 +204,8 @@ typedef struct DynamicRangeControl {
* DSP-specific primitives
*/
typedef struct AACDecDSP {
+ void (*init_tables)(void);
+
void (*dequant_scalefactors)(SingleChannelElement *sce);
void (*apply_mid_side_stereo)(AACDecContext *ac, ChannelElement *cpe);
--
2.43.0.381.gb435a96ce8
[-- Attachment #22: 0018-aacdec-template-LTP-application-separately.patch --]
[-- Type: text/x-diff, Size: 13949 bytes --]
From e5ebfc1cb2cb326bc0f2054f345c0f168e9d3406 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 14 Mar 2024 04:52:28 +0100
Subject: [PATCH 18/38] aacdec: template LTP application separately
---
libavcodec/aac/aacdec_dsp_template.c | 76 ++++++++++++++++++++++++-
libavcodec/aac/aacdec_fixed.c | 8 +++
libavcodec/aac/aacdec_float.c | 5 ++
libavcodec/aacdec.h | 2 -
libavcodec/aacdec_fixed.c | 8 +--
libavcodec/aacdec_template.c | 83 ++--------------------------
libavcodec/mips/aacdec_mips.c | 2 +-
7 files changed, 97 insertions(+), 87 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index da7f5fac4f..5e18b30d99 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -30,7 +30,6 @@
*/
#include "libavcodec/aacdec.h"
-#include "libavcodec/aac_defines.h"
#include "libavcodec/lpc_functions.h"
#include "libavcodec/aactab.h"
@@ -238,9 +237,84 @@ static void AAC_RENAME(apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
}
}
+/**
+ * Apply the long term prediction
+ */
+static void AAC_RENAME(apply_ltp)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ const LongTermPrediction *ltp = &sce->ics.ltp;
+ const uint16_t *offsets = sce->ics.swb_offset;
+ int i, sfb;
+
+ if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
+ INTFLOAT *predTime = sce->AAC_RENAME(output);
+ INTFLOAT *predFreq = ac->AAC_RENAME(buf_mdct);
+ int16_t num_samples = 2048;
+
+ if (ltp->lag < 1024)
+ num_samples = ltp->lag + 1024;
+ for (i = 0; i < num_samples; i++)
+ predTime[i] = AAC_MUL30(sce->AAC_RENAME(ltp_state)[i + 2048 - ltp->lag], ltp->AAC_RENAME(coef));
+ memset(&predTime[i], 0, (2048 - i) * sizeof(*predTime));
+
+ ac->AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
+
+ if (sce->tns.present)
+ AAC_RENAME(apply_tns)(predFreq, &sce->tns, &sce->ics, 0);
+
+ for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
+ if (ltp->used[sfb])
+ for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
+ sce->AAC_RENAME(coeffs)[i] += (UINTFLOAT)predFreq[i];
+ }
+}
+
+/**
+ * Update the LTP buffer for next frame
+ */
+static void AAC_RENAME(update_ltp)(AACDecContext *ac, SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ INTFLOAT *saved_ltp = sce->AAC_RENAME(coeffs);
+ const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
+ const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
+ int i;
+
+ if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
+ memcpy(saved_ltp, saved, 512 * sizeof(*saved_ltp));
+ memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
+ ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
+
+ for (i = 0; i < 64; i++)
+ saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
+ } else if (1 && ics->window_sequence[0] == LONG_START_SEQUENCE) {
+ memcpy(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, 448 * sizeof(*saved_ltp));
+ memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
+ ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
+
+ for (i = 0; i < 64; i++)
+ saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
+ } else if (1) { // LONG_STOP or ONLY_LONG
+ ac->fdsp->vector_fmul_reverse(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, &lwindow[512], 512);
+
+ for (i = 0; i < 512; i++)
+ saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], lwindow[511 - i]);
+ }
+
+ memcpy(sce->AAC_RENAME(ltp_state), sce->AAC_RENAME(ltp_state)+1024,
+ 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
+ memcpy(sce->AAC_RENAME(ltp_state) + 1024, sce->AAC_RENAME(output),
+ 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
+ memcpy(sce->AAC_RENAME(ltp_state) + 2048, saved_ltp,
+ 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
.apply_mid_side_stereo = &AAC_RENAME(apply_mid_side_stereo),
.apply_intensity_stereo = &AAC_RENAME(apply_intensity_stereo),
.apply_tns = &AAC_RENAME(apply_tns),
+ .apply_ltp = &AAC_RENAME(apply_ltp),
+ .update_ltp = &AAC_RENAME(update_ltp),
};
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
index 1b41a43a46..9b66f22d2f 100644
--- a/libavcodec/aac/aacdec_fixed.c
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -31,4 +31,12 @@
#define USE_FIXED 1
+#include "libavcodec/aac_defines.h"
+
+#include "libavcodec/aactab.h"
+#include "libavcodec/sinewin_fixed_tablegen.h"
+
+DECLARE_ALIGNED(32, extern int, AAC_RENAME2(aac_kbd_long_1024))[1024];
+DECLARE_ALIGNED(32, extern int, AAC_RENAME2(aac_kbd_short_128))[128];
+
#include "aacdec_dsp_template.c"
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
index a40c1c1f03..ba1b06cc21 100644
--- a/libavcodec/aac/aacdec_float.c
+++ b/libavcodec/aac/aacdec_float.c
@@ -31,4 +31,9 @@
#define USE_FIXED 0
+#include "libavcodec/aac_defines.h"
+
+#include "libavcodec/aactab.h"
+#include "libavcodec/sinewin.h"
+
#include "aacdec_dsp_template.c"
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 3c8d14a53e..109c38d8e2 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -310,14 +310,12 @@ struct AACDecContext {
/* aacdec functions pointers */
void (*imdct_and_windowing)(struct AACDecContext *ac, SingleChannelElement *sce);
- void (*apply_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
union {
void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, float *out,
float *in, IndividualChannelStream *ics);
void (*windowing_and_mdct_ltp_fixed)(struct AACDecContext *ac, int *out,
int *in, IndividualChannelStream *ics);
};
- void (*update_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*vector_pow43)(int *coefs, int len);
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
};
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 2c87cddd6e..7633f4adb0 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -81,10 +81,10 @@
#include <math.h>
#include <string.h>
-DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_long_1024))[1024];
-DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_short_128))[128];
-DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_long_960))[960];
-DECLARE_ALIGNED(32, static int, AAC_RENAME2(aac_kbd_short_120))[120];
+DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_long_1024))[1024];
+DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_short_128))[128];
+DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_long_960))[960];
+DECLARE_ALIGNED(32, int, AAC_RENAME2(aac_kbd_short_120))[120];
/* @name ltp_coef
* Table of the LTP coefficients
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 7a33357a3c..041ac0a90e 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2393,79 +2393,6 @@ static void windowing_and_mdct_ltp(AACDecContext *ac, INTFLOAT *out,
ac->mdct_ltp_fn(ac->mdct_ltp, out, in, sizeof(INTFLOAT));
}
-/**
- * Apply the long term prediction
- */
-static void apply_ltp(AACDecContext *ac, SingleChannelElement *sce)
-{
- const LongTermPrediction *ltp = &sce->ics.ltp;
- const uint16_t *offsets = sce->ics.swb_offset;
- int i, sfb;
-
- if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
- INTFLOAT *predTime = sce->AAC_RENAME(output);
- INTFLOAT *predFreq = ac->AAC_RENAME(buf_mdct);
- int16_t num_samples = 2048;
-
- if (ltp->lag < 1024)
- num_samples = ltp->lag + 1024;
- for (i = 0; i < num_samples; i++)
- predTime[i] = AAC_MUL30(sce->AAC_RENAME(ltp_state)[i + 2048 - ltp->lag], ltp->AAC_RENAME(coef));
- memset(&predTime[i], 0, (2048 - i) * sizeof(*predTime));
-
- ac->AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
-
- if (sce->tns.present)
- ac->dsp.apply_tns(predFreq, &sce->tns, &sce->ics, 0);
-
- for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
- if (ltp->used[sfb])
- for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
- sce->AAC_RENAME(coeffs)[i] += (UINTFLOAT)predFreq[i];
- }
-}
-
-/**
- * Update the LTP buffer for next frame
- */
-static void update_ltp(AACDecContext *ac, SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *saved = sce->AAC_RENAME(saved);
- INTFLOAT *saved_ltp = sce->AAC_RENAME(coeffs);
- const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
- const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
- int i;
-
- if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
- memcpy(saved_ltp, saved, 512 * sizeof(*saved_ltp));
- memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
- ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
-
- for (i = 0; i < 64; i++)
- saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
- } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
- memcpy(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, 448 * sizeof(*saved_ltp));
- memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
- ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
-
- for (i = 0; i < 64; i++)
- saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
- } else { // LONG_STOP or ONLY_LONG
- ac->fdsp->vector_fmul_reverse(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, &lwindow[512], 512);
-
- for (i = 0; i < 512; i++)
- saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], lwindow[511 - i]);
- }
-
- memcpy(sce->AAC_RENAME(ltp_state), sce->AAC_RENAME(ltp_state)+1024,
- 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
- memcpy(sce->AAC_RENAME(ltp_state) + 1024, sce->AAC_RENAME(output),
- 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
- memcpy(sce->AAC_RENAME(ltp_state) + 2048, saved_ltp,
- 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
-}
-
/**
* Conduct IMDCT and windowing.
*/
@@ -2746,9 +2673,9 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
if (che->ch[0].ics.predictor_present) {
if (che->ch[0].ics.ltp.present)
- ac->apply_ltp(ac, &che->ch[0]);
+ ac->dsp.apply_ltp(ac, &che->ch[0]);
if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
- ac->apply_ltp(ac, &che->ch[1]);
+ ac->dsp.apply_ltp(ac, &che->ch[1]);
}
}
if (che->ch[0].tns.present)
@@ -2762,11 +2689,11 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
imdct_and_window(ac, &che->ch[0]);
if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
- ac->update_ltp(ac, &che->ch[0]);
+ ac->dsp.update_ltp(ac, &che->ch[0]);
if (type == TYPE_CPE) {
imdct_and_window(ac, &che->ch[1]);
if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
- ac->update_ltp(ac, &che->ch[1]);
+ ac->dsp.update_ltp(ac, &che->ch[1]);
}
if (ac->oc[1].m4ac.sbr > 0) {
AAC_RENAME(ff_aac_sbr_apply)(ac, che, type,
@@ -3208,9 +3135,7 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
static void aacdec_init(AACDecContext *c)
{
c->imdct_and_windowing = imdct_and_windowing;
- c->apply_ltp = apply_ltp;
c->AAC_RENAME(windowing_and_mdct_ltp) = windowing_and_mdct_ltp;
- c->update_ltp = update_ltp;
#if USE_FIXED
c->vector_pow43 = vector_pow43;
c->subband_scale = subband_scale;
diff --git a/libavcodec/mips/aacdec_mips.c b/libavcodec/mips/aacdec_mips.c
index 834794d9a2..5b71bb97ab 100644
--- a/libavcodec/mips/aacdec_mips.c
+++ b/libavcodec/mips/aacdec_mips.c
@@ -436,7 +436,7 @@ void ff_aacdec_init_mips(AACDecContext *c)
#if HAVE_INLINE_ASM
#if HAVE_MIPSFPU
c->imdct_and_windowing = imdct_and_windowing_mips;
- c->apply_ltp = apply_ltp_mips;
+ c->dsp.apply_ltp = apply_ltp_mips;
c->update_ltp = update_ltp_mips;
#endif /* HAVE_MIPSFPU */
#endif /* HAVE_INLINE_ASM */
--
2.43.0.381.gb435a96ce8
[-- Attachment #23: 0017-aacdec-template-TNS-application-separately.patch --]
[-- Type: text/x-diff, Size: 9617 bytes --]
From 3c097d4601bc61230af993ccd1227acfd08e2b05 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 22:20:59 +0100
Subject: [PATCH 17/38] aacdec: template TNS application separately
---
libavcodec/aac/aacdec_dsp_template.c | 65 +++++++++++++++++++++++++
libavcodec/aacdec.h | 6 ---
libavcodec/aacdec_template.c | 73 ++--------------------------
libavcodec/mips/aacdec_mips.c | 2 +-
4 files changed, 71 insertions(+), 75 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 102091d331..da7f5fac4f 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -31,6 +31,7 @@
#include "libavcodec/aacdec.h"
#include "libavcodec/aac_defines.h"
+#include "libavcodec/lpc_functions.h"
#include "libavcodec/aactab.h"
@@ -174,8 +175,72 @@ static void AAC_RENAME(apply_intensity_stereo)(AACDecContext *ac,
}
}
+/**
+ * Decode Temporal Noise Shaping filter coefficients and apply all-pole filters; reference: 4.6.9.3.
+ *
+ * @param decode 1 if tool is used normally, 0 if tool is used in LTP.
+ * @param coef spectral coefficients
+ */
+static void AAC_RENAME(apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
+ IndividualChannelStream *ics, int decode)
+{
+ const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
+ int w, filt, m, i;
+ int bottom, top, order, start, end, size, inc;
+ INTFLOAT *coef_param = _coef_param;
+ INTFLOAT lpc[TNS_MAX_ORDER];
+ INTFLOAT tmp[TNS_MAX_ORDER+1];
+ UINTFLOAT *coef = coef_param;
+
+ if(!mmm)
+ return;
+
+ for (w = 0; w < ics->num_windows; w++) {
+ bottom = ics->num_swb;
+ for (filt = 0; filt < tns->n_filt[w]; filt++) {
+ top = bottom;
+ bottom = FFMAX(0, top - tns->length[w][filt]);
+ order = tns->order[w][filt];
+ if (order == 0)
+ continue;
+
+ // tns_decode_coef
+ compute_lpc_coefs(tns->AAC_RENAME(coef)[w][filt], order, lpc, 0, 0, 0);
+
+ start = ics->swb_offset[FFMIN(bottom, mmm)];
+ end = ics->swb_offset[FFMIN( top, mmm)];
+ if ((size = end - start) <= 0)
+ continue;
+ if (tns->direction[w][filt]) {
+ inc = -1;
+ start = end - 1;
+ } else {
+ inc = 1;
+ }
+ start += w * 128;
+
+ if (decode) {
+ // ar filter
+ for (m = 0; m < size; m++, start += inc)
+ for (i = 1; i <= FFMIN(m, order); i++)
+ coef[start] -= AAC_MUL26((INTFLOAT)coef[start - i * inc], lpc[i - 1]);
+ } else {
+ // ma filter
+ for (m = 0; m < size; m++, start += inc) {
+ tmp[0] = coef[start];
+ for (i = 1; i <= FFMIN(m, order); i++)
+ coef[start] += AAC_MUL26(tmp[i], lpc[i - 1]);
+ for (i = order; i > 0; i--)
+ tmp[i] = tmp[i - 1];
+ }
+ }
+ }
+ }
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
.apply_mid_side_stereo = &AAC_RENAME(apply_mid_side_stereo),
.apply_intensity_stereo = &AAC_RENAME(apply_intensity_stereo),
+ .apply_tns = &AAC_RENAME(apply_tns),
};
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 9078c2a4e6..3c8d14a53e 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -311,12 +311,6 @@ struct AACDecContext {
/* aacdec functions pointers */
void (*imdct_and_windowing)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*apply_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
- union {
- void (*apply_tns)(float coef[1024], TemporalNoiseShaping *tns,
- IndividualChannelStream *ics, int decode);
- void (*apply_tns_fixed)(int coef[1024], TemporalNoiseShaping *tns,
- IndividualChannelStream *ics, int decode);
- };
union {
void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, float *out,
float *in, IndividualChannelStream *ics);
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 5e98e6b8ef..7a33357a3c 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2366,68 +2366,6 @@ static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cn
return res;
}
-/**
- * Decode Temporal Noise Shaping filter coefficients and apply all-pole filters; reference: 4.6.9.3.
- *
- * @param decode 1 if tool is used normally, 0 if tool is used in LTP.
- * @param coef spectral coefficients
- */
-static void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns,
- IndividualChannelStream *ics, int decode)
-{
- const int mmm = FFMIN(ics->tns_max_bands, ics->max_sfb);
- int w, filt, m, i;
- int bottom, top, order, start, end, size, inc;
- INTFLOAT lpc[TNS_MAX_ORDER];
- INTFLOAT tmp[TNS_MAX_ORDER+1];
- UINTFLOAT *coef = coef_param;
-
- if(!mmm)
- return;
-
- for (w = 0; w < ics->num_windows; w++) {
- bottom = ics->num_swb;
- for (filt = 0; filt < tns->n_filt[w]; filt++) {
- top = bottom;
- bottom = FFMAX(0, top - tns->length[w][filt]);
- order = tns->order[w][filt];
- if (order == 0)
- continue;
-
- // tns_decode_coef
- compute_lpc_coefs(tns->AAC_RENAME(coef)[w][filt], order, lpc, 0, 0, 0);
-
- start = ics->swb_offset[FFMIN(bottom, mmm)];
- end = ics->swb_offset[FFMIN( top, mmm)];
- if ((size = end - start) <= 0)
- continue;
- if (tns->direction[w][filt]) {
- inc = -1;
- start = end - 1;
- } else {
- inc = 1;
- }
- start += w * 128;
-
- if (decode) {
- // ar filter
- for (m = 0; m < size; m++, start += inc)
- for (i = 1; i <= FFMIN(m, order); i++)
- coef[start] -= AAC_MUL26((INTFLOAT)coef[start - i * inc], lpc[i - 1]);
- } else {
- // ma filter
- for (m = 0; m < size; m++, start += inc) {
- tmp[0] = coef[start];
- for (i = 1; i <= FFMIN(m, order); i++)
- coef[start] += AAC_MUL26(tmp[i], lpc[i - 1]);
- for (i = order; i > 0; i--)
- tmp[i] = tmp[i - 1];
- }
- }
- }
- }
-}
-
/**
* Apply windowing and MDCT to obtain the spectral
* coefficient from the predicted sample by LTP.
@@ -2478,7 +2416,7 @@ static void apply_ltp(AACDecContext *ac, SingleChannelElement *sce)
ac->AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
if (sce->tns.present)
- ac->AAC_RENAME(apply_tns)(predFreq, &sce->tns, &sce->ics, 0);
+ ac->dsp.apply_tns(predFreq, &sce->tns, &sce->ics, 0);
for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
if (ltp->used[sfb])
@@ -2814,11 +2752,11 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
}
}
if (che->ch[0].tns.present)
- ac->AAC_RENAME(apply_tns)(che->ch[0].AAC_RENAME(coeffs),
- &che->ch[0].tns, &che->ch[0].ics, 1);
+ ac->dsp.apply_tns(che->ch[0].AAC_RENAME(coeffs),
+ &che->ch[0].tns, &che->ch[0].ics, 1);
if (che->ch[1].tns.present)
- ac->AAC_RENAME(apply_tns)(che->ch[1].AAC_RENAME(coeffs),
- &che->ch[1].tns, &che->ch[1].ics, 1);
+ ac->dsp.apply_tns(che->ch[1].AAC_RENAME(coeffs),
+ &che->ch[1].tns, &che->ch[1].ics, 1);
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, AAC_RENAME(apply_dependent_coupling));
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
@@ -3271,7 +3209,6 @@ static void aacdec_init(AACDecContext *c)
{
c->imdct_and_windowing = imdct_and_windowing;
c->apply_ltp = apply_ltp;
- c->AAC_RENAME(apply_tns) = apply_tns;
c->AAC_RENAME(windowing_and_mdct_ltp) = windowing_and_mdct_ltp;
c->update_ltp = update_ltp;
#if USE_FIXED
diff --git a/libavcodec/mips/aacdec_mips.c b/libavcodec/mips/aacdec_mips.c
index 2820f980a4..834794d9a2 100644
--- a/libavcodec/mips/aacdec_mips.c
+++ b/libavcodec/mips/aacdec_mips.c
@@ -275,7 +275,7 @@ static void apply_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
ac->windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
if (sce->tns.present)
- ac->apply_tns(predFreq, &sce->tns, &sce->ics, 0);
+ ac->dsp.apply_tns(predFreq, &sce->tns, &sce->ics, 0);
for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
if (ltp->used[sfb])
--
2.43.0.381.gb435a96ce8
[-- Attachment #24: 0016-aacdec-template-intensity-stereo-application-separat.patch --]
[-- Type: text/x-diff, Size: 6274 bytes --]
From 782c6b4dd4e0265366b5336cdc408c8d5c1ef6af Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 22:01:44 +0100
Subject: [PATCH 16/38] aacdec: template intensity stereo application
separately
---
libavcodec/aac/aacdec_dsp_template.c | 53 +++++++++++++++++++++++++++
libavcodec/aacdec_template.c | 54 +---------------------------
2 files changed, 54 insertions(+), 53 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 3a43e1b04e..102091d331 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -122,7 +122,60 @@ static void AAC_RENAME(apply_mid_side_stereo)(AACDecContext *ac, ChannelElement
}
}
+/**
+ * intensity stereo decoding; reference: 4.6.8.2.3
+ *
+ * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
+ * [1] mask is decoded from bitstream; [2] mask is all 1s;
+ * [3] reserved for scalable AAC
+ */
+static void AAC_RENAME(apply_intensity_stereo)(AACDecContext *ac,
+ ChannelElement *cpe, int ms_present)
+{
+ const IndividualChannelStream *ics = &cpe->ch[1].ics;
+ SingleChannelElement *sce1 = &cpe->ch[1];
+ INTFLOAT *coef0 = cpe->ch[0].AAC_RENAME(coeffs), *coef1 = cpe->ch[1].AAC_RENAME(coeffs);
+ const uint16_t *offsets = ics->swb_offset;
+ int g, group, i, idx = 0;
+ int c;
+ INTFLOAT scale;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb;) {
+ if (sce1->band_type[idx] == INTENSITY_BT ||
+ sce1->band_type[idx] == INTENSITY_BT2) {
+ const int bt_run_end = sce1->band_type_run_end[idx];
+ for (; i < bt_run_end; i++, idx++) {
+ c = -1 + 2 * (sce1->band_type[idx] - 14);
+ if (ms_present)
+ c *= 1 - 2 * cpe->ms_mask[idx];
+ scale = c * sce1->AAC_RENAME(sf)[idx];
+ for (group = 0; group < ics->group_len[g]; group++)
+#if USE_FIXED
+ ac->subband_scale(coef1 + group * 128 + offsets[i],
+ coef0 + group * 128 + offsets[i],
+ scale,
+ 23,
+ offsets[i + 1] - offsets[i] ,ac->avctx);
+#else
+ ac->fdsp->vector_fmul_scalar(coef1 + group * 128 + offsets[i],
+ coef0 + group * 128 + offsets[i],
+ scale,
+ offsets[i + 1] - offsets[i]);
+#endif /* USE_FIXED */
+ }
+ } else {
+ int bt_run_end = sce1->band_type_run_end[idx];
+ idx += bt_run_end - i;
+ i = bt_run_end;
+ }
+ }
+ coef0 += ics->group_len[g] * 128;
+ coef1 += ics->group_len[g] * 128;
+ }
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
.apply_mid_side_stereo = &AAC_RENAME(apply_mid_side_stereo),
+ .apply_intensity_stereo = &AAC_RENAME(apply_intensity_stereo),
};
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index e0208743d8..5e98e6b8ef 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2061,58 +2061,6 @@ fail:
return ret;
}
-/**
- * intensity stereo decoding; reference: 4.6.8.2.3
- *
- * @param ms_present Indicates mid/side stereo presence. [0] mask is all 0s;
- * [1] mask is decoded from bitstream; [2] mask is all 1s;
- * [3] reserved for scalable AAC
- */
-static void apply_intensity_stereo(AACDecContext *ac,
- ChannelElement *cpe, int ms_present)
-{
- const IndividualChannelStream *ics = &cpe->ch[1].ics;
- SingleChannelElement *sce1 = &cpe->ch[1];
- INTFLOAT *coef0 = cpe->ch[0].AAC_RENAME(coeffs), *coef1 = cpe->ch[1].AAC_RENAME(coeffs);
- const uint16_t *offsets = ics->swb_offset;
- int g, group, i, idx = 0;
- int c;
- INTFLOAT scale;
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb;) {
- if (sce1->band_type[idx] == INTENSITY_BT ||
- sce1->band_type[idx] == INTENSITY_BT2) {
- const int bt_run_end = sce1->band_type_run_end[idx];
- for (; i < bt_run_end; i++, idx++) {
- c = -1 + 2 * (sce1->band_type[idx] - 14);
- if (ms_present)
- c *= 1 - 2 * cpe->ms_mask[idx];
- scale = c * sce1->AAC_RENAME(sf)[idx];
- for (group = 0; group < ics->group_len[g]; group++)
-#if USE_FIXED
- ac->subband_scale(coef1 + group * 128 + offsets[i],
- coef0 + group * 128 + offsets[i],
- scale,
- 23,
- offsets[i + 1] - offsets[i] ,ac->avctx);
-#else
- ac->fdsp->vector_fmul_scalar(coef1 + group * 128 + offsets[i],
- coef0 + group * 128 + offsets[i],
- scale,
- offsets[i + 1] - offsets[i]);
-#endif /* USE_FIXED */
- }
- } else {
- int bt_run_end = sce1->band_type_run_end[idx];
- idx += bt_run_end - i;
- i = bt_run_end;
- }
- }
- coef0 += ics->group_len[g] * 128;
- coef1 += ics->group_len[g] * 128;
- }
-}
-
/**
* Decode a channel_pair_element; reference: table 4.4.
*
@@ -2155,7 +2103,7 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
}
}
- apply_intensity_stereo(ac, cpe, ms_present);
+ ac->dsp.apply_intensity_stereo(ac, cpe, ms_present);
return 0;
}
--
2.43.0.381.gb435a96ce8
[-- Attachment #25: 0015-aacdec-template-mid-side-stereo-application-separate.patch --]
[-- Type: text/x-diff, Size: 4529 bytes --]
From 811a99e5b1a289160757d36e009dc41885e792e4 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 21:59:35 +0100
Subject: [PATCH 15/38] aacdec: template mid/side stereo application separately
---
libavcodec/aac/aacdec_dsp_template.c | 35 +++++++++++++++++++++++++++
libavcodec/aacdec_template.c | 36 +---------------------------
2 files changed, 36 insertions(+), 35 deletions(-)
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
index 9a43cb71e0..3a43e1b04e 100644
--- a/libavcodec/aac/aacdec_dsp_template.c
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -88,6 +88,41 @@ static void AAC_RENAME(dequant_scalefactors)(SingleChannelElement *sce)
}
}
+/**
+ * Mid/Side stereo decoding; reference: 4.6.8.1.3.
+ */
+static void AAC_RENAME(apply_mid_side_stereo)(AACDecContext *ac, ChannelElement *cpe)
+{
+ const IndividualChannelStream *ics = &cpe->ch[0].ics;
+ INTFLOAT *ch0 = cpe->ch[0].AAC_RENAME(coeffs);
+ INTFLOAT *ch1 = cpe->ch[1].AAC_RENAME(coeffs);
+ int g, i, group, idx = 0;
+ const uint16_t *offsets = ics->swb_offset;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb; i++, idx++) {
+ if (cpe->ms_mask[idx] &&
+ cpe->ch[0].band_type[idx] < NOISE_BT &&
+ cpe->ch[1].band_type[idx] < NOISE_BT) {
+#if USE_FIXED
+ for (group = 0; group < ics->group_len[g]; group++) {
+ ac->fdsp->butterflies_fixed(ch0 + group * 128 + offsets[i],
+ ch1 + group * 128 + offsets[i],
+ offsets[i+1] - offsets[i]);
+#else
+ for (group = 0; group < ics->group_len[g]; group++) {
+ ac->fdsp->butterflies_float(ch0 + group * 128 + offsets[i],
+ ch1 + group * 128 + offsets[i],
+ offsets[i+1] - offsets[i]);
+#endif /* USE_FIXED */
+ }
+ }
+ }
+ ch0 += ics->group_len[g] * 128;
+ ch1 += ics->group_len[g] * 128;
+ }
+}
+
const AACDecDSP AAC_RENAME(aac_dsp) = {
.dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
+ .apply_mid_side_stereo = &AAC_RENAME(apply_mid_side_stereo),
};
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index d4d564cc14..e0208743d8 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -2061,40 +2061,6 @@ fail:
return ret;
}
-/**
- * Mid/Side stereo decoding; reference: 4.6.8.1.3.
- */
-static void apply_mid_side_stereo(AACDecContext *ac, ChannelElement *cpe)
-{
- const IndividualChannelStream *ics = &cpe->ch[0].ics;
- INTFLOAT *ch0 = cpe->ch[0].AAC_RENAME(coeffs);
- INTFLOAT *ch1 = cpe->ch[1].AAC_RENAME(coeffs);
- int g, i, group, idx = 0;
- const uint16_t *offsets = ics->swb_offset;
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb; i++, idx++) {
- if (cpe->ms_mask[idx] &&
- cpe->ch[0].band_type[idx] < NOISE_BT &&
- cpe->ch[1].band_type[idx] < NOISE_BT) {
-#if USE_FIXED
- for (group = 0; group < ics->group_len[g]; group++) {
- ac->fdsp->butterflies_fixed(ch0 + group * 128 + offsets[i],
- ch1 + group * 128 + offsets[i],
- offsets[i+1] - offsets[i]);
-#else
- for (group = 0; group < ics->group_len[g]; group++) {
- ac->fdsp->butterflies_float(ch0 + group * 128 + offsets[i],
- ch1 + group * 128 + offsets[i],
- offsets[i+1] - offsets[i]);
-#endif /* USE_FIXED */
- }
- }
- }
- ch0 += ics->group_len[g] * 128;
- ch1 += ics->group_len[g] * 128;
- }
-}
-
/**
* intensity stereo decoding; reference: 4.6.8.2.3
*
@@ -2182,7 +2148,7 @@ static int decode_cpe(AACDecContext *ac, GetBitContext *gb, ChannelElement *cpe)
if (common_window) {
if (ms_present)
- apply_mid_side_stereo(ac, cpe);
+ ac->dsp.apply_mid_side_stereo(ac, cpe);
if (ac->oc[1].m4ac.object_type == AOT_AAC_MAIN) {
apply_prediction(ac, &cpe->ch[0]);
apply_prediction(ac, &cpe->ch[1]);
--
2.43.0.381.gb435a96ce8
[-- Attachment #26: 0014-aacdec-template-scalefactor-dequantization-separatel.patch --]
[-- Type: text/x-diff, Size: 10890 bytes --]
From 711784691aaccc394ca3e75c49af57a2434d65cc Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 21:53:49 +0100
Subject: [PATCH 14/38] aacdec: template scalefactor dequantization separately
---
libavcodec/aac/Makefile | 6 +-
libavcodec/aac/aacdec.c | 5 ++
libavcodec/aac/aacdec_dsp_template.c | 93 ++++++++++++++++++++++++++++
libavcodec/aac/aacdec_fixed.c | 34 ++++++++++
libavcodec/aac/aacdec_float.c | 34 ++++++++++
libavcodec/aacdec_template.c | 56 +----------------
6 files changed, 171 insertions(+), 57 deletions(-)
create mode 100644 libavcodec/aac/aacdec_dsp_template.c
create mode 100644 libavcodec/aac/aacdec_fixed.c
create mode 100644 libavcodec/aac/aacdec_float.c
diff --git a/libavcodec/aac/Makefile b/libavcodec/aac/Makefile
index 29e0ef0a2c..c3e525d373 100644
--- a/libavcodec/aac/Makefile
+++ b/libavcodec/aac/Makefile
@@ -1,5 +1,7 @@
clean::
$(RM) $(CLEANSUFFIXES:%=libavcodec/aac/%)
-OBJS-$(CONFIG_AAC_DECODER) += aac/aacdec.o aac/aacdec_tab.o
-OBJS-$(CONFIG_AAC_FIXED_DECODER) += aac/aacdec.o aac/aacdec_tab.o
+OBJS-$(CONFIG_AAC_DECODER) += aac/aacdec.o aac/aacdec_tab.o \
+ aac/aacdec_float.o
+OBJS-$(CONFIG_AAC_FIXED_DECODER) += aac/aacdec.o aac/aacdec_tab.o \
+ aac/aacdec_fixed.o
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 358fe598e5..00353bddc7 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -45,6 +45,9 @@
#include "libavutil/tx.h"
#include "libavutil/version.h"
+extern const AACDecDSP aac_dsp;
+extern const AACDecDSP aac_dsp_fixed;
+
av_cold int ff_aac_decode_close(AVCodecContext *avctx)
{
AACDecContext *ac = avctx->priv_data;
@@ -115,6 +118,8 @@ av_cold int ff_aac_decode_init_common(AVCodecContext *avctx)
if (ret < 0)
return ret;
+ ac->dsp = is_fixed ? aac_dsp_fixed : aac_dsp;
+
return 0;
}
diff --git a/libavcodec/aac/aacdec_dsp_template.c b/libavcodec/aac/aacdec_dsp_template.c
new file mode 100644
index 0000000000..9a43cb71e0
--- /dev/null
+++ b/libavcodec/aac/aacdec_dsp_template.c
@@ -0,0 +1,93 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#include "libavcodec/aacdec.h"
+#include "libavcodec/aac_defines.h"
+
+#include "libavcodec/aactab.h"
+
+/**
+ * Convert integer scalefactors to the decoder's native expected
+ * scalefactor values.
+ */
+static void AAC_RENAME(dequant_scalefactors)(SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ const enum BandType *band_type = sce->band_type;
+ const int *band_type_run_end = sce->band_type_run_end;
+ const int *sfo = sce->sfo;
+ INTFLOAT *sf = sce->AAC_RENAME(sf);
+
+ int g, i, idx = 0;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb;) {
+ int run_end = band_type_run_end[idx];
+ switch (band_type[idx]) {
+ case ZERO_BT:
+ for (; i < run_end; i++, idx++)
+ sf[idx] = FIXR(0.);
+ break;
+ case INTENSITY_BT: /* fallthrough */
+ case INTENSITY_BT2:
+ for (; i < run_end; i++, idx++) {
+#if USE_FIXED
+ sf[idx] = 100 - sfo[idx];
+#else
+ sf[idx] = ff_aac_pow2sf_tab[-sfo[idx] + POW_SF2_ZERO];
+#endif /* USE_FIXED */
+ }
+ break;
+ case NOISE_BT:
+ for (; i < run_end; i++, idx++) {
+#if USE_FIXED
+ sf[idx] = -(100 + sfo[idx]);
+#else
+ sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
+#endif /* USE_FIXED */
+ }
+ break;
+ default:
+ for (; i < run_end; i++, idx++) {
+#if USE_FIXED
+ sf[idx] = -sfo[idx];
+#else
+ sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] - 100 + POW_SF2_ZERO];
+#endif /* USE_FIXED */
+ }
+ break;
+ }
+ }
+ }
+}
+
+const AACDecDSP AAC_RENAME(aac_dsp) = {
+ .dequant_scalefactors = &AAC_RENAME(dequant_scalefactors),
+};
diff --git a/libavcodec/aac/aacdec_fixed.c b/libavcodec/aac/aacdec_fixed.c
new file mode 100644
index 0000000000..1b41a43a46
--- /dev/null
+++ b/libavcodec/aac/aacdec_fixed.c
@@ -0,0 +1,34 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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 USE_FIXED 1
+
+#include "aacdec_dsp_template.c"
diff --git a/libavcodec/aac/aacdec_float.c b/libavcodec/aac/aacdec_float.c
new file mode 100644
index 0000000000..a40c1c1f03
--- /dev/null
+++ b/libavcodec/aac/aacdec_float.c
@@ -0,0 +1,34 @@
+/*
+ * AAC decoder
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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 USE_FIXED 0
+
+#include "aacdec_dsp_template.c"
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index a204069361..d4d564cc14 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1511,60 +1511,6 @@ static int decode_scalefactors(AACDecContext *ac, int sfo[120],
return 0;
}
-/**
- * Convert integer scalefactors to the decoder's native expected
- * scalefactor values.
- */
-static void dequant_scalefactors(SingleChannelElement *sce)
-{
- IndividualChannelStream *ics = &sce->ics;
- const enum BandType *band_type = sce->band_type;
- const int *band_type_run_end = sce->band_type_run_end;
- const int *sfo = sce->sfo;
- INTFLOAT *sf = sce->AAC_RENAME(sf);
-
- int g, i, idx = 0;
- for (g = 0; g < ics->num_window_groups; g++) {
- for (i = 0; i < ics->max_sfb;) {
- int run_end = band_type_run_end[idx];
- switch (band_type[idx]) {
- case ZERO_BT:
- for (; i < run_end; i++, idx++)
- sf[idx] = FIXR(0.);
- break;
- case INTENSITY_BT: /* fallthrough */
- case INTENSITY_BT2:
- for (; i < run_end; i++, idx++) {
-#if USE_FIXED
- sf[idx] = 100 - sfo[idx];
-#else
- sf[idx] = ff_aac_pow2sf_tab[-sfo[idx] + POW_SF2_ZERO];
-#endif /* USE_FIXED */
- }
- break;
- case NOISE_BT:
- for (; i < run_end; i++, idx++) {
-#if USE_FIXED
- sf[idx] = -(100 + sfo[idx]);
-#else
- sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
-#endif /* USE_FIXED */
- }
- break;
- default:
- for (; i < run_end; i++, idx++) {
-#if USE_FIXED
- sf[idx] = -sfo[idx];
-#else
- sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] - 100 + POW_SF2_ZERO];
-#endif /* USE_FIXED */
- }
- break;
- }
- }
- }
-}
-
/**
* Decode pulse data; reference: table 4.7.
*/
@@ -2060,7 +2006,7 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
sce->band_type, sce->band_type_run_end)) < 0)
goto fail;
- dequant_scalefactors(sce);
+ ac->dsp.dequant_scalefactors(sce);
pulse_present = 0;
if (!scale_flag) {
--
2.43.0.381.gb435a96ce8
[-- Attachment #27: 0013-aacdec-switch-ify-scalefactor-decoding.patch --]
[-- Type: text/x-diff, Size: 2539 bytes --]
From c04dda7f3a15e8df73ddabd5e3cf46a2d951bcb6 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 07:16:57 +0100
Subject: [PATCH 13/38] aacdec: switch-ify scalefactor decoding
Brings it in line with dequantization.
---
libavcodec/aacdec_template.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index b7eaa7216a..a204069361 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1459,11 +1459,13 @@ static int decode_scalefactors(AACDecContext *ac, int sfo[120],
for (g = 0; g < ics->num_window_groups; g++) {
for (i = 0; i < ics->max_sfb;) {
int run_end = band_type_run_end[idx];
- if (band_type[idx] == ZERO_BT) {
+ switch (band_type[idx]) {
+ case ZERO_BT:
for (; i < run_end; i++, idx++)
sfo[idx] = 0;
- } else if ((band_type[idx] == INTENSITY_BT) ||
- (band_type[idx] == INTENSITY_BT2)) {
+ break;
+ case INTENSITY_BT: /* fallthrough */
+ case INTENSITY_BT2:
for (; i < run_end; i++, idx++) {
offset[2] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
clipped_offset = av_clip(offset[2], -155, 100);
@@ -1475,7 +1477,8 @@ static int decode_scalefactors(AACDecContext *ac, int sfo[120],
}
sfo[idx] = clipped_offset;
}
- } else if (band_type[idx] == NOISE_BT) {
+ break;
+ case NOISE_BT:
for (; i < run_end; i++, idx++) {
if (noise_flag-- > 0)
offset[1] += get_bits(gb, NOISE_PRE_BITS) - NOISE_PRE;
@@ -1490,7 +1493,8 @@ static int decode_scalefactors(AACDecContext *ac, int sfo[120],
}
sfo[idx] = clipped_offset;
}
- } else {
+ break;
+ default:
for (; i < run_end; i++, idx++) {
offset[0] += get_vlc2(gb, ff_vlc_scalefactors, 7, 3) - SCALE_DIFF_ZERO;
if (offset[0] > 255U) {
@@ -1500,6 +1504,7 @@ static int decode_scalefactors(AACDecContext *ac, int sfo[120],
}
sfo[idx] = offset[0];
}
+ break;
}
}
}
--
2.43.0.381.gb435a96ce8
[-- Attachment #28: 0012-aacdec-give-spectrum-dequant-decode-SCE-rather-than-.patch --]
[-- Type: text/x-diff, Size: 2074 bytes --]
From c7344f433f1189fc2bdefb39fecd16bc709f4ebd Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 07:11:55 +0100
Subject: [PATCH 12/38] aacdec: give spectrum dequant+decode SCE rather than an
ICS
Eliminates using templated values in function definition.
---
libavcodec/aacdec_template.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 066dd58056..b7eaa7216a 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1659,14 +1659,16 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb,
* @return Returns error status. 0 - OK, !0 - error
*/
static int decode_spectrum_and_dequant(AACDecContext *ac, INTFLOAT coef[1024],
- GetBitContext *gb, const INTFLOAT sf[120],
+ GetBitContext *gb,
int pulse_present, const Pulse *pulse,
- const IndividualChannelStream *ics,
- enum BandType band_type[120])
+ SingleChannelElement *sce)
{
int i, k, g, idx = 0;
+ IndividualChannelStream *ics = &sce->ics;
const int c = 1024 / ics->num_windows;
const uint16_t *offsets = ics->swb_offset;
+ const INTFLOAT *sf = sce->AAC_RENAME(sf);
+ const enum BandType *band_type = sce->band_type;
INTFLOAT *coef_base = coef;
for (g = 0; g < ics->num_windows; g++)
@@ -2093,8 +2095,9 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
}
}
- ret = decode_spectrum_and_dequant(ac, out, gb, sce->AAC_RENAME(sf), pulse_present,
- &pulse, ics, sce->band_type);
+ ret = decode_spectrum_and_dequant(ac, out, gb,
+ pulse_present,
+ &pulse, sce);
if (ret < 0)
goto fail;
--
2.43.0.381.gb435a96ce8
[-- Attachment #29: 0011-aacdec-separate-out-scalefactor-dequantization-from-.patch --]
[-- Type: text/x-diff, Size: 6594 bytes --]
From c98909e18d642042b3d74a449e01839c666d55a4 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 07:11:22 +0100
Subject: [PATCH 11/38] aacdec: separate out scalefactor dequantization from
decoding
Allows to template away dequantization.
---
libavcodec/aacdec.h | 1 +
libavcodec/aacdec_template.c | 79 ++++++++++++++++++++++++++++--------
2 files changed, 63 insertions(+), 17 deletions(-)
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 052ed59e01..9078c2a4e6 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -147,6 +147,7 @@ typedef struct SingleChannelElement {
TemporalNoiseShaping tns;
enum BandType band_type[128]; ///< band types
int band_type_run_end[120]; ///< band type run end points
+ int sfo[120]; ///< scalefactor offsets
INTFLOAT_UNION(sf, [120]); ///< scalefactors
INTFLOAT_ALIGNED_UNION(32, coeffs, 1024); ///< coefficients for IMDCT, maybe processed
INTFLOAT_ALIGNED_UNION(32, saved, 1536); ///< overlap
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 893f8d3a73..066dd58056 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1445,7 +1445,8 @@ static int decode_band_types(AACDecContext *ac, enum BandType band_type[120],
*
* @return Returns error status. 0 - OK, !0 - error
*/
-static int decode_scalefactors(AACDecContext *ac, INTFLOAT sf[120], GetBitContext *gb,
+static int decode_scalefactors(AACDecContext *ac, int sfo[120],
+ GetBitContext *gb,
unsigned int global_gain,
IndividualChannelStream *ics,
enum BandType band_type[120],
@@ -1460,7 +1461,7 @@ static int decode_scalefactors(AACDecContext *ac, INTFLOAT sf[120], GetBitContex
int run_end = band_type_run_end[idx];
if (band_type[idx] == ZERO_BT) {
for (; i < run_end; i++, idx++)
- sf[idx] = FIXR(0.);
+ sfo[idx] = 0;
} else if ((band_type[idx] == INTENSITY_BT) ||
(band_type[idx] == INTENSITY_BT2)) {
for (; i < run_end; i++, idx++) {
@@ -1472,11 +1473,7 @@ static int decode_scalefactors(AACDecContext *ac, INTFLOAT sf[120], GetBitContex
"Clipped intensity stereo position (%d -> %d)",
offset[2], clipped_offset);
}
-#if USE_FIXED
- sf[idx] = 100 - clipped_offset;
-#else
- sf[idx] = ff_aac_pow2sf_tab[-clipped_offset + POW_SF2_ZERO];
-#endif /* USE_FIXED */
+ sfo[idx] = clipped_offset;
}
} else if (band_type[idx] == NOISE_BT) {
for (; i < run_end; i++, idx++) {
@@ -1491,11 +1488,7 @@ static int decode_scalefactors(AACDecContext *ac, INTFLOAT sf[120], GetBitContex
"Clipped noise gain (%d -> %d)",
offset[1], clipped_offset);
}
-#if USE_FIXED
- sf[idx] = -(100 + clipped_offset);
-#else
- sf[idx] = -ff_aac_pow2sf_tab[clipped_offset + POW_SF2_ZERO];
-#endif /* USE_FIXED */
+ sfo[idx] = clipped_offset;
}
} else {
for (; i < run_end; i++, idx++) {
@@ -1505,16 +1498,66 @@ static int decode_scalefactors(AACDecContext *ac, INTFLOAT sf[120], GetBitContex
"Scalefactor (%d) out of range.\n", offset[0]);
return AVERROR_INVALIDDATA;
}
+ sfo[idx] = offset[0];
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Convert integer scalefactors to the decoder's native expected
+ * scalefactor values.
+ */
+static void dequant_scalefactors(SingleChannelElement *sce)
+{
+ IndividualChannelStream *ics = &sce->ics;
+ const enum BandType *band_type = sce->band_type;
+ const int *band_type_run_end = sce->band_type_run_end;
+ const int *sfo = sce->sfo;
+ INTFLOAT *sf = sce->AAC_RENAME(sf);
+
+ int g, i, idx = 0;
+ for (g = 0; g < ics->num_window_groups; g++) {
+ for (i = 0; i < ics->max_sfb;) {
+ int run_end = band_type_run_end[idx];
+ switch (band_type[idx]) {
+ case ZERO_BT:
+ for (; i < run_end; i++, idx++)
+ sf[idx] = FIXR(0.);
+ break;
+ case INTENSITY_BT: /* fallthrough */
+ case INTENSITY_BT2:
+ for (; i < run_end; i++, idx++) {
#if USE_FIXED
- sf[idx] = -offset[0];
+ sf[idx] = 100 - sfo[idx];
#else
- sf[idx] = -ff_aac_pow2sf_tab[offset[0] - 100 + POW_SF2_ZERO];
+ sf[idx] = ff_aac_pow2sf_tab[-sfo[idx] + POW_SF2_ZERO];
#endif /* USE_FIXED */
}
+ break;
+ case NOISE_BT:
+ for (; i < run_end; i++, idx++) {
+#if USE_FIXED
+ sf[idx] = -(100 + sfo[idx]);
+#else
+ sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] + POW_SF2_ZERO];
+#endif /* USE_FIXED */
+ }
+ break;
+ default:
+ for (; i < run_end; i++, idx++) {
+#if USE_FIXED
+ sf[idx] = -sfo[idx];
+#else
+ sf[idx] = -ff_aac_pow2sf_tab[sfo[idx] - 100 + POW_SF2_ZERO];
+#endif /* USE_FIXED */
+ }
+ break;
}
}
}
- return 0;
}
/**
@@ -2006,10 +2049,12 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
if ((ret = decode_band_types(ac, sce->band_type,
sce->band_type_run_end, gb, ics)) < 0)
goto fail;
- if ((ret = decode_scalefactors(ac, sce->AAC_RENAME(sf), gb, global_gain, ics,
- sce->band_type, sce->band_type_run_end)) < 0)
+ if ((ret = decode_scalefactors(ac, sce->sfo, gb, global_gain, ics,
+ sce->band_type, sce->band_type_run_end)) < 0)
goto fail;
+ dequant_scalefactors(sce);
+
pulse_present = 0;
if (!scale_flag) {
if (!eld_syntax && (pulse_present = get_bits1(gb))) {
--
2.43.0.381.gb435a96ce8
[-- Attachment #30: 0010-aacdec-add-a-decoder-DSP-structure.patch --]
[-- Type: text/x-diff, Size: 2477 bytes --]
From 2b720797ba4bbbc0231aa5f75f7d8f8113e3b0aa Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 13 Mar 2024 06:35:38 +0100
Subject: [PATCH 10/38] aacdec: add a decoder DSP structure
To be used to abstract away DSP functions.
---
libavcodec/aacdec.h | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index e55fea6e40..052ed59e01 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -41,6 +41,8 @@
#include "aac.h"
#include "mpeg4audio.h"
+typedef struct AACDecContext AACDecContext;
+
/**
* Output configuration status
*/
@@ -197,12 +199,37 @@ typedef struct DynamicRangeControl {
*/
} DynamicRangeControl;
+/**
+ * DSP-specific primitives
+ */
+typedef struct AACDecDSP {
+ void (*dequant_scalefactors)(SingleChannelElement *sce);
+
+ void (*apply_mid_side_stereo)(AACDecContext *ac, ChannelElement *cpe);
+ void (*apply_intensity_stereo)(AACDecContext *ac, ChannelElement *cpe,
+ int ms_present);
+
+ void (*apply_tns)(void *_coef_param, TemporalNoiseShaping *tns,
+ IndividualChannelStream *ics, int decode);
+
+ void (*apply_ltp)(AACDecContext *ac, SingleChannelElement *sce);
+ void (*update_ltp)(AACDecContext *ac, SingleChannelElement *sce);
+
+ void (*imdct_and_windowing)(AACDecContext *ac, SingleChannelElement *sce);
+ void (*imdct_and_windowing_960)(AACDecContext *ac, SingleChannelElement *sce);
+ void (*imdct_and_windowing_ld)(AACDecContext *ac, SingleChannelElement *sce);
+ void (*imdct_and_windowing_eld)(AACDecContext *ac, SingleChannelElement *sce);
+} AACDecDSP;
+
/**
* main AAC decoding context
*/
-typedef struct AACDecContext {
+struct AACDecContext {
const struct AVClass *class;
struct AVCodecContext *avctx;
+
+ AACDecDSP dsp;
+
struct AVFrame *frame;
int is_saved; ///< Set if elements have stored overlap from previous frame.
@@ -298,7 +325,7 @@ typedef struct AACDecContext {
void (*update_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*vector_pow43)(int *coefs, int len);
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
-} AACDecContext;
+};
#if defined(USE_FIXED) && USE_FIXED
#define fdsp RENAME_FIXED(fdsp)
--
2.43.0.381.gb435a96ce8
[-- Attachment #31: 0009-avcodec-aacdec_template-Deduplicate-common-part-of-a.patch --]
[-- Type: text/x-diff, Size: 7027 bytes --]
From dcf9c26c648e93f80272a42efea367669008b7e8 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 1 Mar 2024 02:17:22 +0100
Subject: [PATCH 09/38] avcodec/aacdec_template: Deduplicate common part of
aac_decode_init()
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aac/aacdec.c | 42 ++++++++++++++++++++++++++++++++++++
libavcodec/aac_defines.h | 2 --
libavcodec/aacdec.c | 1 -
libavcodec/aacdec.h | 1 +
libavcodec/aacdec_fixed.c | 1 -
libavcodec/aacdec_template.c | 30 +-------------------------
6 files changed, 44 insertions(+), 33 deletions(-)
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 4095509d16..358fe598e5 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -32,10 +32,12 @@
#include <limits.h>
#include <stddef.h>
+#include "libavcodec/aac.h"
#include "libavcodec/aacsbr.h"
#include "libavcodec/aacdec.h"
#include "libavcodec/avcodec.h"
#include "libavutil/attributes.h"
+#include "libavutil/error.h"
#include "libavutil/log.h"
#include "libavutil/macros.h"
#include "libavutil/mem.h"
@@ -76,6 +78,46 @@ av_cold int ff_aac_decode_close(AVCodecContext *avctx)
return 0;
}
+av_cold int ff_aac_decode_init_common(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int is_fixed = ac->is_fixed, ret;
+ float scale_fixed, scale_float;
+ const float *const scalep = is_fixed ? &scale_fixed : &scale_float;
+ enum AVTXType tx_type = is_fixed ? AV_TX_INT32_MDCT : AV_TX_FLOAT_MDCT;
+
+ if (avctx->ch_layout.nb_channels > MAX_CHANNELS) {
+ av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ ac->random_state = 0x1f2e3d4c;
+
+#define MDCT_INIT(s, fn, len, sval) \
+ scale_fixed = (sval) * 128.0f; \
+ scale_float = (sval) / 32768.0f; \
+ ret = av_tx_init(&s, &fn, tx_type, 1, len, scalep, 0); \
+ if (ret < 0) \
+ return ret
+
+ MDCT_INIT(ac->mdct120, ac->mdct120_fn, 120, 1.0/120);
+ MDCT_INIT(ac->mdct128, ac->mdct128_fn, 128, 1.0/128);
+ MDCT_INIT(ac->mdct480, ac->mdct480_fn, 480, 1.0/480);
+ MDCT_INIT(ac->mdct512, ac->mdct512_fn, 512, 1.0/512);
+ MDCT_INIT(ac->mdct960, ac->mdct960_fn, 960, 1.0/960);
+ MDCT_INIT(ac->mdct1024, ac->mdct1024_fn, 1024, 1.0/1024);
+#undef MDCT_INIT
+
+ /* LTP forward MDCT */
+ scale_fixed = -1.0;
+ scale_float = -32786.0*2 + 36;
+ ret = av_tx_init(&ac->mdct_ltp, &ac->mdct_ltp_fn, tx_type, 0, 1024, scalep, 0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
#define OFF(field) offsetof(AACDecContext, field)
static const AVOption options[] = {
diff --git a/libavcodec/aac_defines.h b/libavcodec/aac_defines.h
index 75bc40744a..a3b662115b 100644
--- a/libavcodec/aac_defines.h
+++ b/libavcodec/aac_defines.h
@@ -42,7 +42,6 @@ typedef int AAC_SIGNE;
#define Q23(a) (int)((a) * 8388608.0 + 0.5)
#define Q30(x) (int)((x)*1073741824.0 + 0.5)
#define Q31(x) (int)((x)*2147483648.0 + 0.5)
-#define TX_SCALE(x) ((x) * 128.0f)
#define GET_GAIN(x, y) (-(y) * (1 << (x))) + 1024
#define AAC_MUL16(x, y) (int)(((int64_t)(x) * (y) + 0x8000) >> 16)
#define AAC_MUL26(x, y) (int)(((int64_t)(x) * (y) + 0x2000000) >> 26)
@@ -110,7 +109,6 @@ typedef unsigned AAC_SIGNE;
#define Q23(x) ((float)(x))
#define Q30(x) ((float)(x))
#define Q31(x) ((float)(x))
-#define TX_SCALE(x) ((x) / 32768.0f)
#define GET_GAIN(x, y) powf((x), -(y))
#define AAC_MUL16(x, y) ((x) * (y))
#define AAC_MUL26(x, y) ((x) * (y))
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 86b9161e64..67cdda8cde 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -33,7 +33,6 @@
*/
#define USE_FIXED 0
-#define TX_TYPE AV_TX_FLOAT_MDCT
#include "libavutil/float_dsp.h"
#include "avcodec.h"
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index b05e68f51c..e55fea6e40 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -306,6 +306,7 @@ typedef struct AACDecContext {
extern const struct AVClass ff_aac_decoder_class;
+int ff_aac_decode_init_common(struct AVCodecContext *avctx);
int ff_aac_decode_close(struct AVCodecContext *avctx);
void ff_aacdec_init_mips(AACDecContext *c);
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 8ed98226e9..2c87cddd6e 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -59,7 +59,6 @@
*/
#define USE_FIXED 1
-#define TX_TYPE AV_TX_INT32_MDCT
#include "libavutil/fixed_dsp.h"
#include "avcodec.h"
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 8ee62f7764..893f8d3a73 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1144,7 +1144,6 @@ static AVOnce aac_table_init = AV_ONCE_INIT;
static av_cold int aac_decode_init(AVCodecContext *avctx)
{
- float scale;
AACDecContext *ac = avctx->priv_data;
int ret;
@@ -1203,11 +1202,6 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
}
}
- if (avctx->ch_layout.nb_channels > MAX_CHANNELS) {
- av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
- return AVERROR_INVALIDDATA;
- }
-
#if USE_FIXED
ac->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT);
#else
@@ -1217,29 +1211,7 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
return AVERROR(ENOMEM);
}
- ac->random_state = 0x1f2e3d4c;
-
-#define MDCT_INIT(s, fn, len, sval) \
- scale = sval; \
- ret = av_tx_init(&s, &fn, TX_TYPE, 1, len, &scale, 0); \
- if (ret < 0) \
- return ret;
-
- MDCT_INIT(ac->mdct120, ac->mdct120_fn, 120, TX_SCALE(1.0/120))
- MDCT_INIT(ac->mdct128, ac->mdct128_fn, 128, TX_SCALE(1.0/128))
- MDCT_INIT(ac->mdct480, ac->mdct480_fn, 480, TX_SCALE(1.0/480))
- MDCT_INIT(ac->mdct512, ac->mdct512_fn, 512, TX_SCALE(1.0/512))
- MDCT_INIT(ac->mdct960, ac->mdct960_fn, 960, TX_SCALE(1.0/960))
- MDCT_INIT(ac->mdct1024, ac->mdct1024_fn, 1024, TX_SCALE(1.0/1024))
-#undef MDCT_INIT
-
- /* LTP forward MDCT */
- scale = USE_FIXED ? -1.0 : -32786.0*2 + 36;
- ret = av_tx_init(&ac->mdct_ltp, &ac->mdct_ltp_fn, TX_TYPE, 0, 1024, &scale, 0);
- if (ret < 0)
- return ret;
-
- return 0;
+ return ff_aac_decode_init_common(avctx);
}
/**
--
2.43.0.381.gb435a96ce8
[-- Attachment #32: 0008-avcodec-aacdec_template-Deduplicate-AVClass-AVOption.patch --]
[-- Type: text/x-diff, Size: 7686 bytes --]
From 90aebc52f106ce7f68e7e9c155a29929df0d76bf Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 1 Mar 2024 01:00:08 +0100
Subject: [PATCH 08/38] avcodec/aacdec_template: Deduplicate AVClass+AVOptions
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aac/aacdec.c | 39 ++++++++++++++++++++++++++++++++++++
libavcodec/aacdec.c | 3 +--
libavcodec/aacdec.h | 2 ++
libavcodec/aacdec_fixed.c | 3 +--
libavcodec/aacdec_template.c | 32 -----------------------------
5 files changed, 43 insertions(+), 36 deletions(-)
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
index 021f94e1e5..4095509d16 100644
--- a/libavcodec/aac/aacdec.c
+++ b/libavcodec/aac/aacdec.c
@@ -29,13 +29,19 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <limits.h>
+#include <stddef.h>
+
#include "libavcodec/aacsbr.h"
#include "libavcodec/aacdec.h"
#include "libavcodec/avcodec.h"
#include "libavutil/attributes.h"
+#include "libavutil/log.h"
#include "libavutil/macros.h"
#include "libavutil/mem.h"
+#include "libavutil/opt.h"
#include "libavutil/tx.h"
+#include "libavutil/version.h"
av_cold int ff_aac_decode_close(AVCodecContext *avctx)
{
@@ -69,3 +75,36 @@ av_cold int ff_aac_decode_close(AVCodecContext *avctx)
return 0;
}
+
+#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
+#define OFF(field) offsetof(AACDecContext, field)
+static const AVOption options[] = {
+ /**
+ * AVOptions for Japanese DTV specific extensions (ADTS only)
+ */
+ {"dual_mono_mode", "Select the channel to decode for dual mono",
+ OFF(force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2,
+ AACDEC_FLAGS, .unit = "dual_mono_mode"},
+
+ {"auto", "autoselection", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
+ {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
+ {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
+ {"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
+
+ { "channel_order", "Order in which the channels are to be exported",
+ OFF(output_channel_order), AV_OPT_TYPE_INT,
+ { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, AACDEC_FLAGS, .unit = "channel_order" },
+ { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST,
+ { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
+ { "coded", "order in which the channels are coded in the bitstream",
+ 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
+
+ {NULL},
+};
+
+const AVClass ff_aac_decoder_class = {
+ .class_name = "AAC decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index cfad0ab01a..86b9161e64 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -36,7 +36,6 @@
#define TX_TYPE AV_TX_FLOAT_MDCT
#include "libavutil/float_dsp.h"
-#include "libavutil/opt.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "get_bits.h"
@@ -554,6 +553,7 @@ const FFCodec ff_aac_decoder = {
CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
.p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC,
+ .p.priv_class = &ff_aac_decoder_class,
.priv_data_size = sizeof(AACDecContext),
.init = aac_decode_init,
.close = ff_aac_decode_close,
@@ -565,7 +565,6 @@ const FFCodec ff_aac_decoder = {
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.p.ch_layouts = ff_aac_ch_layout,
.flush = flush,
- .p.priv_class = &aac_decoder_class,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
};
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index cb9d1637b3..b05e68f51c 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -304,6 +304,8 @@ typedef struct AACDecContext {
#define fdsp RENAME_FIXED(fdsp)
#endif
+extern const struct AVClass ff_aac_decoder_class;
+
int ff_aac_decode_close(struct AVCodecContext *avctx);
void ff_aacdec_init_mips(AACDecContext *c);
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 4a5f678bca..8ed98226e9 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -62,7 +62,6 @@
#define TX_TYPE AV_TX_INT32_MDCT
#include "libavutil/fixed_dsp.h"
-#include "libavutil/opt.h"
#include "avcodec.h"
#include "codec_internal.h"
#include "get_bits.h"
@@ -498,6 +497,7 @@ const FFCodec ff_aac_fixed_decoder = {
CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
.p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC,
+ .p.priv_class = &ff_aac_decoder_class,
.priv_data_size = sizeof(AACDecContext),
.init = aac_decode_init,
.close = ff_aac_decode_close,
@@ -508,7 +508,6 @@ const FFCodec ff_aac_fixed_decoder = {
.p.capabilities = AV_CODEC_CAP_CHANNEL_CONF | AV_CODEC_CAP_DR1,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.p.ch_layouts = ff_aac_ch_layout,
- .p.priv_class = &aac_decoder_class,
.p.profiles = NULL_IF_CONFIG_SMALL(ff_aac_profiles),
.flush = flush,
};
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 1d1be6306d..8ee62f7764 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -3400,35 +3400,3 @@ static void aacdec_init(AACDecContext *c)
#endif
#endif /* !USE_FIXED */
}
-/**
- * AVOptions for Japanese DTV specific extensions (ADTS only)
- */
-#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
-#define OFF(field) offsetof(AACDecContext, field)
-static const AVOption options[] = {
- {"dual_mono_mode", "Select the channel to decode for dual mono",
- OFF(force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2,
- AACDEC_FLAGS, .unit = "dual_mono_mode"},
-
- {"auto", "autoselection", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
- {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
- {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
- {"both", "Select both channels", 0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, .unit = "dual_mono_mode"},
-
- { "channel_order", "Order in which the channels are to be exported",
- OFF(output_channel_order), AV_OPT_TYPE_INT,
- { .i64 = CHANNEL_ORDER_DEFAULT }, 0, 1, AACDEC_FLAGS, .unit = "channel_order" },
- { "default", "normal libavcodec channel order", 0, AV_OPT_TYPE_CONST,
- { .i64 = CHANNEL_ORDER_DEFAULT }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
- { "coded", "order in which the channels are coded in the bitstream",
- 0, AV_OPT_TYPE_CONST, { .i64 = CHANNEL_ORDER_CODED }, .flags = AACDEC_FLAGS, .unit = "channel_order" },
-
- {NULL},
-};
-
-static const AVClass aac_decoder_class = {
- .class_name = "AAC decoder",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
-};
--
2.43.0.381.gb435a96ce8
[-- Attachment #33: 0007-avcodec-aacdec_template-Deduplicate-aac_decode_close.patch --]
[-- Type: text/x-diff, Size: 9099 bytes --]
From 88842a61ea309bcfc547a6c8c7cf4f1a0eb4dc73 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 1 Mar 2024 00:50:13 +0100
Subject: [PATCH 07/38] avcodec/aacdec_template: Deduplicate aac_decode_close()
This is possible now that both AAC decoders share the same
context.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aac/Makefile | 4 +-
libavcodec/aac/aacdec.c | 71 ++++++++++++++++++++++++++++++++++++
libavcodec/aacdec.c | 4 +-
libavcodec/aacdec.h | 4 ++
libavcodec/aacdec_fixed.c | 2 +-
libavcodec/aacdec_template.c | 27 +-------------
libavcodec/aacsbr.h | 11 +++++-
7 files changed, 91 insertions(+), 32 deletions(-)
create mode 100644 libavcodec/aac/aacdec.c
diff --git a/libavcodec/aac/Makefile b/libavcodec/aac/Makefile
index 52facdf4cf..29e0ef0a2c 100644
--- a/libavcodec/aac/Makefile
+++ b/libavcodec/aac/Makefile
@@ -1,5 +1,5 @@
clean::
$(RM) $(CLEANSUFFIXES:%=libavcodec/aac/%)
-OBJS-$(CONFIG_AAC_DECODER) += aac/aacdec_tab.o
-OBJS-$(CONFIG_AAC_FIXED_DECODER) += aac/aacdec_tab.o
+OBJS-$(CONFIG_AAC_DECODER) += aac/aacdec.o aac/aacdec_tab.o
+OBJS-$(CONFIG_AAC_FIXED_DECODER) += aac/aacdec.o aac/aacdec_tab.o
diff --git a/libavcodec/aac/aacdec.c b/libavcodec/aac/aacdec.c
new file mode 100644
index 0000000000..021f94e1e5
--- /dev/null
+++ b/libavcodec/aac/aacdec.c
@@ -0,0 +1,71 @@
+/*
+ * Common parts of the AAC decoders
+ * Copyright (c) 2005-2006 Oded Shimon ( ods15 ods15 dyndns org )
+ * Copyright (c) 2006-2007 Maxim Gavrilov ( maxim.gavrilov gmail com )
+ * Copyright (c) 2008-2013 Alex Converse <alex.converse@gmail.com>
+ *
+ * AAC LATM decoder
+ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
+ * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net>
+ *
+ * AAC decoder fixed-point implementation
+ * Copyright (c) 2013
+ * MIPS Technologies, Inc., California.
+ *
+ * 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
+ */
+
+#include "libavcodec/aacsbr.h"
+#include "libavcodec/aacdec.h"
+#include "libavcodec/avcodec.h"
+#include "libavutil/attributes.h"
+#include "libavutil/macros.h"
+#include "libavutil/mem.h"
+#include "libavutil/tx.h"
+
+av_cold int ff_aac_decode_close(AVCodecContext *avctx)
+{
+ AACDecContext *ac = avctx->priv_data;
+ int is_fixed = ac->is_fixed;
+ void (*sbr_close)(ChannelElement *che) = is_fixed ? RENAME_FIXED(ff_aac_sbr_ctx_close)
+ : ff_aac_sbr_ctx_close;
+
+ for (int type = 0; type < FF_ARRAY_ELEMS(ac->che); type++) {
+ for (int i = 0; i < MAX_ELEM_ID; i++) {
+ if (ac->che[type][i]) {
+ sbr_close(ac->che[type][i]);
+ av_freep(&ac->che[type][i]);
+ }
+ }
+ }
+
+ av_tx_uninit(&ac->mdct120);
+ av_tx_uninit(&ac->mdct128);
+ av_tx_uninit(&ac->mdct480);
+ av_tx_uninit(&ac->mdct512);
+ av_tx_uninit(&ac->mdct960);
+ av_tx_uninit(&ac->mdct1024);
+ av_tx_uninit(&ac->mdct_ltp);
+
+ // Compiler will optimize this branch away.
+ if (is_fixed)
+ av_freep(&ac->RENAME_FIXED(fdsp));
+ else
+ av_freep(&ac->fdsp);
+
+ return 0;
+}
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 209034388b..cfad0ab01a 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -556,7 +556,7 @@ const FFCodec ff_aac_decoder = {
.p.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACDecContext),
.init = aac_decode_init,
- .close = aac_decode_close,
+ .close = ff_aac_decode_close,
FF_CODEC_DECODE_CB(aac_decode_frame),
.p.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
@@ -581,7 +581,7 @@ const FFCodec ff_aac_latm_decoder = {
.p.id = AV_CODEC_ID_AAC_LATM,
.priv_data_size = sizeof(struct LATMContext),
.init = latm_decode_init,
- .close = aac_decode_close,
+ .close = ff_aac_decode_close,
FF_CODEC_DECODE_CB(latm_decode_frame),
.p.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index fbdf688487..cb9d1637b3 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -278,6 +278,8 @@ typedef struct AACDecContext {
int warned_gain_control;
int warned_he_aac_mono;
+ int is_fixed;
+
/* aacdec functions pointers */
void (*imdct_and_windowing)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*apply_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
@@ -302,6 +304,8 @@ typedef struct AACDecContext {
#define fdsp RENAME_FIXED(fdsp)
#endif
+int ff_aac_decode_close(struct AVCodecContext *avctx);
+
void ff_aacdec_init_mips(AACDecContext *c);
#endif /* AVCODEC_AACDEC_H */
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 5efb259665..4a5f678bca 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -500,7 +500,7 @@ const FFCodec ff_aac_fixed_decoder = {
.p.id = AV_CODEC_ID_AAC,
.priv_data_size = sizeof(AACDecContext),
.init = aac_decode_init,
- .close = aac_decode_close,
+ .close = ff_aac_decode_close,
FF_CODEC_DECODE_CB(aac_decode_frame),
.p.sample_fmts = (const enum AVSampleFormat[]) {
AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_NONE
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 31be1fa1aa..1d1be6306d 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1148,6 +1148,8 @@ static av_cold int aac_decode_init(AVCodecContext *avctx)
AACDecContext *ac = avctx->priv_data;
int ret;
+ ac->is_fixed = USE_FIXED;
+
if (avctx->sample_rate > 96000)
return AVERROR_INVALIDDATA;
@@ -3380,31 +3382,6 @@ static int aac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
return buf_size > buf_offset ? buf_consumed : buf_size;
}
-static av_cold int aac_decode_close(AVCodecContext *avctx)
-{
- AACDecContext *ac = avctx->priv_data;
- int i, type;
-
- for (i = 0; i < MAX_ELEM_ID; i++) {
- for (type = 0; type < 4; type++) {
- if (ac->che[type][i])
- AAC_RENAME(ff_aac_sbr_ctx_close)(ac->che[type][i]);
- av_freep(&ac->che[type][i]);
- }
- }
-
- av_tx_uninit(&ac->mdct120);
- av_tx_uninit(&ac->mdct128);
- av_tx_uninit(&ac->mdct480);
- av_tx_uninit(&ac->mdct512);
- av_tx_uninit(&ac->mdct960);
- av_tx_uninit(&ac->mdct1024);
- av_tx_uninit(&ac->mdct_ltp);
-
- av_freep(&ac->fdsp);
- return 0;
-}
-
static void aacdec_init(AACDecContext *c)
{
c->imdct_and_windowing = imdct_and_windowing;
diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h
index 855885ce87..4ace1e04d4 100644
--- a/libavcodec/aacsbr.h
+++ b/libavcodec/aacsbr.h
@@ -33,6 +33,8 @@
#include "aacdec.h"
#include "aac_defines.h"
+#include "libavutil/attributes_internal.h"
+
#define ENVELOPE_ADJUSTMENT_OFFSET 2
#define NOISE_FLOOR_OFFSET 6
@@ -66,6 +68,7 @@ enum {
EXTENSION_ID_PS = 2,
};
+FF_VISIBILITY_PUSH_HIDDEN
/** Initialize SBR. */
void AAC_RENAME(ff_aac_sbr_init)(void);
/**
@@ -73,13 +76,17 @@ void AAC_RENAME(ff_aac_sbr_init)(void);
* initialize the SBR context contained in it.
*/
int AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac, ChannelElement **che, int id_aac);
-/** Close one SBR context. */
-void AAC_RENAME(ff_aac_sbr_ctx_close)(ChannelElement *che);
+
+/** Close the SBR context implicitly contained in a ChannelElement. */
+void RENAME_FIXED(ff_aac_sbr_ctx_close)(ChannelElement *che);
+void ff_aac_sbr_ctx_close(ChannelElement *che);
+
/** Decode one SBR element. */
int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
GetBitContext *gb, int crc, int cnt, int id_aac);
/** Apply one SBR element to one AAC element. */
void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, ChannelElement *che,
int id_aac, INTFLOAT* L, INTFLOAT* R);
+FF_VISIBILITY_POP_HIDDEN
#endif /* AVCODEC_AACSBR_H */
--
2.43.0.381.gb435a96ce8
[-- Attachment #34: 0006-avcodec-aacdec-Use-same-AACDecContext-for-fixed-and-.patch --]
[-- Type: text/x-diff, Size: 26278 bytes --]
From 55100a94535a1e6248d435a02b1b346fb23dd389 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 29 Feb 2024 23:03:17 +0100
Subject: [PATCH 06/38] avcodec/aacdec: Use same AACDecContext for fixed and
float
Up until now, there was one AACDecContext for the fixed
and one for the floating point decoder. These differed
mostly in certain arrays which were int for the fixed-point
and float for the floating point decoder; there were also
differences in corresponding function pointers.
Yet in order to deduplicate the enormous amount of currently
duplicated code between the float and the fixed-point decoder,
one needs common contexts. Given that int and float have the
same size on all common systems, this commit replaces these
arrays by unions of int arrays and of float arrays. The names
of these arrays have been chosen to be compatible with
AAC_RENAME().
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aacdec.c | 4 +-
libavcodec/aacdec.h | 53 ++++++++++-----
libavcodec/aacdec_fixed.c | 8 +--
libavcodec/aacdec_template.c | 124 ++++++++++++++++++----------------
libavcodec/mips/aacdec_mips.c | 6 +-
5 files changed, 113 insertions(+), 82 deletions(-)
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 6907d348f8..209034388b 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -249,8 +249,8 @@ static void apply_independent_coupling(AACDecContext *ac,
ChannelElement *cce, int index)
{
const float gain = cce->coup.gain[index][0];
- const float *src = cce->ch[0].ret;
- float *dest = target->ret;
+ const float *src = cce->ch[0].output;
+ float *dest = target->output;
const int len = 1024 << (ac->oc[1].m4ac.sbr == 1);
ac->fdsp->vector_fmac_scalar(dest, src, gain, len);
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index a64c375d1f..fbdf688487 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -39,7 +39,6 @@
#include "libavutil/tx.h"
#include "aac.h"
-#include "aac_defines.h"
#include "mpeg4audio.h"
/**
@@ -70,13 +69,24 @@ enum CouplingPoint {
// Supposed to be equal to AAC_RENAME() in case of USE_FIXED.
#define RENAME_FIXED(name) name ## _fixed
+#define INTFLOAT_UNION(name, elems) \
+ union { \
+ int RENAME_FIXED(name) elems; \
+ float name elems; \
+ };
+
+#define INTFLOAT_ALIGNED_UNION(alignment, name, nb_elems) \
+ union { \
+ DECLARE_ALIGNED(alignment, int, RENAME_FIXED(name))[nb_elems]; \
+ DECLARE_ALIGNED(alignment, float, name)[nb_elems]; \
+ };
/**
* Long Term Prediction
*/
typedef struct LongTermPrediction {
int8_t present;
int16_t lag;
- INTFLOAT coef;
+ INTFLOAT_UNION(coef,);
int8_t used[MAX_LTP_LONG_SFB];
} LongTermPrediction;
@@ -110,7 +120,7 @@ typedef struct TemporalNoiseShaping {
int length[8][4];
int direction[8][4];
int order[8][4];
- INTFLOAT coef[8][4][TNS_MAX_ORDER];
+ INTFLOAT_UNION(coef, [8][4][TNS_MAX_ORDER]);
} TemporalNoiseShaping;
/**
@@ -124,7 +134,7 @@ typedef struct ChannelCoupling {
int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for right channel;
* [2] list of gains for left channel; [3] lists of gains for both channels
*/
- INTFLOAT gain[16][120];
+ INTFLOAT_UNION(gain, [16][120]);
} ChannelCoupling;
/**
@@ -135,16 +145,19 @@ typedef struct SingleChannelElement {
TemporalNoiseShaping tns;
enum BandType band_type[128]; ///< band types
int band_type_run_end[120]; ///< band type run end points
- INTFLOAT sf[120]; ///< scalefactors
- DECLARE_ALIGNED(32, INTFLOAT, coeffs)[1024]; ///< coefficients for IMDCT, maybe processed
- DECLARE_ALIGNED(32, INTFLOAT, saved)[1536]; ///< overlap
- DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer
- DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP
+ INTFLOAT_UNION(sf, [120]); ///< scalefactors
+ INTFLOAT_ALIGNED_UNION(32, coeffs, 1024); ///< coefficients for IMDCT, maybe processed
+ INTFLOAT_ALIGNED_UNION(32, saved, 1536); ///< overlap
+ INTFLOAT_ALIGNED_UNION(32, ret_buf, 2048); ///< PCM output buffer
+ INTFLOAT_ALIGNED_UNION(16, ltp_state, 3072); ///< time signal for LTP
union {
struct PredictorStateFixed *RENAME_FIXED(predictor_state);
struct PredictorState *predictor_state;
};
- INTFLOAT *ret; ///< PCM output
+ union {
+ float *output; ///< PCM output
+ int *RENAME_FIXED(output); ///< PCM output
+ };
} SingleChannelElement;
/**
@@ -210,8 +223,8 @@ typedef struct AACDecContext {
* (We do not want to have these on the stack.)
* @{
*/
- DECLARE_ALIGNED(32, INTFLOAT, buf_mdct)[1024];
- DECLARE_ALIGNED(32, INTFLOAT, temp)[128];
+ INTFLOAT_ALIGNED_UNION(32, buf_mdct, 1024);
+ INTFLOAT_ALIGNED_UNION(32, temp, 128);
/** @} */
/**
@@ -268,10 +281,18 @@ typedef struct AACDecContext {
/* aacdec functions pointers */
void (*imdct_and_windowing)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*apply_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
- void (*apply_tns)(INTFLOAT coef[1024], TemporalNoiseShaping *tns,
- IndividualChannelStream *ics, int decode);
- void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, INTFLOAT *out,
- INTFLOAT *in, IndividualChannelStream *ics);
+ union {
+ void (*apply_tns)(float coef[1024], TemporalNoiseShaping *tns,
+ IndividualChannelStream *ics, int decode);
+ void (*apply_tns_fixed)(int coef[1024], TemporalNoiseShaping *tns,
+ IndividualChannelStream *ics, int decode);
+ };
+ union {
+ void (*windowing_and_mdct_ltp)(struct AACDecContext *ac, float *out,
+ float *in, IndividualChannelStream *ics);
+ void (*windowing_and_mdct_ltp_fixed)(struct AACDecContext *ac, int *out,
+ int *in, IndividualChannelStream *ics);
+ };
void (*update_ltp)(struct AACDecContext *ac, SingleChannelElement *sce);
void (*vector_pow43)(int *coefs, int len);
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 055b40b547..5efb259665 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -402,8 +402,8 @@ static void apply_dependent_coupling_fixed(AACDecContext *ac,
{
IndividualChannelStream *ics = &cce->ch[0].ics;
const uint16_t *offsets = ics->swb_offset;
- int *dest = target->coeffs;
- const int *src = cce->ch[0].coeffs;
+ int *dest = target->coeffs_fixed;
+ const int *src = cce->ch[0].coeffs_fixed;
int g, i, group, k, idx = 0;
if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
av_log(ac->avctx, AV_LOG_ERROR,
@@ -466,8 +466,8 @@ static void apply_independent_coupling_fixed(AACDecContext *ac,
{
int i, c, shift, round, tmp;
const int gain = cce->coup.gain[index][0];
- const int *src = cce->ch[0].ret;
- unsigned int *dest = target->ret;
+ const int *src = cce->ch[0].output_fixed;
+ unsigned int *dest = target->output_fixed;
const int len = 1024 << (ac->oc[1].m4ac.sbr == 1);
c = cce_scale_fixed[gain & 7];
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 4f7d6051ae..31be1fa1aa 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -166,8 +166,8 @@ static int frame_configure_elements(AVCodecContext *avctx)
for (id = 0; id < MAX_ELEM_ID; id++) {
ChannelElement *che = ac->che[type][id];
if (che) {
- che->ch[0].ret = che->ch[0].ret_buf;
- che->ch[1].ret = che->ch[1].ret_buf;
+ che->ch[0].AAC_RENAME(output) = che->ch[0].AAC_RENAME(ret_buf);
+ che->ch[1].AAC_RENAME(output) = che->ch[1].AAC_RENAME(ret_buf);
}
}
}
@@ -184,7 +184,7 @@ static int frame_configure_elements(AVCodecContext *avctx)
/* map output channel pointers to AVFrame data */
for (ch = 0; ch < avctx->ch_layout.nb_channels; ch++) {
if (ac->output_element[ch])
- ac->output_element[ch]->ret = (INTFLOAT *)ac->frame->extended_data[ch];
+ ac->output_element[ch]->AAC_RENAME(output) = (INTFLOAT *)ac->frame->extended_data[ch];
}
return 0;
@@ -1288,7 +1288,7 @@ static void decode_ltp(LongTermPrediction *ltp,
int sfb;
ltp->lag = get_bits(gb, 11);
- ltp->coef = AAC_RENAME2(ltp_coef)[get_bits(gb, 3)];
+ ltp->AAC_RENAME(coef) = AAC_RENAME2(ltp_coef)[get_bits(gb, 3)];
for (sfb = 0; sfb < FFMIN(max_sfb, MAX_LTP_LONG_SFB); sfb++)
ltp->used[sfb] = get_bits1(gb);
}
@@ -1601,7 +1601,7 @@ static int decode_tns(AACDecContext *ac, TemporalNoiseShaping *tns,
tmp2_idx = 2 * coef_compress + coef_res;
for (i = 0; i < tns->order[w][filt]; i++)
- tns->coef[w][filt][i] = AAC_RENAME2(tns_tmp2_map)[tmp2_idx][get_bits(gb, coef_len)];
+ tns->AAC_RENAME(coef)[w][filt][i] = AAC_RENAME2(tns_tmp2_map)[tmp2_idx][get_bits(gb, coef_len)];
}
}
}
@@ -1952,7 +1952,8 @@ static void apply_prediction(AACDecContext *ac, SingleChannelElement *sce)
for (k = sce->ics.swb_offset[sfb];
k < sce->ics.swb_offset[sfb + 1];
k++) {
- predict(&sce->AAC_RENAME(predictor_state)[k], &sce->coeffs[k],
+ predict(&sce->AAC_RENAME(predictor_state)[k],
+ &sce->AAC_RENAME(coeffs)[k],
sce->ics.predictor_present &&
sce->ics.prediction_used[sfb]);
}
@@ -2005,7 +2006,7 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
Pulse pulse;
TemporalNoiseShaping *tns = &sce->tns;
IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *out = sce->coeffs;
+ INTFLOAT *out = sce->AAC_RENAME(coeffs);
int global_gain, eld_syntax, er_syntax, pulse_present = 0;
int ret;
@@ -2031,7 +2032,7 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
if ((ret = decode_band_types(ac, sce->band_type,
sce->band_type_run_end, gb, ics)) < 0)
goto fail;
- if ((ret = decode_scalefactors(ac, sce->sf, gb, global_gain, ics,
+ if ((ret = decode_scalefactors(ac, sce->AAC_RENAME(sf), gb, global_gain, ics,
sce->band_type, sce->band_type_run_end)) < 0)
goto fail;
@@ -2073,7 +2074,7 @@ static int decode_ics(AACDecContext *ac, SingleChannelElement *sce,
}
}
- ret = decode_spectrum_and_dequant(ac, out, gb, sce->sf, pulse_present,
+ ret = decode_spectrum_and_dequant(ac, out, gb, sce->AAC_RENAME(sf), pulse_present,
&pulse, ics, sce->band_type);
if (ret < 0)
goto fail;
@@ -2093,8 +2094,8 @@ fail:
static void apply_mid_side_stereo(AACDecContext *ac, ChannelElement *cpe)
{
const IndividualChannelStream *ics = &cpe->ch[0].ics;
- INTFLOAT *ch0 = cpe->ch[0].coeffs;
- INTFLOAT *ch1 = cpe->ch[1].coeffs;
+ INTFLOAT *ch0 = cpe->ch[0].AAC_RENAME(coeffs);
+ INTFLOAT *ch1 = cpe->ch[1].AAC_RENAME(coeffs);
int g, i, group, idx = 0;
const uint16_t *offsets = ics->swb_offset;
for (g = 0; g < ics->num_window_groups; g++) {
@@ -2133,7 +2134,7 @@ static void apply_intensity_stereo(AACDecContext *ac,
{
const IndividualChannelStream *ics = &cpe->ch[1].ics;
SingleChannelElement *sce1 = &cpe->ch[1];
- INTFLOAT *coef0 = cpe->ch[0].coeffs, *coef1 = cpe->ch[1].coeffs;
+ INTFLOAT *coef0 = cpe->ch[0].AAC_RENAME(coeffs), *coef1 = cpe->ch[1].AAC_RENAME(coeffs);
const uint16_t *offsets = ics->swb_offset;
int g, group, i, idx = 0;
int c;
@@ -2147,7 +2148,7 @@ static void apply_intensity_stereo(AACDecContext *ac,
c = -1 + 2 * (sce1->band_type[idx] - 14);
if (ms_present)
c *= 1 - 2 * cpe->ms_mask[idx];
- scale = c * sce1->sf[idx];
+ scale = c * sce1->AAC_RENAME(sf)[idx];
for (group = 0; group < ics->group_len[g]; group++)
#if USE_FIXED
ac->subband_scale(coef1 + group * 128 + offsets[i],
@@ -2507,7 +2508,7 @@ static void apply_tns(INTFLOAT coef_param[1024], TemporalNoiseShaping *tns,
continue;
// tns_decode_coef
- compute_lpc_coefs(tns->coef[w][filt], order, lpc, 0, 0, 0);
+ compute_lpc_coefs(tns->AAC_RENAME(coef)[w][filt], order, lpc, 0, 0, 0);
start = ics->swb_offset[FFMIN(bottom, mmm)];
end = ics->swb_offset[FFMIN( top, mmm)];
@@ -2577,25 +2578,25 @@ static void apply_ltp(AACDecContext *ac, SingleChannelElement *sce)
int i, sfb;
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
- INTFLOAT *predTime = sce->ret;
- INTFLOAT *predFreq = ac->buf_mdct;
+ INTFLOAT *predTime = sce->AAC_RENAME(output);
+ INTFLOAT *predFreq = ac->AAC_RENAME(buf_mdct);
int16_t num_samples = 2048;
if (ltp->lag < 1024)
num_samples = ltp->lag + 1024;
for (i = 0; i < num_samples; i++)
- predTime[i] = AAC_MUL30(sce->ltp_state[i + 2048 - ltp->lag], ltp->coef);
+ predTime[i] = AAC_MUL30(sce->AAC_RENAME(ltp_state)[i + 2048 - ltp->lag], ltp->AAC_RENAME(coef));
memset(&predTime[i], 0, (2048 - i) * sizeof(*predTime));
- ac->windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
+ ac->AAC_RENAME(windowing_and_mdct_ltp)(ac, predFreq, predTime, &sce->ics);
if (sce->tns.present)
- ac->apply_tns(predFreq, &sce->tns, &sce->ics, 0);
+ ac->AAC_RENAME(apply_tns)(predFreq, &sce->tns, &sce->ics, 0);
for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
if (ltp->used[sfb])
for (i = offsets[sfb]; i < offsets[sfb + 1]; i++)
- sce->coeffs[i] += (UINTFLOAT)predFreq[i];
+ sce->AAC_RENAME(coeffs)[i] += (UINTFLOAT)predFreq[i];
}
}
@@ -2605,8 +2606,8 @@ static void apply_ltp(AACDecContext *ac, SingleChannelElement *sce)
static void update_ltp(AACDecContext *ac, SingleChannelElement *sce)
{
IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *saved = sce->saved;
- INTFLOAT *saved_ltp = sce->coeffs;
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ INTFLOAT *saved_ltp = sce->AAC_RENAME(coeffs);
const INTFLOAT *lwindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
int i;
@@ -2614,27 +2615,30 @@ static void update_ltp(AACDecContext *ac, SingleChannelElement *sce)
if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
memcpy(saved_ltp, saved, 512 * sizeof(*saved_ltp));
memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
- ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
+ ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
for (i = 0; i < 64; i++)
- saved_ltp[i + 512] = AAC_MUL31(ac->buf_mdct[1023 - i], swindow[63 - i]);
+ saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
} else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
- memcpy(saved_ltp, ac->buf_mdct + 512, 448 * sizeof(*saved_ltp));
+ memcpy(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, 448 * sizeof(*saved_ltp));
memset(saved_ltp + 576, 0, 448 * sizeof(*saved_ltp));
- ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960, &swindow[64], 64);
+ ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->AAC_RENAME(buf_mdct) + 960, &swindow[64], 64);
for (i = 0; i < 64; i++)
- saved_ltp[i + 512] = AAC_MUL31(ac->buf_mdct[1023 - i], swindow[63 - i]);
+ saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], swindow[63 - i]);
} else { // LONG_STOP or ONLY_LONG
- ac->fdsp->vector_fmul_reverse(saved_ltp, ac->buf_mdct + 512, &lwindow[512], 512);
+ ac->fdsp->vector_fmul_reverse(saved_ltp, ac->AAC_RENAME(buf_mdct) + 512, &lwindow[512], 512);
for (i = 0; i < 512; i++)
- saved_ltp[i + 512] = AAC_MUL31(ac->buf_mdct[1023 - i], lwindow[511 - i]);
+ saved_ltp[i + 512] = AAC_MUL31(ac->AAC_RENAME(buf_mdct)[1023 - i], lwindow[511 - i]);
}
- memcpy(sce->ltp_state, sce->ltp_state+1024, 1024 * sizeof(*sce->ltp_state));
- memcpy(sce->ltp_state+1024, sce->ret, 1024 * sizeof(*sce->ltp_state));
- memcpy(sce->ltp_state+2048, saved_ltp, 1024 * sizeof(*sce->ltp_state));
+ memcpy(sce->AAC_RENAME(ltp_state), sce->AAC_RENAME(ltp_state)+1024,
+ 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
+ memcpy(sce->AAC_RENAME(ltp_state) + 1024, sce->AAC_RENAME(output),
+ 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
+ memcpy(sce->AAC_RENAME(ltp_state) + 2048, saved_ltp,
+ 1024 * sizeof(*sce->AAC_RENAME(ltp_state)));
}
/**
@@ -2643,14 +2647,14 @@ static void update_ltp(AACDecContext *ac, SingleChannelElement *sce)
static void imdct_and_windowing(AACDecContext *ac, SingleChannelElement *sce)
{
IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *in = sce->coeffs;
- INTFLOAT *out = sce->ret;
- INTFLOAT *saved = sce->saved;
+ INTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_long_1024) : AAC_RENAME2(sine_1024);
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME2(aac_kbd_short_128) : AAC_RENAME2(sine_128);
- INTFLOAT *buf = ac->buf_mdct;
- INTFLOAT *temp = ac->temp;
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
+ INTFLOAT *temp = ac->AAC_RENAME(temp);
int i;
// imdct
@@ -2707,14 +2711,14 @@ static void imdct_and_windowing(AACDecContext *ac, SingleChannelElement *sce)
static void imdct_and_windowing_960(AACDecContext *ac, SingleChannelElement *sce)
{
IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *in = sce->coeffs;
- INTFLOAT *out = sce->ret;
- INTFLOAT *saved = sce->saved;
+ INTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
const INTFLOAT *swindow = ics->use_kb_window[0] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
const INTFLOAT *lwindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_long_960) : AAC_RENAME(sine_960);
const INTFLOAT *swindow_prev = ics->use_kb_window[1] ? AAC_RENAME(aac_kbd_short_120) : AAC_RENAME(sine_120);
- INTFLOAT *buf = ac->buf_mdct;
- INTFLOAT *temp = ac->temp;
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
+ INTFLOAT *temp = ac->AAC_RENAME(temp);
int i;
// imdct
@@ -2768,10 +2772,10 @@ static void imdct_and_windowing_960(AACDecContext *ac, SingleChannelElement *sce
static void imdct_and_windowing_ld(AACDecContext *ac, SingleChannelElement *sce)
{
IndividualChannelStream *ics = &sce->ics;
- INTFLOAT *in = sce->coeffs;
- INTFLOAT *out = sce->ret;
- INTFLOAT *saved = sce->saved;
- INTFLOAT *buf = ac->buf_mdct;
+ INTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
// imdct
ac->mdct512_fn(ac->mdct512, buf, in, sizeof(INTFLOAT));
@@ -2792,10 +2796,10 @@ static void imdct_and_windowing_ld(AACDecContext *ac, SingleChannelElement *sce)
static void imdct_and_windowing_eld(AACDecContext *ac, SingleChannelElement *sce)
{
- UINTFLOAT *in = sce->coeffs;
- INTFLOAT *out = sce->ret;
- INTFLOAT *saved = sce->saved;
- INTFLOAT *buf = ac->buf_mdct;
+ UINTFLOAT *in = sce->AAC_RENAME(coeffs);
+ INTFLOAT *out = sce->AAC_RENAME(output);
+ INTFLOAT *saved = sce->AAC_RENAME(saved);
+ INTFLOAT *buf = ac->AAC_RENAME(buf_mdct);
int i;
const int n = ac->oc[1].m4ac.frame_length_short ? 480 : 512;
const int n2 = n >> 1;
@@ -2923,9 +2927,11 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
}
}
if (che->ch[0].tns.present)
- ac->apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
+ ac->AAC_RENAME(apply_tns)(che->ch[0].AAC_RENAME(coeffs),
+ &che->ch[0].tns, &che->ch[0].ics, 1);
if (che->ch[1].tns.present)
- ac->apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
+ ac->AAC_RENAME(apply_tns)(che->ch[1].AAC_RENAME(coeffs),
+ &che->ch[1].tns, &che->ch[1].ics, 1);
if (type <= TYPE_CPE)
apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, AAC_RENAME(apply_dependent_coupling));
if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
@@ -2938,7 +2944,9 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
ac->update_ltp(ac, &che->ch[1]);
}
if (ac->oc[1].m4ac.sbr > 0) {
- AAC_RENAME(ff_aac_sbr_apply)(ac, che, type, che->ch[0].ret, che->ch[1].ret);
+ AAC_RENAME(ff_aac_sbr_apply)(ac, che, type,
+ che->ch[0].AAC_RENAME(output),
+ che->ch[1].AAC_RENAME(output));
}
}
if (type <= TYPE_CCE)
@@ -2949,9 +2957,11 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
int j;
/* preparation for resampler */
for(j = 0; j<samples; j++){
- che->ch[0].ret[j] = (int32_t)av_clip64((int64_t)che->ch[0].ret[j]*128, INT32_MIN, INT32_MAX-0x8000)+0x8000;
+ che->ch[0].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[0].output_fixed[j]*128,
+ INT32_MIN, INT32_MAX-0x8000)+0x8000;
if (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))
- che->ch[1].ret[j] = (int32_t)av_clip64((int64_t)che->ch[1].ret[j]*128, INT32_MIN, INT32_MAX-0x8000)+0x8000;
+ che->ch[1].output_fixed[j] = (int32_t)av_clip64((int64_t)che->ch[1].output_fixed[j]*128,
+ INT32_MIN, INT32_MAX-0x8000)+0x8000;
}
}
#endif /* USE_FIXED */
@@ -3399,8 +3409,8 @@ static void aacdec_init(AACDecContext *c)
{
c->imdct_and_windowing = imdct_and_windowing;
c->apply_ltp = apply_ltp;
- c->apply_tns = apply_tns;
- c->windowing_and_mdct_ltp = windowing_and_mdct_ltp;
+ c->AAC_RENAME(apply_tns) = apply_tns;
+ c->AAC_RENAME(windowing_and_mdct_ltp) = windowing_and_mdct_ltp;
c->update_ltp = update_ltp;
#if USE_FIXED
c->vector_pow43 = vector_pow43;
diff --git a/libavcodec/mips/aacdec_mips.c b/libavcodec/mips/aacdec_mips.c
index 456e270915..2820f980a4 100644
--- a/libavcodec/mips/aacdec_mips.c
+++ b/libavcodec/mips/aacdec_mips.c
@@ -116,7 +116,7 @@ static void imdct_and_windowing_mips(AACDecContext *ac, SingleChannelElement *sc
{
IndividualChannelStream *ics = &sce->ics;
float *in = sce->coeffs;
- float *out = sce->ret;
+ float *out = sce->output;
float *saved = sce->saved;
const float *swindow = ics->use_kb_window[0] ? ff_aac_kbd_short_128 : ff_sine_128;
const float *lwindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_long_1024 : ff_sine_1024;
@@ -232,7 +232,7 @@ static void apply_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
int j, k;
if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
- float *predTime = sce->ret;
+ float *predTime = sce->output;
float *predFreq = ac->buf_mdct;
float *p_predTime;
int16_t num_samples = 2048;
@@ -425,7 +425,7 @@ static void update_ltp_mips(AACDecContext *ac, SingleChannelElement *sce)
}
float_copy(sce->ltp_state, sce->ltp_state + 1024, 1024);
- float_copy(sce->ltp_state + 1024, sce->ret, 1024);
+ float_copy(sce->ltp_state + 1024, sce->output, 1024);
float_copy(sce->ltp_state + 2048, saved_ltp, 1024);
}
#endif /* HAVE_MIPSFPU */
--
2.43.0.381.gb435a96ce8
[-- Attachment #35: 0005-avcodec-aacdec-PredictorState-array-out-of-SingleCha.patch --]
[-- Type: text/x-diff, Size: 6470 bytes --]
From 2eab18b0dbc01cea451744446559c926b4adfc00 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 29 Feb 2024 22:12:48 +0100
Subject: [PATCH 05/38] avcodec/aacdec: PredictorState array out of
SingleChannelElement
sizeof(PredictorState) is different for the floating-point and
the fixed-point AAC decoders; this is an obstacle for deduplicating
code between these decoders. So don't include this array in
SingleChannelElement, instead add a union of pointers to the
fixed-point PredictorState and the floating-point PredictorState.
The actual arrays are part of the extended ChannelElement
to be allocated by ff_aac_sbr_ctx_alloc_init(); it also
sets the pointers.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aac.h | 17 -----------------
libavcodec/aac_defines.h | 28 ++++++++++++++++++++++++++++
libavcodec/aacdec.h | 5 ++++-
libavcodec/aacdec_template.c | 8 ++++----
libavcodec/aacenc.h | 14 ++++++++++++++
libavcodec/aacsbr_template.c | 3 +++
6 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/libavcodec/aac.h b/libavcodec/aac.h
index 89f838eab5..9508760fa6 100644
--- a/libavcodec/aac.h
+++ b/libavcodec/aac.h
@@ -30,9 +30,6 @@
#ifndef AVCODEC_AAC_H
#define AVCODEC_AAC_H
-
-#include "aac_defines.h"
-
#define MAX_CHANNELS 64
#define MAX_ELEM_ID 16
@@ -85,20 +82,6 @@ enum ChannelPosition {
AAC_CHANNEL_CC = 5,
};
-/**
- * Predictor State
- */
-typedef struct PredictorState {
- AAC_FLOAT cor0;
- AAC_FLOAT cor1;
- AAC_FLOAT var0;
- AAC_FLOAT var1;
- AAC_FLOAT r0;
- AAC_FLOAT r1;
- AAC_FLOAT k1;
- AAC_FLOAT x_est;
-} PredictorState;
-
#define MAX_PREDICTORS 672
#define SCALE_DIV_512 36 ///< scalefactor difference that corresponds to scale difference in 512 times
diff --git a/libavcodec/aac_defines.h b/libavcodec/aac_defines.h
index a0c23c33ff..75bc40744a 100644
--- a/libavcodec/aac_defines.h
+++ b/libavcodec/aac_defines.h
@@ -72,6 +72,20 @@ typedef int AAC_SIGNE;
0x40000000) >> 31)
#define AAC_HALF_SUM(x, y) (((x) >> 1) + ((y) >> 1))
+/**
+ * Predictor State
+ */
+typedef struct PredictorStateFixed {
+ SoftFloat cor0;
+ SoftFloat cor1;
+ SoftFloat var0;
+ SoftFloat var1;
+ SoftFloat r0;
+ SoftFloat r1;
+ SoftFloat k1;
+ SoftFloat x_est;
+} PredictorState;
+
#ifdef LPC_USE_FIXED
#error aac_defines.h must be included before lpc_functions.h for fixed point decoder
#endif
@@ -112,6 +126,20 @@ typedef unsigned AAC_SIGNE;
#define AAC_MSUB31_V3(x, y, z) ((x) - (y)) * (z)
#define AAC_HALF_SUM(x, y) ((x) + (y)) * 0.5f
+/**
+ * Predictor State
+ */
+typedef struct PredictorState {
+ float cor0;
+ float cor1;
+ float var0;
+ float var1;
+ float r0;
+ float r1;
+ float k1;
+ float x_est;
+} PredictorState;
+
#endif /* USE_FIXED */
#endif /* AVCODEC_AAC_DEFINES_H */
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index e5165e9b54..a64c375d1f 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -140,7 +140,10 @@ typedef struct SingleChannelElement {
DECLARE_ALIGNED(32, INTFLOAT, saved)[1536]; ///< overlap
DECLARE_ALIGNED(32, INTFLOAT, ret_buf)[2048]; ///< PCM output buffer
DECLARE_ALIGNED(16, INTFLOAT, ltp_state)[3072]; ///< time signal for LTP
- PredictorState predictor_state[MAX_PREDICTORS];
+ union {
+ struct PredictorStateFixed *RENAME_FIXED(predictor_state);
+ struct PredictorState *predictor_state;
+ };
INTFLOAT *ret; ///< PCM output
} SingleChannelElement;
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 84c5309a80..4f7d6051ae 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -1941,7 +1941,7 @@ static void apply_prediction(AACDecContext *ac, SingleChannelElement *sce)
int sfb, k;
if (!sce->ics.predictor_initialized) {
- reset_all_predictors(sce->predictor_state);
+ reset_all_predictors(sce->AAC_RENAME(predictor_state));
sce->ics.predictor_initialized = 1;
}
@@ -1952,16 +1952,16 @@ static void apply_prediction(AACDecContext *ac, SingleChannelElement *sce)
for (k = sce->ics.swb_offset[sfb];
k < sce->ics.swb_offset[sfb + 1];
k++) {
- predict(&sce->predictor_state[k], &sce->coeffs[k],
+ predict(&sce->AAC_RENAME(predictor_state)[k], &sce->coeffs[k],
sce->ics.predictor_present &&
sce->ics.prediction_used[sfb]);
}
}
if (sce->ics.predictor_reset_group)
- reset_predictor_group(sce->predictor_state,
+ reset_predictor_group(sce->AAC_RENAME(predictor_state),
sce->ics.predictor_reset_group);
} else
- reset_all_predictors(sce->predictor_state);
+ reset_all_predictors(sce->AAC_RENAME(predictor_state));
}
static void decode_gain_control(SingleChannelElement * sce, GetBitContext * gb)
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 8899f90ac7..d07960620e 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -49,6 +49,20 @@ typedef enum AACCoder {
AAC_CODER_NB,
}AACCoder;
+/**
+ * Predictor State
+ */
+typedef struct PredictorState {
+ float cor0;
+ float cor1;
+ float var0;
+ float var1;
+ float r0;
+ float r1;
+ float k1;
+ float x_est;
+} PredictorState;
+
typedef struct AACEncOptions {
int coder;
int pns;
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index 31887ee5ee..8bc2605db8 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -39,6 +39,7 @@
typedef struct ExtChannelElement {
ChannelElement ch;
+ PredictorState predictor_state[2][MAX_PREDICTORS];
SpectralBandReplication sbr;
} ExtChannelElement;
@@ -86,6 +87,8 @@ av_cold int AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac,
return AVERROR(ENOMEM);
*che = &ext->ch;
sbr = &ext->sbr;
+ ext->ch.ch[0].AAC_RENAME(predictor_state) = ext->predictor_state[0];
+ ext->ch.ch[1].AAC_RENAME(predictor_state) = ext->predictor_state[1];
sbr->kx[0] = sbr->kx[1];
sbr->id_aac = id_aac;
--
2.43.0.381.gb435a96ce8
[-- Attachment #36: 0004-avcodec-aacdec-Always-include-AV-Fixed-Float-DSPCont.patch --]
[-- Type: text/x-diff, Size: 1777 bytes --]
From 9ed5ada7ae0dfc819a26b3e6a762c6c199ef7fd3 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 29 Feb 2024 17:06:47 +0100
Subject: [PATCH 04/38] avcodec/aacdec: Always include
AV(Fixed|Float)DSPContext in AACDecContext
Up until now, AACDecContext included pointers to one of these
contexts depending upon USE_FIXED. Yet deduplicating
the common parts of the float and fixed-point AAC decoders
needs common structures, so we put both of these pointers
in a union.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aacdec.h | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index e8d3297d17..e5165e9b54 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -67,6 +67,9 @@ enum CouplingPoint {
AFTER_IMDCT = 3,
};
+// Supposed to be equal to AAC_RENAME() in case of USE_FIXED.
+#define RENAME_FIXED(name) name ## _fixed
+
/**
* Long Term Prediction
*/
@@ -227,11 +230,10 @@ typedef struct AACDecContext {
av_tx_fn mdct960_fn;
av_tx_fn mdct1024_fn;
av_tx_fn mdct_ltp_fn;
-#if USE_FIXED
- AVFixedDSPContext *fdsp;
-#else
- AVFloatDSPContext *fdsp;
-#endif /* USE_FIXED */
+ union {
+ AVFixedDSPContext *RENAME_FIXED(fdsp);
+ AVFloatDSPContext *fdsp;
+ };
int random_state;
/** @} */
@@ -272,6 +274,10 @@ typedef struct AACDecContext {
void (*subband_scale)(int *dst, int *src, int scale, int offset, int len, void *log_context);
} AACDecContext;
+#if defined(USE_FIXED) && USE_FIXED
+#define fdsp RENAME_FIXED(fdsp)
+#endif
+
void ff_aacdec_init_mips(AACDecContext *c);
#endif /* AVCODEC_AACDEC_H */
--
2.43.0.381.gb435a96ce8
[-- Attachment #37: 0003-avcodec-aacdec-Split-SBR-context-from-ChannelElement.patch --]
[-- Type: text/x-diff, Size: 5882 bytes --]
From d81aedc49fbe728bc927e6a4d8448c9664830940 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Thu, 29 Feb 2024 16:42:01 +0100
Subject: [PATCH 03/38] avcodec/aacdec: Split SBR context from ChannelElement
The AAC fixed-point and floating-point decoders have
a lot of duplicated code; the main obstacle to
deduplicating it is that several structures with the
same name are actually different types, because
they contain INTFLOATs (int or float) and AAC_FLOATs
(SoftFloat or float). SoftFloat and float typically
have different sizes, so dealing with it is the more
complicated of the two.
AAC_FLOAT is mainly used in the sbr code and structures,
so one can still deduplicate the code by only exposing
the common part of ChannelElement (without SBR context)
to the common decoder part. One prerequisite of this
is to move allocating the whole ChannelElement to
code that will stay unduplicated. It is most natural
to move said allocation to ff_aac_sbr_ctx_init().
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aacdec.h | 2 --
libavcodec/aacdec_template.c | 5 +----
libavcodec/aacsbr.h | 7 +++++--
libavcodec/aacsbr_template.c | 28 +++++++++++++++++++++-------
4 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/libavcodec/aacdec.h b/libavcodec/aacdec.h
index 1b245f9258..e8d3297d17 100644
--- a/libavcodec/aacdec.h
+++ b/libavcodec/aacdec.h
@@ -41,7 +41,6 @@
#include "aac.h"
#include "aac_defines.h"
#include "mpeg4audio.h"
-#include "sbr.h"
/**
* Output configuration status
@@ -153,7 +152,6 @@ typedef struct ChannelElement {
SingleChannelElement ch[2];
// CCE specific
ChannelCoupling coup;
- SpectralBandReplication sbr;
} ChannelElement;
typedef struct OutputConfiguration {
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index 3d64c376d4..84c5309a80 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -133,10 +133,7 @@ static av_cold int che_configure(AACDecContext *ac,
return AVERROR_INVALIDDATA;
if (che_pos) {
if (!ac->che[type][id]) {
- int ret;
- if (!(ac->che[type][id] = av_mallocz(sizeof(ChannelElement))))
- return AVERROR(ENOMEM);
- ret = AAC_RENAME(ff_aac_sbr_ctx_init)(ac, ac->che[type][id], type);
+ int ret = AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(ac, &ac->che[type][id], type);
if (ret < 0)
return ret;
}
diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h
index 36289d23f2..855885ce87 100644
--- a/libavcodec/aacsbr.h
+++ b/libavcodec/aacsbr.h
@@ -68,8 +68,11 @@ enum {
/** Initialize SBR. */
void AAC_RENAME(ff_aac_sbr_init)(void);
-/** Initialize one SBR context. */
-int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, ChannelElement *che, int id_aac);
+/**
+ * Allocate an ExtChannelElement (if necessary) and
+ * initialize the SBR context contained in it.
+ */
+int AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac, ChannelElement **che, int id_aac);
/** Close one SBR context. */
void AAC_RENAME(ff_aac_sbr_ctx_close)(ChannelElement *che);
/** Decode one SBR element. */
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index fe9bf982b2..31887ee5ee 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -37,6 +37,16 @@
#include "avcodec.h"
#include "libavutil/qsort.h"
+typedef struct ExtChannelElement {
+ ChannelElement ch;
+ SpectralBandReplication sbr;
+} ExtChannelElement;
+
+static inline SpectralBandReplication *get_sbr(ChannelElement *ch)
+{
+ return &((ExtChannelElement*)ch)->sbr;
+}
+
static av_cold void aacsbr_tableinit(void)
{
int n;
@@ -64,14 +74,18 @@ static void sbr_turnoff(SpectralBandReplication *sbr) {
memset(&sbr->spectrum_params, -1, sizeof(SpectrumParameters));
}
-av_cold int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, ChannelElement *che, int id_aac)
+av_cold int AAC_RENAME(ff_aac_sbr_ctx_alloc_init)(AACDecContext *ac,
+ ChannelElement **che, int id_aac)
{
- SpectralBandReplication *sbr = &che->sbr;
+ SpectralBandReplication *sbr;
+ ExtChannelElement *ext = av_mallocz(sizeof(*ext));
int ret;
float scale;
- if (sbr->mdct)
- return 0;
+ if (!ext)
+ return AVERROR(ENOMEM);
+ *che = &ext->ch;
+ sbr = &ext->sbr;
sbr->kx[0] = sbr->kx[1];
sbr->id_aac = id_aac;
@@ -105,7 +119,7 @@ av_cold int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, ChannelElement *c
av_cold void AAC_RENAME(ff_aac_sbr_ctx_close)(ChannelElement *che)
{
- SpectralBandReplication *sbr = &che->sbr;
+ SpectralBandReplication *sbr = get_sbr(che);
av_tx_uninit(&sbr->mdct);
av_tx_uninit(&sbr->mdct_ana);
}
@@ -1096,7 +1110,7 @@ int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext *ac, ChannelElement *c
GetBitContext *gb_host, int crc,
int cnt, int id_aac)
{
- SpectralBandReplication *sbr = &che->sbr;
+ SpectralBandReplication *sbr = get_sbr(che);
unsigned int num_sbr_bits = 0, num_align_bits;
unsigned bytes_read;
GetBitContext gbc = *gb_host, *gb = &gbc;
@@ -1463,7 +1477,7 @@ 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, INTFLOAT* L, INTFLOAT* R)
{
- SpectralBandReplication *sbr = &che->sbr;
+ SpectralBandReplication *sbr = get_sbr(che);
int downsampled = ac->oc[1].m4ac.ext_sample_rate < sbr->sample_rate;
int ch;
int nch = (id_aac == TYPE_CPE) ? 2 : 1;
--
2.43.0.381.gb435a96ce8
[-- Attachment #38: 0002-avcodec-aacsbr-Make-ff_aac_sbr_-funcs-accept-Channel.patch --]
[-- Type: text/x-diff, Size: 9365 bytes --]
From 28557d01c7ca42abc2fc18edf704bd7af945ae7e Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
Date: Fri, 1 Mar 2024 03:04:21 +0100
Subject: [PATCH 02/38] avcodec/aacsbr: Make ff_aac_sbr_* funcs accept
ChannelElement*
Each ChannelElement contains exactly one SpectralBandReplication
structure; the latter structure contains lots of buffers
whose size depend upon USE_FIXED (i.e. AAC_FLOAT arrays).
This complicates deduplicating the parts of the AAC decoder
that are duplicated between the fixed-point and the floating
point decoder.
In order to fix this, the SpectralBandReplication structure
will be moved from the part of ChannelElement visible to
the common code. Therefore the ff_aac_sbr_* functions
are ported to accept a ChannelElement*; they will then have
to translate that to the corresponding SpectralBandReplication*
themselves (which is possible, because there are floating-point
and fixed-point versions of these functions).
While just at it, also ensure that these functions are properly
namespaced.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
libavcodec/aacdec.c | 1 -
libavcodec/aacdec_fixed.c | 1 -
libavcodec/aacdec_template.c | 10 +++++-----
libavcodec/aacsbr.h | 18 +++++++-----------
libavcodec/aacsbr_template.c | 17 +++++++++++------
libavcodec/mips/aacsbr_mips.c | 1 +
libavcodec/sbr.h | 2 ++
7 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 0a9ff1bfaf..6907d348f8 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -49,7 +49,6 @@
#include "aac/aacdec_tab.h"
#include "adts_header.h"
#include "cbrt_data.h"
-#include "sbr.h"
#include "aacsbr.h"
#include "mpeg4audio.h"
#include "profiles.h"
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 681e502e42..055b40b547 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -75,7 +75,6 @@
#include "aac/aacdec_tab.h"
#include "adts_header.h"
#include "cbrt_data.h"
-#include "sbr.h"
#include "aacsbr.h"
#include "mpeg4audio.h"
#include "profiles.h"
diff --git a/libavcodec/aacdec_template.c b/libavcodec/aacdec_template.c
index aa856d7fe1..3d64c376d4 100644
--- a/libavcodec/aacdec_template.c
+++ b/libavcodec/aacdec_template.c
@@ -136,7 +136,7 @@ static av_cold int che_configure(AACDecContext *ac,
int ret;
if (!(ac->che[type][id] = av_mallocz(sizeof(ChannelElement))))
return AVERROR(ENOMEM);
- ret = AAC_RENAME(ff_aac_sbr_ctx_init)(ac, &ac->che[type][id]->sbr, type);
+ ret = AAC_RENAME(ff_aac_sbr_ctx_init)(ac, ac->che[type][id], type);
if (ret < 0)
return ret;
}
@@ -153,7 +153,7 @@ static av_cold int che_configure(AACDecContext *ac,
}
} else {
if (ac->che[type][id])
- AAC_RENAME(ff_aac_sbr_ctx_close)(&ac->che[type][id]->sbr);
+ AAC_RENAME(ff_aac_sbr_ctx_close)(ac->che[type][id]);
av_freep(&ac->che[type][id]);
}
return 0;
@@ -2460,7 +2460,7 @@ static int decode_extension_payload(AACDecContext *ac, GetBitContext *gb, int cn
ac->oc[1].m4ac.sbr = 1;
ac->avctx->profile = AV_PROFILE_AAC_HE;
}
- res = AAC_RENAME(ff_decode_sbr_extension)(ac, &che->sbr, gb, crc_flag, cnt, elem_type);
+ res = AAC_RENAME(ff_aac_sbr_decode_extension)(ac, che, gb, crc_flag, cnt, elem_type);
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");
ac->warned_he_aac_mono = 1;
@@ -2941,7 +2941,7 @@ static void spectral_to_sample(AACDecContext *ac, int samples)
ac->update_ltp(ac, &che->ch[1]);
}
if (ac->oc[1].m4ac.sbr > 0) {
- AAC_RENAME(ff_sbr_apply)(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret);
+ AAC_RENAME(ff_aac_sbr_apply)(ac, che, type, che->ch[0].ret, che->ch[1].ret);
}
}
if (type <= TYPE_CCE)
@@ -3381,7 +3381,7 @@ static av_cold int aac_decode_close(AVCodecContext *avctx)
for (i = 0; i < MAX_ELEM_ID; i++) {
for (type = 0; type < 4; type++) {
if (ac->che[type][i])
- AAC_RENAME(ff_aac_sbr_ctx_close)(&ac->che[type][i]->sbr);
+ AAC_RENAME(ff_aac_sbr_ctx_close)(ac->che[type][i]);
av_freep(&ac->che[type][i]);
}
}
diff --git a/libavcodec/aacsbr.h b/libavcodec/aacsbr.h
index cb680cc548..36289d23f2 100644
--- a/libavcodec/aacsbr.h
+++ b/libavcodec/aacsbr.h
@@ -30,14 +30,12 @@
#define AVCODEC_AACSBR_H
#include "get_bits.h"
+#include "aacdec.h"
#include "aac_defines.h"
-#include "sbr.h"
#define ENVELOPE_ADJUSTMENT_OFFSET 2
#define NOISE_FLOOR_OFFSET 6
-struct AACDecContext;
-
/**
* SBR VLC tables
*/
@@ -71,16 +69,14 @@ enum {
/** Initialize SBR. */
void AAC_RENAME(ff_aac_sbr_init)(void);
/** Initialize one SBR context. */
-int AAC_RENAME(ff_aac_sbr_ctx_init)(struct AACDecContext *ac, SpectralBandReplication *sbr, int id_aac);
+int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, ChannelElement *che, int id_aac);
/** Close one SBR context. */
-void AAC_RENAME(ff_aac_sbr_ctx_close)(SpectralBandReplication *sbr);
+void AAC_RENAME(ff_aac_sbr_ctx_close)(ChannelElement *che);
/** Decode one SBR element. */
-int AAC_RENAME(ff_decode_sbr_extension)(struct AACDecContext *ac, SpectralBandReplication *sbr,
- GetBitContext *gb, int crc, int cnt, int id_aac);
+int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
+ GetBitContext *gb, int crc, int cnt, int id_aac);
/** Apply one SBR element to one AAC element. */
-void AAC_RENAME(ff_sbr_apply)(struct AACDecContext *ac, SpectralBandReplication *sbr, int id_aac,
- INTFLOAT* L, INTFLOAT *R);
-
-void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c);
+void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, ChannelElement *che,
+ int id_aac, INTFLOAT* L, INTFLOAT* R);
#endif /* AVCODEC_AACSBR_H */
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index eadd6fa2d3..fe9bf982b2 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -64,8 +64,9 @@ static void sbr_turnoff(SpectralBandReplication *sbr) {
memset(&sbr->spectrum_params, -1, sizeof(SpectrumParameters));
}
-av_cold int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, SpectralBandReplication *sbr, int id_aac)
+av_cold int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, ChannelElement *che, int id_aac)
{
+ SpectralBandReplication *sbr = &che->sbr;
int ret;
float scale;
@@ -102,8 +103,9 @@ av_cold int AAC_RENAME(ff_aac_sbr_ctx_init)(AACDecContext *ac, SpectralBandRepli
return 0;
}
-av_cold void AAC_RENAME(ff_aac_sbr_ctx_close)(SpectralBandReplication *sbr)
+av_cold void AAC_RENAME(ff_aac_sbr_ctx_close)(ChannelElement *che)
{
+ SpectralBandReplication *sbr = &che->sbr;
av_tx_uninit(&sbr->mdct);
av_tx_uninit(&sbr->mdct_ana);
}
@@ -1090,9 +1092,11 @@ static void sbr_reset(AACDecContext *ac, SpectralBandReplication *sbr)
*
* @return Returns number of bytes consumed from the TYPE_FIL element.
*/
-int AAC_RENAME(ff_decode_sbr_extension)(AACDecContext *ac, SpectralBandReplication *sbr,
- GetBitContext *gb_host, int crc, int cnt, int id_aac)
+int AAC_RENAME(ff_aac_sbr_decode_extension)(AACDecContext *ac, ChannelElement *che,
+ GetBitContext *gb_host, int crc,
+ int cnt, int id_aac)
{
+ SpectralBandReplication *sbr = &che->sbr;
unsigned int num_sbr_bits = 0, num_align_bits;
unsigned bytes_read;
GetBitContext gbc = *gb_host, *gb = &gbc;
@@ -1456,9 +1460,10 @@ static void sbr_env_estimate(AAC_FLOAT (*e_curr)[48], INTFLOAT X_high[64][40][2]
}
}
-void AAC_RENAME(ff_sbr_apply)(AACDecContext *ac, SpectralBandReplication *sbr, int id_aac,
- INTFLOAT* L, INTFLOAT* R)
+void AAC_RENAME(ff_aac_sbr_apply)(AACDecContext *ac, ChannelElement *che,
+ int id_aac, INTFLOAT* L, INTFLOAT* R)
{
+ SpectralBandReplication *sbr = &che->sbr;
int downsampled = ac->oc[1].m4ac.ext_sample_rate < sbr->sample_rate;
int ch;
int nch = (id_aac == TYPE_CPE) ? 2 : 1;
diff --git a/libavcodec/mips/aacsbr_mips.c b/libavcodec/mips/aacsbr_mips.c
index e0715491e6..eea48b360b 100644
--- a/libavcodec/mips/aacsbr_mips.c
+++ b/libavcodec/mips/aacsbr_mips.c
@@ -53,6 +53,7 @@
#include "libavcodec/aacdec.h"
#include "libavcodec/aacsbr.h"
+#include "libavcodec/sbr.h"
#include "libavutil/mem_internal.h"
#include "libavutil/mips/asmdefs.h"
diff --git a/libavcodec/sbr.h b/libavcodec/sbr.h
index fe3a39603a..d17b52aa4f 100644
--- a/libavcodec/sbr.h
+++ b/libavcodec/sbr.h
@@ -217,4 +217,6 @@ struct SpectralBandReplication {
AACSBRContext c;
};
+void ff_aacsbr_func_ptr_init_mips(AACSBRContext *c);
+
#endif /* AVCODEC_SBR_H */
--
2.43.0.381.gb435a96ce8
[-- Attachment #39: 0001-aacdec-move-aacdec_common-to-aac-aacdec_tab.patch --]
[-- Type: text/x-diff, Size: 5397 bytes --]
From d3dac825a1ea0c82a9a799ff9415a5a8a598d47e Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 29 Feb 2024 04:52:58 +0100
Subject: [PATCH 01/38] aacdec: move aacdec_common to aac/aacdec_tab
Start to clean up the decoder.
Also renames a confusingly named file.
---
libavcodec/Makefile | 5 +++--
libavcodec/aac/Makefile | 5 +++++
libavcodec/{aacdec_common.c => aac/aacdec_tab.c} | 11 ++++++-----
libavcodec/{aacdectab.h => aac/aacdec_tab.h} | 8 ++++----
libavcodec/aacdec.c | 2 +-
libavcodec/aacdec_fixed.c | 2 +-
libavcodec/aacsbr_template.c | 2 +-
7 files changed, 21 insertions(+), 14 deletions(-)
create mode 100644 libavcodec/aac/Makefile
rename libavcodec/{aacdec_common.c => aac/aacdec_tab.c} (99%)
rename libavcodec/{aacdectab.h => aac/aacdec_tab.h} (91%)
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 708434ac76..71bef865f5 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -63,6 +63,7 @@ OBJS = ac3_parser.o \
xiph.o \
# subsystems
+include $(SRC_PATH)/libavcodec/aac/Makefile
include $(SRC_PATH)/libavcodec/vvc/Makefile
-include $(SRC_PATH)/libavcodec/$(ARCH)/vvc/Makefile
OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
@@ -177,11 +178,11 @@ OBJS-$(CONFIG_WMV2DSP) += wmv2dsp.o
OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
-OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aacdec_common.o aactab.o \
+OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o \
aacsbr.o aacps_common.o aacps_float.o \
kbdwin.o \
sbrdsp.o aacpsdsp_float.o cbrt_data.o
-OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aacdec_common.o aactab.o \
+OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o \
aacsbr_fixed.o aacps_common.o aacps_fixed.o \
kbdwin.o \
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
diff --git a/libavcodec/aac/Makefile b/libavcodec/aac/Makefile
new file mode 100644
index 0000000000..52facdf4cf
--- /dev/null
+++ b/libavcodec/aac/Makefile
@@ -0,0 +1,5 @@
+clean::
+ $(RM) $(CLEANSUFFIXES:%=libavcodec/aac/%)
+
+OBJS-$(CONFIG_AAC_DECODER) += aac/aacdec_tab.o
+OBJS-$(CONFIG_AAC_FIXED_DECODER) += aac/aacdec_tab.o
diff --git a/libavcodec/aacdec_common.c b/libavcodec/aac/aacdec_tab.c
similarity index 99%
rename from libavcodec/aacdec_common.c
rename to libavcodec/aac/aacdec_tab.c
index 145c718047..45a84a9a72 100644
--- a/libavcodec/aacdec_common.c
+++ b/libavcodec/aac/aacdec_tab.c
@@ -25,11 +25,12 @@
* Common code and tables of the AAC fixed- and floating-point decoders
*/
-#include "aac.h"
-#include "aacdectab.h"
-#include "aacps.h"
-#include "aactab.h"
-#include "vlc.h"
+#include "aacdec_tab.h"
+
+#include "libavcodec/aac.h"
+#include "libavcodec/aacps.h"
+#include "libavcodec/aactab.h"
+#include "libavcodec/vlc.h"
#include "libavutil/attributes.h"
#include "libavutil/thread.h"
diff --git a/libavcodec/aacdectab.h b/libavcodec/aac/aacdec_tab.h
similarity index 91%
rename from libavcodec/aacdectab.h
rename to libavcodec/aac/aacdec_tab.h
index 184508f2f3..70e49af202 100644
--- a/libavcodec/aacdectab.h
+++ b/libavcodec/aac/aacdec_tab.h
@@ -25,12 +25,12 @@
* @author Maxim Gavrilov ( maxim.gavrilov gmail com )
*/
-#ifndef AVCODEC_AACDECTAB_H
-#define AVCODEC_AACDECTAB_H
+#ifndef AVCODEC_AAC_AACDEC_TAB_H
+#define AVCODEC_AAC_AACDEC_TAB_H
#include <stdint.h>
-#include "vlc.h"
+#include "libavcodec/vlc.h"
#include "libavutil/attributes_internal.h"
#include "libavutil/channel_layout.h"
@@ -52,4 +52,4 @@ extern const int16_t ff_aac_channel_map[3][4][6];
extern const AVChannelLayout ff_aac_ch_layout[];
FF_VISIBILITY_POP_HIDDEN
-#endif /* AVCODEC_AACDECTAB_H */
+#endif /* AVCODEC_AAC_AACDEC_TAB_H */
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c
index 97e51dd72a..0a9ff1bfaf 100644
--- a/libavcodec/aacdec.c
+++ b/libavcodec/aacdec.c
@@ -46,7 +46,7 @@
#include "aac.h"
#include "aacdec.h"
#include "aactab.h"
-#include "aacdectab.h"
+#include "aac/aacdec_tab.h"
#include "adts_header.h"
#include "cbrt_data.h"
#include "sbr.h"
diff --git a/libavcodec/aacdec_fixed.c b/libavcodec/aacdec_fixed.c
index 305bb0ba9a..681e502e42 100644
--- a/libavcodec/aacdec_fixed.c
+++ b/libavcodec/aacdec_fixed.c
@@ -72,7 +72,7 @@
#include "aac.h"
#include "aacdec.h"
#include "aactab.h"
-#include "aacdectab.h"
+#include "aac/aacdec_tab.h"
#include "adts_header.h"
#include "cbrt_data.h"
#include "sbr.h"
diff --git a/libavcodec/aacsbr_template.c b/libavcodec/aacsbr_template.c
index cdfaed636b..eadd6fa2d3 100644
--- a/libavcodec/aacsbr_template.c
+++ b/libavcodec/aacsbr_template.c
@@ -33,7 +33,7 @@
*/
#include "aacdec.h"
-#include "aacdectab.h"
+#include "aac/aacdec_tab.h"
#include "avcodec.h"
#include "libavutil/qsort.h"
--
2.43.0.381.gb435a96ce8
[-- Attachment #40: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
[not found] ` <NuwZLzA--3-9@lynne.ee-NuwcmRV----9>
@ 2024-04-10 16:48 ` Lynne
2024-04-10 18:18 ` Michael Niedermayer
0 siblings, 1 reply; 12+ messages in thread
From: Lynne @ 2024-04-10 16:48 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Apr 8, 2024, 09:36 by dev@lynne.ee:
> The following patchset refactors the AAC decoder step by step,
> removing all large-scale templating and abstracting away typed
> DSP functions from symbol parsing.
>
> This series saves 110Kib of binary data from libavcodec.so
> when compiled with Clang 18 with -O3, after stripping.
>
> The patchset can also be viewed here:
> https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
>
> Fate passes on each step, and I've been running this patchset for
> a week with no issues.
>
> This also prepares the decoder for USAC support.
>
I've rebased the linked repo to current git master if anyone
wants to test.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-10 16:48 ` Lynne
@ 2024-04-10 18:18 ` Michael Niedermayer
2024-04-10 21:51 ` Michael Niedermayer
2024-04-10 21:56 ` Michael Niedermayer
0 siblings, 2 replies; 12+ messages in thread
From: Michael Niedermayer @ 2024-04-10 18:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1143 bytes --]
On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
> Apr 8, 2024, 09:36 by dev@lynne.ee:
>
> > The following patchset refactors the AAC decoder step by step,
> > removing all large-scale templating and abstracting away typed
> > DSP functions from symbol parsing.
> >
> > This series saves 110Kib of binary data from libavcodec.so
> > when compiled with Clang 18 with -O3, after stripping.
> >
> > The patchset can also be viewed here:
> > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
> >
> > Fate passes on each step, and I've been running this patchset for
> > a week with no issues.
> >
> > This also prepares the decoder for USAC support.
> >
>
> I've rebased the linked repo to current git master if anyone
> wants to test.
thanks, i will try to test it
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Old school: Use the lowest level language in which you can solve the problem
conveniently.
New school: Use the highest level language in which the latest supercomputer
can solve the problem without the user falling asleep waiting.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-10 18:18 ` Michael Niedermayer
@ 2024-04-10 21:51 ` Michael Niedermayer
2024-04-10 21:56 ` Michael Niedermayer
1 sibling, 0 replies; 12+ messages in thread
From: Michael Niedermayer @ 2024-04-10 21:51 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 1819 bytes --]
On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
> > Apr 8, 2024, 09:36 by dev@lynne.ee:
> >
> > > The following patchset refactors the AAC decoder step by step,
> > > removing all large-scale templating and abstracting away typed
> > > DSP functions from symbol parsing.
> > >
> > > This series saves 110Kib of binary data from libavcodec.so
> > > when compiled with Clang 18 with -O3, after stripping.
> > >
> > > The patchset can also be viewed here:
> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
> > >
> > > Fate passes on each step, and I've been running this patchset for
> > > a week with no issues.
> > >
> > > This also prepares the decoder for USAC support.
> > >
> >
> > I've rebased the linked repo to current git master if anyone
> > wants to test.
>
> thanks, i will try to test it
build fails on mips
make -j32 -k
CC libavcodec/aac/aacdec_float.o
src/libavcodec/aac/aacdec_float.c: In function ‘init’:
src/libavcodec/aac/aacdec_float.c:81:5: error: implicit declaration of function ‘ff_aacdec_init_mips’; did you mean ‘ff_float_dsp_init_mips’? [-Werror=implicit-function-declaration]
ff_aacdec_init_mips(ac);
^~~~~~~~~~~~~~~~~~~
ff_float_dsp_init_mips
cc1: some warnings being treated as errors
src/ffbuild/common.mak:81: recipe for target 'libavcodec/aac/aacdec_float.o' failed
make: *** [libavcodec/aac/aacdec_float.o] Error 1
make: Target 'all' not remade because of errors.
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Into a blind darkness they enter who follow after the Ignorance,
they as if into a greater darkness enter who devote themselves
to the Knowledge alone. -- Isha Upanishad
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-10 18:18 ` Michael Niedermayer
2024-04-10 21:51 ` Michael Niedermayer
@ 2024-04-10 21:56 ` Michael Niedermayer
2024-04-11 5:42 ` Lynne
1 sibling, 1 reply; 12+ messages in thread
From: Michael Niedermayer @ 2024-04-10 21:56 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2087 bytes --]
On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
> > Apr 8, 2024, 09:36 by dev@lynne.ee:
> >
> > > The following patchset refactors the AAC decoder step by step,
> > > removing all large-scale templating and abstracting away typed
> > > DSP functions from symbol parsing.
> > >
> > > This series saves 110Kib of binary data from libavcodec.so
> > > when compiled with Clang 18 with -O3, after stripping.
> > >
> > > The patchset can also be viewed here:
> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
> > >
> > > Fate passes on each step, and I've been running this patchset for
> > > a week with no issues.
> > >
> > > This also prepares the decoder for USAC support.
> > >
> >
> > I've rebased the linked repo to current git master if anyone
> > wants to test.
>
> thanks, i will try to test it
make fate-source
TEST source
--- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
+++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
@@ -22,6 +22,13 @@
compat/djgpp/math.h
compat/float/float.h
compat/float/limits.h
+libavcodec/aac/aacdec.h
+libavcodec/aac/aacdec_fixed_coupling.h
+libavcodec/aac/aacdec_fixed_dequant.h
+libavcodec/aac/aacdec_fixed_prediction.h
+libavcodec/aac/aacdec_float_coupling.h
+libavcodec/aac/aacdec_float_prediction.h
+libavcodec/aac/aacdec_latm.h
libavcodec/bitstream_template.h
tools/decode_simple.h
Use of av_clip() where av_clip_uintp2() could be used:
Test source failed. Look at tests/data/fate/source.err for details.
tests/Makefile:310: recipe for target 'fate-source' failed
make: *** [fate-source] Error 1
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Any man who breaks a law that conscience tells him is unjust and willingly
accepts the penalty by staying in jail in order to arouse the conscience of
the community on the injustice of the law is at that moment expressing the
very highest respect for law. - Martin Luther King Jr
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-10 21:56 ` Michael Niedermayer
@ 2024-04-11 5:42 ` Lynne
2024-04-11 22:45 ` Michael Niedermayer
0 siblings, 1 reply; 12+ messages in thread
From: Lynne @ 2024-04-11 5:42 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Apr 10, 2024, 23:57 by michael@niedermayer.cc:
> On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
>
>> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
>> > Apr 8, 2024, 09:36 by dev@lynne.ee:
>> >
>> > > The following patchset refactors the AAC decoder step by step,
>> > > removing all large-scale templating and abstracting away typed
>> > > DSP functions from symbol parsing.
>> > >
>> > > This series saves 110Kib of binary data from libavcodec.so
>> > > when compiled with Clang 18 with -O3, after stripping.
>> > >
>> > > The patchset can also be viewed here:
>> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
>> > >
>> > > Fate passes on each step, and I've been running this patchset for
>> > > a week with no issues.
>> > >
>> > > This also prepares the decoder for USAC support.
>> > >
>> >
>> > I've rebased the linked repo to current git master if anyone
>> > wants to test.
>>
>> thanks, i will try to test it
>>
>
> make fate-source
>
> TEST source
> --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
> +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
> @@ -22,6 +22,13 @@
> compat/djgpp/math.h
> compat/float/float.h
> compat/float/limits.h
> +libavcodec/aac/aacdec.h
> +libavcodec/aac/aacdec_fixed_coupling.h
> +libavcodec/aac/aacdec_fixed_dequant.h
> +libavcodec/aac/aacdec_fixed_prediction.h
> +libavcodec/aac/aacdec_float_coupling.h
> +libavcodec/aac/aacdec_float_prediction.h
> +libavcodec/aac/aacdec_latm.h
> libavcodec/bitstream_template.h
> tools/decode_simple.h
> Use of av_clip() where av_clip_uintp2() could be used:
> Test source failed. Look at tests/data/fate/source.err for details.
> tests/Makefile:310: recipe for target 'fate-source' failed
> make: *** [fate-source] Error 1
>
Thanks for testing. Fixed both issues in the repo.
Was only testing with fate-aac while developing.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-11 5:42 ` Lynne
@ 2024-04-11 22:45 ` Michael Niedermayer
2024-04-12 9:11 ` Lynne
[not found] ` <NvGZy8P--7-9@lynne.ee-NvG_0xp----9>
0 siblings, 2 replies; 12+ messages in thread
From: Michael Niedermayer @ 2024-04-11 22:45 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 4115 bytes --]
On Thu, Apr 11, 2024 at 07:42:37AM +0200, Lynne wrote:
> Apr 10, 2024, 23:57 by michael@niedermayer.cc:
>
> > On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
> >
> >> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
> >> > Apr 8, 2024, 09:36 by dev@lynne.ee:
> >> >
> >> > > The following patchset refactors the AAC decoder step by step,
> >> > > removing all large-scale templating and abstracting away typed
> >> > > DSP functions from symbol parsing.
> >> > >
> >> > > This series saves 110Kib of binary data from libavcodec.so
> >> > > when compiled with Clang 18 with -O3, after stripping.
> >> > >
> >> > > The patchset can also be viewed here:
> >> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
> >> > >
> >> > > Fate passes on each step, and I've been running this patchset for
> >> > > a week with no issues.
> >> > >
> >> > > This also prepares the decoder for USAC support.
> >> > >
> >> >
> >> > I've rebased the linked repo to current git master if anyone
> >> > wants to test.
> >>
> >> thanks, i will try to test it
> >>
> >
> > make fate-source
> >
> > TEST source
> > --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
> > +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
> > @@ -22,6 +22,13 @@
> > compat/djgpp/math.h
> > compat/float/float.h
> > compat/float/limits.h
> > +libavcodec/aac/aacdec.h
> > +libavcodec/aac/aacdec_fixed_coupling.h
> > +libavcodec/aac/aacdec_fixed_dequant.h
> > +libavcodec/aac/aacdec_fixed_prediction.h
> > +libavcodec/aac/aacdec_float_coupling.h
> > +libavcodec/aac/aacdec_float_prediction.h
> > +libavcodec/aac/aacdec_latm.h
> > libavcodec/bitstream_template.h
> > tools/decode_simple.h
> > Use of av_clip() where av_clip_uintp2() could be used:
> > Test source failed. Look at tests/data/fate/source.err for details.
> > tests/Makefile:310: recipe for target 'fate-source' failed
> > make: *** [fate-source] Error 1
> >
>
> Thanks for testing. Fixed both issues in the repo.
> Was only testing with fate-aac while developing.
mips:
make -k
LD ffmpeg_g
libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
collect2: error: ld returned 1 exit status
Makefile:136: recipe for target 'ffmpeg_g' failed
make: *** [ffmpeg_g] Error 1
LD ffprobe_g
libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
collect2: error: ld returned 1 exit status
Makefile:136: recipe for target 'ffprobe_g' failed
make: *** [ffprobe_g] Error 1
make: Target 'all' not remade because of errors.
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
I have never wished to cater to the crowd; for what I know they do not
approve, and what they approve I do not know. -- Epicurus
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-11 22:45 ` Michael Niedermayer
@ 2024-04-12 9:11 ` Lynne
2024-04-21 22:18 ` Michael Niedermayer
[not found] ` <NvGZy8P--7-9@lynne.ee-NvG_0xp----9>
1 sibling, 1 reply; 12+ messages in thread
From: Lynne @ 2024-04-12 9:11 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Apr 12, 2024, 00:45 by michael@niedermayer.cc:
> On Thu, Apr 11, 2024 at 07:42:37AM +0200, Lynne wrote:
>
>> Apr 10, 2024, 23:57 by michael@niedermayer.cc:
>>
>> > On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
>> >
>> >> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
>> >> > Apr 8, 2024, 09:36 by dev@lynne.ee:
>> >> >
>> >> > > The following patchset refactors the AAC decoder step by step,
>> >> > > removing all large-scale templating and abstracting away typed
>> >> > > DSP functions from symbol parsing.
>> >> > >
>> >> > > This series saves 110Kib of binary data from libavcodec.so
>> >> > > when compiled with Clang 18 with -O3, after stripping.
>> >> > >
>> >> > > The patchset can also be viewed here:
>> >> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
>> >> > >
>> >> > > Fate passes on each step, and I've been running this patchset for
>> >> > > a week with no issues.
>> >> > >
>> >> > > This also prepares the decoder for USAC support.
>> >> > >
>> >> >
>> >> > I've rebased the linked repo to current git master if anyone
>> >> > wants to test.
>> >>
>> >> thanks, i will try to test it
>> >>
>> >
>> > make fate-source
>> >
>> > TEST source
>> > --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
>> > +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
>> > @@ -22,6 +22,13 @@
>> > compat/djgpp/math.h
>> > compat/float/float.h
>> > compat/float/limits.h
>> > +libavcodec/aac/aacdec.h
>> > +libavcodec/aac/aacdec_fixed_coupling.h
>> > +libavcodec/aac/aacdec_fixed_dequant.h
>> > +libavcodec/aac/aacdec_fixed_prediction.h
>> > +libavcodec/aac/aacdec_float_coupling.h
>> > +libavcodec/aac/aacdec_float_prediction.h
>> > +libavcodec/aac/aacdec_latm.h
>> > libavcodec/bitstream_template.h
>> > tools/decode_simple.h
>> > Use of av_clip() where av_clip_uintp2() could be used:
>> > Test source failed. Look at tests/data/fate/source.err for details.
>> > tests/Makefile:310: recipe for target 'fate-source' failed
>> > make: *** [fate-source] Error 1
>> >
>>
>> Thanks for testing. Fixed both issues in the repo.
>> Was only testing with fate-aac while developing.
>>
>
> mips:
>
> make -k
> LD ffmpeg_g
> libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
> aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
> sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
> sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
> libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
> aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
> aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
> collect2: error: ld returned 1 exit status
> Makefile:136: recipe for target 'ffmpeg_g' failed
> make: *** [ffmpeg_g] Error 1
> LD ffprobe_g
> libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
> aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
> sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
> sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
> libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
> aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
> aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
> collect2: error: ld returned 1 exit status
> Makefile:136: recipe for target 'ffprobe_g' failed
> make: *** [ffprobe_g] Error 1
> make: Target 'all' not remade because of errors.
>
Fixed. This should be all.
On the Loongson machine I have access to, I can't compile FFmpeg
due to missing asm/errno.h kernel header, while on the standard MIPS64
machine I can access, compilation worked either way.
Would you mind testing again the new version in the repo?
Thanks.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
[not found] ` <NvGZy8P--7-9@lynne.ee-NvG_0xp----9>
@ 2024-04-21 12:39 ` Lynne
0 siblings, 0 replies; 12+ messages in thread
From: Lynne @ 2024-04-21 12:39 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Apr 12, 2024, 11:12 by dev@lynne.ee:
> Apr 12, 2024, 00:45 by michael@niedermayer.cc:
>
>> On Thu, Apr 11, 2024 at 07:42:37AM +0200, Lynne wrote:
>>
>>> Apr 10, 2024, 23:57 by michael@niedermayer.cc:
>>>
>>> > On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
>>> >
>>> >> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
>>> >> > Apr 8, 2024, 09:36 by dev@lynne.ee:
>>> >> >
>>> >> > > The following patchset refactors the AAC decoder step by step,
>>> >> > > removing all large-scale templating and abstracting away typed
>>> >> > > DSP functions from symbol parsing.
>>> >> > >
>>> >> > > This series saves 110Kib of binary data from libavcodec.so
>>> >> > > when compiled with Clang 18 with -O3, after stripping.
>>> >> > >
>>> >> > > The patchset can also be viewed here:
>>> >> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
>>> >> > >
>>> >> > > Fate passes on each step, and I've been running this patchset for
>>> >> > > a week with no issues.
>>> >> > >
>>> >> > > This also prepares the decoder for USAC support.
>>> >> > >
>>> >> >
>>> >> > I've rebased the linked repo to current git master if anyone
>>> >> > wants to test.
>>> >>
>>> >> thanks, i will try to test it
>>> >>
>>> >
>>> > make fate-source
>>> >
>>> > TEST source
>>> > --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
>>> > +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
>>> > @@ -22,6 +22,13 @@
>>> > compat/djgpp/math.h
>>> > compat/float/float.h
>>> > compat/float/limits.h
>>> > +libavcodec/aac/aacdec.h
>>> > +libavcodec/aac/aacdec_fixed_coupling.h
>>> > +libavcodec/aac/aacdec_fixed_dequant.h
>>> > +libavcodec/aac/aacdec_fixed_prediction.h
>>> > +libavcodec/aac/aacdec_float_coupling.h
>>> > +libavcodec/aac/aacdec_float_prediction.h
>>> > +libavcodec/aac/aacdec_latm.h
>>> > libavcodec/bitstream_template.h
>>> > tools/decode_simple.h
>>> > Use of av_clip() where av_clip_uintp2() could be used:
>>> > Test source failed. Look at tests/data/fate/source.err for details.
>>> > tests/Makefile:310: recipe for target 'fate-source' failed
>>> > make: *** [fate-source] Error 1
>>> >
>>>
>>> Thanks for testing. Fixed both issues in the repo.
>>> Was only testing with fate-aac while developing.
>>>
>>
>> mips:
>>
>> make -k
>> LD ffmpeg_g
>> libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
>> aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
>> sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
>> sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
>> libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
>> aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
>> aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
>> collect2: error: ld returned 1 exit status
>> Makefile:136: recipe for target 'ffmpeg_g' failed
>> make: *** [ffmpeg_g] Error 1
>> LD ffprobe_g
>> libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
>> aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
>> sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
>> sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
>> libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
>> aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
>> aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
>> collect2: error: ld returned 1 exit status
>> Makefile:136: recipe for target 'ffprobe_g' failed
>> make: *** [ffprobe_g] Error 1
>> make: Target 'all' not remade because of errors.
>>
>
> Fixed. This should be all.
> On the Loongson machine I have access to, I can't compile FFmpeg
> due to missing asm/errno.h kernel header, while on the standard MIPS64
> machine I can access, compilation worked either way.
> Would you mind testing again the new version in the repo?
>
Ping. I'm probably the only one who'll touch the AAC code in the near
future, but I wouldn't push this branch without a review first.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-12 9:11 ` Lynne
@ 2024-04-21 22:18 ` Michael Niedermayer
2024-04-22 7:20 ` Lynne
[not found] ` <Nw3fLeH--3-9@lynne.ee-Nw3fPhs----9>
0 siblings, 2 replies; 12+ messages in thread
From: Michael Niedermayer @ 2024-04-21 22:18 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 4967 bytes --]
On Fri, Apr 12, 2024 at 11:11:53AM +0200, Lynne wrote:
> Apr 12, 2024, 00:45 by michael@niedermayer.cc:
>
> > On Thu, Apr 11, 2024 at 07:42:37AM +0200, Lynne wrote:
> >
> >> Apr 10, 2024, 23:57 by michael@niedermayer.cc:
> >>
> >> > On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
> >> >
> >> >> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
> >> >> > Apr 8, 2024, 09:36 by dev@lynne.ee:
> >> >> >
> >> >> > > The following patchset refactors the AAC decoder step by step,
> >> >> > > removing all large-scale templating and abstracting away typed
> >> >> > > DSP functions from symbol parsing.
> >> >> > >
> >> >> > > This series saves 110Kib of binary data from libavcodec.so
> >> >> > > when compiled with Clang 18 with -O3, after stripping.
> >> >> > >
> >> >> > > The patchset can also be viewed here:
> >> >> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
> >> >> > >
> >> >> > > Fate passes on each step, and I've been running this patchset for
> >> >> > > a week with no issues.
> >> >> > >
> >> >> > > This also prepares the decoder for USAC support.
> >> >> > >
> >> >> >
> >> >> > I've rebased the linked repo to current git master if anyone
> >> >> > wants to test.
> >> >>
> >> >> thanks, i will try to test it
> >> >>
> >> >
> >> > make fate-source
> >> >
> >> > TEST source
> >> > --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
> >> > +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
> >> > @@ -22,6 +22,13 @@
> >> > compat/djgpp/math.h
> >> > compat/float/float.h
> >> > compat/float/limits.h
> >> > +libavcodec/aac/aacdec.h
> >> > +libavcodec/aac/aacdec_fixed_coupling.h
> >> > +libavcodec/aac/aacdec_fixed_dequant.h
> >> > +libavcodec/aac/aacdec_fixed_prediction.h
> >> > +libavcodec/aac/aacdec_float_coupling.h
> >> > +libavcodec/aac/aacdec_float_prediction.h
> >> > +libavcodec/aac/aacdec_latm.h
> >> > libavcodec/bitstream_template.h
> >> > tools/decode_simple.h
> >> > Use of av_clip() where av_clip_uintp2() could be used:
> >> > Test source failed. Look at tests/data/fate/source.err for details.
> >> > tests/Makefile:310: recipe for target 'fate-source' failed
> >> > make: *** [fate-source] Error 1
> >> >
> >>
> >> Thanks for testing. Fixed both issues in the repo.
> >> Was only testing with fate-aac while developing.
> >>
> >
> > mips:
> >
> > make -k
> > LD ffmpeg_g
> > libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
> > aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> > aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> > libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
> > sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
> > sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
> > libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
> > aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
> > aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
> > collect2: error: ld returned 1 exit status
> > Makefile:136: recipe for target 'ffmpeg_g' failed
> > make: *** [ffmpeg_g] Error 1
> > LD ffprobe_g
> > libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
> > aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> > aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
> > libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
> > sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
> > sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
> > libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
> > aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
> > aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
> > collect2: error: ld returned 1 exit status
> > Makefile:136: recipe for target 'ffprobe_g' failed
> > make: *** [ffprobe_g] Error 1
> > make: Target 'all' not remade because of errors.
> >
>
> Fixed. This should be all.
> On the Loongson machine I have access to, I can't compile FFmpeg
> due to missing asm/errno.h kernel header, while on the standard MIPS64
> machine I can access, compilation worked either way.
> Would you mind testing again the new version in the repo?
it works on my qemu based mips. I did give the loongson to anton 2 years ago
so i have no native loongson to test it with
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Those who would give up essential Liberty, to purchase a little
temporary Safety, deserve neither Liberty nor Safety -- Benjamin Franklin
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
2024-04-21 22:18 ` Michael Niedermayer
@ 2024-04-22 7:20 ` Lynne
[not found] ` <Nw3fLeH--3-9@lynne.ee-Nw3fPhs----9>
1 sibling, 0 replies; 12+ messages in thread
From: Lynne @ 2024-04-22 7:20 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Apr 22, 2024, 00:19 by michael@niedermayer.cc:
> On Fri, Apr 12, 2024 at 11:11:53AM +0200, Lynne wrote:
>
>> Apr 12, 2024, 00:45 by michael@niedermayer.cc:
>>
>> > On Thu, Apr 11, 2024 at 07:42:37AM +0200, Lynne wrote:
>> >
>> >> Apr 10, 2024, 23:57 by michael@niedermayer.cc:
>> >>
>> >> > On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
>> >> >
>> >> >> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
>> >> >> > Apr 8, 2024, 09:36 by dev@lynne.ee:
>> >> >> >
>> >> >> > > The following patchset refactors the AAC decoder step by step,
>> >> >> > > removing all large-scale templating and abstracting away typed
>> >> >> > > DSP functions from symbol parsing.
>> >> >> > >
>> >> >> > > This series saves 110Kib of binary data from libavcodec.so
>> >> >> > > when compiled with Clang 18 with -O3, after stripping.
>> >> >> > >
>> >> >> > > The patchset can also be viewed here:
>> >> >> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
>> >> >> > >
>> >> >> > > Fate passes on each step, and I've been running this patchset for
>> >> >> > > a week with no issues.
>> >> >> > >
>> >> >> > > This also prepares the decoder for USAC support.
>> >> >> > >
>> >> >> >
>> >> >> > I've rebased the linked repo to current git master if anyone
>> >> >> > wants to test.
>> >> >>
>> >> >> thanks, i will try to test it
>> >> >>
>> >> >
>> >> > make fate-source
>> >> >
>> >> > TEST source
>> >> > --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
>> >> > +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
>> >> > @@ -22,6 +22,13 @@
>> >> > compat/djgpp/math.h
>> >> > compat/float/float.h
>> >> > compat/float/limits.h
>> >> > +libavcodec/aac/aacdec.h
>> >> > +libavcodec/aac/aacdec_fixed_coupling.h
>> >> > +libavcodec/aac/aacdec_fixed_dequant.h
>> >> > +libavcodec/aac/aacdec_fixed_prediction.h
>> >> > +libavcodec/aac/aacdec_float_coupling.h
>> >> > +libavcodec/aac/aacdec_float_prediction.h
>> >> > +libavcodec/aac/aacdec_latm.h
>> >> > libavcodec/bitstream_template.h
>> >> > tools/decode_simple.h
>> >> > Use of av_clip() where av_clip_uintp2() could be used:
>> >> > Test source failed. Look at tests/data/fate/source.err for details.
>> >> > tests/Makefile:310: recipe for target 'fate-source' failed
>> >> > make: *** [fate-source] Error 1
>> >> >
>> >>
>> >> Thanks for testing. Fixed both issues in the repo.
>> >> Was only testing with fate-aac while developing.
>> >>
>> >
>> > mips:
>> >
>> > make -k
>> > LD ffmpeg_g
>> > libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
>> > aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> > aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> > libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
>> > sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
>> > sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
>> > libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
>> > aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
>> > aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
>> > collect2: error: ld returned 1 exit status
>> > Makefile:136: recipe for target 'ffmpeg_g' failed
>> > make: *** [ffmpeg_g] Error 1
>> > LD ffprobe_g
>> > libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
>> > aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> > aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>> > libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
>> > sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
>> > sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
>> > libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
>> > aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
>> > aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
>> > collect2: error: ld returned 1 exit status
>> > Makefile:136: recipe for target 'ffprobe_g' failed
>> > make: *** [ffprobe_g] Error 1
>> > make: Target 'all' not remade because of errors.
>> >
>>
>> Fixed. This should be all.
>> On the Loongson machine I have access to, I can't compile FFmpeg
>> due to missing asm/errno.h kernel header, while on the standard MIPS64
>> machine I can access, compilation worked either way.
>>
>> Would you mind testing again the new version in the repo?
>>
>
> it works on my qemu based mips. I did give the loongson to anton 2 years ago
> so i have no native loongson to test it with
>
Thanks. That sounds good enough for me, really the main
potential issue I see with this is that it changes the way files
are organized to be more like the VVC decoder.
Since no one seems bothered by that, I'll move on with pushing
this tomorrow.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [FFmpeg-devel] [PATCHSET] AAC decoder refactor
[not found] ` <Nw3fLeH--3-9@lynne.ee-Nw3fPhs----9>
@ 2024-04-23 7:02 ` Lynne
0 siblings, 0 replies; 12+ messages in thread
From: Lynne @ 2024-04-23 7:02 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Apr 22, 2024, 09:20 by dev@lynne.ee:
> Apr 22, 2024, 00:19 by michael@niedermayer.cc:
>
>> On Fri, Apr 12, 2024 at 11:11:53AM +0200, Lynne wrote:
>>
>>> Apr 12, 2024, 00:45 by michael@niedermayer.cc:
>>>
>>> > On Thu, Apr 11, 2024 at 07:42:37AM +0200, Lynne wrote:
>>> >
>>> >> Apr 10, 2024, 23:57 by michael@niedermayer.cc:
>>> >>
>>> >> > On Wed, Apr 10, 2024 at 08:18:11PM +0200, Michael Niedermayer wrote:
>>> >> >
>>> >> >> On Wed, Apr 10, 2024 at 06:48:26PM +0200, Lynne wrote:
>>> >> >> > Apr 8, 2024, 09:36 by dev@lynne.ee:
>>> >> >> >
>>> >> >> > > The following patchset refactors the AAC decoder step by step,
>>> >> >> > > removing all large-scale templating and abstracting away typed
>>> >> >> > > DSP functions from symbol parsing.
>>> >> >> > >
>>> >> >> > > This series saves 110Kib of binary data from libavcodec.so
>>> >> >> > > when compiled with Clang 18 with -O3, after stripping.
>>> >> >> > >
>>> >> >> > > The patchset can also be viewed here:
>>> >> >> > > https://github.com/cyanreg/FFmpeg/tree/aac_cleanup
>>> >> >> > >
>>> >> >> > > Fate passes on each step, and I've been running this patchset for
>>> >> >> > > a week with no issues.
>>> >> >> > >
>>> >> >> > > This also prepares the decoder for USAC support.
>>> >> >> > >
>>> >> >> >
>>> >> >> > I've rebased the linked repo to current git master if anyone
>>> >> >> > wants to test.
>>> >> >>
>>> >> >> thanks, i will try to test it
>>> >> >>
>>> >> >
>>> >> > make fate-source
>>> >> >
>>> >> > TEST source
>>> >> > --- ./tests/ref/fate/source 2024-04-08 18:26:00.670129617 +0200
>>> >> > +++ tests/data/fate/source 2024-04-10 23:56:18.032896853 +0200
>>> >> > @@ -22,6 +22,13 @@
>>> >> > compat/djgpp/math.h
>>> >> > compat/float/float.h
>>> >> > compat/float/limits.h
>>> >> > +libavcodec/aac/aacdec.h
>>> >> > +libavcodec/aac/aacdec_fixed_coupling.h
>>> >> > +libavcodec/aac/aacdec_fixed_dequant.h
>>> >> > +libavcodec/aac/aacdec_fixed_prediction.h
>>> >> > +libavcodec/aac/aacdec_float_coupling.h
>>> >> > +libavcodec/aac/aacdec_float_prediction.h
>>> >> > +libavcodec/aac/aacdec_latm.h
>>> >> > libavcodec/bitstream_template.h
>>> >> > tools/decode_simple.h
>>> >> > Use of av_clip() where av_clip_uintp2() could be used:
>>> >> > Test source failed. Look at tests/data/fate/source.err for details.
>>> >> > tests/Makefile:310: recipe for target 'fate-source' failed
>>> >> > make: *** [fate-source] Error 1
>>> >> >
>>> >>
>>> >> Thanks for testing. Fixed both issues in the repo.
>>> >> Was only testing with fate-aac while developing.
>>> >>
>>> >
>>> > mips:
>>> >
>>> > make -k
>>> > LD ffmpeg_g
>>> > libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
>>> > aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>>> > aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>>> > libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
>>> > sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
>>> > sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
>>> > libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
>>> > aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
>>> > aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
>>> > collect2: error: ld returned 1 exit status
>>> > Makefile:136: recipe for target 'ffmpeg_g' failed
>>> > make: *** [ffmpeg_g] Error 1
>>> > LD ffprobe_g
>>> > libavcodec/libavcodec.a(aacsbr.o): In function `ff_aac_sbr_ctx_alloc_init':
>>> > aacsbr.c:(.text.unlikely+0x1d4): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>>> > aacsbr.c:(.text.unlikely+0x200): undefined reference to `ff_aacsbr_func_ptr_init_mips'
>>> > libavcodec/libavcodec.a(sbrdsp.o): In function `ff_sbrdsp_init':
>>> > sbrdsp.c:(.text.unlikely+0x10): undefined reference to `ff_sbrdsp_init_mips'
>>> > sbrdsp.c:(.text.unlikely+0xb4): undefined reference to `ff_sbrdsp_init_mips'
>>> > libavcodec/libavcodec.a(aacpsdsp_float.o): In function `ff_psdsp_init':
>>> > aacpsdsp_float.c:(.text.unlikely+0x10): undefined reference to `ff_psdsp_init_mips'
>>> > aacpsdsp_float.c:(.text.unlikely+0x6c): undefined reference to `ff_psdsp_init_mips'
>>> > collect2: error: ld returned 1 exit status
>>> > Makefile:136: recipe for target 'ffprobe_g' failed
>>> > make: *** [ffprobe_g] Error 1
>>> > make: Target 'all' not remade because of errors.
>>> >
>>>
>>> Fixed. This should be all.
>>> On the Loongson machine I have access to, I can't compile FFmpeg
>>> due to missing asm/errno.h kernel header, while on the standard MIPS64
>>> machine I can access, compilation worked either way.
>>>
>>> Would you mind testing again the new version in the repo?
>>>
>>
>> it works on my qemu based mips. I did give the loongson to anton 2 years ago
>> so i have no native loongson to test it with
>>
>
> Thanks. That sounds good enough for me, really the main
> potential issue I see with this is that it changes the way files
> are organized to be more like the VVC decoder.
> Since no one seems bothered by that, I'll move on with pushing
> this tomorrow.
>
Patchset pushed. Thanks for the reviews and testing,
and for Andreas for the commits he did.
Final savings:
All measurements done on libavcodec/libavcodec.so.61 with a
default configuration after stripping:
x86-64:
clang-18 with -Os
Before: 10601800
After: 10589512
clang-18 with -O3
Before: 15377624
After: 15340760
gcc-14 with -O3
Before: 15377624
After: 15340760
gcc-14 with -Os
Before: 10601800
After: 10589512
aarch64:
gcc-12 with -O3
Before: 12444560
After: 12399504
clang-17 with -O3
Before: 12436368
After: 12399504
Disabling everything but audio encoders and decoders
seems like it saves more, but to keep it far, this is the
default config with everything enabled.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-04-23 7:02 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-08 7:36 [FFmpeg-devel] [PATCHSET] AAC decoder refactor Lynne
[not found] ` <NuwZLzA--3-9@lynne.ee-NuwcmRV----9>
2024-04-10 16:48 ` Lynne
2024-04-10 18:18 ` Michael Niedermayer
2024-04-10 21:51 ` Michael Niedermayer
2024-04-10 21:56 ` Michael Niedermayer
2024-04-11 5:42 ` Lynne
2024-04-11 22:45 ` Michael Niedermayer
2024-04-12 9:11 ` Lynne
2024-04-21 22:18 ` Michael Niedermayer
2024-04-22 7:20 ` Lynne
[not found] ` <Nw3fLeH--3-9@lynne.ee-Nw3fPhs----9>
2024-04-23 7:02 ` Lynne
[not found] ` <NvGZy8P--7-9@lynne.ee-NvG_0xp----9>
2024-04-21 12:39 ` Lynne
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git