shithub: libvpx

Download patch

ref: f496f601fb2e48390c822f89df60c6b2398026ab
parent: cb00be1fa20c1a3955d62c1939646f4fd5d31224
author: Ronald S. Bultje <rbultje@google.com>
date: Wed Feb 6 10:30:21 EST 2013

Add tile column size limits (256 pixels min, 4096 pixels max).

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

--- a/test/tile_independence_test.cc
+++ b/test/tile_independence_test.cc
@@ -29,8 +29,8 @@
       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 @@
   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 @@
 }
 
 VP9_INSTANTIATE_TEST_CASE(TileIndependenceTest,
-                          ::testing::Values(VP8_TWO_TILE_COLUMNS,
-                                            VP8_FOUR_TILE_COLUMNS));
+                          ::testing::Range(0, 2, 1));
 
 }  // namespace
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -279,7 +279,7 @@
   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;
 
--- /dev/null
+++ b/vp9/common/vp9_tile_common.c
@@ -1,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;
+}
--- /dev/null
+++ b/vp9/common/vp9_tile_common.h
@@ -1,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_
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -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 @@
 
   /* 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,18 +1797,10 @@
         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 */
@@ -1811,21 +1807,15 @@
         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 @@
         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);
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -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 @@
   }
 
   /* 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 @@
   }
 
   {
-    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 @@
         total_size += 4;
       }
 
-      mb_start = mb_end;
       total_size += residual_bc.pos;
     }
 
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -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 @@
 
     {
       // 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);
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -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 @@
     vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                        "Failed to allocate scaled source buffer");
 
-
   vpx_free(cpi->tok);
 
   {
@@ -1107,7 +1107,18 @@
   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);
   VP9_COMMON *const cm = &cpi->common;
@@ -1145,7 +1156,8 @@
   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 @@
   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
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -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 @@
   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 @@
   // 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 @@
         }
       }
     }
-
-    mb_start = mb_end;
   }
 
   // Work out probability tree for coding segments without prediction
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -59,6 +59,8 @@
 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
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -54,7 +54,7 @@
       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 @@
 
   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);
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -256,19 +256,6 @@
 } 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.
--