Commit f496f601 authored by Ronald S. Bultje's avatar Ronald S. Bultje Committed by Gerrit Code Review

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
parent cb00be1f
......@@ -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
......@@ -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;
......
/*
* 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;
}
/*
* 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_
......@@ -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);
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment