]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/vp9.c
avcodec/dcadec: Only upsample as much data as is there
[ffmpeg] / libavcodec / vp9.c
index c7f351bdd736faa6f85768d30b0d0803692700a3..0405c051d91f4cf04e00a9aab563a23f7c48b87d 100644 (file)
@@ -74,6 +74,7 @@ typedef struct VP9Frame {
     AVBufferRef *extradata;
     uint8_t *segmentation_map;
     struct VP9mvrefPair *mv;
+    int uses_2pass;
 } VP9Frame;
 
 struct VP9Filter {
@@ -100,7 +101,7 @@ typedef struct VP9Context {
     VP56RangeCoder *c_b;
     unsigned c_b_size;
     VP9Block *b_base, *b;
-    int pass, uses_2pass, last_uses_2pass;
+    int pass;
     int row, row7, col, col7;
     uint8_t *dst[3];
     ptrdiff_t y_stride, uv_stride;
@@ -128,8 +129,9 @@ typedef struct VP9Context {
     uint8_t varcompref[2];
     ThreadFrame refs[8], next_refs[8];
 #define CUR_FRAME 0
-#define LAST_FRAME 1
-    VP9Frame frames[2];
+#define REF_FRAME_MVPAIR 1
+#define REF_FRAME_SEGMAP 2
+    VP9Frame frames[3];
 
     struct {
         uint8_t level;
@@ -277,12 +279,6 @@ static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f)
     f->segmentation_map = f->extradata->data;
     f->mv = (struct VP9mvrefPair *) (f->extradata->data + sz);
 
-    // retain segmentation map if it doesn't update
-    if (s->segmentation.enabled && !s->segmentation.update_map &&
-        !s->intraonly && !s->keyframe && !s->errorres) {
-        memcpy(f->segmentation_map, s->frames[LAST_FRAME].segmentation_map, sz);
-    }
-
     return 0;
 }
 
@@ -305,6 +301,7 @@ static int vp9_ref_frame(AVCodecContext *ctx, VP9Frame *dst, VP9Frame *src)
 
     dst->segmentation_map = src->segmentation_map;
     dst->mv = src->mv;
+    dst->uses_2pass = src->uses_2pass;
 
     return 0;
 }
@@ -361,12 +358,12 @@ static int update_block_buffers(AVCodecContext *ctx)
 {
     VP9Context *s = ctx->priv_data;
 
-    if (s->b_base && s->block_base && s->block_alloc_using_2pass == s->uses_2pass)
+    if (s->b_base && s->block_base && s->block_alloc_using_2pass == s->frames[CUR_FRAME].uses_2pass)
         return 0;
 
     av_free(s->b_base);
     av_free(s->block_base);
-    if (s->uses_2pass) {
+    if (s->frames[CUR_FRAME].uses_2pass) {
         int sbs = s->sb_cols * s->sb_rows;
 
         s->b_base = av_malloc_array(s->cols * s->rows, sizeof(VP9Block));
@@ -389,7 +386,7 @@ static int update_block_buffers(AVCodecContext *ctx)
         s->uveob_base[0] = s->eob_base + 256;
         s->uveob_base[1] = s->uveob_base[0] + 64;
     }
-    s->block_alloc_using_2pass = s->uses_2pass;
+    s->block_alloc_using_2pass = s->frames[CUR_FRAME].uses_2pass;
 
     return 0;
 }
@@ -490,7 +487,6 @@ static int decode_frame_header(AVCodecContext *ctx,
         *ref = get_bits(&s->gb, 3);
         return 0;
     }
-    s->last_uses_2pass = s->uses_2pass;
     s->last_keyframe  = s->keyframe;
     s->keyframe       = !get_bits1(&s->gb);
     last_invisible    = s->invisible;
@@ -693,10 +689,10 @@ static int decode_frame_header(AVCodecContext *ctx,
         for (j = 1; j < 4; j++) {
             s->segmentation.feat[i].lflvl[j][0] =
                 av_clip_uintp2(lflvl + ((s->lf_delta.ref[j] +
-                                         s->lf_delta.mode[0]) << sh), 6);
+                                         s->lf_delta.mode[0]) * (1 << sh)), 6);
             s->segmentation.feat[i].lflvl[j][1] =
                 av_clip_uintp2(lflvl + ((s->lf_delta.ref[j] +
-                                         s->lf_delta.mode[1]) << sh), 6);
+                                         s->lf_delta.mode[1]) * (1 << sh)), 6);
         }
     }
 
