[NORMATIVE] Film grain for odd frame dimensions

BUG=aomedia:1598

Change-Id: Ib956914578bc94a5dc465c9b5ef4ee94a0f21480
diff --git a/aom_dsp/grain_synthesis.c b/aom_dsp/grain_synthesis.c
index 01f518e..880144d 100644
--- a/aom_dsp/grain_synthesis.c
+++ b/aom_dsp/grain_synthesis.c
@@ -792,6 +792,33 @@
   return;
 }
 
+static void extend_even(uint8_t *dst, int dst_stride, int width, int height,
+                        int use_high_bit_depth) {
+  if ((width & 1) == 0 && (height & 1) == 0) return;
+  if (use_high_bit_depth) {
+    uint16_t *dst16 = (uint16_t *)dst;
+    if (width & 1) {
+      for (int i = 0; i < height; ++i)
+        dst16[i * dst_stride + width] = dst16[i * dst_stride + width - 1];
+    }
+    width = (width + 1) & (~1);
+    if (height & 1) {
+      memcpy(&dst16[height * dst_stride], &dst16[(height - 1) * dst_stride],
+             sizeof(*dst16) * width);
+    }
+  } else {
+    if (width & 1) {
+      for (int i = 0; i < height; ++i)
+        dst[i * dst_stride + width] = dst[i * dst_stride + width - 1];
+    }
+    width = (width + 1) & (~1);
+    if (height & 1) {
+      memcpy(&dst[height * dst_stride], &dst[(height - 1) * dst_stride],
+             sizeof(*dst) * width);
+    }
+  }
+}
+
 static void ver_boundary_overlap(int *left_block, int left_stride,
                                  int *right_block, int right_stride,
                                  int *dst_block, int dst_stride, int width,
@@ -900,20 +927,28 @@
 
   dst->r_w = src->r_w;
   dst->r_h = src->r_h;
+  dst->d_w = src->d_w;
+  dst->d_h = src->d_h;
+
+  width = src->d_w % 2 ? src->d_w + 1 : src->d_w;
+  height = src->d_h % 2 ? src->d_h + 1 : src->d_h;
 
   copy_rect(src->planes[AOM_PLANE_Y], src->stride[AOM_PLANE_Y],
-            dst->planes[AOM_PLANE_Y], dst->stride[AOM_PLANE_Y], dst->d_w,
-            dst->d_h, use_high_bit_depth);
+            dst->planes[AOM_PLANE_Y], dst->stride[AOM_PLANE_Y], src->d_w,
+            src->d_h, use_high_bit_depth);
+  // Note that dst is already assumed to be aligned to even.
+  extend_even(dst->planes[AOM_PLANE_Y], dst->stride[AOM_PLANE_Y], src->d_w,
+              src->d_h, use_high_bit_depth);
 
   if (!src->monochrome) {
     copy_rect(src->planes[AOM_PLANE_U], src->stride[AOM_PLANE_U],
               dst->planes[AOM_PLANE_U], dst->stride[AOM_PLANE_U],
-              dst->d_w >> chroma_subsamp_x, dst->d_h >> chroma_subsamp_y,
+              width >> chroma_subsamp_x, height >> chroma_subsamp_y,
               use_high_bit_depth);
 
     copy_rect(src->planes[AOM_PLANE_V], src->stride[AOM_PLANE_V],
               dst->planes[AOM_PLANE_V], dst->stride[AOM_PLANE_V],
-              dst->d_w >> chroma_subsamp_x, dst->d_h >> chroma_subsamp_y,
+              width >> chroma_subsamp_x, height >> chroma_subsamp_y,
               use_high_bit_depth);
   }
 
@@ -925,8 +960,6 @@
   luma_stride = dst->stride[AOM_PLANE_Y] >> use_high_bit_depth;
   chroma_stride = dst->stride[AOM_PLANE_U] >> use_high_bit_depth;
 
-  width = dst->d_w;
-  height = dst->d_h;
   params->bit_depth = dst->bit_depth;
 
   av1_add_film_grain_run(params, luma, cb, cr, height, width, luma_stride,
diff --git a/av1/av1_dx_iface.c b/av1/av1_dx_iface.c
index 052f3b7..e5d56bd 100644
--- a/av1/av1_dx_iface.c
+++ b/av1/av1_dx_iface.c
@@ -519,12 +519,14 @@
 
   if (grain_img_buf &&
       (img->d_w != grain_img_buf->d_w || img->d_h != grain_img_buf->d_h ||
-       img->fmt != grain_img_buf->fmt)) {
+       img->fmt != grain_img_buf->fmt || !(img->d_h % 2) || !(img->d_w % 2))) {
     aom_img_free(grain_img_buf);
     grain_img_buf = NULL;
   }
   if (!grain_img_buf) {
-    grain_img_buf = aom_img_alloc(NULL, img->fmt, img->d_w, img->d_h, 16);
+    int w_even = img->d_w % 2 ? img->d_w + 1 : img->d_w;
+    int h_even = img->d_h % 2 ? img->d_h + 1 : img->d_h;
+    grain_img_buf = aom_img_alloc(NULL, img->fmt, w_even, h_even, 16);
     grain_img_buf->bit_depth = img->bit_depth;
   }