av1: Allow odd width/height for YUV420

Allow odd width/height values for the gav1 software decoder.

Notes:
* We already allocate the graphic block with a stride that is a
  multiple of 16, that behavior is retained.
* We also allocate the graphic buffer with a height alignment of 2 (this
  change is needed because fetchGraphicBlock fails for odd height
  values.
* We set the correct "crop" value in createGraphicBuffer() which will
  handle odd width/height appropriately.
* This change also enables decoding of AVIF images that have odd
  dimensions.

This CL contains changes to the mainline files.

Test: CtsMediaTestCases still pass
Bug: 175243729

Change-Id: I6b811fed5cc9c599177fffd24d4d96d65c52ae8e
(cherry picked from commit db0859ec13856e57a6107a615279cf7ad19013d6)
Merged-In: I6b811fed5cc9c599177fffd24d4d96d65c52ae8e
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 434246f..5295822 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -45,23 +45,23 @@
 
     if (isMonochrome) {
         // Fill with neutral U/V values.
-        for (size_t i = 0; i < height / 2; ++i) {
-            memset(dstV, kNeutralUVBitDepth8, width / 2);
-            memset(dstU, kNeutralUVBitDepth8, width / 2);
+        for (size_t i = 0; i < (height + 1) / 2; ++i) {
+            memset(dstV, kNeutralUVBitDepth8, (width + 1) / 2);
+            memset(dstU, kNeutralUVBitDepth8, (width + 1) / 2);
             dstV += dstUVStride;
             dstU += dstUVStride;
         }
         return;
     }
 
-    for (size_t i = 0; i < height / 2; ++i) {
-        memcpy(dstV, srcV, width / 2);
+    for (size_t i = 0; i < (height + 1) / 2; ++i) {
+        memcpy(dstV, srcV, (width + 1) / 2);
         srcV += srcVStride;
         dstV += dstUVStride;
     }
 
-    for (size_t i = 0; i < height / 2; ++i) {
-        memcpy(dstU, srcU, width / 2);
+    for (size_t i = 0; i < (height + 1) / 2; ++i) {
+        memcpy(dstU, srcU, (width + 1) / 2);
         srcU += srcUStride;
         dstU += dstUVStride;
     }
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 2ed8541..e5fbe99 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -55,8 +55,8 @@
         DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
             .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
             .withFields({
-                C2F(mSize, width).inRange(2, 4096, 2),
-                C2F(mSize, height).inRange(2, 4096, 2),
+                C2F(mSize, width).inRange(2, 4096),
+                C2F(mSize, height).inRange(2, 4096),
             })
             .withSetter(SizeSetter)
             .build());
@@ -650,8 +650,12 @@
   }
   C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
 
-  c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16), mHeight, format,
-                                            usage, &block);
+  // We always create a graphic block that is width aligned to 16 and height
+  // aligned to 2. We set the correct "crop" value of the image in the call to
+  // createGraphicBuffer() by setting the correct image dimensions.
+  c2_status_t err = pool->fetchGraphicBlock(align(mWidth, 16),
+                                            align(mHeight, 2), format, usage,
+                                            &block);
 
   if (err != C2_OK) {
     ALOGE("fetchGraphicBlock for Output failed with status %d", err);