46ea9ec719
This commit enables a fast reference motion vector search scheme. It checks the nearest top and left neighboring blocks to decide the most probable predicted motion vector. If it finds the two have the same motion vectors, it then skip finding exterior range for the second most probable motion vector, and correspondingly skips the check for NEARMV. The runtime of speed -5 goes down pedestrian at 1080p 29377 ms -> 27783 ms vidyo at 720p 11830 ms -> 10990 ms i.e., 6%-8% speed-up. For rtc set, the compression performance goes down by about -1.3% for both speed -5 and -6. Change-Id: I2a7794fa99734f739f8b30519ad4dfd511ab91a5
191 lines
6.7 KiB
C
191 lines
6.7 KiB
C
|
|
/*
|
|
* Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "vp9/common/vp9_mvref_common.h"
|
|
|
|
// This function searches the neighbourhood of a given MB/SB
|
|
// to try and find candidate reference vectors.
|
|
static void find_mv_refs_idx(const VP9_COMMON *cm, const MACROBLOCKD *xd,
|
|
const TileInfo *const tile,
|
|
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
|
|
int_mv *mv_ref_list,
|
|
int block, int mi_row, int mi_col) {
|
|
const int *ref_sign_bias = cm->ref_frame_sign_bias;
|
|
int i, refmv_count = 0;
|
|
const MODE_INFO *prev_mi = cm->coding_use_prev_mi && cm->prev_mi
|
|
? cm->prev_mi_grid_visible[mi_row * xd->mi_stride + mi_col]
|
|
: NULL;
|
|
const MB_MODE_INFO *const prev_mbmi = prev_mi ? &prev_mi->mbmi : NULL;
|
|
|
|
|
|
const POSITION *const mv_ref_search = mv_ref_blocks[mi->mbmi.sb_type];
|
|
|
|
int different_ref_found = 0;
|
|
int context_counter = 0;
|
|
|
|
// Blank the reference vector list
|
|
vpx_memset(mv_ref_list, 0, sizeof(*mv_ref_list) * MAX_MV_REF_CANDIDATES);
|
|
|
|
// The nearest 2 blocks are treated differently
|
|
// if the size < 8x8 we get the mv from the bmi substructure,
|
|
// and we also need to keep a mode count.
|
|
for (i = 0; i < 2; ++i) {
|
|
const POSITION *const mv_ref = &mv_ref_search[i];
|
|
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
|
|
const MODE_INFO *const candidate_mi = xd->mi[mv_ref->col + mv_ref->row *
|
|
xd->mi_stride];
|
|
const MB_MODE_INFO *const candidate = &candidate_mi->mbmi;
|
|
// Keep counts for entropy encoding.
|
|
context_counter += mode_2_counter[candidate->mode];
|
|
different_ref_found = 1;
|
|
|
|
if (candidate->ref_frame[0] == ref_frame)
|
|
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 0, mv_ref->col, block));
|
|
else if (candidate->ref_frame[1] == ref_frame)
|
|
ADD_MV_REF_LIST(get_sub_block_mv(candidate_mi, 1, mv_ref->col, block));
|
|
}
|
|
}
|
|
|
|
// Check the rest of the neighbors in much the same way
|
|
// as before except we don't need to keep track of sub blocks or
|
|
// mode counts.
|
|
for (; i < MVREF_NEIGHBOURS; ++i) {
|
|
const POSITION *const mv_ref = &mv_ref_search[i];
|
|
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
|
|
const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row *
|
|
xd->mi_stride]->mbmi;
|
|
different_ref_found = 1;
|
|
|
|
if (candidate->ref_frame[0] == ref_frame)
|
|
ADD_MV_REF_LIST(candidate->mv[0]);
|
|
else if (candidate->ref_frame[1] == ref_frame)
|
|
ADD_MV_REF_LIST(candidate->mv[1]);
|
|
}
|
|
}
|
|
|
|
// Check the last frame's mode and mv info.
|
|
if (prev_mbmi) {
|
|
if (prev_mbmi->ref_frame[0] == ref_frame)
|
|
ADD_MV_REF_LIST(prev_mbmi->mv[0]);
|
|
else if (prev_mbmi->ref_frame[1] == ref_frame)
|
|
ADD_MV_REF_LIST(prev_mbmi->mv[1]);
|
|
}
|
|
|
|
// Since we couldn't find 2 mvs from the same reference frame
|
|
// go back through the neighbors and find motion vectors from
|
|
// different reference frames.
|
|
if (different_ref_found) {
|
|
for (i = 0; i < MVREF_NEIGHBOURS; ++i) {
|
|
const POSITION *mv_ref = &mv_ref_search[i];
|
|
if (is_inside(tile, mi_col, mi_row, cm->mi_rows, mv_ref)) {
|
|
const MB_MODE_INFO *const candidate = &xd->mi[mv_ref->col + mv_ref->row
|
|
* xd->mi_stride]->mbmi;
|
|
|
|
// If the candidate is INTRA we don't want to consider its mv.
|
|
IF_DIFF_REF_FRAME_ADD_MV(candidate);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Since we still don't have a candidate we'll try the last frame.
|
|
if (prev_mbmi)
|
|
IF_DIFF_REF_FRAME_ADD_MV(prev_mbmi);
|
|
|
|
Done:
|
|
|
|
mi->mbmi.mode_context[ref_frame] = counter_to_context[context_counter];
|
|
|
|
// Clamp vectors
|
|
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i)
|
|
clamp_mv_ref(&mv_ref_list[i].as_mv, xd);
|
|
}
|
|
|
|
void vp9_find_mv_refs(const VP9_COMMON *cm, const MACROBLOCKD *xd,
|
|
const TileInfo *const tile,
|
|
MODE_INFO *mi, MV_REFERENCE_FRAME ref_frame,
|
|
int_mv *mv_ref_list,
|
|
int mi_row, int mi_col) {
|
|
find_mv_refs_idx(cm, xd, tile, mi, ref_frame, mv_ref_list, -1,
|
|
mi_row, mi_col);
|
|
}
|
|
|
|
static void lower_mv_precision(MV *mv, int allow_hp) {
|
|
const int use_hp = allow_hp && vp9_use_mv_hp(mv);
|
|
if (!use_hp) {
|
|
if (mv->row & 1)
|
|
mv->row += (mv->row > 0 ? -1 : 1);
|
|
if (mv->col & 1)
|
|
mv->col += (mv->col > 0 ? -1 : 1);
|
|
}
|
|
}
|
|
|
|
|
|
void vp9_find_best_ref_mvs(MACROBLOCKD *xd, int allow_hp,
|
|
int_mv *mvlist, int_mv *nearest, int_mv *near) {
|
|
int i;
|
|
// Make sure all the candidates are properly clamped etc
|
|
for (i = 0; i < MAX_MV_REF_CANDIDATES; ++i) {
|
|
lower_mv_precision(&mvlist[i].as_mv, allow_hp);
|
|
clamp_mv2(&mvlist[i].as_mv, xd);
|
|
}
|
|
*nearest = mvlist[0];
|
|
*near = mvlist[1];
|
|
}
|
|
|
|
void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *cm, MACROBLOCKD *xd,
|
|
const TileInfo *const tile,
|
|
int block, int ref, int mi_row, int mi_col,
|
|
int_mv *nearest, int_mv *near) {
|
|
int_mv mv_list[MAX_MV_REF_CANDIDATES];
|
|
MODE_INFO *const mi = xd->mi[0];
|
|
b_mode_info *bmi = mi->bmi;
|
|
int n;
|
|
|
|
assert(MAX_MV_REF_CANDIDATES == 2);
|
|
|
|
find_mv_refs_idx(cm, xd, tile, mi, mi->mbmi.ref_frame[ref], mv_list, block,
|
|
mi_row, mi_col);
|
|
|
|
near->as_int = 0;
|
|
switch (block) {
|
|
case 0:
|
|
nearest->as_int = mv_list[0].as_int;
|
|
near->as_int = mv_list[1].as_int;
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
nearest->as_int = bmi[0].as_mv[ref].as_int;
|
|
for (n = 0; n < MAX_MV_REF_CANDIDATES; ++n)
|
|
if (nearest->as_int != mv_list[n].as_int) {
|
|
near->as_int = mv_list[n].as_int;
|
|
break;
|
|
}
|
|
break;
|
|
case 3: {
|
|
int_mv candidates[2 + MAX_MV_REF_CANDIDATES];
|
|
candidates[0] = bmi[1].as_mv[ref];
|
|
candidates[1] = bmi[0].as_mv[ref];
|
|
candidates[2] = mv_list[0];
|
|
candidates[3] = mv_list[1];
|
|
|
|
nearest->as_int = bmi[2].as_mv[ref].as_int;
|
|
for (n = 0; n < 2 + MAX_MV_REF_CANDIDATES; ++n)
|
|
if (nearest->as_int != candidates[n].as_int) {
|
|
near->as_int = candidates[n].as_int;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
assert("Invalid block index.");
|
|
}
|
|
}
|