vc2enc: cache bits per quantizer, calculate wasted bits
authorRostislav Pehlivanov <atomnuker@gmail.com>
Sat, 27 Feb 2016 18:24:28 +0000 (18:24 +0000)
committerRostislav Pehlivanov <atomnuker@gmail.com>
Sun, 28 Feb 2016 19:06:29 +0000 (19:06 +0000)
Needed for following commits, also a speed increase.

Signed-off-by: Rostislav Pehlivanov <atomnuker@gmail.com>
libavcodec/vc2enc.c

index fd2abd5456c2e1d2a2fb3ee171466d66af82f440..1d74cd56051f5efafd7d32b11300fdab86867817 100644 (file)
@@ -36,6 +36,9 @@
  * (COEF_LUT_TAB*MAX_QUANT_INDEX) since the sign is appended during encoding */
 #define COEF_LUT_TAB 2048
 
+/* Per slice quantization bit cost cache */
+#define SLICE_CACHED_QUANTIZERS 30
+
 enum VC2_QM {
     VC2_QM_DEF = 0,
     VC2_QM_COL,
@@ -61,14 +64,22 @@ typedef struct Plane {
     ptrdiff_t coef_stride;
 } Plane;
 
+typedef struct BitCostCache {
+    int bits;
+    int quantizer;
+} BitCostCache;
+
 typedef struct SliceArgs {
     PutBitContext pb;
+    BitCostCache cache[SLICE_CACHED_QUANTIZERS];
+    int cached_results;
     void *ctx;
     int x;
     int y;
     int quant_idx;
     int bits_ceil;
     int bits_floor;
+    int bytes_left;
     int bytes;
 } SliceArgs;
 
@@ -583,13 +594,19 @@ static void encode_subband(VC2EncContext *s, PutBitContext *pb, int sx, int sy,
     }
 }
 
-static int count_hq_slice(VC2EncContext *s, int slice_x,
-                          int slice_y, int quant_idx)
+static int count_hq_slice(VC2EncContext *s, BitCostCache *cache,
+                          int *cached_results, int slice_x, int slice_y,
+                          int quant_idx)
 {
-    int x, y;
+    int i, x, y;
     uint8_t quants[MAX_DWT_LEVELS][4];
     int bits = 0, p, level, orientation;
 
+    if (cache && *cached_results)
+        for (i = 0; i < *cached_results; i++)
+            if (cache[i].quantizer == quant_idx)
+                return cache[i].bits;
+
     bits += 8*s->prefix_bytes;
     bits += 8; /* quant_idx */
 
@@ -639,6 +656,12 @@ static int count_hq_slice(VC2EncContext *s, int slice_x,
         bits += pad_c*8;
     }
 
+    if (cache) {
+        cache[*cached_results].quantizer = quant_idx;
+        cache[*cached_results].bits = bits;
+        *cached_results = FFMIN(*cached_results + 1, SLICE_CACHED_QUANTIZERS);
+    }
+
     return bits;
 }
 
@@ -655,12 +678,14 @@ static int rate_control(AVCodecContext *avctx, void *arg)
     int quant = s->q_start, range = s->q_start/3;
     const int top = slice_dat->bits_ceil;
     const int bottom = slice_dat->bits_floor;
-    int bits = count_hq_slice(s, sx, sy, quant);
+    int bits = count_hq_slice(s, slice_dat->cache, &slice_dat->cached_results,
+                              sx, sy, quant);
     range -= range & 1; /* Make it an even number */
     while ((bits > top) || (bits < bottom)) {
         range *= bits > top ? +1 : -1;
         quant = av_clip(quant + range, 0, s->q_ceil);
-        bits = count_hq_slice(s, sx, sy, quant);
+        bits = count_hq_slice(s, slice_dat->cache, &slice_dat->cached_results,
+                              sx, sy, quant);
         range = av_clip(range/2, 1, s->q_ceil);
         if (quant_buf[1] == quant) {
             quant = bits_last < bits ? quant_buf[0] : quant;
@@ -673,6 +698,7 @@ static int rate_control(AVCodecContext *avctx, void *arg)
     }
     slice_dat->quant_idx = av_clip(quant, 0, s->q_ceil);
     slice_dat->bytes = FFALIGN((bits >> 3), s->size_scaler) + 4 + s->prefix_bytes;
+    slice_dat->bytes_left = s->slice_max_bytes - slice_dat->bytes;
 
     return 0;
 }
@@ -688,6 +714,7 @@ static void calc_slice_sizes(VC2EncContext *s)
             args->ctx = s;
             args->x = slice_x;
             args->y = slice_y;
+            args->cached_results = 0;
             args->bits_ceil = s->slice_max_bytes << 3;
             args->bits_floor = s->slice_min_bytes << 3;
         }