AAC encoder: memoize quantize_band_cost
authorClaudio Freire <klaussfreire@gmail.com>
Mon, 12 Oct 2015 06:56:22 +0000 (03:56 -0300)
committerClaudio Freire <klaussfreire@gmail.com>
Mon, 12 Oct 2015 06:56:22 +0000 (03:56 -0300)
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
libavcodec/aaccoder_twoloop.h
libavcodec/aacenc.c
libavcodec/aacenc.h
libavcodec/aacenc_quantization.h
libavcodec/aacenc_quantization_misc.h [new file with mode: 0644]
libavcodec/mips/aaccoder_mips.c

index 7a576fd..b8bd895 100644 (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
index a46f8dc..2cc9a52 100644 (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,
index 3e21bff..9e96cbc 100644 (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, \
index 99f50ed..98b38a4 100644 (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 */
index 1c3df38..69f9739 100644 (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 */
diff --git a/libavcodec/aacenc_quantization_misc.h b/libavcodec/aacenc_quantization_misc.h
new file mode 100644 (file)
index 0000000..eaa71c9
--- /dev/null
@@ -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 */
index e85bf8c..269a124 100644 (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);