Add tile column size limits (256 pixels min, 4096 pixels max).
authorRonald S. Bultje <rbultje@google.com>
Wed, 6 Feb 2013 23:30:21 +0000 (15:30 -0800)
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>
Tue, 12 Feb 2013 18:33:34 +0000 (10:33 -0800)
This is after discussion with the hardware team. Update the unit test
to take these sizes into account. Split out some duplicate code into
a separate file so it can be shared.

Change-Id: I8311d11b0191d8bb37e8eb4ac962beb217e1bff5

12 files changed:
test/tile_independence_test.cc
vp9/common/vp9_onyxc_int.h
vp9/common/vp9_tile_common.c [new file with mode: 0644]
vp9/common/vp9_tile_common.h [new file with mode: 0644]
vp9/decoder/vp9_decodframe.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_encodeframe.c
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_segmentation.c
vp9/vp9_common.mk
vp9/vp9_cx_iface.c
vpx/vp8cx.h

index e9d2ca8..c9f82ef 100644 (file)
@@ -29,8 +29,8 @@ class TileIndependenceTest : public ::libvpx_test::EncoderTest,
       md5_fw_order_(), md5_inv_order_() {
     init_flags_ = VPX_CODEC_USE_PSNR;
     vpx_codec_dec_cfg_t cfg;
-    cfg.w = 352;
-    cfg.h = 288;
+    cfg.w = 704;
+    cfg.h = 144;
     cfg.threads = 1;
     cfg.inv_tile_order = 0;
     fw_dec_ = codec_->CreateDecoder(cfg, 0);
@@ -83,7 +83,7 @@ TEST_P(TileIndependenceTest, MD5Match) {
   cfg_.g_lag_in_frames = 25;
   cfg_.rc_end_usage = VPX_VBR;
 
-  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 704, 144,
                                      timebase.den, timebase.num, 0, 30);
   ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
 
@@ -97,7 +97,6 @@ TEST_P(TileIndependenceTest, MD5Match) {
 }
 
 VP9_INSTANTIATE_TEST_CASE(TileIndependenceTest,
-                          ::testing::Values(VP8_TWO_TILE_COLUMNS,
-                                            VP8_FOUR_TILE_COLUMNS));
+                          ::testing::Range(0, 2, 1));
 
 }  // namespace
index 5e57228..a333a4b 100644 (file)
@@ -279,7 +279,7 @@ typedef struct VP9Common {
   int error_resilient_mode;
   int frame_parallel_decoding_mode;
 
-  int tile_columns;
+  int tile_columns, log2_tile_columns;
   int cur_tile_mb_col_start, cur_tile_mb_col_end, cur_tile_idx;
 } VP9_COMMON;
 
diff --git a/vp9/common/vp9_tile_common.c b/vp9/common/vp9_tile_common.c
new file mode 100644 (file)
index 0000000..02e0d14
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "vp9/common/vp9_tile_common.h"
+
+void vp9_get_tile_offsets(VP9_COMMON *cm, int *min_tile_off,
+                          int *max_tile_off) {
+  const int log2_n_tiles = cm->log2_tile_columns;
+  const int tile_idx = cm->cur_tile_idx;
+  const int mb_cols = cm->mb_cols;
+  const int sb_cols = (mb_cols + 3) >> 2;
+  const int sb_off1 = (tile_idx * sb_cols) >> log2_n_tiles;
+  const int sb_off2 = ((tile_idx + 1) * sb_cols) >> log2_n_tiles;
+
+  *min_tile_off = (sb_off1 << 2) > mb_cols ? mb_cols : (sb_off1 << 2);
+  *max_tile_off = (sb_off2 << 2) > mb_cols ? mb_cols : (sb_off2 << 2);
+}
+
+#define MIN_TILE_WIDTH_SBS (MIN_TILE_WIDTH >> 6)
+#define MAX_TILE_WIDTH_SBS (MAX_TILE_WIDTH >> 6)
+
+void vp9_get_tile_n_bits(VP9_COMMON *cm, int *min_log2_n_tiles_ptr,
+                         int *delta_log2_n_tiles) {
+  const int sb_cols = (cm->mb_cols + 3) >> 2;
+  int min_log2_n_tiles, max_log2_n_tiles;
+
+  for (max_log2_n_tiles = 0;
+       (sb_cols >> max_log2_n_tiles) >= MIN_TILE_WIDTH_SBS;
+       max_log2_n_tiles++) {}
+  for (min_log2_n_tiles = 0;
+       (MAX_TILE_WIDTH_SBS << min_log2_n_tiles) < sb_cols;
+       min_log2_n_tiles++) {}
+
+  *min_log2_n_tiles_ptr = min_log2_n_tiles;
+  *delta_log2_n_tiles = max_log2_n_tiles - min_log2_n_tiles;
+}
diff --git a/vp9/common/vp9_tile_common.h b/vp9/common/vp9_tile_common.h
new file mode 100644 (file)
index 0000000..653b6b4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef VP9_COMMON_VP9_TILE_COMMON_H_
+#define VP9_COMMON_VP9_TILE_COMMON_H_
+
+#include "vp9/common/vp9_onyxc_int.h"
+
+#define MIN_TILE_WIDTH 256
+#define MAX_TILE_WIDTH 4096
+
+extern void vp9_get_tile_offsets(VP9_COMMON *cm, int *min_tile_off,
+                                 int *max_tile_off);
+
+extern void vp9_get_tile_n_bits(VP9_COMMON *cm, int *min_log2_n_tiles,
+                                int *delta_log2_n_tiles);
+
+#endif  // VP9_COMMON_VP9_TILE_COMMON_H_
index 3324186..b8e867a 100644 (file)
@@ -31,6 +31,7 @@
 #include "vp9/decoder/vp9_dboolhuff.h"
 
 #include "vp9/common/vp9_seg_common.h"
