This commit redistributes the leftover bytes amongst the top 150 slices
in terms of size (in the hopes that they'll be the ones bitrate starved).

A more perceptual method would probably need to cut bits off from slices
which don't need much, but that'll be implemented later.

The cached quantizer bit cost helped to keep this search from barely
taking CPU time.

Signed-off-by: Rostislav Pehlivanov <atomnu...@gmail.com>
---
 libavcodec/vc2enc.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c
index 600a8ac..df71953 100644
--- a/libavcodec/vc2enc.c
+++ b/libavcodec/vc2enc.c
@@ -39,6 +39,9 @@
 /* Per slice quantization bit cost cache */
 #define SLICE_CACHED_QUANTIZERS 30
 
+/* Decides the cutoff point in # of slices to distribute the leftover bytes */
+#define SLICE_REDIST_TOTAL 150
+
 enum VC2_QM {
     VC2_QM_DEF = 0,
     VC2_QM_COL,
@@ -780,9 +783,13 @@ static int encode_hq_slice(AVCodecContext *avctx, void 
*arg)
 static int encode_slices(VC2EncContext *s)
 {
     uint8_t *buf;
-    int slice_x, slice_y, skip = 0;
+    int i, slice_x, slice_y, skip = 0;
+    int bytes_left = 0;
     SliceArgs *enc_args = s->slice_args;
 
+    int bytes_top[SLICE_REDIST_TOTAL] = {0};
+    SliceArgs *top_loc[SLICE_REDIST_TOTAL] = {NULL};
+
     avpriv_align_put_bits(&s->pb);
     flush_put_bits(&s->pb);
     buf = put_bits_ptr(&s->pb);
@@ -790,6 +797,47 @@ static int encode_slices(VC2EncContext *s)
     for (slice_y = 0; slice_y < s->num_y; slice_y++) {
         for (slice_x = 0; slice_x < s->num_x; slice_x++) {
             SliceArgs *args = &enc_args[s->num_x*slice_y + slice_x];
+            bytes_left += args->bytes_left;
+            for (i = 0; i < FFMIN(SLICE_REDIST_TOTAL, s->num_x*s->num_y); i++) 
{
+                if (args->bytes > bytes_top[i]) {
+                    bytes_top[i] = args->bytes;
+                    top_loc[i] = args;
+                    break;
+                }
+            }
+        }
+    }
+
+    while (1) {
+        int distributed = 0;
+        for (i = 0; i < FFMIN(SLICE_REDIST_TOTAL, s->num_x*s->num_y); i++) {
+            SliceArgs *args;
+            int bits, bytes, diff, prev_bytes, new_idx;
+            if (bytes_left <= 0)
+                break;
+            if (!top_loc[i] || !top_loc[i]->quant_idx)
+                break;
+            args = top_loc[i];
+            prev_bytes = args->bytes;
+            new_idx = av_clip(args->quant_idx - 1, 0, s->q_ceil);
+            bits = count_hq_slice(s, args->cache, &args->cached_results,
+                                  args->x, args->y, new_idx);
+            bytes = FFALIGN((bits >> 3), s->size_scaler) + 4 + s->prefix_bytes;
+            diff = bytes - prev_bytes;
+            if ((bytes_left - diff) >= 0) {
+                args->quant_idx = new_idx;
+                args->bytes = bytes;
+                bytes_left -= diff;
+                distributed++;
+            }
+        }
+        if (!distributed)
+            break;
+    }
+
+    for (slice_y = 0; slice_y < s->num_y; slice_y++) {
+        for (slice_x = 0; slice_x < s->num_x; slice_x++) {
+            SliceArgs *args = &enc_args[s->num_x*slice_y + slice_x];
             init_put_bits(&args->pb, buf + skip, args->bytes);
             s->q_avg = (s->q_avg + args->quant_idx)/2;
             skip += args->bytes;
@@ -1042,6 +1090,8 @@ static av_cold int vc2_encode_init(AVCodecContext *avctx)
     s->strict_compliance = 1;
 
     s->q_avg = 0;
+    s->slice_max_bytes = 0;
+    s->slice_min_bytes = 0;
 
     /* Mark unknown as progressive */
     s->interlaced = !((avctx->field_order == AV_FIELD_UNKNOWN) ||
-- 
2.7.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to