Add chroma 2x2 block experiment

Support the use of 2x2 prediction and transform block size for
chroma components. This experiment builds on top of cb4x4. It
brings back the loss in performance gains due to 4x4 chroma
component constrain. The coding gains for lowres are up from 1.5%
to 2.5%.

Change-Id: I8e461e230c2d920f6df1af9d935ebe9dfa3820d9
diff --git a/av1/common/blockd.c b/av1/common/blockd.c
index a0342db..a689b81 100644
--- a/av1/common/blockd.c
+++ b/av1/common/blockd.c
@@ -130,7 +130,7 @@
   // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
   // transform size varies per plane, look it up in a common way.
   const TX_SIZE tx_size = plane ? get_uv_tx_size(mbmi, pd) : mbmi->tx_size;
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
   const BLOCK_SIZE plane_bsize =
       AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
 #else
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index 950e564..a79cd08 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -924,7 +924,7 @@
 
   uv_txsize = uv_txsize_lookup[mbmi->sb_type][mbmi->tx_size][pd->subsampling_x]
                               [pd->subsampling_y];
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
   uv_txsize = AOMMAX(uv_txsize, TX_4X4);
 #endif
   assert(uv_txsize != TX_INVALID);
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index fd70332..6bb0ce3 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -585,8 +585,10 @@
     xd->plane[i].width = (bw * MI_SIZE) >> xd->plane[i].subsampling_x;
     xd->plane[i].height = (bh * MI_SIZE) >> xd->plane[i].subsampling_y;
 
+#if !CONFIG_CHROMA_2X2
     xd->plane[i].width = AOMMAX(xd->plane[i].width, 4);
     xd->plane[i].height = AOMMAX(xd->plane[i].height, 4);
+#endif
   }
 }
 
@@ -728,6 +730,9 @@
 
 #if CONFIG_CB4X4
 static INLINE int is_chroma_reference(const int mi_row, const int mi_col) {
+#if CONFIG_CHROMA_2X2
+  return 1;
+#endif
   return !((mi_row & 0x01) || (mi_col & 0x01));
 }
 #endif
diff --git a/av1/common/reconintra.c b/av1/common/reconintra.c
index 367efdd..bdb9e5e 100644
--- a/av1/common/reconintra.c
+++ b/av1/common/reconintra.c
@@ -1895,7 +1895,7 @@
   const int mi_col = -xd->mb_to_left_edge >> (3 + MI_SIZE_LOG2);
   const int txwpx = tx_size_wide[tx_size];
   const int txhpx = tx_size_high[tx_size];
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
   const int xr_chr_offset = (plane && bsize < BLOCK_8X8) ? 2 : 0;
   const int yd_chr_offset = (plane && bsize < BLOCK_8X8) ? 2 : 0;
 #else
@@ -1918,7 +1918,7 @@
   const PARTITION_TYPE partition = xd->mi[0]->mbmi.partition;
 #endif
 
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
   // force 4x4 chroma component block size.
   if (plane && bsize < BLOCK_8X8) bsize = BLOCK_8X8;
 #endif
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index b9cb37a..8447606 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1659,8 +1659,12 @@
       const int stepr = tx_size_high_unit[tx_size];
       const int stepc = tx_size_wide_unit[tx_size];
 #if CONFIG_CB4X4
+#if CONFIG_CHROMA_2X2
+      const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
+#else
       const BLOCK_SIZE plane_bsize =
           AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
+#endif  // CONFIG_CHROMA_2X2
 #else
       const BLOCK_SIZE plane_bsize =
           get_plane_block_size(AOMMAX(BLOCK_8X8, bsize), pd);
@@ -1744,8 +1748,12 @@
       for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
         const struct macroblockd_plane *const pd = &xd->plane[plane];
 #if CONFIG_CB4X4
+#if CONFIG_CHROMA_2X2
+        const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd);
+#else
         const BLOCK_SIZE plane_bsize =
             AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
+#endif  // CONFIG_CHROMA_2X2
 #else
         const BLOCK_SIZE plane_bsize =
             get_plane_block_size(AOMMAX(BLOCK_8X8, bsize), pd);
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index 567cf01..12a0004 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -887,7 +887,7 @@
   if (x->skip) return;
 
   for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
     if (bsize < BLOCK_8X8 && plane && !is_chroma_reference(mi_row, mi_col))
       continue;
     if (plane) bsize = AOMMAX(bsize, BLOCK_8X8);
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 54a3225..bf6c94c 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -974,7 +974,7 @@
   for (plane = plane_from; plane <= plane_to; ++plane) {
     struct macroblock_plane *const p = &x->plane[plane];
     struct macroblockd_plane *const pd = &xd->plane[plane];
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
     const BLOCK_SIZE bs = AOMMAX(BLOCK_4X4, get_plane_block_size(bsize, pd));
 #else
     const BLOCK_SIZE bs = get_plane_block_size(bsize, pd);
@@ -3721,7 +3721,7 @@
 
   if (ref_best_rd < 0) is_cost_valid = 0;
 
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
   if (x->skip_chroma_rd) return is_cost_valid;
   bsize = AOMMAX(BLOCK_8X8, bsize);
 #endif
@@ -4347,7 +4347,7 @@
 
   av1_init_rd_stats(rd_stats);
 
-#if CONFIG_CB4X4
+#if CONFIG_CB4X4 && !CONFIG_CHROMA_2X2
   if (x->skip_chroma_rd) return is_cost_valid;
   bsize = AOMMAX(BLOCK_8X8, bsize);
 #endif
@@ -4845,6 +4845,10 @@
   // appropriate speed flag is set.
   (void)ctx;
 #if CONFIG_CB4X4
+#if CONFIG_CHROMA_2X2
+  rd_pick_intra_sbuv_mode(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
+                          bsize, max_tx_size);
+#else
   max_tx_size = AOMMAX(max_tx_size, TX_4X4);
   if (x->skip_chroma_rd) {
     *rate_uv = 0;
@@ -4854,10 +4858,13 @@
     *mode_uv = DC_PRED;
     return;
   }
-#endif
-
   rd_pick_intra_sbuv_mode(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
                           bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize, max_tx_size);
+#endif  // CONFIG_CHROMA_2X2
+#else
+  rd_pick_intra_sbuv_mode(cpi, x, rate_uv, rate_uv_tokenonly, dist_uv, skip_uv,
+                          bsize < BLOCK_8X8 ? BLOCK_8X8 : bsize, max_tx_size);
+#endif  // CONFIG_CB4X4
   *mode_uv = x->e_mbd.mi[0]->mbmi.uv_mode;
 }
 
@@ -9059,7 +9066,9 @@
                                    [pd[1].subsampling_x][pd[1].subsampling_y];
 
 #if CONFIG_CB4X4
+#if !CONFIG_CHROMA_2X2
   max_uv_tx_size = AOMMAX(max_uv_tx_size, TX_4X4);
+#endif
   if (!x->skip_chroma_rd)
     rd_pick_intra_sbuv_mode(cpi, x, &rate_uv, &rate_uv_tokenonly, &dist_uv,
                             &uv_skip, bsize, max_uv_tx_size);