diff --git a/test/tile_independence_test.cc b/test/tile_independence_test.cc index e9d2ca8da..c9f82ef88 100644 --- a/test/tile_independence_test.cc +++ b/test/tile_independence_test.cc @@ -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 diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index 5e57228b4..a333a4b02 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -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 index 000000000..02e0d1461 --- /dev/null +++ b/vp9/common/vp9_tile_common.c @@ -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 index 000000000..653b6b4f6 --- /dev/null +++ b/vp9/common/vp9_tile_common.h @@ -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_ diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 3324186ef..b8e867a0e 100644 --- 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 @@ -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); diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index a3c407865..c5f2a70c6 100644 --- 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 @@ -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; } diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 927a1b901..c5f717f5f 100644 --- 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 @@ -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); diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index ad5fe7819..73b7b1f5f 100644 --- 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 @@ 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 diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c index 17d8f25bd..710ca7ea0 100644 --- 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 @@ 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 diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk index d8d95a136..eb152f521 100644 --- a/vp9/vp9_common.mk +++ b/vp9/vp9_common.mk @@ -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 diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 0b8677285..80320c44a 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.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); diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index 79bb5827f..d483c47cc 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -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.