Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/2] aacenc: remove support for AAC Main profile
@ 2025-02-08  4:12 Lynne
  2025-02-08  4:12 ` [FFmpeg-devel] [PATCH 2/2] aacenc: remove support for AAC LTP profile Lynne
  0 siblings, 1 reply; 2+ messages in thread
From: Lynne @ 2025-02-08  4:12 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Lynne

The Main profile of AAC is... terrible.
It enables the use of delta coding across coefficients of two frames
to try to increase compression, and it enabled one more pole for TNS
filters.

What the AAC authors failed to take into account were basic
mathematics, as MDCT leakage (e.g. the spread of each frequency when
represented in a discrete spectrum) is significant in most audio codecs.
This leads to huge variations between each frame, basically rendering
prediction completely pointless.

In fact, enabling AAC-Main prediction does not, in general, even recoup
the metadata losses from signalling the profile and prediction properties
in the first place. So you lose efficiency by using AAC Main.

The rumor is that it was put in the AAC spec for patent reasons, though
patent-wise, it has about as much use as a patent for a bicycle designed
for use by snakes.

The only other thing AAC Main changes is it permits 3-pole TNS filters.
When AAC's bands are absolutely tiny, except for very high frequency bands,
where you're likely to use PNS instead.

Just get rid of it.
---
 doc/encoders.texi        |  15 +-
 libavcodec/Makefile      |   1 -
 libavcodec/aaccoder.c    |  13 --
 libavcodec/aacenc.c      |  44 +----
 libavcodec/aacenc.h      |  11 --
 libavcodec/aacenc_pred.c | 347 ---------------------------------------
 libavcodec/aacenc_pred.h |  47 ------
 libavcodec/aacenc_tns.c  |   2 +-
 libavcodec/aacenctab.h   |   1 -
 9 files changed, 5 insertions(+), 476 deletions(-)
 delete mode 100644 libavcodec/aacenc_pred.c
 delete mode 100644 libavcodec/aacenc_pred.h

diff --git a/doc/encoders.texi b/doc/encoders.texi
index c0795fe5fd..f3fcc1aa60 100644
--- a/doc/encoders.texi
+++ b/doc/encoders.texi
@@ -106,15 +106,8 @@ debugging by setting the option to "disable".
 Enables the use of the long term prediction extension which increases coding
 efficiency in very low bandwidth situations such as encoding of voice or
 solo piano music by extending constant harmonic peaks in bands throughout
-frames. This option is implied by profile:a aac_low and is incompatible with
-aac_pred. Use in conjunction with @option{-ar} to decrease the samplerate.
-
-@item aac_pred
-Enables the use of a more traditional style of prediction where the spectral
-coefficients transmitted are replaced by the difference of the current
-coefficients minus the previous "predicted" coefficients. In theory and sometimes
-in practice this can improve quality for low to mid bitrate audio.
-This option implies the aac_main profile and is incompatible with aac_ltp.
+frames. This option is implied by profile:a aac_low.
+Use in conjunction with @option{-ar} to decrease the samplerate.
 
 @item profile
 Sets the encoding profile, possible values:
@@ -132,10 +125,6 @@ MPEG4 specifications.
 Long term prediction profile, is enabled by and will enable the @option{aac_ltp}
 option. Introduced in MPEG4.
 
-@item aac_main
-Main-type prediction profile, is enabled by and will enable the @option{aac_pred}
-option. Introduced in MPEG2.
-
 @end table
 If this option is unspecified it is set to @samp{aac_low}.
 @end table
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 9630074205..82fc9c9dc6 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -199,7 +199,6 @@ OBJS-$(CONFIG_AAC_ENCODER)             += aacenc.o aaccoder.o aacenctab.o    \
                                           aacenc_is.o \
                                           aacenc_tns.o \
                                           aacenc_ltp.o \
-                                          aacenc_pred.o \
                                           psymodel.o kbdwin.o \
                                           mpeg4audio_sample_rates.o
 OBJS-$(CONFIG_AAC_MEDIACODEC_DECODER)  += mediacodecdec.o
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 4ce54ca886..1999f588e4 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -48,7 +48,6 @@
 #include "aacenc_is.h"
 #include "aacenc_tns.h"
 #include "aacenc_ltp.h"
-#include "aacenc_pred.h"
 
 #include "libavcodec/aaccoder_twoloop.h"
 
@@ -1123,10 +1122,7 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         quantize_and_encode_band,
         ff_aac_encode_tns_info,
         ff_aac_encode_ltp_info,
-        ff_aac_encode_main_pred,
-        ff_aac_adjust_common_pred,
         ff_aac_adjust_common_ltp,
-        ff_aac_apply_main_pred,
         ff_aac_apply_tns,
         ff_aac_update_ltp,
         ff_aac_ltp_insert_new_frame,
@@ -1137,7 +1133,6 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         ff_aac_search_for_ltp,
         search_for_ms,
         ff_aac_search_for_is,
-        ff_aac_search_for_pred,
     },
     [AAC_CODER_TWOLOOP] = {
         search_for_quantizers_twoloop,
@@ -1145,10 +1140,7 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         quantize_and_encode_band,
         ff_aac_encode_tns_info,
         ff_aac_encode_ltp_info,
-        ff_aac_encode_main_pred,
-        ff_aac_adjust_common_pred,
         ff_aac_adjust_common_ltp,
-        ff_aac_apply_main_pred,
         ff_aac_apply_tns,
         ff_aac_update_ltp,
         ff_aac_ltp_insert_new_frame,
@@ -1159,7 +1151,6 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         ff_aac_search_for_ltp,
         search_for_ms,
         ff_aac_search_for_is,
-        ff_aac_search_for_pred,
     },
     [AAC_CODER_FAST] = {
         search_for_quantizers_fast,
@@ -1167,10 +1158,7 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         quantize_and_encode_band,
         ff_aac_encode_tns_info,
         ff_aac_encode_ltp_info,
-        ff_aac_encode_main_pred,
-        ff_aac_adjust_common_pred,
         ff_aac_adjust_common_ltp,
-        ff_aac_apply_main_pred,
         ff_aac_apply_tns,
         ff_aac_update_ltp,
         ff_aac_ltp_insert_new_frame,
@@ -1181,6 +1169,5 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         ff_aac_search_for_ltp,
         search_for_ms,
         ff_aac_search_for_is,
-        ff_aac_search_for_pred,
     },
 };
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index 3ff61f788b..f1bc078cb0 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -502,7 +502,7 @@ static void put_ics_info(AACEncContext *s, IndividualChannelStream *info)
     put_bits(&s->pb, 1, info->use_kb_window[0]);
     if (info->window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
         put_bits(&s->pb, 6, info->max_sfb);
-        put_bits(&s->pb, 1, !!info->predictor_present);
+        put_bits(&s->pb, 1, 0); /* No predictor present */
     } else {
         put_bits(&s->pb, 4, info->max_sfb);
         for (w = 1; w < 8; w++)
@@ -764,8 +764,6 @@ static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s,
     put_bits(&s->pb, 8, sce->sf_idx[0]);
     if (!common_window) {
         put_ics_info(s, &sce->ics);
-        if (s->coder->encode_main_pred)
-            s->coder->encode_main_pred(s, sce);
         if (s->coder->encode_ltp_info)
             s->coder->encode_ltp_info(s, sce, 0);
     }
@@ -976,10 +974,8 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
             for (ch = 0; ch < chans; ch++) {
                 sce = &cpe->ch[ch];
                 coeffs[ch] = sce->coeffs;
-                sce->ics.predictor_present = 0;
                 sce->ics.ltp.present = 0;
                 memset(sce->ics.ltp.used, 0, sizeof(sce->ics.ltp.used));
-                memset(sce->ics.prediction_used, 0, sizeof(sce->ics.prediction_used));
                 memset(&sce->tns, 0, sizeof(TemporalNoiseShaping));
                 for (w = 0; w < 128; w++)
                     if (sce->band_type[w] > RESERVED_BT)
@@ -1032,24 +1028,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 if (cpe->is_mode) is_mode = 1;
                 apply_intensity_stereo(cpe);
             }
-            if (s->options.pred) { /* Prediction */
-                for (ch = 0; ch < chans; ch++) {
-                    sce = &cpe->ch[ch];
-                    s->cur_channel = start_ch + ch;
-                    if (s->options.pred && s->coder->search_for_pred)
-                        s->coder->search_for_pred(s, sce);
-                    if (cpe->ch[ch].ics.predictor_present) pred_mode = 1;
-                }
-                if (s->coder->adjust_common_pred)
-                    s->coder->adjust_common_pred(s, cpe);
-                for (ch = 0; ch < chans; ch++) {
-                    sce = &cpe->ch[ch];
-                    s->cur_channel = start_ch + ch;
-                    if (s->options.pred && s->coder->apply_main_pred)
-                        s->coder->apply_main_pred(s, sce);
-                }
-                s->cur_channel = start_ch;
-            }
             if (s->options.mid_side) { /* Mid/Side stereo */
                 if (s->options.mid_side == -1 && s->coder->search_for_ms)
                     s->coder->search_for_ms(s, cpe);
@@ -1074,8 +1052,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 put_bits(&s->pb, 1, cpe->common_window);
                 if (cpe->common_window) {
                     put_ics_info(s, &cpe->ch[0].ics);
-                    if (s->coder->encode_main_pred)
-                        s->coder->encode_main_pred(s, &cpe->ch[0]);
                     if (s->coder->encode_ltp_info)
                         s->coder->encode_ltp_info(s, &cpe->ch[0], 1);
                     encode_ms_info(&s->pb, cpe);
@@ -1310,10 +1286,9 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
     for (i = 0; i < FF_ARRAY_ELEMS(aacenc_profiles); i++)
         if (avctx->profile == aacenc_profiles[i])
             break;
+    ERROR_IF(i == FF_ARRAY_ELEMS(aacenc_profiles), "Profile not supported!\n");
     if (avctx->profile == AV_PROFILE_MPEG2_AAC_LOW) {
         avctx->profile = AV_PROFILE_AAC_LOW;
-        ERROR_IF(s->options.pred,
-                 "Main prediction unavailable in the \"mpeg2_aac_low\" profile\n");
         ERROR_IF(s->options.ltp,
                  "LTP prediction unavailable in the \"mpeg2_aac_low\" profile\n");
         WARN_IF(s->options.pns,
@@ -1321,24 +1296,10 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
         s->options.pns = 0;
     } else if (avctx->profile == AV_PROFILE_AAC_LTP) {
         s->options.ltp = 1;
-        ERROR_IF(s->options.pred,
-                 "Main prediction unavailable in the \"aac_ltp\" profile\n");
-    } else if (avctx->profile == AV_PROFILE_AAC_MAIN) {
-        s->options.pred = 1;
-        ERROR_IF(s->options.ltp,
-                 "LTP prediction unavailable in the \"aac_main\" profile\n");
     } else if (s->options.ltp) {
         avctx->profile = AV_PROFILE_AAC_LTP;
         WARN_IF(1,
                 "Chainging profile to \"aac_ltp\"\n");
-        ERROR_IF(s->options.pred,
-                 "Main prediction unavailable in the \"aac_ltp\" profile\n");
-    } else if (s->options.pred) {
-        avctx->profile = AV_PROFILE_AAC_MAIN;
-        WARN_IF(1,
-                "Chainging profile to \"aac_main\"\n");
-        ERROR_IF(s->options.ltp,
-                 "LTP prediction unavailable in the \"aac_main\" profile\n");
     }
     s->profile = avctx->profile;
 
@@ -1400,7 +1361,6 @@ static const AVOption aacenc_options[] = {
     {"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
     {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
     {"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
-    {"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
     {"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
     FF_AAC_PROFILE_OPTS
     {NULL}
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index ae15f91e06..8389699141 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -69,7 +69,6 @@ typedef struct AACEncOptions {
     int tns;
     int ltp;
     int pce;
-    int pred;
     int mid_side;
     int intensity_stereo;
 } AACEncOptions;
@@ -99,11 +98,6 @@ typedef struct IndividualChannelStream {
     int num_swb;                ///< number of scalefactor window bands
     int num_windows;
     int tns_max_bands;
-    int predictor_present;
-    int predictor_initialized;
-    int predictor_reset_group;
-    int predictor_reset_count[31];  ///< used to count prediction resets
-    uint8_t prediction_used[41];
     uint8_t window_clipping[8]; ///< set if a certain window is near clipping
     float clip_avoidance_factor; ///< set if any window is near clipping to the necessary atennuation factor to avoid it
 } IndividualChannelStream;
@@ -140,7 +134,6 @@ typedef struct SingleChannelElement {
     DECLARE_ALIGNED(32, float, ret_buf)[2048];      ///< PCM output buffer
     DECLARE_ALIGNED(16, float, ltp_state)[3072];    ///< time signal for LTP
     DECLARE_ALIGNED(32, float, lcoeffs)[1024];      ///< MDCT of LTP coefficients
-    DECLARE_ALIGNED(32, float, prcoeffs)[1024];     ///< Main prediction coefs
     PredictorState predictor_state[MAX_PREDICTORS];
 } SingleChannelElement;
 
@@ -169,10 +162,7 @@ typedef struct AACCoefficientsEncoder {
                                      int scale_idx, int cb, const float lambda, int rtz);
     void (*encode_tns_info)(struct AACEncContext *s, SingleChannelElement *sce);
     void (*encode_ltp_info)(struct AACEncContext *s, SingleChannelElement *sce, int common_window);
-    void (*encode_main_pred)(struct AACEncContext *s, SingleChannelElement *sce);
-    void (*adjust_common_pred)(struct AACEncContext *s, ChannelElement *cpe);
     void (*adjust_common_ltp)(struct AACEncContext *s, ChannelElement *cpe);
-    void (*apply_main_pred)(struct AACEncContext *s, SingleChannelElement *sce);
     void (*apply_tns_filt)(struct AACEncContext *s, SingleChannelElement *sce);
     void (*update_ltp)(struct AACEncContext *s, SingleChannelElement *sce);
     void (*ltp_insert_new_frame)(struct AACEncContext *s);
@@ -183,7 +173,6 @@ typedef struct AACCoefficientsEncoder {
     void (*search_for_ltp)(struct AACEncContext *s, SingleChannelElement *sce, int common_window);
     void (*search_for_ms)(struct AACEncContext *s, ChannelElement *cpe);
     void (*search_for_is)(struct AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
-    void (*search_for_pred)(struct AACEncContext *s, SingleChannelElement *sce);
 } AACCoefficientsEncoder;
 
 extern const AACCoefficientsEncoder ff_aac_coders[];
diff --git a/libavcodec/aacenc_pred.c b/libavcodec/aacenc_pred.c
deleted file mode 100644
index a486c44d42..0000000000
--- a/libavcodec/aacenc_pred.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * AAC encoder main-type prediction
- * Copyright (C) 2015 Rostislav Pehlivanov
- *
- * 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 encoder main-type prediction
- * @author Rostislav Pehlivanov ( atomnuker gmail com )
- */
-
-#include "aactab.h"
-#include "aacenc_pred.h"
-#include "aacenc_utils.h"
-#include "aacenc_is.h"            /* <- Needed for common window distortions */
-#include "aacenc_quantization.h"
-
-#define RESTORE_PRED(sce, sfb) \
-        if (sce->ics.prediction_used[sfb]) {\
-            sce->ics.prediction_used[sfb] = 0;\
-            sce->band_type[sfb] = sce->band_alt[sfb];\
-        }
-
-static inline float flt16_round(float pf)
-{
-    union av_intfloat32 tmp;
-    tmp.f = pf;
-    tmp.i = (tmp.i + 0x00008000U) & 0xFFFF0000U;
-    return tmp.f;
-}
-
-static 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 inline float flt16_trunc(float pf)
-{
-    union av_intfloat32 pun;
-    pun.f = pf;
-    pun.i &= 0xFFFF0000U;
-    return pun.f;
-}
-
-static inline void predict(PredictorState *ps, float *coef, float *rcoef, int set)
-{
-    float k2;
-    const float a     = 0.953125; // 61.0 / 64
-    const float alpha = 0.90625;  // 29.0 / 32
-    const float   k1 = ps->k1;
-    const float   r0 = ps->r0,     r1 = ps->r1;
-    const float cor0 = ps->cor0, cor1 = ps->cor1;
-    const float var0 = ps->var0, var1 = ps->var1;
-    const float e0 = *coef - ps->x_est;
-    const float e1 = e0 - k1 * r0;
-
-    if (set)
-        *coef = e0;
-
-    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);
-
-    /* Prediction for next frame */
-    ps->k1   = ps->var0 > 1 ? ps->cor0 * flt16_even(a / ps->var0) : 0;
-    k2       = ps->var1 > 1 ? ps->cor1 * flt16_even(a / ps->var1) : 0;
-    *rcoef   = ps->x_est = flt16_round(ps->k1*ps->r0 + k2*ps->r1);
-}
-
-static inline void reset_predict_state(PredictorState *ps)
-{
-    ps->r0    = 0.0f;
-    ps->r1    = 0.0f;
-    ps->k1    = 0.0f;
-    ps->cor0  = 0.0f;
-    ps->cor1  = 0.0f;
-    ps->var0  = 1.0f;
-    ps->var1  = 1.0f;
-    ps->x_est = 0.0f;
-}
-
-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(SingleChannelElement *sce, int group_num)
-{
-    int i;
-    PredictorState *ps = sce->predictor_state;
-    for (i = group_num - 1; i < MAX_PREDICTORS; i += 30)
-        reset_predict_state(&ps[i]);
-}
-
-void ff_aac_apply_main_pred(AACEncContext *s, SingleChannelElement *sce)
-{
-    int sfb, k;
-    const int pmax = FFMIN(sce->ics.max_sfb, ff_aac_pred_sfb_max[s->samplerate_index]);
-
-    if (sce->ics.window_sequence[0] != EIGHT_SHORT_SEQUENCE) {
-        for (sfb = 0; sfb < pmax; sfb++) {
-            for (k = sce->ics.swb_offset[sfb]; k < sce->ics.swb_offset[sfb + 1]; k++) {
-                predict(&sce->predictor_state[k], &sce->coeffs[k], &sce->prcoeffs[k],
-                        sce->ics.predictor_present && sce->ics.prediction_used[sfb]);
-            }
-        }
-        if (sce->ics.predictor_reset_group) {
-            reset_predictor_group(sce, sce->ics.predictor_reset_group);
-        }
-    } else {
-        reset_all_predictors(sce->predictor_state);
-    }
-}
-
-/* If inc = 0 you can check if this returns 0 to see if you can reset freely */
-static inline int update_counters(IndividualChannelStream *ics, int inc)
-{
-    int i;
-    for (i = 1; i < 31; i++) {
-        ics->predictor_reset_count[i] += inc;
-        if (ics->predictor_reset_count[i] > PRED_RESET_FRAME_MIN)
-            return i; /* Reset this immediately */
-    }
-    return 0;
-}
-
-void ff_aac_adjust_common_pred(AACEncContext *s, ChannelElement *cpe)
-{
-    int start, w, w2, g, i, count = 0;
-    SingleChannelElement *sce0 = &cpe->ch[0];
-    SingleChannelElement *sce1 = &cpe->ch[1];
-    const int pmax0 = FFMIN(sce0->ics.max_sfb, ff_aac_pred_sfb_max[s->samplerate_index]);
-    const int pmax1 = FFMIN(sce1->ics.max_sfb, ff_aac_pred_sfb_max[s->samplerate_index]);
-    const int pmax  = FFMIN(pmax0, pmax1);
-
-    if (!cpe->common_window ||
-        sce0->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE ||
-        sce1->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE)
-        return;
-
-    for (w = 0; w < sce0->ics.num_windows; w += sce0->ics.group_len[w]) {
-        start = 0;
-        for (g = 0; g < sce0->ics.num_swb; g++) {
-            int sfb = w*16+g;
-            int sum = sce0->ics.prediction_used[sfb] + sce1->ics.prediction_used[sfb];
-            float ener0 = 0.0f, ener1 = 0.0f, ener01 = 0.0f;
-            struct AACISError ph_err1, ph_err2, *erf;
-            if (sfb < PRED_SFB_START || sfb > pmax || sum != 2) {
-                RESTORE_PRED(sce0, sfb);
-                RESTORE_PRED(sce1, sfb);
-                start += sce0->ics.swb_sizes[g];
-                continue;
-            }
-            for (w2 = 0; w2 < sce0->ics.group_len[w]; w2++) {
-                for (i = 0; i < sce0->ics.swb_sizes[g]; i++) {
-                    float coef0 = sce0->pcoeffs[start+(w+w2)*128+i];
-                    float coef1 = sce1->pcoeffs[start+(w+w2)*128+i];
-                    ener0  += coef0*coef0;
-                    ener1  += coef1*coef1;
-                    ener01 += (coef0 + coef1)*(coef0 + coef1);
-                }
-            }
-            ph_err1 = ff_aac_is_encoding_err(s, cpe, start, w, g,
-                                             ener0, ener1, ener01, 1, -1);
-            ph_err2 = ff_aac_is_encoding_err(s, cpe, start, w, g,
-                                             ener0, ener1, ener01, 1, +1);
-            erf = ph_err1.error < ph_err2.error ? &ph_err1 : &ph_err2;
-            if (erf->pass) {
-                sce0->ics.prediction_used[sfb] = 1;
-                sce1->ics.prediction_used[sfb] = 1;
-                count++;
-            } else {
-                RESTORE_PRED(sce0, sfb);
-                RESTORE_PRED(sce1, sfb);
-            }
-            start += sce0->ics.swb_sizes[g];
-        }
-    }
-
-    sce1->ics.predictor_present = sce0->ics.predictor_present = !!count;
-}
-
-static void update_pred_resets(SingleChannelElement *sce)
-{
-    int i, max_group_id_c, max_frame = 0;
-    float avg_frame = 0.0f;
-    IndividualChannelStream *ics = &sce->ics;
-
-    /* Update the counters and immediately update any frame behind schedule */
-    if ((ics->predictor_reset_group = update_counters(&sce->ics, 1)))
-        return;
-
-    for (i = 1; i < 31; i++) {
-        /* Count-based */
-        if (ics->predictor_reset_count[i] > max_frame) {
-            max_group_id_c = i;
-            max_frame = ics->predictor_reset_count[i];
-        }
-        avg_frame = (ics->predictor_reset_count[i] + avg_frame)/2;
-    }
-
-    if (max_frame > PRED_RESET_MIN) {
-        ics->predictor_reset_group = max_group_id_c;
-    } else {
-        ics->predictor_reset_group = 0;
-    }
-}
-
-void ff_aac_search_for_pred(AACEncContext *s, SingleChannelElement *sce)
-{
-    int sfb, i, count = 0, cost_coeffs = 0, cost_pred = 0;
-    const int pmax = FFMIN(sce->ics.max_sfb, ff_aac_pred_sfb_max[s->samplerate_index]);
-    float *O34  = &s->scoefs[128*0], *P34 = &s->scoefs[128*1];
-    float *SENT = &s->scoefs[128*2], *S34 = &s->scoefs[128*3];
-    float *QERR = &s->scoefs[128*4];
-
-    if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
-        sce->ics.predictor_present = 0;
-        return;
-    }
-
-    if (!sce->ics.predictor_initialized) {
-        reset_all_predictors(sce->predictor_state);
-        sce->ics.predictor_initialized = 1;
-        memcpy(sce->prcoeffs, sce->coeffs, 1024*sizeof(float));
-        for (i = 1; i < 31; i++)
-            sce->ics.predictor_reset_count[i] = i;
-    }
-
-    update_pred_resets(sce);
-    memcpy(sce->band_alt, sce->band_type, sizeof(sce->band_type));
-
-    for (sfb = PRED_SFB_START; sfb < pmax; sfb++) {
-        int cost1, cost2, cb_p;
-        float dist1, dist2, dist_spec_err = 0.0f;
-        const int cb_n = sce->zeroes[sfb] ? 0 : sce->band_type[sfb];
-        const int cb_min = sce->zeroes[sfb] ? 0 : 1;
-        const int cb_max = sce->zeroes[sfb] ? 0 : RESERVED_BT;
-        const int start_coef = sce->ics.swb_offset[sfb];
-        const int num_coeffs = sce->ics.swb_offset[sfb + 1] - start_coef;
-        const FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[sfb];
-
-        if (start_coef + num_coeffs > MAX_PREDICTORS ||
-            (s->cur_channel && sce->band_type[sfb] >= INTENSITY_BT2) ||
-            sce->band_type[sfb] == NOISE_BT)
-            continue;
-
-        /* Normal coefficients */
-        s->aacdsp.abs_pow34(O34, &sce->coeffs[start_coef], num_coeffs);
-        dist1 = ff_quantize_and_encode_band_cost(s, NULL, &sce->coeffs[start_coef], NULL,
-                                                 O34, num_coeffs, sce->sf_idx[sfb],
-                                                 cb_n, s->lambda / band->threshold, INFINITY, &cost1, NULL);
-        cost_coeffs += cost1;
-
-        /* Encoded coefficients - needed for #bits, band type and quant. error */
-        for (i = 0; i < num_coeffs; i++)
-            SENT[i] = sce->coeffs[start_coef + i] - sce->prcoeffs[start_coef + i];
-        s->aacdsp.abs_pow34(S34, SENT, num_coeffs);
-        if (cb_n < RESERVED_BT)
-            cb_p = av_clip(find_min_book(find_max_val(1, num_coeffs, S34), sce->sf_idx[sfb]), cb_min, cb_max);
-        else
-            cb_p = cb_n;
-        ff_quantize_and_encode_band_cost(s, NULL, SENT, QERR, S34, num_coeffs,
-                                         sce->sf_idx[sfb], cb_p, s->lambda / band->threshold, INFINITY,
-                                         &cost2, NULL);
-
-        /* Reconstructed coefficients - needed for distortion measurements */
-        for (i = 0; i < num_coeffs; i++)
-            sce->prcoeffs[start_coef + i] += QERR[i] != 0.0f ? (sce->prcoeffs[start_coef + i] - QERR[i]) : 0.0f;
-        s->aacdsp.abs_pow34(P34, &sce->prcoeffs[start_coef], num_coeffs);
-        if (cb_n < RESERVED_BT)
-            cb_p = av_clip(find_min_book(find_max_val(1, num_coeffs, P34), sce->sf_idx[sfb]), cb_min, cb_max);
-        else
-            cb_p = cb_n;
-        dist2 = ff_quantize_and_encode_band_cost(s, NULL, &sce->prcoeffs[start_coef], NULL,
-                                                 P34, num_coeffs, sce->sf_idx[sfb],
-                                                 cb_p, s->lambda / band->threshold, INFINITY, NULL, NULL);
-        for (i = 0; i < num_coeffs; i++)
-            dist_spec_err += (O34[i] - P34[i])*(O34[i] - P34[i]);
-        dist_spec_err *= s->lambda / band->threshold;
-        dist2 += dist_spec_err;
-
-        if (dist2 <= dist1 && cb_p <= cb_n) {
-            cost_pred += cost2;
-            sce->ics.prediction_used[sfb] = 1;
-            sce->band_alt[sfb]  = cb_n;
-            sce->band_type[sfb] = cb_p;
-            count++;
-        } else {
-            cost_pred += cost1;
-            sce->band_alt[sfb] = cb_p;
-        }
-    }
-
-    if (count && cost_coeffs < cost_pred) {
-        count = 0;
-        for (sfb = PRED_SFB_START; sfb < pmax; sfb++)
-            RESTORE_PRED(sce, sfb);
-        memset(&sce->ics.prediction_used, 0, sizeof(sce->ics.prediction_used));
-    }
-
-    sce->ics.predictor_present = !!count;
-}
-
-/**
- * Encoder predictors data.
- */
-void ff_aac_encode_main_pred(AACEncContext *s, SingleChannelElement *sce)
-{
-    int sfb;
-    IndividualChannelStream *ics = &sce->ics;
-    const int pmax = FFMIN(ics->max_sfb, ff_aac_pred_sfb_max[s->samplerate_index]);
-
-    if (s->profile != AV_PROFILE_AAC_MAIN ||
-        !ics->predictor_present)
-        return;
-
-    put_bits(&s->pb, 1, !!ics->predictor_reset_group);
-    if (ics->predictor_reset_group)
-        put_bits(&s->pb, 5, ics->predictor_reset_group);
-    for (sfb = 0; sfb < pmax; sfb++)
-        put_bits(&s->pb, 1, ics->prediction_used[sfb]);
-}
diff --git a/libavcodec/aacenc_pred.h b/libavcodec/aacenc_pred.h
deleted file mode 100644
index aa305f45a5..0000000000
--- a/libavcodec/aacenc_pred.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * AAC encoder main-type prediction
- * Copyright (C) 2015 Rostislav Pehlivanov
- *
- * 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 encoder main-type prediction
- * @author Rostislav Pehlivanov ( atomnuker gmail com )
- */
-
-#ifndef AVCODEC_AACENC_PRED_H
-#define AVCODEC_AACENC_PRED_H
-
-#include "aacenc.h"
-
-/* Every predictor group needs to get reset at least once in this many frames */
-#define PRED_RESET_FRAME_MIN 240
-
-/* Any frame with less than this amount of frames since last reset is ok */
-#define PRED_RESET_MIN 64
-
-/* Raise to filter any low frequency artifacts due to prediction */
-#define PRED_SFB_START 10
-
-void ff_aac_apply_main_pred(AACEncContext *s, SingleChannelElement *sce);
-void ff_aac_adjust_common_pred(AACEncContext *s, ChannelElement *cpe);
-void ff_aac_search_for_pred(AACEncContext *s, SingleChannelElement *sce);
-void ff_aac_encode_main_pred(AACEncContext *s, SingleChannelElement *sce);
-
-#endif /* AVCODEC_AACENC_PRED_H */
diff --git a/libavcodec/aacenc_tns.c b/libavcodec/aacenc_tns.c
index fa3cd2af39..7884c035cb 100644
--- a/libavcodec/aacenc_tns.c
+++ b/libavcodec/aacenc_tns.c
@@ -168,7 +168,7 @@ void ff_aac_search_for_tns(AACEncContext *s, SingleChannelElement *sce)
     const int c_bits = is8 ? TNS_Q_BITS_IS8 == 4 : TNS_Q_BITS == 4;
     const int sfb_start = av_clip(tns_min_sfb[is8][s->samplerate_index], 0, mmm);
     const int sfb_end   = av_clip(sce->ics.num_swb, 0, mmm);
-    const int order = is8 ? 7 : s->profile == AV_PROFILE_AAC_LOW ? 12 : TNS_MAX_ORDER;
+    const int order = is8 ? 7 : 12;
     const int slant = sce->ics.window_sequence[0] == LONG_STOP_SEQUENCE  ? 1 :
                       sce->ics.window_sequence[0] == LONG_START_SEQUENCE ? 0 : 2;
     const int sfb_len = sfb_end - sfb_start;
diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h
index f2d6f597bc..78e424a675 100644
--- a/libavcodec/aacenctab.h
+++ b/libavcodec/aacenctab.h
@@ -125,7 +125,6 @@ static const unsigned char aac_maxval_cb[] = {
 };
 
 static const int aacenc_profiles[] = {
-    AV_PROFILE_AAC_MAIN,
     AV_PROFILE_AAC_LOW,
     AV_PROFILE_AAC_LTP,
     AV_PROFILE_MPEG2_AAC_LOW,
-- 
2.47.2
_______________________________________________
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] 2+ messages in thread

* [FFmpeg-devel] [PATCH 2/2] aacenc: remove support for AAC LTP profile
  2025-02-08  4:12 [FFmpeg-devel] [PATCH 1/2] aacenc: remove support for AAC Main profile Lynne
@ 2025-02-08  4:12 ` Lynne
  0 siblings, 0 replies; 2+ messages in thread
