Add the max-tile tool with uniform tile support

This adds the tool CONFIG_MAX_TILE
Uniform tiles are implemented using power of two number of rows or columns.
Maximum number of rows or columns is 64
Explicit tiles will follow in a later commit once the command line API is updated for this

Change-Id: Ia8d22e7f4aa779448211496c644937afdf037228
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 4b72fb2..07a28e4 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -3601,6 +3601,72 @@
   }
 }
 
+#if CONFIG_MAX_TILE
+
+// Same function as write_uniform but writing to uncompresses header wb
+static void wb_write_uniform(struct aom_write_bit_buffer *wb, int n, int v) {
+  const int l = get_unsigned_bits(n);
+  const int m = (1 << l) - n;
+  if (l == 0) return;
+  if (v < m) {
+    aom_wb_write_literal(wb, v, l - 1);
+  } else {
+    aom_wb_write_literal(wb, m + ((v - m) >> 1), l - 1);
+    aom_wb_write_literal(wb, (v - m) & 1, 1);
+  }
+}
+
+static void write_tile_info_max_tile(const AV1_COMMON *const cm,
+                                     struct aom_write_bit_buffer *wb) {
+  int width_mi = ALIGN_POWER_OF_TWO(cm->mi_cols, MAX_MIB_SIZE_LOG2);
+  int height_mi = ALIGN_POWER_OF_TWO(cm->mi_rows, MAX_MIB_SIZE_LOG2);
+  int width_sb = width_mi >> MAX_MIB_SIZE_LOG2;
+  int height_sb = height_mi >> MAX_MIB_SIZE_LOG2;
+  int size_sb, i;
+
+  aom_wb_write_bit(wb, cm->uniform_tile_spacing_flag);
+
+  if (cm->uniform_tile_spacing_flag) {
+    // Uniform spaced tiles with power-of-two number of rows and columns
+    // tile columns
+    int ones = cm->log2_tile_cols - cm->min_log2_tile_cols;
+    while (ones--) {
+      aom_wb_write_bit(wb, 1);
+    }
+    if (cm->log2_tile_cols < cm->max_log2_tile_cols) {
+      aom_wb_write_bit(wb, 0);
+    }
+
+    // rows
+    ones = cm->log2_tile_rows - cm->min_log2_tile_rows;
+    while (ones--) {
+      aom_wb_write_bit(wb, 1);
+    }
+    if (cm->log2_tile_rows < cm->max_log2_tile_rows) {
+      aom_wb_write_bit(wb, 0);
+    }
+  } else {
+    // Explicit tiles with configurable tile widths and heights
+    // columns
+    for (i = 0; i < cm->tile_cols; i++) {
+      size_sb = cm->tile_col_start_sb[i + 1] - cm->tile_col_start_sb[i];
+      wb_write_uniform(wb, AOMMIN(width_sb, MAX_TILE_WIDTH_SB), size_sb - 1);
+      width_sb -= size_sb;
+    }
+    assert(width_sb == 0);
+
+    // rows
+    for (i = 0; i < cm->tile_rows; i++) {
+      size_sb = cm->tile_row_start_sb[i + 1] - cm->tile_row_start_sb[i];
+      wb_write_uniform(wb, AOMMIN(height_sb, cm->max_tile_height_sb),
+                       size_sb - 1);
+      height_sb -= size_sb;
+    }
+    assert(height_sb == 0);
+  }
+}
+#endif
+
 static void write_tile_info(const AV1_COMMON *const cm,
                             struct aom_write_bit_buffer *wb) {
 #if CONFIG_EXT_TILE
@@ -3633,20 +3699,25 @@
 #endif  // CONFIG_EXT_PARTITION
   } else {
 #endif  // CONFIG_EXT_TILE
-    int min_log2_tile_cols, max_log2_tile_cols, ones;
-    av1_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
 
-    // columns
-    ones = cm->log2_tile_cols - min_log2_tile_cols;
-    while (ones--) aom_wb_write_bit(wb, 1);
+#if CONFIG_MAX_TILE
+    write_tile_info_max_tile(cm, wb);
+#else
+  int min_log2_tile_cols, max_log2_tile_cols, ones;
+  av1_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
 
-    if (cm->log2_tile_cols < max_log2_tile_cols) aom_wb_write_bit(wb, 0);
+  // columns
+  ones = cm->log2_tile_cols - min_log2_tile_cols;
+  while (ones--) aom_wb_write_bit(wb, 1);
 
-    // rows
-    aom_wb_write_bit(wb, cm->log2_tile_rows != 0);
-    if (cm->log2_tile_rows != 0) aom_wb_write_bit(wb, cm->log2_tile_rows != 1);
+  if (cm->log2_tile_cols < max_log2_tile_cols) aom_wb_write_bit(wb, 0);
+
+  // rows
+  aom_wb_write_bit(wb, cm->log2_tile_rows != 0);
+  if (cm->log2_tile_rows != 0) aom_wb_write_bit(wb, cm->log2_tile_rows != 1);
+#endif
 #if CONFIG_DEPENDENT_HORZTILES
-    if (cm->log2_tile_rows != 0) aom_wb_write_bit(wb, cm->dependent_horz_tiles);
+    if (cm->tile_rows > 1) aom_wb_write_bit(wb, cm->dependent_horz_tiles);
 #endif
 #if CONFIG_EXT_TILE
   }
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 858c9af..0fcc8e6 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -863,6 +863,33 @@
 #endif
 }
 
