From 5cc53c2e530d128d80c94320a7263521e43257d2 Mon Sep 17 00:00:00 2001 From: Rostislav Pehlivanov Date: Sat, 27 Feb 2016 18:24:28 +0000 Subject: [PATCH] vc2enc: cache bits per quantizer, calculate wasted bits Needed for following commits, also a speed increase. Signed-off-by: Rostislav Pehlivanov --- libavcodec/vc2enc.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c index fd2abd5456..1d74cd5605 100644 --- a/libavcodec/vc2enc.c +++ b/libavcodec/vc2enc.c @@ -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; }