Commit d3afdb90 authored by David Barker's avatar David Barker Committed by Yaowu Xu

[NORMATIVE-DECODING] Fix above/left chroma block selection

As pointed out by rsbultje, my previous patch to is_smooth()
(a883e6ea) was not quite correct. This is because, when we're
making a chroma prediction, the uv_mode for the above/left chroma
predictions is not necessarily in above_mbmi/left_mbmi. Instead,
it may be in any of several places, depending on subsampling and
the values of mi_row/mi_col.

The cleanest solution is to explicitly maintain pointers to the
above and left chroma blocks. Then we can simply look at those
pointers when we want to know the above or left uv_mode.

Also include a bit of refactoring of get_filt_type: It seems
to be recalculating what's already in xd->{above,left}_mi,
so just use those directly.

BUG=aomedia:1362

Change-Id: I0230474a50d43b78cb587a2b553da9ca78cec0c6
parent 5c4848d6
......@@ -588,6 +588,8 @@ typedef struct macroblockd {
MODE_INFO *above_mi;
MB_MODE_INFO *left_mbmi;
MB_MODE_INFO *above_mbmi;
MB_MODE_INFO *chroma_left_mbmi;
MB_MODE_INFO *chroma_above_mbmi;
int up_available;
int left_available;
......
......@@ -894,12 +894,15 @@ static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
}
#endif // CONFIG_DEPENDENT_HORZTILES
const int ss_x = xd->plane[1].subsampling_x;
const int ss_y = xd->plane[1].subsampling_y;
xd->left_available = (mi_col > tile->mi_col_start);
xd->chroma_up_available = xd->up_available;
xd->chroma_left_available = xd->left_available;
if (xd->plane[1].subsampling_x && bw < mi_size_wide[BLOCK_8X8])
if (ss_x && bw < mi_size_wide[BLOCK_8X8])
xd->chroma_left_available = (mi_col - 1) > tile->mi_col_start;
if (xd->plane[1].subsampling_y && bh < mi_size_high[BLOCK_8X8])
if (ss_y && bh < mi_size_high[BLOCK_8X8])
xd->chroma_up_available = (mi_row - 1) > tile->mi_row_start;
if (xd->up_available) {
xd->above_mi = xd->mi[-xd->mi_stride];
......@@ -919,6 +922,29 @@ static INLINE void set_mi_row_col(MACROBLOCKD *xd, const TileInfo *const tile,
xd->left_mbmi = NULL;
}
const int chroma_ref = ((mi_row & 0x01) || !(bh & 0x01) || !ss_y) &&
((mi_col & 0x01) || !(bw & 0x01) || !ss_x);
if (chroma_ref) {
// To help calculate the "above" and "left" chroma blocks, note that the
// current block may cover multiple luma blocks (eg, if partitioned into
// 4x4 luma blocks).
// First, find the top-left-most luma block covered by this chroma block
MODE_INFO **base_mi =
&xd->mi[-(mi_row & ss_y) * xd->mi_stride - (mi_col & ss_x)];
// Then, we consider the luma region covered by the left or above 4x4 chroma
// prediction. We want to point to the chroma reference block in that
// region, which is the bottom-right-most mi unit.
// This leads to the following offsets:
MODE_INFO *chroma_above_mi =
xd->chroma_up_available ? base_mi[-xd->mi_stride + ss_x] : NULL;
xd->chroma_above_mbmi = chroma_above_mi ? &chroma_above_mi->mbmi : NULL;
MODE_INFO *chroma_left_mi =
xd->chroma_left_available ? base_mi[ss_y * xd->mi_stride - 1] : NULL;
xd->chroma_left_mbmi = chroma_left_mi ? &chroma_left_mi->mbmi : NULL;
}
xd->n8_h = bh;
xd->n8_w = bw;
xd->is_sec_rect = 0;
......
......@@ -1407,11 +1407,19 @@ static int is_smooth(const MB_MODE_INFO *mbmi, int plane) {
}
static int get_filt_type(const MACROBLOCKD *xd, int plane) {
const MB_MODE_INFO *ab = xd->up_available ? &xd->mi[-xd->mi_stride]->mbmi : 0;
const MB_MODE_INFO *le = xd->left_available ? &xd->mi[-1]->mbmi : 0;
int ab_sm, le_sm;
const int ab_sm = ab ? is_smooth(ab, plane) : 0;
const int le_sm = le ? is_smooth(le, plane) : 0;
if (plane == 0) {
const MB_MODE_INFO *ab = xd->above_mbmi;
const MB_MODE_INFO *le = xd->left_mbmi;
ab_sm = ab ? is_smooth(ab, plane) : 0;
le_sm = le ? is_smooth(le, plane) : 0;
} else {
const MB_MODE_INFO *ab = xd->chroma_above_mbmi;
const MB_MODE_INFO *le = xd->chroma_left_mbmi;
ab_sm = ab ? is_smooth(ab, plane) : 0;
le_sm = le ? is_smooth(le, plane) : 0;
}
return (ab_sm || le_sm) ? 1 : 0;
}
......
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