+#include "vp9/common/vp9_tile_common.h"
 #include "vp9_rtcd.h"
 
 #include <assert.h>
@@ -1769,15 +1770,18 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
 
   /* tile info */
   {
-    int log2_tile_cols;
     const unsigned char *data_ptr = data + first_partition_length_in_bytes;
-    int tile, mb_start, mb_end;
+    int tile, delta_log2_tiles;
 
-    log2_tile_cols = vp9_read_bit(&header_bc);
-    if (log2_tile_cols) {
-      log2_tile_cols += vp9_read_bit(&header_bc);
+    vp9_get_tile_n_bits(pc, &pc->log2_tile_columns, &delta_log2_tiles);
+    while (delta_log2_tiles--) {
+      if (vp9_read_bit(&header_bc)) {
+        pc->log2_tile_columns++;
+      } else {
+        break;
+      }
     }
-    pc->tile_columns = 1 << log2_tile_cols;
+    pc->tile_columns = 1 << pc->log2_tile_columns;
 
     vpx_memset(pc->above_context, 0,
                sizeof(ENTROPY_CONTEXT_PLANES) * pc->mb_cols);
@@ -1793,39 +1797,25 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
         data_ptr2[tile - 1] += 4;
         data_ptr2[tile] = data_ptr2[tile - 1] + size;
       }
-      for (mb_end = pc->mb_cols, tile = pc->tile_columns - 1;
-           tile >= 0; tile--) {
-        // calculate end of tile column
-        const int sb_cols = (pc->mb_cols + 3) >> 2;
-        const int sb_start = (sb_cols * tile) >> log2_tile_cols;
-        mb_start = ((sb_start << 2) > pc->mb_cols) ?
-                    pc->mb_cols : (sb_start << 2);
-
+      for (tile = pc->tile_columns - 1; tile >= 0; tile--) {
         pc->cur_tile_idx = tile;
-        pc->cur_tile_mb_col_start = mb_start;
-        pc->cur_tile_mb_col_end   = mb_end;
-
+        vp9_get_tile_offsets(pc, &pc->cur_tile_mb_col_start,
+                             &pc->cur_tile_mb_col_end);
         setup_token_decoder(pbi, data_ptr2[tile], &residual_bc);
 
         /* Decode a row of superblocks */
         for (mb_row = 0; mb_row < pc->mb_rows; mb_row += 4) {
           decode_sb_row(pbi, pc, mb_row, xd, &residual_bc);
         }
-        mb_end = mb_start;
         if (tile == pc->tile_columns - 1)
           bc_bak = residual_bc;
       }
       residual_bc = bc_bak;
     } else {
-      for (mb_start = 0, tile = 0; tile < pc->tile_columns; tile++) {
-        // calculate end of tile column
-        const int sb_cols = (pc->mb_cols + 3) >> 2;
-        const int sb_end = (sb_cols * (tile + 1)) >> log2_tile_cols;
-        mb_end = ((sb_end << 2) > pc->mb_cols) ? pc->mb_cols : (sb_end << 2);
-
+      for (tile = 0; tile < pc->tile_columns; tile++) {
         pc->cur_tile_idx = tile;
-        pc->cur_tile_mb_col_start = mb_start;
-        pc->cur_tile_mb_col_end   = mb_end;
+        vp9_get_tile_offsets(pc, &pc->cur_tile_mb_col_start,
+                             &pc->cur_tile_mb_col_end);
 
         if (tile < pc->tile_columns - 1)
           setup_token_decoder(pbi, data_ptr + 4, &residual_bc);
@@ -1836,7 +1826,6 @@ int vp9_decode_frame(VP9D_COMP *pbi, const unsigned char **p_data_end) {
         for (mb_row = 0; mb_row < pc->mb_rows; mb_row += 4) {
           decode_sb_row(pbi, pc, mb_row, xd, &residual_bc);
         }
-        mb_start = mb_end;
         if (tile < pc->tile_columns - 1) {
           int size = data_ptr[0] + (data_ptr[1] << 8) + (data_ptr[2] << 16) +
                     (data_ptr[3] << 24);
index a3c4078..c5f2a70 100644 (file)
@@ -14,6 +14,7 @@
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_entropymv.h"
 #include "vp9/common/vp9_findnearmv.h"
+#include "vp9/common/vp9_tile_common.h"
 #include "vp9/encoder/vp9_mcomp.h"
 #include "vp9/common/vp9_systemdependent.h"
 #include <assert.h>
@@ -2026,9 +2027,19 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
   }
 
   /* tiling */
-  vp9_write(&header_bc, pc->tile_columns > 1, 128);
-  if (pc->tile_columns > 1) {
-    vp9_write(&header_bc, pc->tile_columns > 2, 128);
+  {
+    int min_log2_tiles, delta_log2_tiles, n_tile_bits, n;
+
+    vp9_get_tile_n_bits(pc, &min_log2_tiles, &delta_log2_tiles);
+    n_tile_bits = pc->log2_tile_columns - min_log2_tiles;
+    for (n = 0; n < delta_log2_tiles; n++) {
+      if (n_tile_bits--) {
+        vp9_write_bit(&header_bc, 1);
+      } else {
+        vp9_write_bit(&header_bc, 0);
+        break;
+      }
+    }
   }
 
   vp9_stop_encode(&header_bc);
@@ -2058,21 +2069,14 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
   }
 
   {
-    int mb_start = 0, tile;
-    int total_size = 0;
+    int tile, total_size = 0;
     unsigned char *data_ptr = cx_data + header_bc.pos;
     TOKENEXTRA *tok = cpi->tok;
 
     for (tile = 0; tile < pc->tile_columns; tile++) {
-      // calculate end of tile column
-      const int sb_cols = (pc->mb_cols + 3) >> 2;
-      const int sb_end = (sb_cols * (tile + 1)) >> cpi->oxcf.tile_columns;
-      const int mb_end = ((sb_end << 2) > pc->mb_cols) ?
-                          pc->mb_cols : (sb_end << 2);
-
       pc->cur_tile_idx = tile;
-      pc->cur_tile_mb_col_start = mb_start;
-      pc->cur_tile_mb_col_end = mb_end;
+      vp9_get_tile_offsets(pc, &pc->cur_tile_mb_col_start,
+                           &pc->cur_tile_mb_col_end);
 
       if (tile < pc->tile_columns - 1)
         vp9_start_encode(&residual_bc, data_ptr + total_size + 4);
@@ -2089,7 +2093,6 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
         total_size += 4;
       }
 
-      mb_start = mb_end;
       total_size += residual_bc.pos;
     }
 
index 927a1b9..c5f717f 100644 (file)
@@ -28,6 +28,7 @@
 #include "vp9/common/vp9_findnearmv.h"
 #include "vp9/common/vp9_reconintra.h"
 #include "vp9/common/vp9_seg_common.h"
+#include "vp9/common/vp9_tile_common.h"
 #include "vp9/encoder/vp9_tokenize.h"
 #include "vp9_rtcd.h"
 #include <stdio.h>
@@ -1312,23 +1313,16 @@ static void encode_frame_internal(VP9_COMP *cpi) {
 
     {
       // Take tiles into account and give start/end MB
-      int tile, mb_start = 0;
+      int tile;
 
       for (tile = 0; tile < cm->tile_columns; tile++) {
-        // calculate end of tile column
-        const int sb_cols = (cm->mb_cols + 3) >> 2;
-        const int sb_end = (sb_cols * (tile + 1)) >> cpi->oxcf.tile_columns;
-        const int mb_end = ((sb_end << 2) > cm->mb_cols) ?
-                            cm->mb_cols : (sb_end << 2);
-
         // For each row of SBs in the frame
         cm->cur_tile_idx = tile;
-        cm->cur_tile_mb_col_start = mb_start;
-        cm->cur_tile_mb_col_end = mb_end;
+        vp9_get_tile_offsets(cm, &cm->cur_tile_mb_col_start,
+                             &cm->cur_tile_mb_col_end);
         for (mb_row = 0; mb_row < cm->mb_rows; mb_row += 4) {
           encode_sb_row(cpi, mb_row, &tp, &totalrate);
         }
-        mb_start = mb_end;
       }
 
       cpi->tok_count = (unsigned int)(tp - cpi->tok);
index ad5fe78..73b7b1f 100644 (file)
@@ -23,6 +23,7 @@
 #include "vp9/common/vp9_extend.h"
 #include "vp9/encoder/vp9_ratectrl.h"
 #include "vp9/common/vp9_quant_common.h"
+#include "vp9/common/vp9_tile_common.h"
 #include "vp9/encoder/vp9_segmentation.h"
 #include "./vp9_rtcd.h"
 #include "./vpx_scale_rtcd.h"
@@ -949,7 +950,6 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) {
     vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate scaled source buffer");
 
-
   vpx_free(cpi->tok);
 
   {
@@ -1107,6 +1107,17 @@ rescale(int val, int num, int denom) {
   return (int)(llval * llnum / llden);
 }
 
+static void set_tile_limits(VP9_COMMON *cm) {
+  int min_log2_tiles, max_log2_tiles;
+
+  vp9_get_tile_n_bits(cm, &min_log2_tiles, &max_log2_tiles);
+  max_log2_tiles += min_log2_tiles;
+  if (cm->log2_tile_columns < min_log2_tiles)
+    cm->log2_tile_columns = min_log2_tiles;
+  else if (cm->log2_tile_columns > max_log2_tiles)
+    cm->log2_tile_columns = max_log2_tiles;
+  cm->tile_columns = 1 << cm->log2_tile_columns;
+}
 
 static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
   VP9_COMP *cpi = (VP9_COMP *)(ptr);
@@ -1145,7 +1156,8 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
   cpi->gld_fb_idx = 1;
   cpi->alt_fb_idx = 2;
 
-  cm->tile_columns = 1 << cpi->oxcf.tile_columns;
+  cm->log2_tile_columns = cpi->oxcf.tile_columns;
+  set_tile_limits(cm);
 
 #if VP9_TEMPORAL_ALT_REF
   {
@@ -1372,7 +1384,8 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
   cpi->last_frame_distortion = 0;
 #endif
 
-  cm->tile_columns = 1 << cpi->oxcf.tile_columns;
+  cm->log2_tile_columns = cpi->oxcf.tile_columns;
+  set_tile_limits(cm);
 }
 
 #define M_LOG2_E 0.693147180559945309417
index 17d8f25..710ca7e 100644 (file)
@@ -13,6 +13,7 @@
 #include "vpx_mem/vpx_mem.h"
 #include "vp9/encoder/vp9_segmentation.h"
 #include "vp9/common/vp9_pred_common.h"
+#include "vp9/common/vp9_tile_common.h"
 
 void vp9_update_gf_useage_maps(VP9_COMP *cpi, VP9_COMMON *cm, MACROBLOCK *x) {
   int mb_row, mb_col;
@@ -254,7 +255,7 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) {
   int t_pred_cost = INT_MAX;
 
   int i;
-  int tile, mb_row, mb_col, mb_start = 0;
+  int tile, mb_row, mb_col;
 
   int temporal_predictor_count[PREDICTION_PROBS][2];
   int no_pred_segcounts[MAX_MB_SEGMENTS];
@@ -283,20 +284,14 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) {
   // predicts this one
 
   for (tile = 0; tile < cm->tile_columns; tile++) {
-    // calculate end of tile column
-    const int sb_cols = (cm->mb_cols + 3) >> 2;
-    const int sb_end = (sb_cols * (tile + 1)) >> cpi->oxcf.tile_columns;
-    const int mb_end = ((sb_end << 2) > cm->mb_cols) ?
-                        cm->mb_cols : (sb_end << 2);
-
     cm->cur_tile_idx = tile;
-    cm->cur_tile_mb_col_start = mb_start;
-    cm->cur_tile_mb_col_end = mb_end;
-
-    mi_ptr = cm->mi + mb_start;
+    vp9_get_tile_offsets(cm, &cm->cur_tile_mb_col_start,
+                         &cm->cur_tile_mb_col_end);
+    mi_ptr = cm->mi + cm->cur_tile_mb_col_start;
     for (mb_row = 0; mb_row < cm->mb_rows; mb_row += 4, mi_ptr += 4 * mis) {
       mi = mi_ptr;
-      for (mb_col = mb_start; mb_col < mb_end; mb_col += 4, mi += 4) {
+      for (mb_col = cm->cur_tile_mb_col_start;
+           mb_col < cm->cur_tile_mb_col_end; mb_col += 4, mi += 4) {
         if (mi->mbmi.sb_type == BLOCK_SIZE_SB64X64) {
           count_segs(cpi, mi, no_pred_segcounts, temporal_predictor_count,
                      t_unpred_seg_counts, 4, mb_row, mb_col);
@@ -338,8 +333,6 @@ void vp9_choose_segmap_coding_method(VP9_COMP *cpi) {
         }
       }
     }
-
-    mb_start = mb_end;
   }
 
   // Work out probability tree for coding segments without prediction
index d8d95a1..eb152f5 100644 (file)
@@ -59,6 +59,8 @@ VP9_COMMON_SRCS-yes += common/vp9_setupintrarecon.h
 VP9_COMMON_SRCS-yes += common/vp9_swapyv12buffer.h
 VP9_COMMON_SRCS-yes += common/vp9_systemdependent.h
 VP9_COMMON_SRCS-yes += common/vp9_textblit.h
+VP9_COMMON_SRCS-yes += common/vp9_tile_common.h
+VP9_COMMON_SRCS-yes += common/vp9_tile_common.c
 VP9_COMMON_SRCS-yes += common/vp9_treecoder.h
 VP9_COMMON_SRCS-yes += common/vp9_invtrans.c
 VP9_COMMON_SRCS-yes += common/vp9_loopfilter.c
index 0b86772..80320c4 100644 (file)
@@ -54,7 +54,7 @@ static const struct extraconfig_map extracfg_map[] = {
       0,                          /* noise_sensitivity */
       0,                          /* Sharpness */
       0,                          /* static_thresh */
-      VP8_ONE_TILE_COLUMN,        /* tile_columns */
+      0,                          /* tile_columns */
       0,                          /* arnr_max_frames */
       3,                          /* arnr_strength */
       3,                          /* arnr_type*/
@@ -171,8 +171,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t      *ctx,
 
   RANGE_CHECK_HI(vp8_cfg, noise_sensitivity,  6);
 
-  RANGE_CHECK(vp8_cfg, tile_columns,
-              VP8_ONE_TILE_COLUMN, VP8_FOUR_TILE_COLUMNS);
+  RANGE_CHECK(vp8_cfg, tile_columns, 0, 6);
   RANGE_CHECK_HI(vp8_cfg, Sharpness,       7);
   RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
   RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
index 79bb582..d483c47 100644 (file)
@@ -256,19 +256,6 @@ typedef enum {
 } vp8e_token_partitions;
 
 
-/*!\brief VP8 tile column mode
- *
- * This defines VP9 tiling mode for compressed data, i.e., the number of
- * sub-streams in the bitstream. Used for parallelized encoding/decoding.
- *
- */
-
-typedef enum {
-  VP8_ONE_TILE_COLUMN   = 0,
-  VP8_TWO_TILE_COLUMNS  = 1,
-  VP8_FOUR_TILE_COLUMNS = 2
-} vp8e_tile_column_mode;
-
 /*!\brief VP8 model tuning parameters
  *
  * Changes the encoder to tune for certain types of input material.