Merge "Implement a tile copying method in large-scale tile coding" into nextgen
This commit is contained in:
commit
efb93f518f
@ -2558,7 +2558,8 @@ static void get_tile_buffer(const uint8_t *const data_end,
|
||||
struct vpx_internal_error_info *error_info,
|
||||
const uint8_t **data,
|
||||
vpx_decrypt_cb decrypt_cb, void *decrypt_state,
|
||||
TileBuffer *buf, VP9_COMMON *const cm) {
|
||||
TileBuffer (*tile_buffers)[1024],
|
||||
int tile_size_bytes, int col, int row) {
|
||||
#else
|
||||
static void get_tile_buffer(const uint8_t *const data_end,
|
||||
int is_last,
|
||||
@ -2571,26 +2572,39 @@ static void get_tile_buffer(const uint8_t *const data_end,
|
||||
size_t size;
|
||||
|
||||
#if CONFIG_ROW_TILE
|
||||
size_t copy_size = 0;
|
||||
const uint8_t *copy_data = NULL;
|
||||
|
||||
// mem read function
|
||||
MemRead read_tile_size;
|
||||
setup_size_read(cm->tile_size_bytes, &read_tile_size);
|
||||
setup_size_read(tile_size_bytes, &read_tile_size);
|
||||
#endif
|
||||
|
||||
if (!is_last) {
|
||||
#if CONFIG_ROW_TILE
|
||||
if (!read_is_valid(*data, cm->tile_size_bytes, data_end))
|
||||
if (!read_is_valid(*data, tile_size_bytes, data_end))
|
||||
vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME,
|
||||
"Truncated packet or corrupt tile length");
|
||||
if (decrypt_cb) {
|
||||
uint8_t be_data[4];
|
||||
decrypt_cb(decrypt_state, *data, be_data, 4);
|
||||
decrypt_cb(decrypt_state, *data, be_data, tile_size_bytes);
|
||||
|
||||
// Only read number of bytes in cm->tile_size_bytes.
|
||||
size = read_tile_size(be_data);
|
||||
} else {
|
||||
size = read_tile_size(*data);
|
||||
}
|
||||
*data += cm->tile_size_bytes;
|
||||
|
||||
if ((size >> (tile_size_bytes * 8 - 1)) == 1) {
|
||||
int offset = (size >> (tile_size_bytes - 1) * 8) & 0x7f;
|
||||
|
||||
// Currently, only use tiles in same column as reference tiles.
|
||||
copy_data = tile_buffers[row - offset][col].data;
|
||||
copy_size = tile_buffers[row - offset][col].size;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
*data += tile_size_bytes;
|
||||
#else
|
||||
if (!read_is_valid(*data, 4, data_end))
|
||||
vpx_internal_error(error_info, VPX_CODEC_CORRUPT_FRAME,
|
||||
@ -2613,8 +2627,18 @@ static void get_tile_buffer(const uint8_t *const data_end,
|
||||
size = data_end - *data;
|
||||
}
|
||||
|
||||
#if CONFIG_ROW_TILE
|
||||
if (size > 0) {
|
||||
tile_buffers[row][col].data = *data;
|
||||
tile_buffers[row][col].size = size;
|
||||
} else {
|
||||
tile_buffers[row][col].data = copy_data;
|
||||
tile_buffers[row][col].size = copy_size;
|
||||
}
|
||||
#else
|
||||
buf->data = *data;
|
||||
buf->size = size;
|
||||
#endif
|
||||
|
||||
*data += size;
|
||||
}
|
||||
@ -2633,15 +2657,17 @@ static void get_tile_buffers(VP9Decoder *pbi,
|
||||
MIN(pbi->dec_tile_col, tile_cols - 1);
|
||||
int tile_row_limit = (pbi->dec_tile_row == -1) ? INT_MAX :
|
||||
MIN(pbi->dec_tile_row, tile_rows - 1);
|
||||
int tile_col_size_bytes = cm->tile_col_size_bytes;
|
||||
int tile_size_bytes = cm->tile_size_bytes;
|
||||
|
||||
// tile col size read function
|
||||
MemRead read_tile_col_size;
|
||||
setup_size_read(cm->tile_col_size_bytes, &read_tile_col_size);
|
||||
setup_size_read(tile_col_size_bytes, &read_tile_col_size);
|
||||
|
||||
for (c = 0; c < tile_cols && c <= tile_col_limit; ++c) {
|
||||
if (c < tile_cols - 1) {
|
||||
tile_col_size = read_tile_col_size(data);
|
||||
data += cm->tile_col_size_bytes;
|
||||
data += tile_col_size_bytes;
|
||||
tile_end_col[c] = data + tile_col_size;
|
||||
} else {
|
||||
tile_col_size = data_end - data;
|
||||
@ -2657,15 +2683,18 @@ static void get_tile_buffers(VP9Decoder *pbi,
|
||||
if (tile_col_limit > 0)
|
||||
data = tile_end_col[tile_col_limit - 1];
|
||||
if (tile_col_limit < tile_cols - 1)
|
||||
data += cm->tile_col_size_bytes;
|
||||
data += tile_col_size_bytes;
|
||||
|
||||
for (r = 0; r <= tile_row_limit; ++r) {
|
||||
const int is_last = (r == tile_rows - 1);
|
||||
TileBuffer *const buf = &tile_buffers[r][tile_col_limit];
|
||||
buf->col = tile_col_limit;
|
||||
// The last tile in the row also has a tile header. So here always set
|
||||
// is_last = 0.
|
||||
const int is_last = 0;
|
||||
|
||||
tile_buffers[r][tile_col_limit].col = tile_col_limit;
|
||||
get_tile_buffer(tile_end_col[tile_col_limit], is_last,
|
||||
&pbi->common.error, &data,
|
||||
pbi->decrypt_cb, pbi->decrypt_state, buf, cm);
|
||||
pbi->decrypt_cb, pbi->decrypt_state,
|
||||
tile_buffers, tile_size_bytes, tile_col_limit, r);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -2675,15 +2704,18 @@ static void get_tile_buffers(VP9Decoder *pbi,
|
||||
data = tile_end_col[c - 1];
|
||||
|
||||
if (c < tile_cols - 1)
|
||||
data += cm->tile_col_size_bytes;
|
||||
data += tile_col_size_bytes;
|
||||
|
||||
for (r = 0; r < tile_rows && r <= tile_row_limit; ++r) {
|
||||
const int is_last = (r == tile_rows - 1);
|
||||
TileBuffer *const buf = &tile_buffers[r][c];
|
||||
buf->col = c;
|
||||
// The last tile in the row also has a tile header. So here always set
|
||||
// is_last = 0.
|
||||
const int is_last = 0;
|
||||
|
||||
tile_buffers[r][c].col = c;
|
||||
get_tile_buffer(tile_end_col[c], is_last,
|
||||
&pbi->common.error, &data,
|
||||
pbi->decrypt_cb, pbi->decrypt_state, buf, cm);
|
||||
pbi->decrypt_cb, pbi->decrypt_state,
|
||||
tile_buffers, tile_size_bytes, c, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2767,6 +2799,8 @@ static const uint8_t *decode_tiles(VP9Decoder *pbi,
|
||||
vpx_memset(cm->above_seg_context, 0,
|
||||
sizeof(*cm->above_seg_context) * aligned_cols);
|
||||
|
||||
// Scan the frame data buffer, and get each tile data location as well as its
|
||||
// size.
|
||||
get_tile_buffers(pbi, data, data_end, tile_cols, tile_rows, tile_buffers);
|
||||
|
||||
if (pbi->tile_data == NULL ||
|
||||
|
@ -2170,18 +2170,18 @@ static INLINE void set_tile_size_in_bytes(VP9_COMP *cpi,
|
||||
// bytes needed. Note: This decision is not always guaranteed to be true.
|
||||
// In later bitstream packing, need to check if the actual tile size is
|
||||
// out of the range.
|
||||
if (cpi->max_tile_size < ONE_BYTE_THRESH)
|
||||
if (cpi->max_tile_size < ONE_BYTE_THRESH(0))
|
||||
cm->tile_size_bytes = 1;
|
||||
else if (cpi->max_tile_size < TWO_BYTE_THRESH)
|
||||
else if (cpi->max_tile_size < TWO_BYTE_THRESH(0))
|
||||
cm->tile_size_bytes = 2;
|
||||
else if (cpi->max_tile_size < THREE_BYTE_THRESH)
|
||||
else if (cpi->max_tile_size < THREE_BYTE_THRESH(0))
|
||||
cm->tile_size_bytes = 3;
|
||||
|
||||
if (cpi->max_tile_col_size < ONE_BYTE_THRESH)
|
||||
if (cpi->max_tile_col_size < ONE_BYTE_THRESH(1))
|
||||
cm->tile_col_size_bytes = 1;
|
||||
else if (cpi->max_tile_col_size < TWO_BYTE_THRESH)
|
||||
else if (cpi->max_tile_col_size < TWO_BYTE_THRESH(1))
|
||||
cm->tile_col_size_bytes = 2;
|
||||
else if (cpi->max_tile_col_size < THREE_BYTE_THRESH)
|
||||
else if (cpi->max_tile_col_size < THREE_BYTE_THRESH(1))
|
||||
cm->tile_col_size_bytes = 3;
|
||||
}
|
||||
}
|
||||
@ -2265,18 +2265,18 @@ static int get_refresh_mask(VP9_COMP *cpi) {
|
||||
|
||||
#if CONFIG_ROW_TILE
|
||||
static INLINE void setup_size_storing(int num_bytes, MemPut *output,
|
||||
unsigned int *size_limit) {
|
||||
unsigned int *size_limit, int type) {
|
||||
*output = mem_put_be32;
|
||||
*size_limit = UINT_MAX;
|
||||
if (num_bytes == 3) {
|
||||
*output = mem_put_be24;
|
||||
*size_limit = THREE_BYTE_LIMIT;
|
||||
*size_limit = THREE_BYTE_LIMIT(type);
|
||||
} else if (num_bytes == 2) {
|
||||
*output = mem_put_be16;
|
||||
*size_limit = TWO_BYTE_LIMIT;
|
||||
*size_limit = TWO_BYTE_LIMIT(type);
|
||||
} else if (num_bytes == 1) {
|
||||
*output = mem_put_be8;
|
||||
*size_limit = ONE_BYTE_LIMIT;
|
||||
*size_limit = ONE_BYTE_LIMIT(type);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -2295,6 +2295,7 @@ static size_t encode_tiles(VP9_COMP *cpi, uint8_t *data_ptr) {
|
||||
#if CONFIG_ROW_TILE
|
||||
TOKENEXTRA *(*tok)[1024] = cpi->tile_tok;
|
||||
TileInfo (*tile)[1024] = cpi->tile_info;
|
||||
EncTileBuffer (*tile_buf)[1024] = cpi->tile_buffers;
|
||||
#else
|
||||
TOKENEXTRA *tok[4][1 << 6];
|
||||
TileInfo tile[4][1 << 6];
|
||||
@ -2312,9 +2313,10 @@ static size_t encode_tiles(VP9_COMP *cpi, uint8_t *data_ptr) {
|
||||
unsigned int tile_size_limit;
|
||||
unsigned int tile_col_size_limit;
|
||||
|
||||
setup_size_storing(cm->tile_size_bytes, &output_tile_size, &tile_size_limit);
|
||||
setup_size_storing(cm->tile_size_bytes, &output_tile_size, &tile_size_limit,
|
||||
0);
|
||||
setup_size_storing(cm->tile_col_size_bytes, &output_tile_col_size,
|
||||
&tile_col_size_limit);
|
||||
&tile_col_size_limit, 1);
|
||||
#endif
|
||||
|
||||
vpx_memset(cm->above_seg_context, 0, sizeof(*cm->above_seg_context) *
|
||||
@ -2339,14 +2341,19 @@ static size_t encode_tiles(VP9_COMP *cpi, uint8_t *data_ptr) {
|
||||
total_size += cm->tile_col_size_bytes;
|
||||
|
||||
for (tile_row = 0; tile_row < tile_rows; tile_row++) {
|
||||
const TileInfo * const ptile = &tile[tile_row][tile_col];
|
||||
TileInfo * const ptile = &tile[tile_row][tile_col];
|
||||
EncTileBuffer *const ptile_buf = &tile_buf[tile_row][tile_col];
|
||||
uint8_t *source;
|
||||
int write_tile_data = 1;
|
||||
|
||||
tok_end = tok[tile_row][tile_col] + cpi->tok_count[tile_row][tile_col];
|
||||
|
||||
if (tile_row < tile_rows - 1)
|
||||
vp9_start_encode(&residual_bc, data_ptr + total_size
|
||||
+ cm->tile_size_bytes);
|
||||
else
|
||||
vp9_start_encode(&residual_bc, data_ptr + total_size);
|
||||
// Is CONFIG_ROW_TILE = 1, every tile in the row has a header even for
|
||||
// the last one.
|
||||
ptile_buf->data_start = data_ptr + total_size;
|
||||
source = data_ptr + total_size + cm->tile_size_bytes;
|
||||
|
||||
vp9_start_encode(&residual_bc, source);
|
||||
|
||||
write_modes(cpi, ptile, &residual_bc, &tok[tile_row][tile_col], tok_end);
|
||||
assert(tok[tile_row][tile_col] == tok_end);
|
||||
@ -2362,12 +2369,78 @@ static size_t encode_tiles(VP9_COMP *cpi, uint8_t *data_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tile_row < tile_rows - 1) {
|
||||
ptile_buf->data_size = residual_bc.pos;
|
||||
|
||||
// Check if this tile is a copy tile.
|
||||
// Very low chances to have copy tiles on the key frame. Thus, don't
|
||||
// search on key frame to reduce unnecessary search.
|
||||
if (cm->frame_type != KEY_FRAME && final_packing) {
|
||||
const MV32 candidates[1] = {{1, 0}};
|
||||
int i;
|
||||
|
||||
assert(cm->tile_size_bytes >= 1);
|
||||
|
||||
// (TODO: yunqingwang) For now, only above tile is checked and used.
|
||||
// More candidates such as left tile can be added later.
|
||||
for (i = 0; i < 1; i++) {
|
||||
int cand_row = tile_row - candidates[0].row;
|
||||
int cand_col = tile_col - candidates[0].col;
|
||||
uint8_t tile_hdr;
|
||||
uint8_t *ref_tile;
|
||||
unsigned int ref_tile_size;
|
||||
int identical_tile_offset = 0;
|
||||
|
||||
if (tile_row == 0 )
|
||||
continue;
|
||||
|
||||
tile_hdr = *(tile_buf[cand_row][cand_col].data_start);
|
||||
|
||||
// Read out tcm bit
|
||||
if ((tile_hdr >> 7) == 1) {
|
||||
// The candidate is a copy tile itself
|
||||
tile_hdr &= 0x7f;
|
||||
identical_tile_offset = tile_hdr + 1;
|
||||
ref_tile = tile_buf[cand_row - tile_hdr][cand_col].data_start +
|
||||
cm->tile_size_bytes;
|
||||
ref_tile_size = tile_buf[cand_row - tile_hdr][cand_col].data_size;
|
||||
} else {
|
||||
identical_tile_offset = 1;
|
||||
ref_tile = tile_buf[cand_row][cand_col].data_start +
|
||||
cm->tile_size_bytes;
|
||||
ref_tile_size = tile_buf[cand_row][cand_col].data_size;
|
||||
}
|
||||
|
||||
if (identical_tile_offset < 128 && ref_tile_size == residual_bc.pos) {
|
||||
unsigned int m;
|
||||
uint8_t *cur_tile = tile_buf[tile_row][tile_col].data_start +
|
||||
cm->tile_size_bytes;
|
||||
int match = 1;
|
||||
|
||||
for (m = 0; m < residual_bc.pos; m++) {
|
||||
if (*ref_tile++ != *cur_tile++) {
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match) {
|
||||
write_tile_data = 0;
|
||||
identical_tile_offset |= 0x80;
|
||||
identical_tile_offset <<= (cm->tile_size_bytes - 1) * 8;
|
||||
output_tile_size(data_ptr + total_size, identical_tile_offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (write_tile_data) {
|
||||
// size of this tile
|
||||
output_tile_size(data_ptr + total_size, residual_bc.pos);
|
||||
total_size += cm->tile_size_bytes;
|
||||
total_size += residual_bc.pos;
|
||||
}
|
||||
total_size += residual_bc.pos;
|
||||
|
||||
total_size += cm->tile_size_bytes;
|
||||
}
|
||||
|
||||
if (!is_last_col) {
|
||||
|
@ -22,12 +22,18 @@ extern "C" {
|
||||
void vp9_entropy_mode_init();
|
||||
|
||||
#if CONFIG_ROW_TILE
|
||||
#define ONE_BYTE_LIMIT 255
|
||||
#define TWO_BYTE_LIMIT 65535
|
||||
#define THREE_BYTE_LIMIT 16777215
|
||||
#define ONE_BYTE_THRESH (ONE_BYTE_LIMIT - (ONE_BYTE_LIMIT >> 2))
|
||||
#define TWO_BYTE_THRESH (TWO_BYTE_LIMIT - (TWO_BYTE_LIMIT >> 2))
|
||||
#define THREE_BYTE_THRESH (THREE_BYTE_LIMIT - (THREE_BYTE_LIMIT >> 2))
|
||||
// In the tile header, 1 bit is used for TCM, and the rest bits are used for
|
||||
// TDS. But, no TCM bit in tile column header.
|
||||
// type 0: tile header; type 1: tile column header.
|
||||
#define ONE_BYTE_LIMIT(type) ((type) ? 255 : 127)
|
||||
#define TWO_BYTE_LIMIT(type) ((type) ? 65535 : 32767)
|
||||
#define THREE_BYTE_LIMIT(type) ((type) ? 16777215 : 8388607)
|
||||
#define ONE_BYTE_THRESH(type) \
|
||||
(ONE_BYTE_LIMIT(type) - (ONE_BYTE_LIMIT(type) >> 2))
|
||||
#define TWO_BYTE_THRESH(type) \
|
||||
(TWO_BYTE_LIMIT(type) - (TWO_BYTE_LIMIT(type) >> 2))
|
||||
#define THREE_BYTE_THRESH(type) \
|
||||
(THREE_BYTE_LIMIT(type) - (THREE_BYTE_LIMIT(type) >> 2))
|
||||
|
||||
typedef void (*MemPut)(void *, MEM_VALUE_T);
|
||||
int vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size,
|
||||
|
@ -217,6 +217,13 @@ static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
|
||||
return cfg->best_allowed_q == 0 && cfg->worst_allowed_q == 0;
|
||||
}
|
||||
|
||||
#if CONFIG_ROW_TILE
|
||||
typedef struct EncTileBuffer {
|
||||
uint8_t *data_start;
|
||||
unsigned int data_size;
|
||||
} EncTileBuffer;
|
||||
#endif
|
||||
|
||||
typedef struct VP9_COMP {
|
||||
QUANTS quants;
|
||||
MACROBLOCK mb;
|
||||
@ -441,6 +448,7 @@ typedef struct VP9_COMP {
|
||||
|
||||
#if CONFIG_ROW_TILE
|
||||
TileInfo tile_info[1024][1024];
|
||||
EncTileBuffer tile_buffers[1024][1024];
|
||||
TOKENEXTRA *tile_tok[1024][1024];
|
||||
|
||||
unsigned int max_tile_size;
|
||||
|
Loading…
x
Reference in New Issue
Block a user