@@ -1081,10 +1077,10 @@ static void find_ref_mvs(VP9Context *s,
 
     // MV at this position in previous frame, using same reference frame
     if (s->use_last_frame_mvs) {
-        struct VP9mvrefPair *mv = &s->frames[LAST_FRAME].mv[row * s->sb_cols * 8 + col];
+        struct VP9mvrefPair *mv = &s->frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col];
 
-        if (!s->last_uses_2pass)
-            ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0);
+        if (!s->frames[REF_FRAME_MVPAIR].uses_2pass)
+            ff_thread_await_progress(&s->frames[REF_FRAME_MVPAIR].tf, row >> 3, 0);
         if (mv->ref[0] == ref) {
             RETURN_MV(mv->mv[0]);
         } else if (mv->ref[1] == ref) {
@@ -1123,7 +1119,7 @@ static void find_ref_mvs(VP9Context *s,
 
     // MV at this position in previous frame, using different reference frame
     if (s->use_last_frame_mvs) {
-        struct VP9mvrefPair *mv = &s->frames[LAST_FRAME].mv[row * s->sb_cols * 8 + col];
+        struct VP9mvrefPair *mv = &s->frames[REF_FRAME_MVPAIR].mv[row * s->sb_cols * 8 + col];
 
         // no need to await_progress, because we already did that above
         if (mv->ref[0] != ref && mv->ref[0] >= 0) {
@@ -1347,13 +1343,15 @@ static void decode_mode(AVCodecContext *ctx)
                                     s->left_segpred_ctx[row7]]))) {
         if (!s->errorres) {
             int pred = 8, x;
-            uint8_t *refsegmap = s->frames[LAST_FRAME].segmentation_map;
+            uint8_t *refsegmap = s->frames[REF_FRAME_SEGMAP].segmentation_map;
 
-            if (!s->last_uses_2pass)
-                ff_thread_await_progress(&s->frames[LAST_FRAME].tf, row >> 3, 0);
-            for (y = 0; y < h4; y++)
+            if (!s->frames[REF_FRAME_SEGMAP].uses_2pass)
+                ff_thread_await_progress(&s->frames[REF_FRAME_SEGMAP].tf, row >> 3, 0);
+            for (y = 0; y < h4; y++) {
+                int idx_base = (y + row) * 8 * s->sb_cols + col;
                 for (x = 0; x < w4; x++)
-                    pred = FFMIN(pred, refsegmap[(y + row) * 8 * s->sb_cols + x + col]);
+                    pred = FFMIN(pred, refsegmap[idx_base + x]);
+            }
             av_assert1(pred < 8);
             b->seg_id = pred;
         } else {
@@ -3719,7 +3717,7 @@ static av_cold int vp9_decode_free(AVCodecContext *ctx)
     VP9Context *s = ctx->priv_data;
     int i;
 
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < 3; i++) {
         if (s->frames[i].tf.f->data[0])
             vp9_unref_frame(ctx, &s->frames[i]);
         av_frame_free(&s->frames[i].tf.f);
@@ -3747,6 +3745,7 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
     int size = pkt->size;
     VP9Context *s = ctx->priv_data;
     int res, tile_row, tile_col, i, ref, row, col;
+    int retain_segmap_ref = s->segmentation.enabled && !s->segmentation.update_map;
     ptrdiff_t yoff, uvoff, ls_y, ls_uv;
     AVFrame *f;
 
@@ -3765,10 +3764,17 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
     data += res;
     size -= res;
 
-    if (s->frames[LAST_FRAME].tf.f->data[0])
-        vp9_unref_frame(ctx, &s->frames[LAST_FRAME]);
-    if (!s->keyframe && s->frames[CUR_FRAME].tf.f->data[0] &&
-        (res = vp9_ref_frame(ctx, &s->frames[LAST_FRAME], &s->frames[CUR_FRAME])) < 0)
+    if (!retain_segmap_ref) {
+        if (s->frames[REF_FRAME_SEGMAP].tf.f->data[0])
+            vp9_unref_frame(ctx, &s->frames[REF_FRAME_SEGMAP]);
+        if (!s->keyframe && !s->intraonly && !s->errorres && s->frames[CUR_FRAME].tf.f->data[0] &&
+            (res = vp9_ref_frame(ctx, &s->frames[REF_FRAME_SEGMAP], &s->frames[CUR_FRAME])) < 0)
+            return res;
+    }
+    if (s->frames[REF_FRAME_MVPAIR].tf.f->data[0])
+        vp9_unref_frame(ctx, &s->frames[REF_FRAME_MVPAIR]);
+    if (!s->intraonly && !s->keyframe && !s->errorres && s->frames[CUR_FRAME].tf.f->data[0] &&
+        (res = vp9_ref_frame(ctx, &s->frames[REF_FRAME_MVPAIR], &s->frames[CUR_FRAME])) < 0)
         return res;
     if (s->frames[CUR_FRAME].tf.f->data[0])
         vp9_unref_frame(ctx, &s->frames[CUR_FRAME]);
@@ -3817,7 +3823,7 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
     memset(s->above_uv_nnz_ctx[0], 0, s->sb_cols * 8);
     memset(s->above_uv_nnz_ctx[1], 0, s->sb_cols * 8);
     memset(s->above_segpred_ctx, 0, s->cols);
-    s->pass = s->uses_2pass =
+    s->pass = s->frames[CUR_FRAME].uses_2pass =
         ctx->active_thread_type == FF_THREAD_FRAME && s->refreshctx && !s->parallelmode;
     if ((res = update_block_buffers(ctx)) < 0) {
         av_log(ctx, AV_LOG_ERROR,
@@ -3992,7 +3998,7 @@ static void vp9_decode_flush(AVCodecContext *ctx)
     VP9Context *s = ctx->priv_data;
     int i;
 
-    for (i = 0; i < 2; i++)
+    for (i = 0; i < 3; i++)
         vp9_unref_frame(ctx, &s->frames[i]);
     for (i = 0; i < 8; i++)
         ff_thread_release_buffer(ctx, &s->refs[i]);
@@ -4003,7 +4009,7 @@ static int init_frames(AVCodecContext *ctx)
     VP9Context *s = ctx->priv_data;
     int i;
 
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < 3; i++) {
         s->frames[i].tf.f = av_frame_alloc();
         if (!s->frames[i].tf.f) {
             vp9_decode_free(ctx);
@@ -4053,7 +4059,7 @@ static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo
         free_buffers(s);
     }
 
-    for (i = 0; i < 2; i++) {
+    for (i = 0; i < 3; i++) {
         if (s->frames[i].tf.f->data[0])
             vp9_unref_frame(dst, &s->frames[i]);
         if (ssrc->frames[i].tf.f->data[0]) {
@@ -4072,7 +4078,8 @@ static int vp9_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo
 
     s->invisible = ssrc->invisible;
     s->keyframe = ssrc->keyframe;
-    s->uses_2pass = ssrc->uses_2pass;
+    s->segmentation.enabled = ssrc->segmentation.enabled;
+    s->segmentation.update_map = ssrc->segmentation.update_map;
     memcpy(&s->prob_ctx, &ssrc->prob_ctx, sizeof(s->prob_ctx));
     memcpy(&s->lf_delta, &ssrc->lf_delta, sizeof(s->lf_delta));
     if (ssrc->segmentation.enabled) {