From: Lynne <dev@lynne.ee> To: ffmpeg-devel@ffmpeg.org Cc: Lynne <dev@lynne.ee> Subject: [FFmpeg-devel] [PATCH 1/2] aacenc: remove support for AAC Main profile Date: Sat, 8 Feb 2025 05:12:52 +0100 Message-ID: <20250208041258.217102-1-dev@lynne.ee> (raw) 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".
next reply other threads:[~2025-02-08 4:13 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2025-02-08 4:12 Lynne [this message] 2025-02-08 4:12 ` [FFmpeg-devel] [PATCH 2/2] aacenc: remove support for AAC LTP profile Lynne
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250208041258.217102-1-dev@lynne.ee \ --to=dev@lynne.ee \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
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