At the final round of encoding of each superblock, will go through
each prediction block to check if ncobmc mode is better than non-
overlapped prediction. Note that causal obmc mode is dumped here.

PSNR gain (MOTION_VAR + NCOBMC): -2.845% lowres

Change-Id: Ibe504f7f1882446a08ba426e1e9824bca73bf655
This commit is contained in:
Yue Chen 2017-01-13 11:11:43 -08:00
Родитель 2615d6eaac
Коммит f27b16053e
6 изменённых файлов: 278 добавлений и 16 удалений

Просмотреть файл

@ -736,7 +736,9 @@ void build_inter_predictors(MACROBLOCKD *xd, int plane,
struct macroblockd_plane *const pd = &xd->plane[plane]; struct macroblockd_plane *const pd = &xd->plane[plane];
#if CONFIG_MOTION_VAR #if CONFIG_MOTION_VAR
const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset]; const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset];
#if !CONFIG_CB4X4
const int build_for_obmc = !(mi_col_offset == 0 && mi_row_offset == 0); const int build_for_obmc = !(mi_col_offset == 0 && mi_row_offset == 0);
#endif
#else #else
const MODE_INFO *mi = xd->mi[0]; const MODE_INFO *mi = xd->mi[0];
#endif // CONFIG_MOTION_VAR #endif // CONFIG_MOTION_VAR
@ -2256,9 +2258,7 @@ void av1_build_ncobmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
#if CONFIG_AOM_HIGHBITDEPTH #if CONFIG_AOM_HIGHBITDEPTH
} }
#endif // CONFIG_AOM_HIGHBITDEPTH #endif // CONFIG_AOM_HIGHBITDEPTH
// causal obmc pred
// replace by bottom and right preds
av1_build_prediction_by_bottom_preds(cm, xd, mi_row, mi_col, dst_buf1, av1_build_prediction_by_bottom_preds(cm, xd, mi_row, mi_col, dst_buf1,
dst_width1, dst_height1, dst_stride1); dst_width1, dst_height1, dst_stride1);
av1_build_prediction_by_right_preds(cm, xd, mi_row, mi_col, dst_buf2, av1_build_prediction_by_right_preds(cm, xd, mi_row, mi_col, dst_buf2,

Просмотреть файл

@ -1665,7 +1665,11 @@ static void decode_token_and_recon_block(AV1Decoder *const pbi,
#endif // CONFIG_WARPED_MOTION #endif // CONFIG_WARPED_MOTION
#if CONFIG_MOTION_VAR #if CONFIG_MOTION_VAR
if (mbmi->motion_mode == OBMC_CAUSAL) { if (mbmi->motion_mode == OBMC_CAUSAL) {
#if CONFIG_NCOBMC
av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
#else
av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col); av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
#endif
} }
#endif // CONFIG_MOTION_VAR #endif // CONFIG_MOTION_VAR

Просмотреть файл

@ -2187,19 +2187,21 @@ static void write_tokens_sb(AV1_COMP *cpi, const TileInfo *const tile,
const TOKENEXTRA *const tok_end, int mi_row, const TOKENEXTRA *const tok_end, int mi_row,
int mi_col, BLOCK_SIZE bsize) { int mi_col, BLOCK_SIZE bsize) {
const AV1_COMMON *const cm = &cpi->common; const AV1_COMMON *const cm = &cpi->common;
const int bsl = b_width_log2_lookup[bsize]; const int hbs = mi_size_wide[bsize] / 2;
const int bs = (1 << bsl) / 4;
PARTITION_TYPE partition; PARTITION_TYPE partition;
BLOCK_SIZE subsize; BLOCK_SIZE subsize;
const MODE_INFO *m = NULL; #if CONFIG_CB4X4
const int unify_bsize = 1;
#else
const int unify_bsize = 0;
#endif
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return; if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
m = cm->mi_grid_visible[mi_row * cm->mi_stride + mi_col]; partition = get_partition(cm, mi_row, mi_col, bsize);
partition = partition_lookup[bsl][m->mbmi.sb_type];
subsize = get_subsize(bsize, partition); subsize = get_subsize(bsize, partition);
if (subsize < BLOCK_8X8) { if (subsize < BLOCK_8X8 && !unify_bsize) {
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col); write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
} else { } else {
switch (partition) { switch (partition) {
@ -2208,23 +2210,45 @@ static void write_tokens_sb(AV1_COMP *cpi, const TileInfo *const tile,
break; break;
case PARTITION_HORZ: case PARTITION_HORZ:
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col); write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
if (mi_row + bs < cm->mi_rows) if (mi_row + hbs < cm->mi_rows)
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col); write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col);
break; break;
case PARTITION_VERT: case PARTITION_VERT:
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col); write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
if (mi_col + bs < cm->mi_cols) if (mi_col + hbs < cm->mi_cols)
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs); write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + hbs);
break; break;
case PARTITION_SPLIT: case PARTITION_SPLIT:
write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, subsize); write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col, subsize);
write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col + bs, write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row, mi_col + hbs,
subsize); subsize);
write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col, write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col,
subsize); subsize);
write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row + bs, mi_col + bs, write_tokens_sb(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col + hbs,
subsize); subsize);
break; break;
#if CONFIG_EXT_PARTITION_TYPES
case PARTITION_HORZ_A:
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + hbs);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col);
break;
case PARTITION_HORZ_B:
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col + hbs);
break;
case PARTITION_VERT_A:
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + hbs);
break;
case PARTITION_VERT_B:
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row, mi_col + hbs);
write_tokens_b(cpi, tile, w, tok, tok_end, mi_row + hbs, mi_col + hbs);
break;
#endif // CONFIG_EXT_PARTITION_TYPES
default: assert(0); default: assert(0);
} }
} }

