Commit 7460798b authored by Ronald S. Bultje's avatar Ronald S. Bultje

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
parent 612104bb
......@@ -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;
......
......@@ -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);
}
}
......
......@@ -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;
}
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