Fix non-determinism issue with OWF WPP margin

The previous reasoning used deblocking and fractional motion estimation
together to arrive at a margin of 4 pixels. This was wrong, and with
either of these off, half pixel chroma interpolation could use pixels
outside the intended region.

Deblocking does not currently affect the margin needed.
This commit is contained in:
Ari Koivula 2016-03-08 19:26:40 +02:00
parent 674bfa14ce
commit 1671725c72

View file

@ -59,6 +59,21 @@ static INLINE bool fracmv_within_tile(const encoder_state_t *state, const vector
}
static INLINE int get_wpp_limit(const encoder_state_t *state, const vector2d_t* orig)
{
if (state->encoder_control->owf && state->encoder_control->wpp) {
// Limit motion vectors to the LCU-row below this row.
// To avoid fractional pixel interpolation depending on things outside
// this range, add a margin of 4 pixels.
// - fme needs 4 pixels
// - odd chroma interpolation needs 4 pixels
return 2 * LCU_WIDTH - 4 - orig->y % LCU_WIDTH;
} else {
return -1;
}
}
/**
* \return True if referred block is within current tile.
*/
@ -400,7 +415,7 @@ static unsigned tz_search(const encoder_state_t * const state,
int iDist;
int best_dist = 0;
unsigned best_index = num_cand + 1;
int wpp_limit = -1;
int wpp_limit = get_wpp_limit(state, orig);
int(*calc_mvd)(const encoder_state_t * const, int, int, int,
int16_t[2][2], inter_merge_cand_t[MRG_MAX_NUM_CANDS],
@ -409,18 +424,6 @@ static unsigned tz_search(const encoder_state_t * const state,
calc_mvd = kvz_calc_mvd_cost_cabac;
}
if (state->encoder_control->owf) {
wpp_limit = 2 * LCU_WIDTH - orig->y % LCU_WIDTH;
if (state->encoder_control->fme_level > 0) {
// Fractional motion estimation can change the mv by at most 1 pixel.
wpp_limit -= 1;
}
if (state->encoder_control->deblock_enable) {
// Strong deblock filter modifies 3 pixels.
wpp_limit -= 3;
}
}
// Check the 0-vector, so we can ignore all 0-vectors in the merge cand list.
if (intmv_within_tile(state, orig, 0, 0, width, wpp_limit)) {
best_cost = kvz_image_calc_sad(pic, ref, orig->x, orig->y,
@ -608,7 +611,7 @@ static unsigned hexagon_search(const encoder_state_t * const state,
unsigned i;
// Current best index, either to merge_cands, large_hebx or small_hexbs.
unsigned best_index = num_cand + 1;
int wpp_limit = -1;
int wpp_limit = get_wpp_limit(state, orig);
int (*calc_mvd)(const encoder_state_t * const, int, int, int,
int16_t[2][2], inter_merge_cand_t[MRG_MAX_NUM_CANDS],
@ -617,18 +620,6 @@ static unsigned hexagon_search(const encoder_state_t * const state,
calc_mvd = kvz_calc_mvd_cost_cabac;
}
if (state->encoder_control->owf) {
wpp_limit = 2 * LCU_WIDTH - orig->y % LCU_WIDTH;
if (state->encoder_control->fme_level > 0) {
// Fractional motion estimation can change the mv by at most 1 pixel.
wpp_limit -= 1;
}
if (state->encoder_control->deblock_enable) {
// Strong deblock filter modifies 3 pixels.
wpp_limit -= 3;
}
}
// Check the 0-vector, so we can ignore all 0-vectors in the merge cand list.
if (intmv_within_tile(state, orig, 0, 0, width, wpp_limit)) {
best_cost = kvz_image_calc_sad(pic, ref, orig->x, orig->y,
@ -909,14 +900,7 @@ static unsigned search_frac(const encoder_state_t * const state,
{ -1, -1 }, { 0, -1 }, { 1, -1 }
};
int wpp_limit = -1;
if (state->encoder_control->owf) {
wpp_limit = 2 * LCU_WIDTH - orig->y % LCU_WIDTH;
if (state->encoder_control->deblock_enable) {
// Strong deblock filter modifies 3 pixels.
wpp_limit -= 3;
}
}
int wpp_limit = get_wpp_limit(state, orig);
//Set mv to halfpel precision
vector2d_t mv = { mv_in_out->x >> 2, mv_in_out->y >> 2 };