Просмотреть файл

@ -1635,6 +1635,110 @@ static void update_supertx_param_sb(const AV1_COMP *const cpi, ThreadData *td,
} }
#endif // CONFIG_SUPERTX #endif // CONFIG_SUPERTX
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC
static void set_mode_info_b(const AV1_COMP *const cpi,
const TileInfo *const tile, ThreadData *td,
int mi_row, int mi_col, BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx) {
MACROBLOCK *const x = &td->mb;
set_offsets(cpi, tile, x, mi_row, mi_col, bsize);
update_state(cpi, td, ctx, mi_row, mi_col, bsize, 1);
}
static void set_mode_info_sb(const AV1_COMP *const cpi, ThreadData *td,
const TileInfo *const tile, TOKENEXTRA **tp,
int mi_row, int mi_col, BLOCK_SIZE bsize,
PC_TREE *pc_tree) {
const AV1_COMMON *const cm = &cpi->common;
const int bsl = b_width_log2_lookup[bsize], hbs = (1 << bsl) / 4;
const PARTITION_TYPE partition = pc_tree->partitioning;
BLOCK_SIZE subsize = get_subsize(bsize, partition);
#if CONFIG_EXT_PARTITION_TYPES
const BLOCK_SIZE bsize2 = get_subsize(bsize, PARTITION_SPLIT);
#endif
#if CONFIG_CB4X4
const int unify_bsize = 1;
#else
const int unify_bsize = 0;
assert(bsize >= BLOCK_8X8);
#endif
if (mi_row >= cm->mi_rows || mi_col >= cm->mi_cols) return;
switch (partition) {
case PARTITION_NONE:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize, &pc_tree->none);
break;
case PARTITION_VERT:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
&pc_tree->vertical[0]);
if (mi_col + hbs < cm->mi_cols && (bsize > BLOCK_8X8 || unify_bsize)) {
set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, subsize,
&pc_tree->vertical[1]);
}
break;
case PARTITION_HORZ:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
&pc_tree->horizontal[0]);
if (mi_row + hbs < cm->mi_rows && (bsize > BLOCK_8X8 || unify_bsize)) {
set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, subsize,
&pc_tree->horizontal[1]);
}
break;
case PARTITION_SPLIT:
if (bsize == BLOCK_8X8 && !unify_bsize) {
set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
pc_tree->leaf_split[0]);
} else {
set_mode_info_sb(cpi, td, tile, tp, mi_row, mi_col, subsize,
pc_tree->split[0]);
set_mode_info_sb(cpi, td, tile, tp, mi_row, mi_col + hbs, subsize,
pc_tree->split[1]);
set_mode_info_sb(cpi, td, tile, tp, mi_row + hbs, mi_col, subsize,
pc_tree->split[2]);
set_mode_info_sb(cpi, td, tile, tp, mi_row + hbs, mi_col + hbs, subsize,
pc_tree->split[3]);
}
break;
#if CONFIG_EXT_PARTITION_TYPES
case PARTITION_HORZ_A:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, bsize2,
&pc_tree->horizontala[0]);
set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, bsize2,
&pc_tree->horizontala[1]);
set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, subsize,
&pc_tree->horizontala[2]);
break;
case PARTITION_HORZ_B:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
&pc_tree->horizontalb[0]);
set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, bsize2,
&pc_tree->horizontalb[1]);
set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col + hbs, bsize2,
&pc_tree->horizontalb[2]);
break;
case PARTITION_VERT_A:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, bsize2,
&pc_tree->verticala[0]);
set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col, bsize2,
&pc_tree->verticala[1]);
set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, subsize,
&pc_tree->verticala[2]);
break;
case PARTITION_VERT_B:
set_mode_info_b(cpi, tile, td, mi_row, mi_col, subsize,
&pc_tree->verticalb[0]);
set_mode_info_b(cpi, tile, td, mi_row, mi_col + hbs, bsize2,
&pc_tree->verticalb[1]);
set_mode_info_b(cpi, tile, td, mi_row + hbs, mi_col + hbs, bsize2,
&pc_tree->verticalb[2]);
break;
#endif // CONFIG_EXT_PARTITION_TYPES
default: assert(0 && "Invalid partition type."); break;
}
}
#endif
void av1_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src, void av1_setup_src_planes(MACROBLOCK *x, const YV12_BUFFER_CONFIG *src,
int mi_row, int mi_col) { int mi_row, int mi_col) {
uint8_t *const buffers[3] = { src->y_buffer, src->u_buffer, src->v_buffer }; uint8_t *const buffers[3] = { src->y_buffer, src->u_buffer, src->v_buffer };
@ -2242,11 +2346,27 @@ static void encode_b(const AV1_COMP *const cpi, const TileInfo *const tile,
#endif #endif
PICK_MODE_CONTEXT *ctx, int *rate) { PICK_MODE_CONTEXT *ctx, int *rate) {
MACROBLOCK *const x = &td->mb; MACROBLOCK *const x = &td->mb;
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi;
int check_ncobmc;
#endif
set_offsets(cpi, tile, x, mi_row, mi_col, bsize); set_offsets(cpi, tile, x, mi_row, mi_col, bsize);
#if CONFIG_EXT_PARTITION_TYPES #if CONFIG_EXT_PARTITION_TYPES
x->e_mbd.mi[0]->mbmi.partition = partition; x->e_mbd.mi[0]->mbmi.partition = partition;
#endif #endif
update_state(cpi, td, ctx, mi_row, mi_col, bsize, dry_run); update_state(cpi, td, ctx, mi_row, mi_col, bsize, dry_run);
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC
mbmi = &xd->mi[0]->mbmi;
check_ncobmc =
is_inter_block(mbmi) && motion_mode_allowed(mbmi) >= OBMC_CAUSAL;
if (!dry_run && check_ncobmc) {
av1_check_ncobmc_rd(cpi, x, mi_row, mi_col);
av1_setup_dst_planes(x->e_mbd.plane, get_frame_new_buffer(&cpi->common),
mi_row, mi_col);
}
#endif
encode_superblock(cpi, td, tp, dry_run, mi_row, mi_col, bsize, ctx, rate); encode_superblock(cpi, td, tp, dry_run, mi_row, mi_col, bsize, ctx, rate);
if (!dry_run) { if (!dry_run) {
@ -4357,6 +4477,9 @@ static void rd_pick_partition(const AV1_COMP *const cpi, ThreadData *td,
if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX && if (best_rdc.rate < INT_MAX && best_rdc.dist < INT64_MAX &&
pc_tree->index != 3) { pc_tree->index != 3) {
if (bsize == cm->sb_size) { if (bsize == cm->sb_size) {
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC
set_mode_info_sb(cpi, td, tile_info, tp, mi_row, mi_col, bsize, pc_tree);
#endif
encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, OUTPUT_ENABLED, bsize, encode_sb(cpi, td, tile_info, tp, mi_row, mi_col, OUTPUT_ENABLED, bsize,
pc_tree, NULL); pc_tree, NULL);
} else { } else {
@ -5517,6 +5640,11 @@ static void encode_superblock(const AV1_COMP *const cpi, ThreadData *td,
#if CONFIG_MOTION_VAR #if CONFIG_MOTION_VAR
if (mbmi->motion_mode == OBMC_CAUSAL) { if (mbmi->motion_mode == OBMC_CAUSAL) {
#if CONFIG_NCOBMC
if (dry_run == OUTPUT_ENABLED)
av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
else
#endif
av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col); av1_build_obmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
} }
#endif // CONFIG_MOTION_VAR #endif // CONFIG_MOTION_VAR

Просмотреть файл

@ -11573,4 +11573,105 @@ static void calc_target_weighted_pred(const AV1_COMMON *cm, const MACROBLOCK *x,
#endif // CONFIG_AOM_HIGHBITDEPTH #endif // CONFIG_AOM_HIGHBITDEPTH
} }
} }
#if CONFIG_NCOBMC
void av1_check_ncobmc_rd(const struct AV1_COMP *cpi, struct macroblock *x,
int mi_row, int mi_col) {
const AV1_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
MB_MODE_INFO backup_mbmi;
BLOCK_SIZE bsize = mbmi->sb_type;
int ref, skip_blk, backup_skip = x->skip;
int64_t rd_causal;
RD_STATS rd_stats_y, rd_stats_uv;
int rate_skip0 = av1_cost_bit(av1_get_skip_prob(cm, xd), 0);
int rate_skip1 = av1_cost_bit(av1_get_skip_prob(cm, xd), 1);
// Recompute the best causal predictor and rd
mbmi->motion_mode = SIMPLE_TRANSLATION;
set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, mbmi->ref_frame[ref]);
assert(cfg != NULL);
av1_setup_pre_planes(xd, ref, cfg, mi_row, mi_col,
&xd->block_refs[ref]->sf);
}
av1_setup_dst_planes(x->e_mbd.plane, get_frame_new_buffer(&cpi->common),
mi_row, mi_col);
av1_build_inter_predictors_sb(xd, mi_row, mi_col, NULL, bsize);
av1_subtract_plane(x, bsize, 0);
super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
if (rd_stats_y.skip && rd_stats_uv.skip) {
rd_stats_y.rate = rate_skip1;
rd_stats_uv.rate = 0;
rd_stats_y.dist = rd_stats_y.sse;
rd_stats_uv.dist = rd_stats_uv.sse;
skip_blk = 0;
} else if (RDCOST(x->rdmult, x->rddiv,
(rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
(rd_stats_y.dist + rd_stats_uv.dist)) >
RDCOST(x->rdmult, x->rddiv, rate_skip1,
(rd_stats_y.sse + rd_stats_uv.sse))) {
rd_stats_y.rate = rate_skip1;
rd_stats_uv.rate = 0;
rd_stats_y.dist = rd_stats_y.sse;
rd_stats_uv.dist = rd_stats_uv.sse;
skip_blk = 1;
} else {
rd_stats_y.rate += rate_skip0;
skip_blk = 0;
}
backup_skip = skip_blk;
backup_mbmi = *mbmi;
rd_causal = RDCOST(x->rdmult, x->rddiv, (rd_stats_y.rate + rd_stats_uv.rate),
(rd_stats_y.dist + rd_stats_uv.dist));
rd_causal += RDCOST(x->rdmult, x->rddiv,
av1_cost_bit(cm->fc->motion_mode_prob[bsize][0], 0), 0);
// Check non-causal mode
mbmi->motion_mode = OBMC_CAUSAL;
av1_build_ncobmc_inter_predictors_sb(cm, xd, mi_row, mi_col);
av1_subtract_plane(x, bsize, 0);
super_block_yrd(cpi, x, &rd_stats_y, bsize, INT64_MAX);
super_block_uvrd(cpi, x, &rd_stats_uv, bsize, INT64_MAX);
assert(rd_stats_y.rate != INT_MAX && rd_stats_uv.rate != INT_MAX);
if (rd_stats_y.skip && rd_stats_uv.skip) {
rd_stats_y.rate = rate_skip1;
rd_stats_uv.rate = 0;
rd_stats_y.dist = rd_stats_y.sse;
rd_stats_uv.dist = rd_stats_uv.sse;
skip_blk = 0;
} else if (RDCOST(x->rdmult, x->rddiv,
(rd_stats_y.rate + rd_stats_uv.rate + rate_skip0),
(rd_stats_y.dist + rd_stats_uv.dist)) >
RDCOST(x->rdmult, x->rddiv, rate_skip1,
(rd_stats_y.sse + rd_stats_uv.sse))) {
rd_stats_y.rate = rate_skip1;
rd_stats_uv.rate = 0;
rd_stats_y.dist = rd_stats_y.sse;
rd_stats_uv.dist = rd_stats_uv.sse;
skip_blk = 1;
} else {
rd_stats_y.rate += rate_skip0;
skip_blk = 0;
}
if (rd_causal >
RDCOST(x->rdmult, x->rddiv,
rd_stats_y.rate + rd_stats_uv.rate +
av1_cost_bit(cm->fc->motion_mode_prob[bsize][0], 1),
(rd_stats_y.dist + rd_stats_uv.dist))) {
x->skip = skip_blk;
} else {
*mbmi = backup_mbmi;
x->skip = backup_skip;
}
}
#endif
#endif // CONFIG_MOTION_VAR #endif // CONFIG_MOTION_VAR

Просмотреть файл

@ -176,6 +176,11 @@ void av1_rd_pick_inter_mode_sub8x8(const struct AV1_COMP *cpi,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far); int64_t best_rd_so_far);
#if CONFIG_MOTION_VAR && CONFIG_NCOBMC
void av1_check_ncobmc_rd(const struct AV1_COMP *cpi, struct macroblock *x,
int mi_row, int mi_col);
#endif // CONFIG_MOTION_VAR && CONFIG_NCOBMC
#if CONFIG_SUPERTX #if CONFIG_SUPERTX
#if CONFIG_VAR_TX #if CONFIG_VAR_TX
void av1_tx_block_rd_b(const AV1_COMP *cpi, MACROBLOCK *x, TX_SIZE tx_size, void av1_tx_block_rd_b(const AV1_COMP *cpi, MACROBLOCK *x, TX_SIZE tx_size,