Commit ddee66f2 authored by Jingning Han's avatar Jingning Han
Browse files

Refactor the inter predictor for supertx

This commit unifies the inter predictor used in supertx at both
encoder and decoder sides. It removes the redundant decoder
implementations related to border extension.

Change-Id: I03985cee52604a518394232fa9258ce057af9c00
parent 7ac38a71
......@@ -380,475 +380,6 @@ static int reconstruct_inter_block(MACROBLOCKD *const xd,
}
#endif // !CONFIG_VAR_TX || CONFIG_SUPER_TX
#if CONFIG_SUPERTX
static void build_mc_border(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride,
int x, int y, int b_w, int b_h, int w, int h) {
// Get a pointer to the start of the real data for this row.
const uint8_t *ref_row = src - x - y * src_stride;
if (y >= h)
ref_row += (h - 1) * src_stride;
else if (y > 0)
ref_row += y * src_stride;
do {
int right = 0, copy;
int left = x < 0 ? -x : 0;
if (left > b_w)
left = b_w;
if (x + b_w > w)
right = x + b_w - w;
if (right > b_w)
right = b_w;
copy = b_w - left - right;
if (left)
memset(dst, ref_row[0], left);
if (copy)
memcpy(dst + left, ref_row + x + left, copy);
if (right)
memset(dst + left + copy, ref_row[w - 1], right);
dst += dst_stride;
++y;
if (y > 0 && y < h)
ref_row += src_stride;
} while (--b_h);
}
#if CONFIG_VP9_HIGHBITDEPTH
static void build_mc_border_highbd(const uint8_t *src8, int src_stride,
uint16_t *dst, int dst_stride,
int x, int y, int b_w, int b_h,
int w, int h) {
// Get a pointer to the start of the real data for this row.
const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
const uint16_t *ref_row = src - x - y * src_stride;
if (y >= h)
ref_row += (h - 1) * src_stride;
else if (y > 0)
ref_row += y * src_stride;
do {
int right = 0, copy;
int left = x < 0 ? -x : 0;
if (left > b_w)
left = b_w;
if (x + b_w > w)
right = x + b_w - w;
if (right > b_w)
right = b_w;
copy = b_w - left - right;
if (left)
vpx_memset16(dst, ref_row[0], left);
if (copy)
memcpy(dst + left, ref_row + x + left, copy * sizeof(uint16_t));
if (right)
vpx_memset16(dst + left + copy, ref_row[w - 1], right);
dst += dst_stride;
++y;
if (y > 0 && y < h)
ref_row += src_stride;
} while (--b_h);
}
static void extend_and_predict_highbd(const uint8_t *buf_ptr1,
int pre_buf_stride,
int x0, int y0, int b_w, int b_h,
int frame_width, int frame_height,
int border_offset,
uint8_t *const dst, int dst_buf_stride,
int subpel_x, int subpel_y,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter,
#endif
const struct scale_factors *sf,
#if CONFIG_EXT_INTER
int wedge_offset_x, int wedge_offset_y,
#endif // CONFIG_EXT_INTER
MACROBLOCKD *xd,
int w, int h, int ref, int xs, int ys) {
DECLARE_ALIGNED(16, uint16_t,
mc_buf_high[(MAX_SB_SIZE + 16) * 2 * (MAX_SB_SIZE + 16) * 2]);
const uint8_t *buf_ptr;
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
build_mc_border_highbd(buf_ptr1, pre_buf_stride, mc_buf_high, b_w,
x0, y0, b_w, b_h, frame_width, frame_height);
buf_ptr = CONVERT_TO_BYTEPTR(mc_buf_high) + border_offset;
} else {
build_mc_border(buf_ptr1, pre_buf_stride, (uint8_t *)mc_buf_high, b_w,
x0, y0, b_w, b_h, frame_width, frame_height);
buf_ptr = ((uint8_t *)mc_buf_high) + border_offset;
}
#if CONFIG_EXT_INTER
if (ref && is_interinter_wedge_used(xd->mi[0]->mbmi.sb_type) &&
xd->mi[0]->mbmi.use_wedge_interinter)
vp10_make_masked_inter_predictor(
buf_ptr, b_w, dst, dst_buf_stride,
subpel_x, subpel_y, sf, w, h,
interp_filter, xs, ys,
wedge_offset_x, wedge_offset_y,
xd);
else
#endif // CONFIG_EXT_INTER
vp10_make_inter_predictor(buf_ptr, b_w, dst, dst_buf_stride,
subpel_x, subpel_y, sf, w, h, ref,
interp_filter, xs, ys, xd);
}
#else
static void extend_and_predict(const uint8_t *buf_ptr1, int pre_buf_stride,
int x0, int y0, int b_w, int b_h,
int frame_width, int frame_height,
int border_offset,
uint8_t *const dst, int dst_buf_stride,
int subpel_x, int subpel_y,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter,
#endif
const struct scale_factors *sf,
#if CONFIG_EXT_INTER
int wedge_offset_x, int wedge_offset_y,
#endif // CONFIG_EXT_INTER
MACROBLOCKD *xd,
int w, int h, int ref, int xs, int ys) {
DECLARE_ALIGNED(16, uint8_t,
mc_buf[(MAX_SB_SIZE + 16) * 2 * (MAX_SB_SIZE + 16) * 2]);
const uint8_t *buf_ptr;
build_mc_border(buf_ptr1, pre_buf_stride, mc_buf, b_w,
x0, y0, b_w, b_h, frame_width, frame_height);
buf_ptr = mc_buf + border_offset;
#if CONFIG_EXT_INTER
if (ref && is_interinter_wedge_used(xd->mi[0]->mbmi.sb_type) &&
xd->mi[0]->mbmi.use_wedge_interinter)
vp10_make_masked_inter_predictor(
buf_ptr, b_w, dst, dst_buf_stride,
subpel_x, subpel_y, sf, w, h,
interp_filter, xs, ys,
wedge_offset_x, wedge_offset_y,
xd);
else
#endif // CONFIG_EXT_INTER
vp10_make_inter_predictor(buf_ptr, b_w, dst, dst_buf_stride,
subpel_x, subpel_y, sf, w, h, ref,
interp_filter, xs, ys, xd);
}
#endif // CONFIG_VP9_HIGHBITDEPTH
static void dec_build_inter_predictors(VP10Decoder *const pbi,
MACROBLOCKD *xd, int plane,
#if CONFIG_OBMC
int mi_col_offset, int mi_row_offset,
#endif // CONFIG_OBMC
int bw, int bh,
int x, int y, int w, int h,
#if CONFIG_EXT_INTER
int wedge_offset_x, int wedge_offset_y,
#endif // CONFIG_EXT_INTER
int mi_x, int mi_y,
#if CONFIG_DUAL_FILTER
const INTERP_FILTER *interp_filter,
#else
const INTERP_FILTER interp_filter,
#endif
const struct scale_factors *sf,
struct buf_2d *pre_buf,
struct buf_2d *dst_buf, const MV* mv,
RefCntBuffer *ref_frame_buf,
int is_scaled, int ref) {
VP10_COMMON *const cm = &pbi->common;
struct macroblockd_plane *const pd = &xd->plane[plane];
uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
MV32 scaled_mv;
MV mv_q4;
int xs, ys, x0, y0, x0_16, y0_16, frame_width, frame_height,
buf_stride, subpel_x, subpel_y;
uint8_t *ref_frame, *buf_ptr;
#if CONFIG_EXT_INTER
#if CONFIG_OBMC
const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset];
#else
const MODE_INFO *mi = xd->mi[0];
#endif // CONFIG_OBMC
#endif // CONFIG_EXT_INTER
#if CONFIG_EXT_INTERP
const int i_filter = IsInterpolatingFilter(interp_filter);
#endif // CONFIG_EXT_INTERP
#if CONFIG_OBMC
(void) mi_col_offset;
(void) mi_row_offset;
#endif // CONFIG_OBMC
// Get reference frame pointer, width and height.
if (plane == 0) {
frame_width = ref_frame_buf->buf.y_crop_width;
frame_height = ref_frame_buf->buf.y_crop_height;
ref_frame = ref_frame_buf->buf.y_buffer;
} else {
frame_width = ref_frame_buf->buf.uv_crop_width;
frame_height = ref_frame_buf->buf.uv_crop_height;
ref_frame = plane == 1 ? ref_frame_buf->buf.u_buffer
: ref_frame_buf->buf.v_buffer;
}
mv_q4 = clamp_mv_to_umv_border_sb(xd, mv, bw, bh,
pd->subsampling_x,
pd->subsampling_y);
if (is_scaled) {
// Co-ordinate of containing block to pixel precision.
int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x));
int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y));
// Co-ordinate of the block to 1/16th pixel precision.
x0_16 = (x_start + x) << SUBPEL_BITS;
y0_16 = (y_start + y) << SUBPEL_BITS;
// Co-ordinate of current block in reference frame
// to 1/16th pixel precision.
x0_16 = sf->scale_value_x(x0_16, sf);
y0_16 = sf->scale_value_y(y0_16, sf);
// Map the top left corner of the block into the reference frame.
x0 = sf->scale_value_x(x_start + x, sf);
y0 = sf->scale_value_y(y_start + y, sf);
// Scale the MV and incorporate the sub-pixel offset of the block
// in the reference frame.
scaled_mv = vp10_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
xs = sf->x_step_q4;
ys = sf->y_step_q4;
} else {
// Co-ordinate of containing block to pixel precision.
x0 = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x)) + x;
y0 = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y)) + y;
// Co-ordinate of the block to 1/16th pixel precision.
x0_16 = x0 << SUBPEL_BITS;
y0_16 = y0 << SUBPEL_BITS;
scaled_mv.row = mv_q4.row;
scaled_mv.col = mv_q4.col;
xs = ys = 16;
}
subpel_x = scaled_mv.col & SUBPEL_MASK;
subpel_y = scaled_mv.row & SUBPEL_MASK;
// Calculate the top left corner of the best matching block in the
// reference frame.
x0 += scaled_mv.col >> SUBPEL_BITS;
y0 += scaled_mv.row >> SUBPEL_BITS;
x0_16 += scaled_mv.col;
y0_16 += scaled_mv.row;
// Get reference block pointer.
buf_ptr = ref_frame + y0 * pre_buf->stride + x0;
buf_stride = pre_buf->stride;
// Do border extension if there is motion or the
// width/height is not a multiple of 8 pixels.
if (is_scaled || scaled_mv.col || scaled_mv.row ||
#if CONFIG_EXT_INTERP
!i_filter ||
#endif
(frame_width & 0x7) || (frame_height & 0x7)) {
int y1 = ((y0_16 + (h - 1) * ys) >> SUBPEL_BITS) + 1;
// Get reference block bottom right horizontal coordinate.
int x1 = ((x0_16 + (w - 1) * xs) >> SUBPEL_BITS) + 1;
int x_pad = 0, y_pad = 0;
#if CONFIG_DUAL_FILTER
InterpFilterParams filter_params_y =
vp10_get_interp_filter_params(interp_filter[0]);
InterpFilterParams filter_params_x =
vp10_get_interp_filter_params(interp_filter[1]);
int filter_size = VPXMAX(filter_params_y.taps, filter_params_x.taps);
#else
InterpFilterParams filter_params =
vp10_get_interp_filter_params(interp_filter);
int filter_size = filter_params.taps;
#endif
if (subpel_x ||
#if CONFIG_EXT_INTERP
!i_filter ||
#endif
(sf->x_step_q4 != SUBPEL_SHIFTS)) {
x0 -= filter_size / 2 - 1;
x1 += filter_size / 2;
x_pad = 1;
}
if (subpel_y ||
#if CONFIG_EXT_INTERP
!i_filter ||
#endif
(sf->y_step_q4 != SUBPEL_SHIFTS)) {
y0 -= filter_size / 2 - 1;
y1 += filter_size / 2;
y_pad = 1;
}
// Wait until reference block is ready. Pad 7 more pixels as last 7
// pixels of each superblock row can be changed by next superblock row.
if (cm->frame_parallel_decode)
vp10_frameworker_wait(pbi->frame_worker_owner, ref_frame_buf,
VPXMAX(0, (y1 + 7)) << (plane == 0 ? 0 : 1));
// Skip border extension if block is inside the frame.
if (x0 < 0 || x0 > frame_width - 1 || x1 < 0 || x1 > frame_width - 1 ||
y0 < 0 || y0 > frame_height - 1 || y1 < 0 || y1 > frame_height - 1) {
// Extend the border.
const uint8_t *const buf_ptr1 = ref_frame + y0 * buf_stride + x0;
const int b_w = x1 - x0 + 1;
const int b_h = y1 - y0 + 1;
const int border_offset = y_pad * (filter_size / 2 - 1) * b_w +
x_pad * (filter_size / 2 - 1);
#if CONFIG_VP9_HIGHBITDEPTH
extend_and_predict_highbd(buf_ptr1, buf_stride, x0, y0, b_w, b_h,
frame_width, frame_height, border_offset,
dst, dst_buf->stride,
subpel_x, subpel_y,
interp_filter, sf,
#if CONFIG_EXT_INTER
wedge_offset_x, wedge_offset_y,
#endif // CONFIG_EXT_INTER
xd, w, h, ref, xs, ys);
#else
extend_and_predict(buf_ptr1, buf_stride, x0, y0, b_w, b_h,
frame_width, frame_height, border_offset,
dst, dst_buf->stride,
subpel_x, subpel_y,
interp_filter, sf,
#if CONFIG_EXT_INTER
wedge_offset_x, wedge_offset_y,
#endif // CONFIG_EXT_INTER
xd, w, h, ref, xs, ys);
#endif // CONFIG_VP9_HIGHBITDEPTH
return;
}
} else {
// Wait until reference block is ready. Pad 7 more pixels as last 7
// pixels of each superblock row can be changed by next superblock row.
if (cm->frame_parallel_decode) {
const int y1 = (y0_16 + (h - 1) * ys) >> SUBPEL_BITS;
vp10_frameworker_wait(pbi->frame_worker_owner, ref_frame_buf,
VPXMAX(0, (y1 + 7)) << (plane == 0 ? 0 : 1));
}
}
#if CONFIG_EXT_INTER
if (ref && is_interinter_wedge_used(mi->mbmi.sb_type) &&
mi->mbmi.use_wedge_interinter)
vp10_make_masked_inter_predictor(
buf_ptr, buf_stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h,
interp_filter, xs, ys,
wedge_offset_x, wedge_offset_y,
xd);
else
#endif // CONFIG_EXT_INTER
vp10_make_inter_predictor(buf_ptr, buf_stride, dst, dst_buf->stride,
subpel_x, subpel_y, sf, w, h, ref,
interp_filter, xs, ys, xd);
}
static void dec_build_inter_predictors_sb_sub8x8_extend(
VP10Decoder *const pbi,
MACROBLOCKD *xd,
#if CONFIG_EXT_INTER
int mi_row_ori, int mi_col_ori,
#endif // CONFIG_EXT_INTER
int mi_row, int mi_col,
int block) {
// Prediction function used in supertx:
// Use the mv at current block (which is less than 8x8)
int plane;
const int mi_x = mi_col * MI_SIZE;
const int mi_y = mi_row * MI_SIZE;
#if CONFIG_EXT_INTER
const int wedge_offset_x = (mi_col_ori - mi_col) * MI_SIZE;
const int wedge_offset_y = (mi_row_ori - mi_row) * MI_SIZE;
#endif // CONFIG_EXT_INTER
const MODE_INFO *mi = xd->mi[0];
const int is_compound = has_second_ref(&mi->mbmi);
// For sub8x8 uv:
// Skip uv prediction in supertx except the first block (block = 0)
int max_plane = block ? 1 : MAX_MB_PLANE;
for (plane = 0; plane < max_plane; ++plane) {
struct macroblockd_plane *const pd = &xd->plane[plane];
struct buf_2d *const dst_buf = &pd->dst;
const int num_4x4_w = pd->n4_w;
const int num_4x4_h = pd->n4_h;
const int n4w_x4 = 4 * num_4x4_w;
const int n4h_x4 = 4 * num_4x4_h;
int ref;
for (ref = 0; ref < 1 + is_compound; ++ref) {
const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
struct buf_2d *const pre_buf = &pd->pre[ref];
const int idx = xd->block_refs[ref]->idx;
BufferPool *const pool = pbi->common.buffer_pool;
RefCntBuffer *const ref_frame_buf = &pool->frame_bufs[idx];
const int is_scaled = vp10_is_scaled(sf);
const MV mv = average_split_mvs(pd, mi, ref, block);
dec_build_inter_predictors(pbi, xd, plane,
#if CONFIG_OBMC
0, 0,
#endif // CONFIG_OBMC
n4w_x4, n4h_x4,
0, 0, n4w_x4, n4h_x4,
#if CONFIG_EXT_INTER
wedge_offset_x,
wedge_offset_y,
#endif // CONFIG_EXT_INTER
mi_x, mi_y,
mi->mbmi.interp_filter, sf, pre_buf, dst_buf,
&mv, ref_frame_buf, is_scaled, ref);
}
}
#if CONFIG_EXT_INTER
if (is_interintra_pred(&mi->mbmi))
vp10_build_interintra_predictors(xd,
xd->plane[0].dst.buf,
xd->plane[1].dst.buf,
xd->plane[2].dst.buf,
xd->plane[0].dst.stride,
xd->plane[1].dst.stride,
xd->plane[2].dst.stride,
mi->mbmi.sb_type);
#endif // CONFIG_EXT_INTER
}
#endif // CONFIG_SUPERTX
static INLINE TX_SIZE dec_get_uv_tx_size(const MB_MODE_INFO *mbmi,
int n4_wl, int n4_hl) {
// get minimum log2 num4x4s dimension
......@@ -1081,12 +612,12 @@ static void dec_predict_b_extend(
#endif // CONFIG_EXT_INTER
mi_row_pred, mi_col_pred, bsize_pred);
else
dec_build_inter_predictors_sb_sub8x8_extend(
pbi, xd,
vp10_build_inter_predictors_sb_sub8x8_extend(
xd,
#if CONFIG_EXT_INTER
mi_row_ori, mi_col_ori,
#endif // CONFIG_EXT_INTER
mi_row_pred, mi_col_pred, block);
mi_row_pred, mi_col_pred, bsize_pred, block);
}
static void dec_extend_dir(VP10Decoder *const pbi, MACROBLOCKD *const xd,
......
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