From: Lynne @ 2025-02-08  4:12 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Lynne

The LTP profile of AAC is... terrible.
It was an early 90's attempt at bridging the gap between speech
codecs and general purpose codecs. It did so by trying to exploit the fact
that most speech patterns are regular.

Unfortunately, it went about it the same way as AAC Main, by taking
the previous frame's samples, modifying them through an LPC filter,
transforming them back using a forward MDCT, putting the output
coefficients back into the current frame, and using delta coding.
But once again, they ignored basic mathematics and MDCT leakage.
Thankfully, because AAC LTP is meant to operate at very low bitrates,
the extreme quantization results in most leakage being irrelevant.

Unfortunately, the result is that the output sounds pretty much
terrible regardless of whether LTP is enabled or not.

This was the first attempt at trying to couple speech coding into AAC.
No, the second attempt did not succeed either.
Nnnneither did the third. Or fourth.

For the fifth one, they literally just jammed a speech codec into AAC
with USAC once they saw Opus do it.

Just drop support for encoding AAC LTP. It was always experimental
to begin with.
---
 libavcodec/Makefile     |   1 -
 libavcodec/aaccoder.c   |  16 ---
 libavcodec/aacenc.c     |  41 +------
 libavcodec/aacenc.h     |  20 ----
 libavcodec/aacenc_ltp.c | 236 ----------------------------------------
 libavcodec/aacenc_ltp.h |  41 -------
 libavcodec/aacenctab.h  |   1 -
 7 files changed, 1 insertion(+), 355 deletions(-)
 delete mode 100644 libavcodec/aacenc_ltp.c
 delete mode 100644 libavcodec/aacenc_ltp.h

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 82fc9c9dc6..499f826635 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -198,7 +198,6 @@ OBJS-$(CONFIG_AAC_ENCODER)             += aacenc.o aaccoder.o aacenctab.o    \
                                           aacpsy.o aactab.o      \
                                           aacenc_is.o \
                                           aacenc_tns.o \
