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
This commit is contained in:
parent
612104bb8d
commit
7460798ba5
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user