Commit efd57252 authored by Yaowu Xu's avatar Yaowu Xu Committed by Gerrit Code Review
Browse files

Merge "Encode and decode multiple tile groups" into nextgenv2

parents 3ff8cb76 80188d15
......@@ -391,11 +391,15 @@ typedef struct AV1Common {
#if CONFIG_DERING
int dering_level;
#endif
#if CONFIG_DELTA_Q
int delta_q_present_flag;
// Resolution of delta quant
int delta_q_res;
#endif
#if CONFIG_TILE_GROUPS
int num_tg;
#endif
} AV1_COMMON;
// TODO(hkuang): Don't need to lock the whole pool after implementing atomic
......
......@@ -18,6 +18,10 @@ extern "C" {
struct AV1Common;
#if CONFIG_TILE_GROUPS
#define MAX_NUM_TG 3
#endif
typedef struct TileInfo {
int mi_row_start, mi_row_end;
int mi_col_start, mi_col_end;
......
......@@ -56,6 +56,14 @@
#define MAX_AV1_HEADER_SIZE 80
#define ACCT_STR __func__
static struct aom_read_bit_buffer *init_read_bit_buffer(
AV1Decoder *pbi, struct aom_read_bit_buffer *rb, const uint8_t *data,
const uint8_t *data_end, uint8_t clear_data[MAX_AV1_HEADER_SIZE]);
static int read_compressed_header(AV1Decoder *pbi, const uint8_t *data,
size_t partition_size);
static size_t read_uncompressed_header(AV1Decoder *pbi,
struct aom_read_bit_buffer *rb);
static int is_compound_reference_allowed(const AV1_COMMON *cm) {
int i;
if (frame_is_intra_only(cm)) return 0;
......@@ -2481,6 +2489,17 @@ static void read_tile_info(AV1Decoder *const pbi,
pbi->tile_size_bytes = aom_rb_read_literal(rb, 2) + 1;
}
#endif // CONFIG_EXT_TILE
#if CONFIG_TILE_GROUPS
// Store an index to the location of the tile group information
pbi->tg_size_bit_offset = rb->bit_offset;
pbi->tg_size = 1 << (cm->log2_tile_rows + cm->log2_tile_cols);
if (cm->log2_tile_rows + cm->log2_tile_cols > 0) {
pbi->tg_start =
aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols);
pbi->tg_size =
1 + aom_rb_read_literal(rb, cm->log2_tile_rows + cm->log2_tile_cols);
}
#endif
}
static int mem_get_varsize(const uint8_t *src, const int sz) {
......@@ -2678,6 +2697,43 @@ static void get_tile_buffers(
AV1Decoder *pbi, const uint8_t *data, const uint8_t *data_end,
TileBufferDec (*const tile_buffers)[MAX_TILE_COLS]) {
AV1_COMMON *const cm = &pbi->common;
#if CONFIG_TILE_GROUPS
int r, c;
const int tile_cols = cm->tile_cols;
const int tile_rows = cm->tile_rows;
int tc = 0;
int first_tile_in_tg = 0;
int hdr_offset;
struct aom_read_bit_buffer rb_tg_hdr;
uint8_t clear_data[MAX_AV1_HEADER_SIZE];
const int num_tiles = tile_rows * tile_cols;
const int num_bits = OD_ILOG(num_tiles) - 1;
const int hdr_size = pbi->uncomp_hdr_size + pbi->first_partition_size;
const int tg_size_bit_offset = pbi->tg_size_bit_offset;
for (r = 0; r < tile_rows; ++r) {
for (c = 0; c < tile_cols; ++c, ++tc) {
const int is_last = (r == tile_rows - 1) && (c == tile_cols - 1);
TileBufferDec *const buf = &tile_buffers[r][c];
hdr_offset = (tc && tc == first_tile_in_tg) ? hdr_size : 0;
buf->col = c;
if (hdr_offset) {
init_read_bit_buffer(pbi, &rb_tg_hdr, data, data_end, clear_data);
rb_tg_hdr.bit_offset = tg_size_bit_offset;
if (num_tiles) {
pbi->tg_start = aom_rb_read_literal(&rb_tg_hdr, num_bits);
pbi->tg_size = 1 + aom_rb_read_literal(&rb_tg_hdr, num_bits);
}
}
first_tile_in_tg += tc == first_tile_in_tg ? pbi->tg_size : 0;
data += hdr_offset;
get_tile_buffer(data_end, pbi->tile_size_bytes, is_last,
&pbi->common.error, &data, pbi->decrypt_cb,
pbi->decrypt_state, buf);
}
}
#else
int r, c;
const int tile_cols = cm->tile_cols;
const int tile_rows = cm->tile_rows;
......@@ -2691,6 +2747,7 @@ static void get_tile_buffers(
&data, pbi->decrypt_cb, pbi->decrypt_state, buf);
}
}
#endif
}
#endif // CONFIG_EXT_TILE
......@@ -3527,7 +3584,6 @@ static size_t read_uncompressed_header(AV1Decoder *pbi,
if (sz == 0)
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
"Invalid header size");
return sz;
}
......@@ -3953,7 +4009,56 @@ BITSTREAM_PROFILE av1_read_profile(struct aom_read_bit_buffer *rb) {
if (profile > 2) profile += aom_rb_read_bit(rb);
return (BITSTREAM_PROFILE)profile;
}
#if CONFIG_TILE_GROUPS
static int read_all_headers(AV1Decoder *pbi, struct aom_read_bit_buffer *rb,
const uint8_t **p_data,
const uint8_t **p_data_end) {
AV1_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
YV12_BUFFER_CONFIG *fb = (YV12_BUFFER_CONFIG *)xd->cur_buf;
pbi->first_partition_size = read_uncompressed_header(pbi, rb);
pbi->uncomp_hdr_size = aom_rb_bytes_read(rb);
#if CONFIG_GLOBAL_MOTION
xd->global_motion = cm->global_motion;
#endif // CONFIG_GLOBAL_MOTION
if (!pbi->first_partition_size) {
// showing a frame directly
#if CONFIG_EXT_REFS
if (cm->show_existing_frame)
*p_data_end = *p_data + pbi->uncomp_hdr_size;
else
#endif // CONFIG_EXT_REFS
*p_data_end = *p_data + (cm->profile <= PROFILE_2 ? 1 : 2);
return 1;
}
*p_data += pbi->uncomp_hdr_size;
if (!read_is_valid(*p_data, pbi->first_partition_size, *p_data_end))
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt header length");
*cm->fc = cm->frame_contexts[cm->frame_context_idx];
if (!cm->fc->initialized)
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
"Uninitialized entropy context.");
av1_zero(cm->counts);
xd->corrupted = 0;
fb->corrupted =
read_compressed_header(pbi, *p_data, pbi->first_partition_size);
if (fb->corrupted)
aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
"Decode failed. Frame data header is corrupted.");
*p_data += pbi->first_partition_size;
return 0;
}
#endif
void av1_decode_frame(AV1Decoder *pbi, const uint8_t *data,
const uint8_t *data_end, const uint8_t **p_data_end) {
AV1_COMMON *const cm = &pbi->common;
......
......@@ -107,7 +107,13 @@ typedef struct AV1Decoder {
int acct_enabled;
Accounting accounting;
#endif
size_t uncomp_hdr_size; // Size of the uncompressed header
size_t first_partition_size; // Size of the compressed header
#if CONFIG_TILE_GROUPS
int tg_size; // Number of tiles in the current tilegroup
int tg_start; // First tile in the current tilegroup
int tg_size_bit_offset;
#endif
} AV1Decoder;
int av1_receive_compressed_data(struct AV1Decoder *pbi, size_t size,
......
This diff is collapsed.
......@@ -141,7 +141,13 @@ static void build_nmv_component_cost_table(int *mvcost,
static void update_mv(aom_writer *w, const unsigned int ct[2], aom_prob *cur_p,
aom_prob upd_p) {
(void)upd_p;
av1_cond_prob_diff_update(w, cur_p, ct);
#if CONFIG_TILE_GROUPS
// Just use the maximum number of tile groups to avoid passing in the actual
// number
av1_cond_prob_diff_update(w, cur_p, ct, MAX_NUM_TG);
#else
av1_cond_prob_diff_update(w, cur_p, ct, 1);
#endif
}
static void write_mv_update(const aom_tree_index *tree,
......
......@@ -4563,6 +4563,12 @@ static void encode_frame_to_data_rate(AV1_COMP *cpi, size_t *size,
cm->reset_frame_context = RESET_FRAME_CONTEXT_CURRENT;
}
}
#if CONFIG_TILE_GROUPS
if (cm->error_resilient_mode)
cm->num_tg = MAX_NUM_TG;
else
cm->num_tg = 1;
#endif
// For 1 pass CBR, check if we are dropping this frame.
// Never drop on key frame.
......
......@@ -51,7 +51,8 @@ void av1_clear_segdata(struct segmentation *seg, int segment_id,
// Based on set of segment counts calculate a probability tree
static void calc_segtree_probs(unsigned *segcounts,
aom_prob *segment_tree_probs,
const aom_prob *cur_tree_probs) {
const aom_prob *cur_tree_probs,
const int probwt) {
// Work out probabilities of each segment
const unsigned cc[4] = { segcounts[0] + segcounts[1],
segcounts[2] + segcounts[3],
......@@ -71,8 +72,9 @@ static void calc_segtree_probs(unsigned *segcounts,
for (i = 0; i < 7; i++) {
const unsigned *ct =
i == 0 ? ccc : i < 3 ? cc + (i & 2) : segcounts + (i - 3) * 2;
av1_prob_diff_update_savings_search(
ct, cur_tree_probs[i], &segment_tree_probs[i], DIFF_UPDATE_PROB);
av1_prob_diff_update_savings_search(ct, cur_tree_probs[i],
&segment_tree_probs[i],
DIFF_UPDATE_PROB, probwt);
}
}
......@@ -294,6 +296,11 @@ void av1_choose_segmap_coding_method(AV1_COMMON *cm, MACROBLOCKD *xd) {
int t_pred_cost = INT_MAX;
int i, tile_col, tile_row, mi_row, mi_col;
#if CONFIG_TILE_GROUPS
const int probwt = cm->num_tg;
#else
const int probwt = 1;
#endif
unsigned(*temporal_predictor_count)[2] = cm->counts.seg.pred;
unsigned *no_pred_segcounts = cm->counts.seg.tree_total;
......@@ -333,14 +340,15 @@ void av1_choose_segmap_coding_method(AV1_COMMON *cm, MACROBLOCKD *xd) {
// Work out probability tree for coding segments without prediction
// and the cost.
calc_segtree_probs(no_pred_segcounts, no_pred_tree, segp->tree_probs);
calc_segtree_probs(no_pred_segcounts, no_pred_tree, segp->tree_probs, probwt);
no_pred_cost = cost_segmap(no_pred_segcounts, no_pred_tree);
// Key frames cannot use temporal prediction
if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
// Work out probability tree for coding those segments not
// predicted using the temporal method and the cost.
calc_segtree_probs(t_unpred_seg_counts, t_pred_tree, segp->tree_probs);
calc_segtree_probs(t_unpred_seg_counts, t_pred_tree, segp->tree_probs,
probwt);
t_pred_cost = cost_segmap(t_unpred_seg_counts, t_pred_tree);
// Add in the cost of the signaling for each prediction context.
......@@ -349,9 +357,9 @@ void av1_choose_segmap_coding_method(AV1_COMMON *cm, MACROBLOCKD *xd) {
const int count1 = temporal_predictor_count[i][1];
t_nopred_prob[i] = get_binary_prob(count0, count1);
av1_prob_diff_update_savings_search(temporal_predictor_count[i],
segp->pred_probs[i],
&t_nopred_prob[i], DIFF_UPDATE_PROB);
av1_prob_diff_update_savings_search(
temporal_predictor_count[i], segp->pred_probs[i], &t_nopred_prob[i],
DIFF_UPDATE_PROB, probwt);
// Add in the predictor signaling cost
t_pred_cost += count0 * av1_cost_zero(t_nopred_prob[i]) +
......
......@@ -116,7 +116,8 @@ void av1_write_prob_diff_update(aom_writer *w, aom_prob newp, aom_prob oldp) {
}
int av1_prob_diff_update_savings_search(const unsigned int *ct, aom_prob oldp,
aom_prob *bestp, aom_prob upd) {
aom_prob *bestp, aom_prob upd,
int probwt) {
const uint32_t old_b = cost_branch256(ct, oldp);
int bestsavings = 0;
aom_prob newp, bestnewp = oldp;
......@@ -126,7 +127,7 @@ int av1_prob_diff_update_savings_search(const unsigned int *ct, aom_prob oldp,
const uint32_t new_b = cost_branch256(ct, newp);
const uint32_t update_b =
prob_diff_update_cost(newp, oldp) + av1_cost_upd256;
const int savings = (int)((int64_t)old_b - new_b - update_b);
const int savings = (int)((int64_t)old_b - new_b - update_b * probwt);
if (savings > bestsavings) {
bestsavings = savings;
bestnewp = newp;
......@@ -139,7 +140,7 @@ int av1_prob_diff_update_savings_search(const unsigned int *ct, aom_prob oldp,
int av1_prob_diff_update_savings_search_model(const unsigned int *ct,
const aom_prob *oldp,
aom_prob *bestp, aom_prob upd,
int stepsize) {
int stepsize, int probwt) {
int i, old_b, new_b, update_b, savings, bestsavings;
int newp;
const int step_sign = *bestp > oldp[PIVOT_NODE] ? -1 : 1;
......@@ -164,7 +165,7 @@ int av1_prob_diff_update_savings_search_model(const unsigned int *ct,
new_b += cost_branch256(ct + 2 * i, newplist[i]);
new_b += cost_branch256(ct + 2 * PIVOT_NODE, newplist[PIVOT_NODE]);
update_b = prob_diff_update_cost(newp, oldp[PIVOT_NODE]) + av1_cost_upd256;
savings = old_b - new_b - update_b;
savings = old_b - new_b - update_b * probwt;
if (savings > bestsavings) {
bestsavings = savings;
bestnewp = newp;
......@@ -253,11 +254,11 @@ int av1_prob_update_search_model_subframe(unsigned int ct[ENTROPY_NODES]
#endif // CONFIG_ENTROPY
void av1_cond_prob_diff_update(aom_writer *w, aom_prob *oldp,
const unsigned int ct[2]) {
const unsigned int ct[2], int probwt) {
const aom_prob upd = DIFF_UPDATE_PROB;
aom_prob newp = get_binary_prob(ct[0], ct[1]);
const int savings =
av1_prob_diff_update_savings_search(ct, *oldp, &newp, upd);
av1_prob_diff_update_savings_search(ct, *oldp, &newp, upd, probwt);
assert(newp >= 1);
if (savings > 0) {
aom_write(w, 1, upd);
......@@ -268,12 +269,12 @@ void av1_cond_prob_diff_update(aom_writer *w, aom_prob *oldp,
}
}
int av1_cond_prob_diff_update_savings(aom_prob *oldp,
const unsigned int ct[2]) {
int av1_cond_prob_diff_update_savings(aom_prob *oldp, const unsigned int ct[2],
int probwt) {
const aom_prob upd = DIFF_UPDATE_PROB;
aom_prob newp = get_binary_prob(ct[0], ct[1]);
const int savings =
av1_prob_diff_update_savings_search(ct, *oldp, &newp, upd);
av1_prob_diff_update_savings_search(ct, *oldp, &newp, upd, probwt);
return savings;
}
......
......@@ -19,20 +19,22 @@ extern "C" {
#include "aom_dsp/bitwriter.h"
#include "aom_dsp/prob.h"
void av1_write_prob_diff_update(aom_writer *w, aom_prob newp, aom_prob oldp);
void av1_write_prob_diff_update(aom_writer *w, aom_prob newp, aom_prob oldpm);
void av1_cond_prob_diff_update(aom_writer *w, aom_prob *oldp,
const unsigned int ct[2]);
const unsigned int ct[2], int probwt);
int av1_prob_diff_update_savings_search(const unsigned int *ct, aom_prob oldp,
aom_prob *bestp, aom_prob upd);
aom_prob *bestp, aom_prob upd,
int probwt);
int av1_prob_diff_update_savings_search_model(const unsigned int *ct,
const aom_prob *oldp,
aom_prob *bestp, aom_prob upd,
int stepsize);
int av1_cond_prob_diff_update_savings(aom_prob *oldp, const unsigned int ct[2]);
int stepsize, int probwt);
int av1_cond_prob_diff_update_savings(aom_prob *oldp, const unsigned int ct[2],
int probwt);
#if CONFIG_ENTROPY
int av1_prob_update_search_subframe(unsigned int ct[][2], aom_prob oldp,
aom_prob *bestp, aom_prob upd, int n);
......
......@@ -290,6 +290,7 @@ EXPERIMENT_LIST="
adapt_scan
filter_7bit
parallel_deblocking
tile_groups
"
CONFIG_LIST="
dependency_tracking
......@@ -406,6 +407,7 @@ CMDLINE_SELECT="
aom_highbitdepth
experimental
aom_qm
tile_groups
"
process_cmdline() {
......
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