From b629c67ddfceb7026e407685f04d1bb09cb08d31 Mon Sep 17 00:00:00 2001 From: Claudio Freire Date: Mon, 12 Oct 2015 03:56:22 -0300 Subject: 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. --- libavcodec/Makefile | 2 ++ libavcodec/aaccoder_twoloop.h | 9 +++--- libavcodec/aacenc.c | 10 +++++++ libavcodec/aacenc.h | 13 +++++++++ libavcodec/aacenc_quantization.h | 2 ++ libavcodec/aacenc_quantization_misc.h | 52 +++++++++++++++++++++++++++++++++++ libavcodec/mips/aaccoder_mips.c | 2 ++ 7 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 libavcodec/aacenc_quantization_misc.h (limited to 'libavcodec') diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 7a576fda15..b8bd89530b 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -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 diff --git a/libavcodec/aaccoder_twoloop.h b/libavcodec/aaccoder_twoloop.h index a46f8dc809..2cc9a52d73 100644 --- a/libavcodec/aaccoder_twoloop.h +++ b/libavcodec/aaccoder_twoloop.h @@ -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, diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index 3e21bfffa0..9e96cbcfa1 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -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, \ diff --git a/libavcodec/aacenc.h b/libavcodec/aacenc.h index 99f50edc9c..98b38a4bde 100644 --- a/libavcodec/aacenc.h +++ b/libavcodec/aacenc.h @@ -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 */ diff --git a/libavcodec/aacenc_quantization.h b/libavcodec/aacenc_quantization.h index 1c3df38e9f..69f97396ff 100644 --- a/libavcodec/aacenc_quantization.h +++ b/libavcodec/aacenc_quantization.h @@ -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 */ diff --git a/libavcodec/aacenc_quantization_misc.h b/libavcodec/aacenc_quantization_misc.h new file mode 100644 index 0000000000..eaa71c9689 --- /dev/null +++ b/libavcodec/aacenc_quantization_misc.h @@ -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 */ diff --git a/libavcodec/mips/aaccoder_mips.c b/libavcodec/mips/aaccoder_mips.c index e85bf8c5ca..269a12465f 100644 --- a/libavcodec/mips/aaccoder_mips.c +++ b/libavcodec/mips/aaccoder_mips.c @@ -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); -- cgit v1.2.3