-                                          aacenc_ltp.o \
                                           psymodel.o kbdwin.o \
                                           mpeg4audio_sample_rates.o
 OBJS-$(CONFIG_AAC_MEDIACODEC_DECODER)  += mediacodecdec.o
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 1999f588e4..478eda86f3 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -47,7 +47,6 @@
 
 #include "aacenc_is.h"
 #include "aacenc_tns.h"
-#include "aacenc_ltp.h"
 
 #include "libavcodec/aaccoder_twoloop.h"
 
@@ -1121,16 +1120,11 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         encode_window_bands_info,
         quantize_and_encode_band,
         ff_aac_encode_tns_info,
-        ff_aac_encode_ltp_info,
-        ff_aac_adjust_common_ltp,
         ff_aac_apply_tns,
-        ff_aac_update_ltp,
-        ff_aac_ltp_insert_new_frame,
         set_special_band_scalefactors,
         search_for_pns,
         mark_pns,
         ff_aac_search_for_tns,
-        ff_aac_search_for_ltp,
         search_for_ms,
         ff_aac_search_for_is,
     },
@@ -1139,16 +1133,11 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         codebook_trellis_rate,
         quantize_and_encode_band,
         ff_aac_encode_tns_info,
-        ff_aac_encode_ltp_info,
-        ff_aac_adjust_common_ltp,
         ff_aac_apply_tns,
