From 7460798ba5666e25258a05f1dc7ad462cb3f1b19 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 30 Sep 2015 16:42:59 -0400 Subject: [PATCH] vp10: use superframe marker index/size mechanism for tile size. See issue 1042. Should provide slight bitstream savings in most cases where tiles are being used. Change-Id: Ie2808cf8ef30b3efe50804396900c4d63a3fa026 --- vp10/common/onyxc_int.h | 1 + vp10/decoder/decodeframe.c | 39 ++++++++++++++--- vp10/encoder/bitstream.c | 85 +++++++++++++++++++++++++++++++++++--- 3 files changed, 113 insertions(+), 12 deletions(-) diff --git a/vp10/common/onyxc_int.h b/vp10/common/onyxc_int.h index c345068b0..e2454b0e2 100644 --- a/vp10/common/onyxc_int.h +++ b/vp10/common/onyxc_int.h @@ -279,6 +279,7 @@ typedef struct VP10Common { int error_resilient_mode; int log2_tile_cols, log2_tile_rows; + int tile_sz_mag; int byte_alignment; int skip_loop_filter; diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 62c294266..6619b0004 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -1370,6 +1370,15 @@ static void setup_tile_info(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { cm->log2_tile_rows = vpx_rb_read_bit(rb); if (cm->log2_tile_rows) cm->log2_tile_rows += vpx_rb_read_bit(rb); + +#if CONFIG_MISC_FIXES + // tile size magnitude + if (cm->log2_tile_rows > 0 || cm->log2_tile_cols > 0) { + cm->tile_sz_mag = vpx_rb_read_literal(rb, 2); + } +#else + cm->tile_sz_mag = 3; +#endif } typedef struct TileBuffer { @@ -1378,10 +1387,27 @@ typedef struct TileBuffer { int col; // only used with multi-threaded decoding } TileBuffer; +static int mem_get_varsize(const uint8_t *data, const int mag) { + switch (mag) { + case 0: + return data[0]; + case 1: + return mem_get_le16(data); + case 2: + return mem_get_le24(data); + case 3: + return mem_get_le32(data); + } + + assert("Invalid tile size marker value" && 0); + + return -1; +} + // Reads the next tile returning its size and adjusting '*data' accordingly // based on 'is_last'. static void get_tile_buffer(const uint8_t *const data_end, - int is_last, + const int tile_sz_mag, int is_last, struct vpx_internal_error_info *error_info, const uint8_t **data, vpx_decrypt_cb decrypt_cb, void *decrypt_state, @@ -1395,12 +1421,12 @@ static void get_tile_buffer(const uint8_t *const data_end, if (decrypt_cb) { uint8_t be_data[4]; - decrypt_cb(decrypt_state, *data, be_data, 4); - size = mem_get_be32(be_data); + decrypt_cb(decrypt_state, *data, be_data, tile_sz_mag + 1); + size = mem_get_varsize(be_data, tile_sz_mag); } else { - size = mem_get_be32(*data); + size = mem_get_varsize(*data, tile_sz_mag); } - *data += 4; + *data += tile_sz_mag + 1; if (size > (size_t)(data_end - *data)) vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME, @@ -1426,7 +1452,8 @@ static void get_tile_buffers(VP10Decoder *pbi, const int is_last = (r == tile_rows - 1) && (c == tile_cols - 1); TileBuffer *const buf = &tile_buffers[r][c]; buf->col = c; - get_tile_buffer(data_end, is_last, &pbi->common.error, &data, + get_tile_buffer(data_end, pbi->common.tile_sz_mag, + is_last, &pbi->common.error, &data, pbi->decrypt_cb, pbi->decrypt_state, buf); } } diff --git a/vp10/encoder/bitstream.c b/vp10/encoder/bitstream.c index 485fc53c0..940ae8832 100644 --- a/vp10/encoder/bitstream.c +++ b/vp10/encoder/bitstream.c @@ -940,7 +940,8 @@ static int get_refresh_mask(VP10_COMP *cpi) { } } -static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr) { +static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr, + unsigned int *max_tile_sz) { VP10_COMMON *const cm = &cpi->common; vpx_writer residual_bc; int tile_row, tile_col; @@ -948,6 +949,7 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr) { size_t total_size = 0; const int tile_cols = 1 << cm->log2_tile_cols; const int tile_rows = 1 << cm->log2_tile_rows; + unsigned int max_tile = 0; memset(cm->above_seg_context, 0, sizeof(*cm->above_seg_context) * mi_cols_aligned_to_sb(cm->mi_cols)); @@ -971,13 +973,15 @@ static size_t encode_tiles(VP10_COMP *cpi, uint8_t *data_ptr) { vpx_stop_encode(&residual_bc); if (tile_col < tile_cols - 1 || tile_row < tile_rows - 1) { // size of this tile - mem_put_be32(data_ptr + total_size, residual_bc.pos); + mem_put_le32(data_ptr + total_size, residual_bc.pos); + max_tile = max_tile > residual_bc.pos ? max_tile : residual_bc.pos; total_size += 4; } total_size += residual_bc.pos; } } + *max_tile_sz = max_tile; return total_size; } @@ -1278,15 +1282,62 @@ static size_t write_compressed_header(VP10_COMP *cpi, uint8_t *data) { return header_bc.pos; } -void vp10_pack_bitstream(VP10_COMP *cpi, uint8_t *dest, size_t *size) { +#if CONFIG_MISC_FIXES +static int remux_tiles(uint8_t *dest, const int sz, + const int n_tiles, const int mag) { + int rpos = 0, wpos = 0, n; + + for (n = 0; n < n_tiles; n++) { + int tile_sz; + + if (n == n_tiles - 1) { + tile_sz = sz - rpos; + } else { + tile_sz = mem_get_le32(&dest[rpos]); + rpos += 4; + switch (mag) { + case 0: + dest[wpos] = tile_sz; + break; + case 1: + mem_put_le16(&dest[wpos], tile_sz); + break; + case 2: + mem_put_le24(&dest[wpos], tile_sz); + break; + case 3: // remuxing should only happen if mag < 3 + default: + assert("Invalid value for tile size magnitude" && 0); + } + wpos += mag + 1; + } + + memmove(&dest[wpos], &dest[rpos], tile_sz); + wpos += tile_sz; + rpos += tile_sz; + } + + assert(rpos > wpos); + assert(rpos == sz); + + return wpos; +} +#endif + +void vp10_pack_bitstream(VP10_COMP *const cpi, uint8_t *dest, size_t *size) { + VP10_COMMON *const cm = &cpi->common; uint8_t *data = dest; size_t first_part_size, uncompressed_hdr_size; struct vpx_write_bit_buffer wb = {data, 0}; struct vpx_write_bit_buffer saved_wb; + unsigned int max_tile, data_sz; + const int n_log2_tiles = cm->log2_tile_rows + cm->log2_tile_cols; + const int have_tiles = n_log2_tiles > 0; write_uncompressed_header(cpi, &wb); saved_wb = wb; - vpx_wb_write_literal(&wb, 0, 16); // don't know in advance first part. size + // don't know in advance first part. size + vpx_wb_write_literal(&wb, 0, 16 + have_tiles * 2); uncompressed_hdr_size = vpx_wb_bytes_written(&wb); data += uncompressed_hdr_size; @@ -1295,10 +1346,32 @@ void vp10_pack_bitstream(VP10_COMP *cpi, uint8_t *dest, size_t *size) { first_part_size = write_compressed_header(cpi, data); data += first_part_size; + + data_sz = encode_tiles(cpi, data, &max_tile); +#if CONFIG_MISC_FIXES + if (max_tile > 0) { + int mag; + unsigned int mask; + + // Choose the (tile size) magnitude + for (mag = 0, mask = 0xff; mag < 4; mag++) { + if (max_tile <= mask) + break; + mask <<= 8; + mask |= 0xff; + } + assert(n_log2_tiles > 0); + vpx_wb_write_literal(&saved_wb, mag, 2); + if (mag < 3) + data_sz = remux_tiles(data, data_sz, 1 << n_log2_tiles, mag); + } else { + assert(n_log2_tiles == 0); + } +#endif + data += data_sz; + // TODO(jbb): Figure out what to do if first_part_size > 16 bits. vpx_wb_write_literal(&saved_wb, (int)first_part_size, 16); - data += encode_tiles(cpi, data); - *size = data - dest; } -- 2.40.0