Fix encode/decode mismatch with global/warped motion

When predicting a 4x4 warp block (either using ZEROMV with
global-motion, or the WARPED_CAUSAL motion mode with
warped-motion), the warp filter would previously write
4 bytes to the right of the block.

This caused encode/decode mismatches when encoding with
multiple threads and tile_cols > 1, since in that case
we could end up overwriting already-generated pixels from
the next tile across.

This patch changes the filter so that we only overwrite the
intended pixels.

Change-Id: I3664b44e872e85aa5ccc0a5781f0f9ad994a5b80
diff --git a/av1/common/warped_motion.c b/av1/common/warped_motion.c
index 37358bc..7604cc8 100644
--- a/av1/common/warped_motion.c
+++ b/av1/common/warped_motion.c
@@ -1301,7 +1301,7 @@
       // Vertical filter
       for (k = -4; k < AOMMIN(4, p_row + p_height - i - 4); ++k) {
         int sy = sy4 + gamma * (-4) + delta * k;
-        for (l = -4; l < 4; ++l) {
+        for (l = -4; l < AOMMIN(4, p_col + p_width - j - 4); ++l) {
           uint8_t *p =
               &pred[(i - p_row + k + 4) * p_stride + (j - p_col + l + 4)];
           // At this point, sy = sy4 + gamma * l + delta * k
diff --git a/av1/common/x86/highbd_warp_plane_ssse3.c b/av1/common/x86/highbd_warp_plane_ssse3.c
index 5404876..89b60b0 100644
--- a/av1/common/x86/highbd_warp_plane_ssse3.c
+++ b/av1/common/x86/highbd_warp_plane_ssse3.c
@@ -270,12 +270,15 @@
         // Store, blending with 'pred' if needed
         __m128i *p = (__m128i *)&pred[(i + k + 4) * p_stride + j];
 
-        if (ref_frm) {
-          __m128i orig = _mm_loadu_si128(p);
-          _mm_storeu_si128(p, _mm_avg_epu16(res_16bit, orig));
-        } else {
+        if (ref_frm) res_16bit = _mm_avg_epu16(res_16bit, _mm_loadu_si128(p));
+
+        // Note: If we're outputting a 4x4 block, we need to be very careful
+        // to only output 4 pixels at this point, to avoid encode/decode
+        // mismatches when encoding with multiple threads.
+        if (p_width == 4)
+          _mm_storel_epi64(p, res_16bit);
+        else
           _mm_storeu_si128(p, res_16bit);
-        }
       }
     }
   }
diff --git a/av1/common/x86/warp_plane_sse2.c b/av1/common/x86/warp_plane_sse2.c
index 48de1ac..31de232 100644
--- a/av1/common/x86/warp_plane_sse2.c
+++ b/av1/common/x86/warp_plane_sse2.c
@@ -276,12 +276,15 @@
         // Store, blending with 'pred' if needed
         __m128i *p = (__m128i *)&pred[(i + k + 4) * p_stride + j];
 
-        if (ref_frm) {
-          __m128i orig = _mm_loadl_epi64(p);
-          _mm_storel_epi64(p, _mm_avg_epu8(res_8bit, orig));
-        } else {
+        if (ref_frm) res_8bit = _mm_avg_epu8(res_8bit, _mm_loadl_epi64(p));
+
+        // Note: If we're outputting a 4x4 block, we need to be very careful
+        // to only output 4 pixels at this point, to avoid encode/decode
+        // mismatches when encoding with multiple threads.
+        if (p_width == 4)
+          *(uint32_t *)p = _mm_cvtsi128_si32(res_8bit);
+        else
           _mm_storel_epi64(p, res_8bit);
-        }
       }
     }
   }