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.
This commit is contained in:
Claudio Freire 2015-10-12 03:56:22 -03:00
parent ce0834bdd6
commit b629c67ddf
7 changed files with 86 additions and 4 deletions

View File

@ -915,6 +915,8 @@ SKIPHEADERS += %_tablegen.h \
tableprint_vlc.h \
aaccoder_twoloop.h \
aaccoder_trellis.h \
aacenc_quantization.h \
aacenc_quantization_misc.h \
$(ARCH)/vp56_arith.h \
SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h

View File

@ -287,6 +287,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
if (!allz)
return;
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]) {
start = w*128;
@ -380,7 +381,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b;
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,
sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g],
@ -460,7 +461,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b;
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,
sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g],
@ -588,7 +589,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b;
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,
sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g]-1,
@ -625,7 +626,7 @@ static void search_for_quantizers_twoloop(AVCodecContext *avctx,
for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) {
int b;
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,
sce->ics.swb_sizes[g],
sce->sf_idx[w*16+g]+1,

View File

@ -71,6 +71,16 @@ static void put_audio_specific_config(AVCodecContext *avctx)
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) \
static void apply_ ##type ##_window(AVFloatDSPContext *fdsp, \
SingleChannelElement *sce, \

View File

@ -75,6 +75,15 @@ typedef struct AACCoefficientsEncoder {
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
*/
@ -109,11 +118,15 @@ typedef struct AACEncContext {
DECLARE_ALIGNED(16, int, qcoefs)[96]; ///< quantized coefficients
DECLARE_ALIGNED(32, float, scoefs)[1024]; ///< scaled coefficients
AACQuantizeBandCostCacheEntry quantize_band_cost_cache[256][128]; ///< memoization area for quantize_band_cost
struct {
float *samples;
} buffer;
} AACEncContext;
void ff_aac_coder_init_mips(AACEncContext *c);
void ff_quantize_band_cost_cache_init(struct AACEncContext *s);
#endif /* AVCODEC_AACENC_H */

View File

@ -278,4 +278,6 @@ static inline void quantize_and_encode_band(struct AACEncContext *s, PutBitConte
INFINITY, NULL, NULL, rtz);
}
#include "aacenc_quantization_misc.h"
#endif /* AVCODEC_AACENC_QUANTIZATION_H */

View File

@ -0,0 +1,52 @@
/*
* 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 */

View File

@ -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);
}
#include "libavcodec/aacenc_quantization_misc.h"
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_sizem1 = 1.0f / (swb_size - 1);