shithub: dav1d

Download patch

ref: 74f574eab43f36bd02df4319c65ae8b2a332100d
parent: e9bb49f5d9bc41f28b08cf887276fd38f0962f4f
author: Ronald S. Bultje <rsbultje@gmail.com>
date: Mon Oct 22 15:45:17 EDT 2018

Rename unset_hp_bit() to fix_mv_precision() and add integer-mv support.

Also prevent using warped motion when force_integer_mv=1. Fixes #84.

--- a/src/decode.c
+++ b/src/decode.c
@@ -1308,10 +1308,8 @@
 
             b->mv[0] = mvstack[0].this_mv;
             b->mv[1] = mvstack[0].comp_mv;
-            if (!f->frame_hdr.hp) {
-                unset_hp_bit(&b->mv[0]);
-                unset_hp_bit(&b->mv[1]);
-            }
+            fix_mv_precision(&f->frame_hdr, &b->mv[0]);
+            fix_mv_precision(&f->frame_hdr, &b->mv[1]);
             if (DEBUG_BLOCK_INFO)
                 printf("Post-skipmodeblock[mv=1:y=%d,x=%d,2:y=%d,x=%d,refs=%d+%d\n",
                        b->mv[0].y, b->mv[0].x, b->mv[1].y, b->mv[1].x,
@@ -1431,7 +1429,7 @@
             case NEARMV: \
             case NEARESTMV: \
                 b->mv[idx] = mvstack[b->drl_idx].pfx##_mv; \
-                if (!f->frame_hdr.hp) unset_hp_bit(&b->mv[idx]); \
+                fix_mv_precision(&f->frame_hdr, &b->mv[idx]); \
                 break; \
             case GLOBALMV: \
                 has_subpel_filter |= \
@@ -1438,6 +1436,7 @@
                     f->frame_hdr.gmv[b->ref[idx]].type == WM_TYPE_TRANSLATION; \
                 b->mv[idx] = get_gmv_2d(&f->frame_hdr.gmv[b->ref[idx]], \
                                         t->bx, t->by, bw4, bh4, &f->frame_hdr); \
+                fix_mv_precision(&f->frame_hdr, &b->mv[idx]); \
                 break; \
             case NEWMV: \
                 b->mv[idx] = mvstack[b->drl_idx].pfx##_mv; \
@@ -1557,6 +1556,7 @@
                     b->inter_mode = GLOBALMV;
                     b->mv[0] = get_gmv_2d(&f->frame_hdr.gmv[b->ref[0]],
                                           t->bx, t->by, bw4, bh4, &f->frame_hdr);
+                    fix_mv_precision(&f->frame_hdr, &b->mv[0]);
                     has_subpel_filter = imin(bw4, bh4) == 1 ||
                         f->frame_hdr.gmv[b->ref[0]].type == WM_TYPE_TRANSLATION;
                 } else {
@@ -1585,7 +1585,7 @@
                         b->mv[0] = mvstack[b->drl_idx].this_mv;
                     } else {
                         b->mv[0] = mvlist[0][b->drl_idx];
-                        if (!f->frame_hdr.hp) unset_hp_bit(&b->mv[0]);
+                        fix_mv_precision(&f->frame_hdr, &b->mv[0]);
                     }
                 }
 
@@ -1611,7 +1611,7 @@
                     b->mv[0] = mvstack[b->drl_idx].this_mv;
                 } else {
                     b->mv[0] = mvlist[0][0];
-                    if (!f->frame_hdr.hp) unset_hp_bit(&b->mv[0]);
+                    fix_mv_precision(&f->frame_hdr, &b->mv[0]);
                 }
                 if (DEBUG_BLOCK_INFO)
                     printf("Post-intermode[%d,drl=%d]: r=%d\n",
--- a/src/recon.c
+++ b/src/recon.c
@@ -1084,7 +1084,7 @@
         const Dav1dThreadPicture *const refp = &f->refp[b->ref[0]];
         const enum Filter2d filter_2d = b->filter2d;
 
-        if (imin(bw4, bh4) > 1 &&
+        if (imin(bw4, bh4) > 1 && !f->frame_hdr.force_integer_mv &&
             ((b->inter_mode == GLOBALMV &&
               f->frame_hdr.gmv[b->ref[0]].type > WM_TYPE_TRANSLATION) ||
              (b->motion_mode == MM_WARP &&
@@ -1184,7 +1184,7 @@
                 mc(t, ((pixel *) f->cur.p.data[1 + pl]) + uvdstoff + h_off + v_off, NULL, f->cur.p.stride[1],
                    bw4, bh4, t->bx, t->by, 1 + pl, b->mv[0], refp, filter_2d);
         } else {
-            if (imin(cbw4, cbh4) > 1 &&
+            if (imin(cbw4, cbh4) > 1 && !f->frame_hdr.force_integer_mv &&
                 ((b->inter_mode == GLOBALMV &&
                   f->frame_hdr.gmv[b->ref[0]].type > WM_TYPE_TRANSLATION) ||
                  (b->motion_mode == MM_WARP &&
@@ -1262,7 +1262,7 @@
         for (int i = 0; i < 2; i++) {
             const Dav1dThreadPicture *const refp = &f->refp[b->ref[i]];
 
-            if (b->inter_mode == GLOBALMV_GLOBALMV &&
+            if (b->inter_mode == GLOBALMV_GLOBALMV && !f->frame_hdr.force_integer_mv &&
                 f->frame_hdr.gmv[b->ref[i]].type > WM_TYPE_TRANSLATION)
             {
                 warp_affine(t, NULL, tmp[i], bw4 * 4, b_dim, 0, refp,
@@ -1303,7 +1303,7 @@
             for (int i = 0; i < 2; i++) {
                 const Dav1dThreadPicture *const refp = &f->refp[b->ref[i]];
                 if (b->inter_mode == GLOBALMV_GLOBALMV &&
-                    imin(cbw4, cbh4) > 1 &&
+                    imin(cbw4, cbh4) > 1 && !f->frame_hdr.force_integer_mv &&
                     f->frame_hdr.gmv[b->ref[i]].type > WM_TYPE_TRANSLATION)
                 {
                     warp_affine(t, NULL, tmp[i], bw4 * 2, b_dim, 1 + pl,
--- a/src/ref_mvs.h
+++ b/src/ref_mvs.h
@@ -156,15 +156,25 @@
     } while (--bh4);
 }
 
-// FIXME integer_mv
-static inline void unset_hp_bit(mv *const a) {
-    if (a->x & 1) {
-        if (a->x < 0) a->x++;
-        else          a->x--;
-    }
-    if (a->y & 1) {
-        if (a->y < 0) a->y++;
-        else          a->y--;
+static inline void fix_mv_precision(const Av1FrameHeader *const hdr,
+                                    mv *const mv)
+{
+    if (hdr->force_integer_mv) {
+        const int xmod = mv->x & 7;
+        mv->x &= ~7;
+        mv->x += (xmod > 4 - (mv->x < 0)) << 3;
+        const int ymod = mv->y & 7;
+        mv->y &= ~7;
+        mv->y += (ymod > 4 - (mv->y < 0)) << 3;
+    } else if (!hdr->hp) {
+        if (mv->x & 1) {
+            if (mv->x < 0) mv->x++;
+            else           mv->x--;
+        }
+        if (mv->y & 1) {
+            if (mv->y < 0) mv->y++;
+            else           mv->y--;
+        }
     }
 }