-        ff_aac_update_ltp,
-        ff_aac_ltp_insert_new_frame,
         set_special_band_scalefactors,
         search_for_pns,
         mark_pns,
         ff_aac_search_for_tns,
-        ff_aac_search_for_ltp,
         search_for_ms,
         ff_aac_search_for_is,
     },
@@ -1157,16 +1146,11 @@ const AACCoefficientsEncoder ff_aac_coders[AAC_CODER_NB] = {
         codebook_trellis_rate,
         quantize_and_encode_band,
         ff_aac_encode_tns_info,
-        ff_aac_encode_ltp_info,
-        ff_aac_adjust_common_ltp,
         ff_aac_apply_tns,
-        ff_aac_update_ltp,
-        ff_aac_ltp_insert_new_frame,
         set_special_band_scalefactors,
         search_for_pns,
         mark_pns,
         ff_aac_search_for_tns,
-        ff_aac_search_for_ltp,
         search_for_ms,
         ff_aac_search_for_is,
     },
diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c
index f1bc078cb0..5ed54dbcb3 100644
--- a/libavcodec/aacenc.c
+++ b/libavcodec/aacenc.c
@@ -762,11 +762,8 @@ static int encode_individual_channel(AVCodecContext *avctx, AACEncContext *s,
                                      int common_window)
 {
     put_bits(&s->pb, 8, sce->sf_idx[0]);
-    if (!common_window) {
+    if (!common_window)
         put_ics_info(s, &sce->ics);
-        if (s->coder->encode_ltp_info)
-            s->coder->encode_ltp_info(s, sce, 0);
-    }
     encode_band_info(s, sce);
     encode_scale_factors(avctx, s, sce);
     encode_pulses(s, &sce->pulse);
@@ -933,12 +930,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 
             apply_window_and_mdct(s, sce, overlap);
 
-            if (s->options.ltp && s->coder->update_ltp) {
-                s->coder->update_ltp(s, sce);
-                apply_window[sce->ics.window_sequence[0]](s->fdsp, sce, &sce->ltp_state[0]);
-                s->mdct1024_fn(s->mdct1024, sce->lcoeffs, sce->ret_buf, sizeof(float));
-            }
-
             for (k = 0; k < 1024; k++) {
                 if (!(fabs(cpe->ch[ch].coeffs[k]) < 1E16)) { // Ensure headroom for energy calculation
                     av_log(avctx, AV_LOG_ERROR, "Input contains (near) NaN/+-Inf\n");
@@ -974,8 +965,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
             for (ch = 0; ch < chans; ch++) {
                 sce = &cpe->ch[ch];
                 coeffs[ch] = sce->coeffs;
-                sce->ics.ltp.present = 0;
-                memset(sce->ics.ltp.used, 0, sizeof(sce->ics.ltp.used));
                 memset(&sce->tns, 0, sizeof(TemporalNoiseShaping));
                 for (w = 0; w < 128; w++)
                     if (sce->band_type[w] > RESERVED_BT)
@@ -1036,24 +1025,10 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
                 apply_mid_side_stereo(cpe);
             }
             adjust_frame_information(cpe, chans);
-            if (s->options.ltp) { /* LTP */
-                for (ch = 0; ch < chans; ch++) {
-                    sce = &cpe->ch[ch];
-                    s->cur_channel = start_ch + ch;
-                    if (s->coder->search_for_ltp)
-                        s->coder->search_for_ltp(s, sce, cpe->common_window);
-                    if (sce->ics.ltp.present) pred_mode = 1;
-                }
-                s->cur_channel = start_ch;
-                if (s->coder->adjust_common_ltp)
-                    s->coder->adjust_common_ltp(s, cpe);
-            }
             if (chans == 2) {
                 put_bits(&s->pb, 1, cpe->common_window);
                 if (cpe->common_window) {
                     put_ics_info(s, &cpe->ch[0].ics);
-                    if (s->coder->encode_ltp_info)
-                        s->coder->encode_ltp_info(s, &cpe->ch[0], 1);
                     encode_ms_info(&s->pb, cpe);
                     if (cpe->ms_mode) ms_mode = 1;
                 }
@@ -1138,9 +1113,6 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
         }
     } while (1);
 
-    if (s->options.ltp && s->coder->ltp_insert_new_frame)
-        s->coder->ltp_insert_new_frame(s);
-
     put_bits(&s->pb, 3, TYPE_END);
     flush_put_bits(&s->pb);
 
@@ -1289,17 +1261,9 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
     ERROR_IF(i == FF_ARRAY_ELEMS(aacenc_profiles), "Profile not supported!\n");
     if (avctx->profile == AV_PROFILE_MPEG2_AAC_LOW) {
         avctx->profile = AV_PROFILE_AAC_LOW;
-        ERROR_IF(s->options.ltp,
-                 "LTP prediction unavailable in the \"mpeg2_aac_low\" profile\n");
         WARN_IF(s->options.pns,
                 "PNS unavailable in the \"mpeg2_aac_low\" profile, turning off\n");
         s->options.pns = 0;
-    } else if (avctx->profile == AV_PROFILE_AAC_LTP) {
-        s->options.ltp = 1;
-    } else if (s->options.ltp) {
-        avctx->profile = AV_PROFILE_AAC_LTP;
-        WARN_IF(1,
-                "Chainging profile to \"aac_ltp\"\n");
     }
     s->profile = avctx->profile;
 
@@ -1311,8 +1275,6 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
         s->options.intensity_stereo = 0;
         s->options.pns = 0;
     }
-    ERROR_IF(s->options.ltp && avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL,
-             "The LPT profile requires experimental compliance, add -strict -2 to enable!\n");
 
     /* M/S introduces horrible artifacts with multichannel files, this is temporary */
     if (s->channels > 3)
@@ -1360,7 +1322,6 @@ static const AVOption aacenc_options[] = {
     {"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
     {"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
     {"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
-    {"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
     {"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
     FF_AAC_PROFILE_OPTS
     {NULL}
diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h
index 8389699141..360402a06e 100644
--- a/libavcodec/aacenc.h
+++ b/libavcodec/aacenc.h
@@ -67,23 +67,11 @@ typedef struct AACEncOptions {
     int coder;
     int pns;
     int tns;
-    int ltp;
     int pce;
     int mid_side;
     int intensity_stereo;
 } AACEncOptions;
 
-/**
- * Long Term Prediction
- */
-typedef struct LongTermPrediction {
-    int8_t present;
-    int16_t lag;
-    int coef_idx;
-    float coef;
-    int8_t used[MAX_LTP_LONG_SFB];
-} LongTermPrediction;
-
 /**
  * Individual Channel Stream
  */
@@ -92,7 +80,6 @@ typedef struct IndividualChannelStream {
     enum WindowSequence window_sequence[2];
     uint8_t use_kb_window[2];   ///< If set, use Kaiser-Bessel window, otherwise use a sine window.
     uint8_t group_len[8];
-    LongTermPrediction ltp;
     const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
     const uint8_t *swb_sizes;   ///< table of scalefactor band sizes for a particular window
     int num_swb;                ///< number of scalefactor window bands
@@ -132,8 +119,6 @@ typedef struct SingleChannelElement {
     DECLARE_ALIGNED(32, float, pcoeffs)[1024];      ///< coefficients for IMDCT, pristine
     DECLARE_ALIGNED(32, float, coeffs)[1024];       ///< coefficients for IMDCT, maybe processed
     DECLARE_ALIGNED(32, float, ret_buf)[2048];      ///< PCM output buffer
-    DECLARE_ALIGNED(16, float, ltp_state)[3072];    ///< time signal for LTP
-    DECLARE_ALIGNED(32, float, lcoeffs)[1024];      ///< MDCT of LTP coefficients
     PredictorState predictor_state[MAX_PREDICTORS];
 } SingleChannelElement;
 
@@ -161,16 +146,11 @@ typedef struct AACCoefficientsEncoder {
     void (*quantize_and_encode_band)(struct AACEncContext *s, PutBitContext *pb, const float *in, float *out, int size,
                                      int scale_idx, int cb, const float lambda, int rtz);
     void (*encode_tns_info)(struct AACEncContext *s, SingleChannelElement *sce);
-    void (*encode_ltp_info)(struct AACEncContext *s, SingleChannelElement *sce, int common_window);
-    void (*adjust_common_ltp)(struct AACEncContext *s, ChannelElement *cpe);
     void (*apply_tns_filt)(struct AACEncContext *s, SingleChannelElement *sce);
-    void (*update_ltp)(struct AACEncContext *s, SingleChannelElement *sce);
-    void (*ltp_insert_new_frame)(struct AACEncContext *s);
     void (*set_special_band_scalefactors)(struct AACEncContext *s, SingleChannelElement *sce);
     void (*search_for_pns)(struct AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce);
     void (*mark_pns)(struct AACEncContext *s, AVCodecContext *avctx, SingleChannelElement *sce);
     void (*search_for_tns)(struct AACEncContext *s, SingleChannelElement *sce);
-    void (*search_for_ltp)(struct AACEncContext *s, SingleChannelElement *sce, int common_window);
     void (*search_for_ms)(struct AACEncContext *s, ChannelElement *cpe);
     void (*search_for_is)(struct AACEncContext *s, AVCodecContext *avctx, ChannelElement *cpe);
 } AACCoefficientsEncoder;
diff --git a/libavcodec/aacenc_ltp.c b/libavcodec/aacenc_ltp.c
deleted file mode 100644
index 58f7921074..0000000000
--- a/libavcodec/aacenc_ltp.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * AAC encoder long term prediction extension
- * Copyright (C) 2015 Rostislav Pehlivanov
- *
- * 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 encoder long term prediction extension
- * @author Rostislav Pehlivanov ( atomnuker gmail com )
- */
-
-#include "aacenc_ltp.h"
-#include "aacenc_quantization.h"
-#include "aacenc_utils.h"
-
-/**
- * Encode LTP data.
- */
-void ff_aac_encode_ltp_info(AACEncContext *s, SingleChannelElement *sce,
-                            int common_window)
-{
-    int i;
-    IndividualChannelStream *ics = &sce->ics;
-    if (s->profile != AV_PROFILE_AAC_LTP || !ics->predictor_present)
-        return;
-    if (common_window)
-        put_bits(&s->pb, 1, 0);
-    put_bits(&s->pb, 1, ics->ltp.present);
-    if (!ics->ltp.present)
-        return;
-    put_bits(&s->pb, 11, ics->ltp.lag);
-    put_bits(&s->pb, 3,  ics->ltp.coef_idx);
-    for (i = 0; i < FFMIN(ics->max_sfb, MAX_LTP_LONG_SFB); i++)
-        put_bits(&s->pb, 1, ics->ltp.used[i]);
-}
-
-void ff_aac_ltp_insert_new_frame(AACEncContext *s)
-{
-    int i, ch, tag, chans, cur_channel, start_ch = 0;
-    ChannelElement *cpe;
-    SingleChannelElement *sce;
-    for (i = 0; i < s->chan_map[0]; i++) {
-        cpe = &s->cpe[i];
-        tag      = s->chan_map[i+1];
-        chans    = tag == TYPE_CPE ? 2 : 1;
-        for (ch = 0; ch < chans; ch++) {
-            sce = &cpe->ch[ch];
-            cur_channel = start_ch + ch;
-            /* New sample + overlap */
-            memcpy(&sce->ltp_state[0],    &sce->ltp_state[1024], 1024*sizeof(sce->ltp_state[0]));
-            memcpy(&sce->ltp_state[1024], &s->planar_samples[cur_channel][2048], 1024*sizeof(sce->ltp_state[0]));
-            memcpy(&sce->ltp_state[2048], &sce->ret_buf[0], 1024*sizeof(sce->ltp_state[0]));
-            sce->ics.ltp.lag = 0;
-        }
-        start_ch += chans;
-    }
-}
-
-static void get_lag(float *buf, const float *new, LongTermPrediction *ltp)
-{
-    int i, j, lag = 0, max_corr = 0;
-    float max_ratio = 0.0f;
-    for (i = 0; i < 2048; i++) {
-        float corr, s0 = 0.0f, s1 = 0.0f;
-        const int start = FFMAX(0, i - 1024);
-        for (j = start; j < 2048; j++) {
-            const int idx = j - i + 1024;
-            s0 += new[j]*buf[idx];
-            s1 += buf[idx]*buf[idx];
-        }
-        corr = s1 > 0.0f ? s0/sqrt(s1) : 0.0f;
-        if (corr > max_corr) {
-            max_corr = corr;
-            lag = i;
-            max_ratio = corr/(2048-start);
-        }
-    }
-    ltp->lag = FFMAX(av_clip_uintp2(lag, 11), 0);
-    ltp->coef_idx = quant_array_idx(max_ratio, ff_ltp_coef, 8);
-    ltp->coef     = ff_ltp_coef[ltp->coef_idx];
-}
-
-static void generate_samples(float *buf, LongTermPrediction *ltp)
-{
-    int i, samples_num = 2048;
-    if (!ltp->lag) {
-        ltp->present = 0;
-        return;
-    } else if (ltp->lag < 1024) {
-        samples_num = ltp->lag + 1024;
-    }
-    for (i = 0; i < samples_num; i++)
-        buf[i] = ltp->coef*buf[i + 2048 - ltp->lag];
-    memset(&buf[i], 0, (2048 - i)*sizeof(float));
-}
-
-/**
- * Process LTP parameters
- * @see Patent WO2006070265A1
- */
-void ff_aac_update_ltp(AACEncContext *s, SingleChannelElement *sce)
-{
-    float *pred_signal = &sce->ltp_state[0];
-    const float *samples = &s->planar_samples[s->cur_channel][1024];
-
-    if (s->profile != AV_PROFILE_AAC_LTP)
-        return;
-
-    /* Calculate lag */
-    get_lag(pred_signal, samples, &sce->ics.ltp);
-    generate_samples(pred_signal, &sce->ics.ltp);
-}
-
-void ff_aac_adjust_common_ltp(AACEncContext *s, ChannelElement *cpe)
-{
-    int sfb, count = 0;
-    SingleChannelElement *sce0 = &cpe->ch[0];
-    SingleChannelElement *sce1 = &cpe->ch[1];
-
-    if (!cpe->common_window ||
-        sce0->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE ||
-        sce1->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
-        sce0->ics.ltp.present = 0;
-        return;
-    }
-
-    for (sfb = 0; sfb < FFMIN(sce0->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++) {
-        int sum = sce0->ics.ltp.used[sfb] + sce1->ics.ltp.used[sfb];
-        if (sum != 2) {
-            sce0->ics.ltp.used[sfb] = 0;
-        } else {
-            count++;
-        }
-    }
-
-    sce0->ics.ltp.present = !!count;
-    sce0->ics.predictor_present = !!count;
-}
-
-/**
- * Mark LTP sfb's
- */
-void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce,
-                           int common_window)
-{
-    int w, g, w2, i, start = 0, count = 0;
-    int saved_bits = -(15 + FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB));
-    float *C34 = &s->scoefs[128*0], *PCD = &s->scoefs[128*1];
-    float *PCD34 = &s->scoefs[128*2];
-    const int max_ltp = FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB);
-
-    if (sce->ics.window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
-        if (sce->ics.ltp.lag) {
-            memset(&sce->ltp_state[0], 0, 3072*sizeof(sce->ltp_state[0]));
-            memset(&sce->ics.ltp, 0, sizeof(LongTermPrediction));
-        }
-        return;
-    }
-
-    if (!sce->ics.ltp.lag || s->lambda > 120.0f)
-        return;
-
-    for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
-        start = 0;
-        for (g = 0;  g < sce->ics.num_swb; g++) {
-            int bits1 = 0, bits2 = 0;
-            float dist1 = 0.0f, dist2 = 0.0f;
-            if (w*16+g > max_ltp) {
-                start += sce->ics.swb_sizes[g];
-                continue;
-            }
-            for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
-                int bits_tmp1, bits_tmp2;
-                FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g];
-                for (i = 0; i < sce->ics.swb_sizes[g]; i++)
-                    PCD[i] = sce->coeffs[start+(w+w2)*128+i] - sce->lcoeffs[start+(w+w2)*128+i];
-                s->aacdsp.abs_pow34(C34,  &sce->coeffs[start+(w+w2)*128],  sce->ics.swb_sizes[g]);
-                s->aacdsp.abs_pow34(PCD34, PCD, sce->ics.swb_sizes[g]);
-                dist1 += quantize_band_cost(s, &sce->coeffs[start+(w+w2)*128], C34, sce->ics.swb_sizes[g],
-                                            sce->sf_idx[(w+w2)*16+g], sce->band_type[(w+w2)*16+g],
-                                            s->lambda/band->threshold, INFINITY, &bits_tmp1, NULL);
-                dist2 += quantize_band_cost(s, PCD, PCD34, sce->ics.swb_sizes[g],
-                                            sce->sf_idx[(w+w2)*16+g],
-                                            sce->band_type[(w+w2)*16+g],
-                                            s->lambda/band->threshold, INFINITY, &bits_tmp2, NULL);
-                bits1 += bits_tmp1;
-                bits2 += bits_tmp2;
-            }
-            if (dist2 < dist1 && bits2 < bits1) {
-                for (w2 = 0; w2 < sce->ics.group_len[w]; w2++)
-                    for (i = 0; i < sce->ics.swb_sizes[g]; i++)
-                        sce->coeffs[start+(w+w2)*128+i] -= sce->lcoeffs[start+(w+w2)*128+i];
-                sce->ics.ltp.used[w*16+g] = 1;
-                saved_bits += bits1 - bits2;
-                count++;
-            }
-            start += sce->ics.swb_sizes[g];
-        }
-    }
-
-    sce->ics.ltp.present = !!count && (saved_bits >= 0);
-    sce->ics.predictor_present = !!sce->ics.ltp.present;
-
-    /* Reset any marked sfbs */
-    if (!sce->ics.ltp.present && !!count) {
-        for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
-            start = 0;
-            for (g = 0;  g < sce->ics.num_swb; g++) {
-                if (sce->ics.ltp.used[w*16+g]) {
-                    for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
-                        for (i = 0; i < sce->ics.swb_sizes[g]; i++) {
-                            sce->coeffs[start+(w+w2)*128+i] += sce->lcoeffs[start+(w+w2)*128+i];
-                        }
-                    }
-                }
-                start += sce->ics.swb_sizes[g];
-            }
-        }
-    }
-}
diff --git a/libavcodec/aacenc_ltp.h b/libavcodec/aacenc_ltp.h
deleted file mode 100644
index 7276878427..0000000000
--- a/libavcodec/aacenc_ltp.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * AAC encoder long term prediction extension
- * Copyright (C) 2015 Rostislav Pehlivanov
- *
- * 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 encoder long term prediction extension
- * @author Rostislav Pehlivanov ( atomnuker gmail com )
- */
-
-#ifndef AVCODEC_AACENC_LTP_H
-#define AVCODEC_AACENC_LTP_H
-
-#include "aacenc.h"
-
-void ff_aac_encode_ltp_info(AACEncContext *s, SingleChannelElement *sce,
-                            int common_window);
-void ff_aac_update_ltp(AACEncContext *s, SingleChannelElement *sce);
-void ff_aac_adjust_common_ltp(AACEncContext *s, ChannelElement *cpe);
-void ff_aac_ltp_insert_new_frame(AACEncContext *s);
-void ff_aac_search_for_ltp(AACEncContext *s, SingleChannelElement *sce,
-                           int common_window);
-
-#endif /* AVCODEC_AACENC_LTP_H */
diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h
index 78e424a675..60e1f22387 100644
--- a/libavcodec/aacenctab.h
+++ b/libavcodec/aacenctab.h
@@ -126,7 +126,6 @@ static const unsigned char aac_maxval_cb[] = {
 
 static const int aacenc_profiles[] = {
     AV_PROFILE_AAC_LOW,
-    AV_PROFILE_AAC_LTP,
     AV_PROFILE_MPEG2_AAC_LOW,
 };
 
-- 
2.47.2
_______________________________________________
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] 2+ messages in thread

end of thread, other threads:[~2025-02-08  4:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-08  4:12 [FFmpeg-devel] [PATCH 1/2] aacenc: remove support for AAC Main profile Lynne
2025-02-08  4:12 ` [FFmpeg-devel] [PATCH 2/2] aacenc: remove support for AAC LTP profile 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