ref: 7460798ba5666e25258a05f1dc7ad462cb3f1b19
parent: 612104bb8dd3b40a635deebaca445f00aa069220
author: Ronald S. Bultje <[email protected]>
date: Wed Sep 30 12:42:59 EDT 2015
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
--- a/vp10/common/onyxc_int.h
+++ b/vp10/common/onyxc_int.h
@@ -279,6 +279,7 @@
int error_resilient_mode;
int log2_tile_cols, log2_tile_rows;
+ int tile_sz_mag;
int byte_alignment;
int skip_loop_filter;
--- a/vp10/decoder/decodeframe.c
+++ b/vp10/decoder/decodeframe.c
@@ -1370,6 +1370,15 @@
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 @@
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 @@
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 @@
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);
}
}
--- a/vp10/encoder/bitstream.c
+++ b/vp10/encoder/bitstream.c
@@ -940,7 +940,8 @@
}
}
-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 @@
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,7 +973,8 @@
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;
}
@@ -978,6 +981,7 @@
total_size += residual_bc.pos;
}
}
+ *max_tile_sz = max_tile;
return total_size;
}
@@ -1278,15 +1282,62 @@
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 @@
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;
}