Commit b629c67d authored by Claudio Freire's avatar Claudio Freire

AAC encoder: memoize quantize_band_cost

The bulk of calls to quantize_band_cost are replaced
by a call to a version that memoizes, greatly improving
performance, since during coefficient search there is
a great deal of repeat work.

Memoization cannot always be applied, so do this in a
different function, and leave the original as-is.
parent ce0834bd
...@@ -915,6 +915,8 @@ SKIPHEADERS += %_tablegen.h \ ...@@ -915,6 +915,8 @@ SKIPHEADERS += %_tablegen.h \
tableprint_vlc.h \ tableprint_vlc.h \
aaccoder_twoloop.h \ aaccoder_twoloop.h \
aaccoder_trellis.h \ aaccoder_trellis.h \
aacenc_quantization.h \
aacenc_quantization_misc.h \
$(ARCH)/vp56_arith.h \ $(ARCH)/vp56_arith.h \
SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h
......
...@@ -287,6 +287,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, ...@@ -287,6 +287,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
if (!allz) if (!allz)
return; return;
abs_pow34_v(s->scoefs, sce->coeffs, 1024); abs_pow34_v(s->scoefs, sce->coeffs, 1024);
ff_quantize_band_cost_cache_init(s);
for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) { for (w = 0; w < sce->ics.num_windows; w += sce->ics.group_len[w]) {
start = w*128; start = w*128;
...@@ -380,7 +381,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, ...@@ -380,7 +381,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b; int b;
float sqenergy; float sqenergy;
dist += quantize_band_cost(s, coefs + w2*128, dist += quantize_band_cost_cached(s, w + w2, g, coefs + w2*128,
scaled + w2*128, scaled + w2*128,
sce->ics.swb_sizes[g], sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g], sce->sf_idx[w*16+g],
...@@ -460,7 +461,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, ...@@ -460,7 +461,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b; int b;
float sqenergy; float sqenergy;
dist += quantize_band_cost(s, coefs + w2*128, dist += quantize_band_cost_cached(s, w + w2, g, coefs + w2*128,
scaled + w2*128, scaled + w2*128,
sce->ics.swb_sizes[g], sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g], sce->sf_idx[w*16+g],
...@@ -588,7 +589,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, ...@@ -588,7 +589,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b; int b;
float sqenergy; float sqenergy;
dist += quantize_band_cost(s, coefs + w2*128, dist += quantize_band_cost_cached(s, w + w2, g, coefs + w2*128,
scaled + w2*128, scaled + w2*128,
sce->ics.swb_sizes[g], sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g]-1, sce->sf_idx[w*16+g]-1,
...@@ -625,7 +626,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx, ...@@ -625,7 +626,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b; int b;
float sqenergy; float sqenergy;
dist += quantize_band_cost(s, coefs + w2*128, dist += quantize_band_cost_cached(s, w + w2, g, coefs + w2*128,
scaled + w2*128, scaled + w2*128,
sce->ics.swb_sizes[g], sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g]+1, sce->sf_idx[w*16+g]+1,
......
...@@ -71,6 +71,16 @@ static void put_audio_specific_config(AVCodecContext *avctx) ...@@ -71,6 +71,16 @@ static void put_audio_specific_config(AVCodecContext *avctx)
flush_put_bits(&pb); flush_put_bits(&pb);
} }
void ff_quantize_band_cost_cache_init(struct AACEncContext *s)
{
int sf, g;
for (sf = 0; sf < 256; sf++) {
for (g = 0; g < 128; g++) {
s->quantize_band_cost_cache[sf][g].bits = -1;
}
}
}
#define WINDOW_FUNC(type) \ #define WINDOW_FUNC(type) \
static void apply_ ##type ##_window(AVFloatDSPContext *fdsp, \ static void apply_ ##type ##_window(AVFloatDSPContext *fdsp, \
SingleChannelElement *sce, \ SingleChannelElement *sce, \
......
...@@ -75,6 +75,15 @@ typedef struct AACCoefficientsEncoder { ...@@ -75,6 +75,15 @@ typedef struct AACCoefficientsEncoder {
extern AACCoefficientsEncoder ff_aac_coders[]; extern AACCoefficientsEncoder ff_aac_coders[];
typedef struct AACQuantizeBandCostCacheEntry {
float rd;
float energy;
int bits; ///< -1 means uninitialized entry
char cb;
char rtz;
char padding[2]; ///< Keeps the entry size a multiple of 32 bits
} AACQuantizeBandCostCacheEntry;
/** /**
* AAC encoder context * AAC encoder context
*/ */
...@@ -109,11 +118,15 @@ typedef struct AACEncContext { ...@@ -109,11 +118,15 @@ typedef struct AACEncContext {
DECLARE_ALIGNED(16, int, qcoefs)[96]; ///< quantized coefficients DECLARE_ALIGNED(16, int, qcoefs)[96]; ///< quantized coefficients
DECLARE_ALIGNED(32, float, scoefs)[1024]; ///< scaled coefficients DECLARE_ALIGNED(32, float, scoefs)[1024]; ///< scaled coefficients
AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost
struct { struct {
float *samples; float *samples;
} buffer; } buffer;
} AACEncContext; } AACEncContext;
void ff_aac_coder_init_mips(AACEncContext *c); void ff_aac_coder_init_mips(AACEncContext *c);
void ff_quantize_band_cost_cache_init(struct AACEncContext *s);
#endif /* AVCODEC_AACENC_H */ #endif /* AVCODEC_AACENC_H */
...@@ -278,4 +278,6 @@ static inline void quantize_and_encode_band(struct AACEncContext *s, PutBitConte ...@@ -278,4 +278,6 @@ static inline void quantize_and_encode_band(struct AACEncContext *s, PutBitConte
INFINITY, NULL, NULL, rtz); INFINITY, NULL, NULL, rtz);
} }
#include "aacenc_quantization_misc.h"
#endif /* AVCODEC_AACENC_QUANTIZATION_H */ #endif /* AVCODEC_AACENC_QUANTIZATION_H */
/*
* AAC encoder quantization
* Copyright (C) 2015 Claudio Freire
*
* 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 quantization misc reusable function templates
* @author Claudio Freire ( klaussfreire gmail com )
*/
#ifndef AVCODEC_AACENC_QUANTIZATION_MISC_H
#define AVCODEC_AACENC_QUANTIZATION_MISC_H
static inline float quantize_band_cost_cached(struct AACEncContext *s, int w, int g, const float *in,
const float *scaled, int size, int scale_idx,
int cb, const float lambda, const float uplim,
int *bits, float *energy, int rtz)
{
AACQuantizeBandCostCacheEntry *entry;
av_assert1(scale_idx >= 0 && scale_idx < 256);
entry = &s->quantize_band_cost_cache[scale_idx][w*16+g];
if (entry->bits < 0 || entry->cb != cb || entry->rtz != rtz) {
entry->rd = quantize_band_cost(s, in, scaled, size, scale_idx,
cb, lambda, uplim, &entry->bits, &entry->energy, rtz);
entry->cb = cb;
entry->rtz = rtz;
}
if (bits)
*bits = entry->bits;
if (energy)
*energy = entry->energy;
return entry->rd;
}
#endif /* AVCODEC_AACENC_QUANTIZATION_MISC_H */
...@@ -2388,6 +2388,8 @@ static float quantize_band_cost(struct AACEncContext *s, const float *in, ...@@ -2388,6 +2388,8 @@ static float quantize_band_cost(struct AACEncContext *s, const float *in,
return get_band_cost(s, NULL, in, scaled, size, scale_idx, cb, lambda, uplim, bits, energy); return get_band_cost(s, NULL, in, scaled, size, scale_idx, cb, lambda, uplim, bits, energy);
} }
#include "libavcodec/aacenc_quantization_misc.h"
static float find_form_factor(int group_len, int swb_size, float thresh, const float *scaled, float nzslope) { static float find_form_factor(int group_len, int swb_size, float thresh, const float *scaled, float nzslope) {
const float iswb_size = 1.0f / swb_size; const float iswb_size = 1.0f / swb_size;
const float iswb_sizem1 = 1.0f / (swb_size - 1); const float iswb_sizem1 = 1.0f / (swb_size - 1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment