[FFmpeg-cvslog] AAC encoder: memoize quantize_band_cost

Claudio Freire git at videolan.org
Mon Oct 12 08:57:51 CEST 2015


ffmpeg | branch: master | Claudio Freire <klaussfreire at gmail.com> | Mon Oct 12 03:56:22 2015 -0300| [b629c67ddfceb7026e407685f04d1bb09cb08d31] | committer: 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.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b629c67ddfceb7026e407685f04d1bb09cb08d31
---

 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(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 7a576fd..b8bd895 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 a46f8dc..2cc9a52 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 3e21bff..9e96cbc 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 99f50ed..98b38a4 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 1c3df38..69f9739 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 0000000..eaa71c9
--- /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 e85bf8c..269a124 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);



More information about the ffmpeg-cvslog mailing list