Re-design motion compensated prediction mode entropy coding system
This commit re-works the entropy coding scheme of the motion compensated prediction modes. It allows a more flexible hyperplane partition for precise classification. Change-Id: Id02d4015a053affea9c19b1188873fbd7b906e92
This commit is contained in:
Родитель
8d264d1042
Коммит
6e03ddffa8
|
@ -231,6 +231,20 @@ static const aom_prob
|
|||
{ 10, 7, 6 }, // a/l both split
|
||||
};
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
static const aom_prob default_newmv_prob[NEWMV_MODE_CONTEXTS] = {
|
||||
200, 180, 150, 150, 110, 70, 60,
|
||||
};
|
||||
|
||||
static const aom_prob default_zeromv_prob[ZEROMV_MODE_CONTEXTS] = {
|
||||
192, 64,
|
||||
};
|
||||
|
||||
static const aom_prob default_refmv_prob[REFMV_MODE_CONTEXTS] = {
|
||||
220, 220, 200, 200, 180, 128,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const aom_prob
|
||||
default_inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1] = {
|
||||
{ 2, 173, 34 }, // 0 = both zero mv
|
||||
|
@ -351,6 +365,11 @@ static void init_mode_probs(FRAME_CONTEXT *fc) {
|
|||
av1_copy(fc->single_ref_prob, default_single_ref_p);
|
||||
fc->tx_probs = default_tx_probs;
|
||||
av1_copy(fc->skip_probs, default_skip_probs);
|
||||
#if CONFIG_REF_MV
|
||||
av1_copy(fc->newmv_prob, default_newmv_prob);
|
||||
av1_copy(fc->zeromv_prob, default_zeromv_prob);
|
||||
av1_copy(fc->refmv_prob, default_refmv_prob);
|
||||
#endif
|
||||
av1_copy(fc->inter_mode_probs, default_inter_mode_probs);
|
||||
#if CONFIG_MISC_FIXES
|
||||
av1_copy(fc->seg.tree_probs, default_seg_probs.tree_probs);
|
||||
|
@ -383,9 +402,21 @@ void av1_adapt_inter_frame_probs(AV1_COMMON *cm) {
|
|||
fc->single_ref_prob[i][j] = mode_mv_merge_probs(
|
||||
pre_fc->single_ref_prob[i][j], counts->single_ref[i][j]);
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
|
||||
fc->newmv_prob[i] = mode_mv_merge_probs(pre_fc->newmv_prob[i],
|
||||
counts->newmv_mode[i]);
|
||||
for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
|
||||
fc->zeromv_prob[i] = mode_mv_merge_probs(pre_fc->zeromv_prob[i],
|
||||
counts->zeromv_mode[i]);
|
||||
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
|
||||
fc->refmv_prob[i] = mode_mv_merge_probs(pre_fc->refmv_prob[i],
|
||||
counts->refmv_mode[i]);
|
||||
#else
|
||||
for (i = 0; i < INTER_MODE_CONTEXTS; i++)
|
||||
aom_tree_merge_probs(av1_inter_mode_tree, pre_fc->inter_mode_probs[i],
|
||||
counts->inter_mode[i], fc->inter_mode_probs[i]);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
|
||||
aom_tree_merge_probs(av1_intra_mode_tree, pre_fc->y_mode_prob[i],
|
||||
|
|
|
@ -55,8 +55,15 @@ typedef struct frame_contexts {
|
|||
aom_prob partition_prob[PARTITION_CONTEXTS][PARTITION_TYPES - 1];
|
||||
av1_coeff_probs_model coef_probs[TX_SIZES][PLANE_TYPES];
|
||||
aom_prob
|
||||
switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS -
|
||||
1];
|
||||
switchable_interp_prob[SWITCHABLE_FILTER_CONTEXTS]
|
||||
[SWITCHABLE_FILTERS - 1];
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
aom_prob newmv_prob[NEWMV_MODE_CONTEXTS];
|
||||
aom_prob zeromv_prob[ZEROMV_MODE_CONTEXTS];
|
||||
aom_prob refmv_prob[REFMV_MODE_CONTEXTS];
|
||||
#endif
|
||||
|
||||
aom_prob inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1];
|
||||
aom_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
|
||||
aom_prob comp_inter_prob[COMP_INTER_CONTEXTS];
|
||||
|
@ -83,6 +90,13 @@ typedef struct FRAME_COUNTS {
|
|||
eob_branch[TX_SIZES][PLANE_TYPES][REF_TYPES][COEF_BANDS][COEFF_CONTEXTS];
|
||||
unsigned int
|
||||
switchable_interp[SWITCHABLE_FILTER_CONTEXTS][SWITCHABLE_FILTERS];
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
unsigned int newmv_mode[NEWMV_MODE_CONTEXTS][2];
|
||||
unsigned int zeromv_mode[ZEROMV_MODE_CONTEXTS][2];
|
||||
unsigned int refmv_mode[REFMV_MODE_CONTEXTS][2];
|
||||
#endif
|
||||
|
||||
unsigned int inter_mode[INTER_MODE_CONTEXTS][INTER_MODES];
|
||||
unsigned int intra_inter[INTRA_INTER_CONTEXTS][2];
|
||||
unsigned int comp_inter[COMP_INTER_CONTEXTS][2];
|
||||
|
|
|
@ -130,6 +130,19 @@ typedef uint8_t PREDICTION_MODE;
|
|||
#define INTER_MODES (1 + NEWMV - NEARESTMV)
|
||||
|
||||
#define SKIP_CONTEXTS 3
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
#define NEWMV_MODE_CONTEXTS 7
|
||||
#define ZEROMV_MODE_CONTEXTS 2
|
||||
#define REFMV_MODE_CONTEXTS 6
|
||||
|
||||
#define ZEROMV_OFFSET 3
|
||||
#define REFMV_OFFSET 4
|
||||
|
||||
#define NEWMV_CTX_MASK ((1 << ZEROMV_OFFSET) - 1)
|
||||
#define ZEROMV_CTX_MASK ((1 << (REFMV_OFFSET - ZEROMV_OFFSET)) - 1)
|
||||
#endif
|
||||
|
||||
#define INTER_MODE_CONTEXTS 7
|
||||
|
||||
/* Segment Feature Masks */
|
||||
|
|
|
@ -11,14 +11,16 @@
|
|||
#include "av1/common/mvref_common.h"
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const int mi_row, const int mi_col, int block,
|
||||
const MV_REFERENCE_FRAME ref_frame,
|
||||
int row_offset,
|
||||
CANDIDATE_MV *ref_mv_stack,
|
||||
uint8_t *refmv_count) {
|
||||
static uint8_t scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const int mi_row, const int mi_col, int block,
|
||||
const MV_REFERENCE_FRAME ref_frame,
|
||||
int row_offset,
|
||||
CANDIDATE_MV *ref_mv_stack,
|
||||
uint8_t *refmv_count) {
|
||||
const TileInfo *const tile = &xd->tile;
|
||||
int i;
|
||||
uint8_t newmv_count = 0;
|
||||
|
||||
for (i = 0; i < xd->n8_w && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
|
||||
POSITION mi_pos;
|
||||
mi_pos.row = row_offset;
|
||||
|
@ -48,6 +50,9 @@ static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
ref_mv_stack[index].this_mv = this_refmv;
|
||||
ref_mv_stack[index].weight = len;
|
||||
++(*refmv_count);
|
||||
|
||||
if (candidate_mbmi->mode == NEWMV)
|
||||
++newmv_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,16 +61,18 @@ static void scan_row_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
++i;
|
||||
}
|
||||
}
|
||||
return newmv_count;
|
||||
}
|
||||
|
||||
static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const int mi_row, const int mi_col, int block,
|
||||
const MV_REFERENCE_FRAME ref_frame,
|
||||
int col_offset,
|
||||
CANDIDATE_MV *ref_mv_stack,
|
||||
uint8_t *refmv_count) {
|
||||
static uint8_t scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const int mi_row, const int mi_col, int block,
|
||||
const MV_REFERENCE_FRAME ref_frame,
|
||||
int col_offset,
|
||||
CANDIDATE_MV *ref_mv_stack,
|
||||
uint8_t *refmv_count) {
|
||||
const TileInfo *const tile = &xd->tile;
|
||||
int i;
|
||||
uint8_t newmv_count = 0;
|
||||
|
||||
for (i = 0; i < xd->n8_h && *refmv_count < MAX_REF_MV_STACK_SIZE;) {
|
||||
POSITION mi_pos;
|
||||
|
@ -95,6 +102,9 @@ static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
ref_mv_stack[index].this_mv = this_refmv;
|
||||
ref_mv_stack[index].weight = len;
|
||||
++(*refmv_count);
|
||||
|
||||
if (candidate_mbmi->mode == NEWMV)
|
||||
++newmv_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,16 +114,18 @@ static void scan_col_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
++i;
|
||||
}
|
||||
}
|
||||
return newmv_count;
|
||||
}
|
||||
|
||||
static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const int mi_row, const int mi_col, int block,
|
||||
const MV_REFERENCE_FRAME ref_frame,
|
||||
int row_offset, int col_offset,
|
||||
CANDIDATE_MV *ref_mv_stack,
|
||||
uint8_t *refmv_count) {
|
||||
static uint8_t scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
const int mi_row, const int mi_col, int block,
|
||||
const MV_REFERENCE_FRAME ref_frame,
|
||||
int row_offset, int col_offset,
|
||||
CANDIDATE_MV *ref_mv_stack,
|
||||
uint8_t *refmv_count) {
|
||||
const TileInfo *const tile = &xd->tile;
|
||||
POSITION mi_pos;
|
||||
uint8_t newmv_count = 0;
|
||||
|
||||
mi_pos.row = row_offset;
|
||||
mi_pos.col = col_offset;
|
||||
|
@ -141,6 +153,9 @@ static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
ref_mv_stack[index].this_mv = this_refmv;
|
||||
ref_mv_stack[index].weight = len;
|
||||
++(*refmv_count);
|
||||
|
||||
if (candidate_mbmi->mode == NEWMV)
|
||||
++newmv_count;
|
||||
}
|
||||
|
||||
if (candidate_mi->mbmi.sb_type < BLOCK_8X8 && block >= 0) {
|
||||
|
@ -167,6 +182,7 @@ static void scan_blk_mbmi(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
} // match reference frame
|
||||
}
|
||||
} // Analyze a single 8x8 block motion information.
|
||||
return newmv_count;
|
||||
}
|
||||
|
||||
static int has_top_right(const MACROBLOCKD *xd,
|
||||
|
@ -213,29 +229,65 @@ static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
int block, int mi_row, int mi_col,
|
||||
uint8_t *mode_context) {
|
||||
int idx, nearest_refmv_count = 0;
|
||||
uint8_t newmv_count = 0;
|
||||
CANDIDATE_MV tmp_mv;
|
||||
int len, nr_len;
|
||||
|
||||
const MV_REF *const prev_frame_mvs_base = cm->use_prev_frame_mvs ?
|
||||
cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col : NULL;
|
||||
|
||||
const int bs = AOMMAX(xd->n8_w, xd->n8_h);
|
||||
const int has_tr = has_top_right(xd, mi_row, mi_col, bs);
|
||||
|
||||
(void) mode_context;
|
||||
mode_context[ref_frame] = 0;
|
||||
|
||||
*refmv_count = 0;
|
||||
|
||||
// Scan the first above row mode info.
|
||||
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
-1, ref_mv_stack, refmv_count);
|
||||
newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
-1, ref_mv_stack, refmv_count);
|
||||
// Scan the first left column mode info.
|
||||
scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
-1, ref_mv_stack, refmv_count);
|
||||
newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
-1, ref_mv_stack, refmv_count);
|
||||
|
||||
// Check top-right boundary
|
||||
if (has_tr)
|
||||
scan_blk_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
-1, 1, ref_mv_stack, refmv_count);
|
||||
newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
-1, 1, ref_mv_stack, refmv_count);
|
||||
|
||||
nearest_refmv_count = *refmv_count;
|
||||
|
||||
if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame) {
|
||||
int ref;
|
||||
int blk_row, blk_col;
|
||||
int coll_blk_count = 0;
|
||||
|
||||
for (blk_row = 0; blk_row < xd->n8_h; ++blk_row) {
|
||||
for (blk_col = 0; blk_col < xd->n8_w; ++blk_col) {
|
||||
const MV_REF *prev_frame_mvs =
|
||||
prev_frame_mvs_base + blk_row * cm->mi_cols + blk_col;
|
||||
|
||||
POSITION mi_pos;
|
||||
mi_pos.row = blk_row;
|
||||
mi_pos.col = blk_col;
|
||||
|
||||
if (!is_inside(&xd->tile, mi_col, mi_row, cm->mi_rows, &mi_pos))
|
||||
continue;
|
||||
|
||||
for (ref = 0; ref < 2; ++ref) {
|
||||
if (prev_frame_mvs->ref_frame[ref] == ref_frame) {
|
||||
if (abs(prev_frame_mvs->mv[ref].as_mv.row) >= 8 ||
|
||||
abs(prev_frame_mvs->mv[ref].as_mv.col) >= 8)
|
||||
mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
|
||||
++coll_blk_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (coll_blk_count == 0)
|
||||
mode_context[ref_frame] |= (1 << ZEROMV_OFFSET);
|
||||
}
|
||||
|
||||
// Scan the second outer area.
|
||||
for (idx = 2; idx <= 4; ++idx) {
|
||||
scan_row_mbmi(cm, xd, mi_row, mi_col, block, ref_frame,
|
||||
|
@ -244,6 +296,39 @@ static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
-idx, ref_mv_stack, refmv_count);
|
||||
}
|
||||
|
||||
switch (nearest_refmv_count) {
|
||||
case 0:
|
||||
mode_context[ref_frame] |= 0;
|
||||
if (*refmv_count >= 1)
|
||||
mode_context[ref_frame] |= 1;
|
||||
|
||||
if (*refmv_count == 1)
|
||||
mode_context[ref_frame] |= (1 << REFMV_OFFSET);
|
||||
else if (*refmv_count >= 2)
|
||||
mode_context[ref_frame] |= (2 << REFMV_OFFSET);
|
||||
break;
|
||||
case 1:
|
||||
mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3;
|
||||
|
||||
if (*refmv_count == 1)
|
||||
mode_context[ref_frame] |= (3 << REFMV_OFFSET);
|
||||
else if (*refmv_count >= 2)
|
||||
mode_context[ref_frame] |= (4 << REFMV_OFFSET);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
default:
|
||||
if (newmv_count >= 2)
|
||||
mode_context[ref_frame] |= 4;
|
||||
else if (newmv_count == 1)
|
||||
mode_context[ref_frame] |= 5;
|
||||
else
|
||||
mode_context[ref_frame] |= 6;
|
||||
|
||||
mode_context[ref_frame] |= (5 << REFMV_OFFSET);
|
||||
break;
|
||||
}
|
||||
|
||||
// Rank the likelihood and assign nearest and near mvs.
|
||||
len = nearest_refmv_count;
|
||||
while (len > 0) {
|
||||
|
|
|
@ -359,6 +359,20 @@ void av1_accumulate_frame_counts(AV1_COMMON *cm, FRAME_COUNTS *counts,
|
|||
for (j = 0; j < SWITCHABLE_FILTERS; j++)
|
||||
cm->counts.switchable_interp[i][j] += counts->switchable_interp[i][j];
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
|
||||
for (j = 0; j < 2; ++j)
|
||||
cm->counts.newmv_mode[i][j] += counts->newmv_mode[i][j];
|
||||
|
||||
for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
|
||||
for (j = 0; j < 2; ++j)
|
||||
cm->counts.zeromv_mode[i][j] += counts->zeromv_mode[i][j];
|
||||
|
||||
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
|
||||
for (j = 0; j < 2; ++j)
|
||||
cm->counts.refmv_mode[i][j] += counts->refmv_mode[i][j];
|
||||
#endif
|
||||
|
||||
for (i = 0; i < INTER_MODE_CONTEXTS; i++)
|
||||
for (j = 0; j < INTER_MODES; j++)
|
||||
cm->counts.inter_mode[i][j] += counts->inter_mode[i][j];
|
||||
|
|
|
@ -125,10 +125,20 @@ static void read_switchable_interp_probs(FRAME_CONTEXT *fc, aom_reader *r) {
|
|||
}
|
||||
|
||||
static void read_inter_mode_probs(FRAME_CONTEXT *fc, aom_reader *r) {
|
||||
int i, j;
|
||||
int i;
|
||||
#if CONFIG_REF_MV
|
||||
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
|
||||
av1_diff_update_prob(r, &fc->newmv_prob[i]);
|
||||
for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
|
||||
av1_diff_update_prob(r, &fc->zeromv_prob[i]);
|
||||
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
|
||||
av1_diff_update_prob(r, &fc->refmv_prob[i]);
|
||||
#else
|
||||
int j;
|
||||
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
|
||||
for (j = 0; j < INTER_MODES - 1; ++j)
|
||||
av1_diff_update_prob(r, &fc->inter_mode_probs[i][j]);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_MISC_FIXES
|
||||
|
|
|
@ -49,13 +49,56 @@ static PREDICTION_MODE read_intra_mode_uv(AV1_COMMON *cm, MACROBLOCKD *xd,
|
|||
}
|
||||
|
||||
static PREDICTION_MODE read_inter_mode(AV1_COMMON *cm, MACROBLOCKD *xd,
|
||||
aom_reader *r, int ctx) {
|
||||
aom_reader *r, uint8_t ctx) {
|
||||
#if CONFIG_REF_MV
|
||||
FRAME_COUNTS *counts = xd->counts;
|
||||
uint8_t mode_ctx = ctx & NEWMV_CTX_MASK;
|
||||
aom_prob mode_prob = cm->fc->newmv_prob[mode_ctx];
|
||||
|
||||
if (aom_read(r, mode_prob) == 0) {
|
||||
if (counts)
|
||||
++counts->newmv_mode[mode_ctx][0];
|
||||
return NEWMV;
|
||||
}
|
||||
if (counts)
|
||||
++counts->newmv_mode[mode_ctx][1];
|
||||
|
||||
mode_ctx = (ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
|
||||
|
||||
if (mode_ctx > 1)
|
||||
assert(0);
|
||||
|
||||
mode_prob = cm->fc->zeromv_prob[mode_ctx];
|
||||
if (aom_read(r, mode_prob) == 0) {
|
||||
if (counts)
|
||||
++counts->zeromv_mode[mode_ctx][0];
|
||||
return ZEROMV;
|
||||
}
|
||||
if (counts)
|
||||
++counts->zeromv_mode[mode_ctx][1];
|
||||
|
||||
mode_ctx = (ctx >> REFMV_OFFSET);
|
||||
mode_prob = cm->fc->refmv_prob[mode_ctx];
|
||||
if (aom_read(r, mode_prob) == 0) {
|
||||
if (counts)
|
||||
++counts->refmv_mode[mode_ctx][0];
|
||||
return NEARESTMV;
|
||||
} else {
|
||||
if (counts)
|
||||
++counts->refmv_mode[mode_ctx][1];
|
||||
return NEARMV;
|
||||
}
|
||||
|
||||
// Invalid prediction mode.
|
||||
assert(0);
|
||||
#else
|
||||
const int mode =
|
||||
aom_read_tree(r, av1_inter_mode_tree, cm->fc->inter_mode_probs[ctx]);
|
||||
FRAME_COUNTS *counts = xd->counts;
|
||||
if (counts) ++counts->inter_mode[ctx][mode];
|
||||
|
||||
return NEARESTMV + mode;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int read_segment_id(aom_reader *r,
|
||||
|
|
|
@ -51,9 +51,11 @@ static const struct av1_token switchable_interp_encodings[SWITCHABLE_FILTERS] =
|
|||
static const struct av1_token partition_encodings[PARTITION_TYPES] = {
|
||||
{ 0, 1 }, { 2, 2 }, { 6, 3 }, { 7, 3 }
|
||||
};
|
||||
#if !CONFIG_REF_MV
|
||||
static const struct av1_token inter_mode_encodings[INTER_MODES] = {
|
||||
{ 2, 2 }, { 6, 3 }, { 0, 1 }, { 7, 3 }
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct av1_token ext_tx_encodings[TX_TYPES];
|
||||
|
||||
|
@ -66,11 +68,31 @@ static void write_intra_mode(aom_writer *w, PREDICTION_MODE mode,
|
|||
av1_write_token(w, av1_intra_mode_tree, probs, &intra_mode_encodings[mode]);
|
||||
}
|
||||
|
||||
static void write_inter_mode(aom_writer *w, PREDICTION_MODE mode,
|
||||
const aom_prob *probs) {
|
||||
static void write_inter_mode(AV1_COMMON *cm,
|
||||
aom_writer *w, PREDICTION_MODE mode,
|
||||
const uint8_t mode_ctx) {
|
||||
#if CONFIG_REF_MV
|
||||
const uint8_t newmv_ctx = mode_ctx & NEWMV_CTX_MASK;
|
||||
const aom_prob newmv_prob = cm->fc->newmv_prob[newmv_ctx];
|
||||
aom_write(w, mode != NEWMV, newmv_prob);
|
||||
|
||||
if (mode != NEWMV) {
|
||||
const uint8_t zeromv_ctx = (mode_ctx >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
|
||||
const aom_prob zeromv_prob = cm->fc->zeromv_prob[zeromv_ctx];
|
||||
aom_write(w, mode != ZEROMV, zeromv_prob);
|
||||
|
||||
if (mode != ZEROMV) {
|
||||
const uint8_t refmv_ctx = (mode_ctx >> REFMV_OFFSET);
|
||||
const aom_prob refmv_prob = cm->fc->refmv_prob[refmv_ctx];
|
||||
aom_write(w, mode != NEARESTMV, refmv_prob);
|
||||
}
|
||||
}
|
||||
#else
|
||||
const aom_prob *const inter_probs = cm->fc->inter_mode_probs[mode_ctx];
|
||||
assert(is_inter_mode(mode));
|
||||
av1_write_token(w, av1_inter_mode_tree, probs,
|
||||
av1_write_token(w, av1_inter_mode_tree, inter_probs,
|
||||
&inter_mode_encodings[INTER_OFFSET(mode)]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void encode_unsigned_max(struct aom_write_bit_buffer *wb, int data,
|
||||
|
@ -125,6 +147,22 @@ static void write_selected_tx_size(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
|||
}
|
||||
}
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
static void update_inter_mode_probs(AV1_COMMON *cm, aom_writer *w,
|
||||
FRAME_COUNTS *counts) {
|
||||
int i;
|
||||
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i)
|
||||
av1_cond_prob_diff_update(w, &cm->fc->newmv_prob[i],
|
||||
counts->newmv_mode[i]);
|
||||
for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i)
|
||||
av1_cond_prob_diff_update(w, &cm->fc->zeromv_prob[i],
|
||||
counts->zeromv_mode[i]);
|
||||
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i)
|
||||
av1_cond_prob_diff_update(w, &cm->fc->refmv_prob[i],
|
||||
counts->refmv_mode[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int write_skip(const AV1_COMMON *cm, const MACROBLOCKD *xd,
|
||||
int segment_id, const MODE_INFO *mi, aom_writer *w) {
|
||||
if (segfeature_active(&cm->seg, segment_id, SEG_LVL_SKIP)) {
|
||||
|
@ -380,13 +418,12 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const MODE_INFO *mi,
|
|||
write_intra_mode(w, mbmi->uv_mode, cm->fc->uv_mode_prob[mode]);
|
||||
} else {
|
||||
const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
|
||||
const aom_prob *const inter_probs = cm->fc->inter_mode_probs[mode_ctx];
|
||||
write_ref_frames(cm, xd, w);
|
||||
|
||||
// If segment skip is not enabled code the mode.
|
||||
if (!segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
|
||||
if (bsize >= BLOCK_8X8) {
|
||||
write_inter_mode(w, mode, inter_probs);
|
||||
write_inter_mode(cm, w, mode, mode_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,7 +445,7 @@ static void pack_inter_mode_mvs(AV1_COMP *cpi, const MODE_INFO *mi,
|
|||
for (idx = 0; idx < 2; idx += num_4x4_w) {
|
||||
const int j = idy * 2 + idx;
|
||||
const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
|
||||
write_inter_mode(w, b_mode, inter_probs);
|
||||
write_inter_mode(cm, w, b_mode, mode_ctx);
|
||||
if (b_mode == NEWMV) {
|
||||
for (ref = 0; ref < 1 + is_compound; ++ref)
|
||||
av1_encode_mv(cpi, w, &mi->bmi[j].as_mv[ref].as_mv,
|
||||
|
@ -1403,10 +1440,13 @@ static size_t write_compressed_header(AV1_COMP *cpi, uint8_t *data) {
|
|||
counts->kf_y_mode[i][j], INTRA_MODES, &header_bc);
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_REF_MV
|
||||
update_inter_mode_probs(cm, &header_bc, counts);
|
||||
#else
|
||||
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
|
||||
prob_diff_update(av1_inter_mode_tree, cm->fc->inter_mode_probs[i],
|
||||
counts->inter_mode[i], INTER_MODES, &header_bc);
|
||||
|
||||
#endif
|
||||
if (cm->interp_filter == SWITCHABLE)
|
||||
update_switchable_interp_probs(cm, &header_bc, counts);
|
||||
|
||||
|
|
|
@ -1161,6 +1161,29 @@ static void rd_pick_sb_modes(AV1_COMP *cpi, TileDataEnc *tile_data,
|
|||
ctx->dist = rd_cost->dist;
|
||||
}
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
static void update_inter_mode_stats(FRAME_COUNTS *counts,
|
||||
PREDICTION_MODE mode,
|
||||
uint8_t mode_context) {
|
||||
uint8_t mode_ctx = mode_context & NEWMV_CTX_MASK;
|
||||
if (mode == NEWMV) {
|
||||
++counts->newmv_mode[mode_ctx][0];
|
||||
return;
|
||||
} else {
|
||||
++counts->newmv_mode[mode_ctx][1];
|
||||
mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
|
||||
if (mode == ZEROMV) {
|
||||
++counts->zeromv_mode[mode_ctx][0];
|
||||
return;
|
||||
} else {
|
||||
++counts->zeromv_mode[mode_ctx][1];
|
||||
mode_ctx = (mode_context >> REFMV_OFFSET);
|
||||
++counts->refmv_mode[mode_ctx][mode != NEARESTMV];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void update_stats(AV1_COMMON *cm, ThreadData *td) {
|
||||
const MACROBLOCK *x = &td->mb;
|
||||
const MACROBLOCKD *const xd = &x->e_mbd;
|
||||
|
@ -1202,7 +1225,11 @@ static void update_stats(AV1_COMMON *cm, ThreadData *td) {
|
|||
const int mode_ctx = mbmi_ext->mode_context[mbmi->ref_frame[0]];
|
||||
if (bsize >= BLOCK_8X8) {
|
||||
const PREDICTION_MODE mode = mbmi->mode;
|
||||
#if CONFIG_REF_MV
|
||||
update_inter_mode_stats(counts, mode, mode_ctx);
|
||||
#else
|
||||
++counts->inter_mode[mode_ctx][INTER_OFFSET(mode)];
|
||||
#endif
|
||||
} else {
|
||||
const int num_4x4_w = num_4x4_blocks_wide_lookup[bsize];
|
||||
const int num_4x4_h = num_4x4_blocks_high_lookup[bsize];
|
||||
|
@ -1211,7 +1238,11 @@ static void update_stats(AV1_COMMON *cm, ThreadData *td) {
|
|||
for (idx = 0; idx < 2; idx += num_4x4_w) {
|
||||
const int j = idy * 2 + idx;
|
||||
const PREDICTION_MODE b_mode = mi->bmi[j].as_mode;
|
||||
#if CONFIG_REF_MV
|
||||
update_inter_mode_stats(counts, b_mode, mode_ctx);
|
||||
#else
|
||||
++counts->inter_mode[mode_ctx][INTER_OFFSET(b_mode)];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -450,6 +450,12 @@ typedef struct AV1_COMP {
|
|||
|
||||
search_site_config ss_cfg;
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
int newmv_mode_cost[NEWMV_MODE_CONTEXTS][2];
|
||||
int zeromv_mode_cost[ZEROMV_MODE_CONTEXTS][2];
|
||||
int refmv_mode_cost[REFMV_MODE_CONTEXTS][2];
|
||||
#endif
|
||||
|
||||
int mbmode_cost[INTRA_MODES];
|
||||
unsigned int inter_mode_cost[INTER_MODE_CONTEXTS][INTER_MODES];
|
||||
int intra_uv_mode_cost[INTRA_MODES][INTRA_MODES];
|
||||
|
|
|
@ -295,9 +295,26 @@ void av1_initialize_rd_consts(AV1_COMP *cpi) {
|
|||
cm->allow_high_precision_mv ? x->nmvcost_hp : x->nmvcost, &cm->fc->nmvc,
|
||||
cm->allow_high_precision_mv);
|
||||
|
||||
#if CONFIG_REF_MV
|
||||
for (i = 0; i < NEWMV_MODE_CONTEXTS; ++i) {
|
||||
cpi->newmv_mode_cost[i][0] = av1_cost_bit(cm->fc->newmv_prob[i], 0);
|
||||
cpi->newmv_mode_cost[i][1] = av1_cost_bit(cm->fc->newmv_prob[i], 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < ZEROMV_MODE_CONTEXTS; ++i) {
|
||||
cpi->zeromv_mode_cost[i][0] = av1_cost_bit(cm->fc->zeromv_prob[i], 0);
|
||||
cpi->zeromv_mode_cost[i][1] = av1_cost_bit(cm->fc->zeromv_prob[i], 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < REFMV_MODE_CONTEXTS; ++i) {
|
||||
cpi->refmv_mode_cost[i][0] = av1_cost_bit(cm->fc->refmv_prob[i], 0);
|
||||
cpi->refmv_mode_cost[i][1] = av1_cost_bit(cm->fc->refmv_prob[i], 1);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
|
||||
av1_cost_tokens((int *)cpi->inter_mode_cost[i],
|
||||
cm->fc->inter_mode_probs[i], av1_inter_mode_tree);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1242,9 +1242,33 @@ static void choose_intra_uv_mode(AV1_COMP *cpi, MACROBLOCK *const x,
|
|||
}
|
||||
|
||||
static int cost_mv_ref(const AV1_COMP *cpi, PREDICTION_MODE mode,
|
||||
int mode_context) {
|
||||
uint8_t mode_context) {
|
||||
#if CONFIG_REF_MV
|
||||
int mode_cost = 0;
|
||||
uint8_t mode_ctx = mode_context & NEWMV_CTX_MASK;
|
||||
|
||||
assert(is_inter_mode(mode));
|
||||
|
||||
if (mode == NEWMV) {
|
||||
mode_cost = cpi->newmv_mode_cost[mode_ctx][0];
|
||||
return mode_cost;
|
||||
} else {
|
||||
mode_cost = cpi->newmv_mode_cost[mode_ctx][1];
|
||||
mode_ctx = (mode_context >> ZEROMV_OFFSET) & ZEROMV_CTX_MASK;
|
||||
if (mode == ZEROMV) {
|
||||
mode_cost += cpi->zeromv_mode_cost[mode_ctx][0];
|
||||
return mode_cost;
|
||||
} else {
|
||||
mode_cost += cpi->zeromv_mode_cost[mode_ctx][1];
|
||||
mode_ctx = (mode_context >> REFMV_OFFSET);
|
||||
mode_cost += cpi->refmv_mode_cost[mode_ctx][mode != NEARESTMV];
|
||||
return mode_cost;
|
||||
}
|
||||
}
|
||||
#else
|
||||
assert(is_inter_mode(mode));
|
||||
return cpi->inter_mode_cost[mode_context][INTER_OFFSET(mode)];
|
||||
#endif
|
||||
}
|
||||
|
||||
static int set_and_cost_bmi_mvs(AV1_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
|
||||
|
|
Загрузка…
Ссылка в новой задаче