+#if CONFIG_MAX_TILE
+
+static void set_tile_info_max_tile(AV1_COMP *cpi) {
+  AV1_COMMON *const cm = &cpi->common;
+
+  av1_get_tile_limits(cm);
+  // Configure uniform spaced tiles
+  // (API is not yet upgraded to general tiles)
+  cm->uniform_tile_spacing_flag = 1;
+
+  // configure tile columns
+  if (cm->uniform_tile_spacing_flag) {
+    cm->log2_tile_cols = AOMMAX(cpi->oxcf.tile_columns, cm->min_log2_tile_cols);
+    cm->log2_tile_cols = AOMMIN(cm->log2_tile_cols, cm->max_log2_tile_cols);
+  }
+  av1_calculate_tile_cols(cm);
+
+  // configure tile rows
+  if (cm->uniform_tile_spacing_flag) {
+    cm->log2_tile_rows = AOMMAX(cpi->oxcf.tile_rows, cm->min_log2_tile_rows);
+    cm->log2_tile_rows = AOMMIN(cm->log2_tile_rows, cm->max_log2_tile_rows);
+  }
+  av1_calculate_tile_rows(cm);
+}
+
+#endif
+
 static void set_tile_info(AV1_COMP *cpi) {
   AV1_COMMON *const cm = &cpi->common;
 #if CONFIG_DEPENDENT_HORZTILES
@@ -904,21 +931,26 @@
     while (cm->tile_rows * cm->tile_height < cm->mi_rows) ++cm->tile_rows;
   } else {
 #endif  // CONFIG_EXT_TILE
-    int min_log2_tile_cols, max_log2_tile_cols;
-    av1_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
 
-    cm->log2_tile_cols =
-        clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
-    cm->log2_tile_rows = cpi->oxcf.tile_rows;
+#if CONFIG_MAX_TILE
+    set_tile_info_max_tile(cpi);
+#else
+  int min_log2_tile_cols, max_log2_tile_cols;
+  av1_get_tile_n_bits(cm->mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
 
-    cm->tile_width = get_tile_size(cm->mi_cols, cm->log2_tile_cols);
-    cm->tile_height = get_tile_size(cm->mi_rows, cm->log2_tile_rows);
+  cm->log2_tile_cols =
+      clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
+  cm->log2_tile_rows = cpi->oxcf.tile_rows;
 
-    const int max_cols = (cm->mi_cols + cm->tile_width - 1) / cm->tile_width;
-    const int max_rows = (cm->mi_rows + cm->tile_height - 1) / cm->tile_height;
+  cm->tile_width = get_tile_size(cm->mi_cols, cm->log2_tile_cols);
+  cm->tile_height = get_tile_size(cm->mi_rows, cm->log2_tile_rows);
 
-    cm->tile_cols = AOMMIN(1 << cm->log2_tile_cols, max_cols);
-    cm->tile_rows = AOMMIN(1 << cm->log2_tile_rows, max_rows);
+  const int max_cols = (cm->mi_cols + cm->tile_width - 1) / cm->tile_width;
+  const int max_rows = (cm->mi_rows + cm->tile_height - 1) / cm->tile_height;
+
+  cm->tile_cols = AOMMIN(1 << cm->log2_tile_cols, max_cols);
+  cm->tile_rows = AOMMIN(1 << cm->log2_tile_rows, max_rows);
+#endif  // CONFIG_MAX_TILE
 #if CONFIG_EXT_TILE
   }
 #endif  // CONFIG_EXT_TILE