Improve rdopt decisions for ext-inter
Relative to previous ext-inter:
lowres: -0.177%
or -0.029% (with USE_RECT_INTERINTRA = 0)
* When predicting interintra modes, the previous code did not provide
the intra predictor with the correct context during rdopt. Add an
explicit 'ctx' parameter to the relevant functions, to provide this
context.
This fixes a nondeterminism bug, which was causing test failures in
*EncoderThreadTest*
* For rectangular blocks, build_intra_predictors_for_interintra needs
to overwrite part of the context buffer in order to set up the
correct context for intra prediction. We now restore the original
contents afterwards.
* Add a flag to enable/disable rectangular interintra prediction;
disabling improves encoding speed but reduces BDRATE improvement.
Change-Id: I7458c036c7f94df9ab1ba0c7efa79aeaa7e17118
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index c43f4c5..fcc924f 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -38,6 +38,11 @@
#define MAX_MB_PLANE 3
+#if CONFIG_EXT_INTER
+// Should we try rectangular interintra predictions?
+#define USE_RECT_INTERINTRA 1
+#endif
+
typedef enum {
KEY_FRAME = 0,
INTER_FRAME = 1,
@@ -85,6 +90,11 @@
} PVQ_QUEUE;
#endif
+typedef struct {
+ uint8_t *plane[MAX_MB_PLANE];
+ int stride[MAX_MB_PLANE];
+} BUFFER_SET;
+
#if CONFIG_EXT_INTER
static INLINE int is_inter_singleref_mode(PREDICTION_MODE mode) {
return mode >= NEARESTMV && mode <= NEWFROMNEARMV;
@@ -884,6 +894,9 @@
#if CONFIG_EXT_INTER
static INLINE int is_interintra_allowed_bsize(const BLOCK_SIZE bsize) {
+#if !USE_RECT_INTERINTRA
+ if (block_size_wide[bsize] != block_size_high[bsize]) return 0;
+#endif
// TODO(debargha): Should this be bsize < BLOCK_LARGEST?
return (bsize >= BLOCK_8X8) && (bsize < BLOCK_64X64);
}
diff --git a/av1/common/reconinter.c b/av1/common/reconinter.c
index 0b1a65a..f40cfc2 100644
--- a/av1/common/reconinter.c
+++ b/av1/common/reconinter.c
@@ -827,54 +827,86 @@
}
void av1_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize) {
+ BUFFER_SET *ctx, BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
#if CONFIG_EXT_INTER
- if (is_interintra_pred(&xd->mi[0]->mbmi))
+ if (is_interintra_pred(&xd->mi[0]->mbmi)) {
+ BUFFER_SET default_ctx = { { xd->plane[0].dst.buf, NULL, NULL },
+ { xd->plane[0].dst.stride, 0, 0 } };
+ if (!ctx) ctx = &default_ctx;
av1_build_interintra_predictors_sby(xd, xd->plane[0].dst.buf,
- xd->plane[0].dst.stride, bsize);
+ xd->plane[0].dst.stride, ctx, bsize);
+ }
+#else
+ (void)ctx;
#endif // CONFIG_EXT_INTER
}
void av1_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize, int plane) {
+ BUFFER_SET *ctx, BLOCK_SIZE bsize,
+ int plane) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane);
#if CONFIG_EXT_INTER
if (is_interintra_pred(&xd->mi[0]->mbmi)) {
+ BUFFER_SET default_ctx = {
+ { 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 }
+ };
+ if (!ctx) ctx = &default_ctx;
if (plane == 0) {
av1_build_interintra_predictors_sby(xd, xd->plane[0].dst.buf,
- xd->plane[0].dst.stride, bsize);
+ xd->plane[0].dst.stride, ctx, bsize);
} else {
av1_build_interintra_predictors_sbc(xd, xd->plane[plane].dst.buf,
- xd->plane[plane].dst.stride, plane,
- bsize);
+ xd->plane[plane].dst.stride, ctx,
+ plane, bsize);
}
}
+#else
+ (void)ctx;
#endif // CONFIG_EXT_INTER
}
void av1_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize) {
+ BUFFER_SET *ctx, BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
MAX_MB_PLANE - 1);
#if CONFIG_EXT_INTER
- if (is_interintra_pred(&xd->mi[0]->mbmi))
+ if (is_interintra_pred(&xd->mi[0]->mbmi)) {
+ BUFFER_SET default_ctx = {
+ { NULL, xd->plane[1].dst.buf, xd->plane[2].dst.buf },
+ { 0, xd->plane[1].dst.stride, xd->plane[2].dst.stride }
+ };
+ if (!ctx) ctx = &default_ctx;
av1_build_interintra_predictors_sbuv(
xd, xd->plane[1].dst.buf, xd->plane[2].dst.buf, xd->plane[1].dst.stride,
- xd->plane[2].dst.stride, bsize);
+ xd->plane[2].dst.stride, ctx, bsize);
+ }
+#else
+ (void)ctx;
#endif // CONFIG_EXT_INTER
}
void av1_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize) {
+ BUFFER_SET *ctx, BLOCK_SIZE bsize) {
build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
MAX_MB_PLANE - 1);
#if CONFIG_EXT_INTER
- if (is_interintra_pred(&xd->mi[0]->mbmi))
+ if (is_interintra_pred(&xd->mi[0]->mbmi)) {
+ BUFFER_SET default_ctx = {
+ { 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 }
+ };
+ if (!ctx) ctx = &default_ctx;
av1_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, bsize);
+ xd->plane[2].dst.stride, ctx, bsize);
+ }
+#else
+ (void)ctx;
#endif // CONFIG_EXT_INTER
}
@@ -1088,11 +1120,15 @@
mi_x, mi_y);
}
#if CONFIG_EXT_INTER
+ BUFFER_SET ctx = { { 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 } };
if (is_interintra_pred(&xd->mi[0]->mbmi))
av1_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, bsize);
+ xd->plane[2].dst.stride, &ctx, bsize);
#endif // CONFIG_EXT_INTER
}
@@ -1845,8 +1881,6 @@
}
#endif // CONFIG_AOM_HIGHBITDEPTH
-// Break down rectangular intra prediction for joint spatio-temporal prediction
-// into two square intra predictions.
static void build_intra_predictors_for_interintra(MACROBLOCKD *xd, uint8_t *ref,
int ref_stride, uint8_t *dst,
int dst_stride,
@@ -1856,14 +1890,24 @@
BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, &xd->plane[plane]);
const int bwl = b_width_log2_lookup[plane_bsize];
const int bhl = b_height_log2_lookup[plane_bsize];
+ TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize];
+#if USE_RECT_INTERINTRA
const int pxbw = 4 << bwl;
const int pxbh = 4 << bhl;
- TX_SIZE max_tx_size = max_txsize_lookup[plane_bsize];
+#if CONFIG_AOM_HIGHBITDEPTH
+ uint16_t tmp16[MAX_SB_SIZE];
+#endif
+ uint8_t tmp[MAX_SB_SIZE];
+#endif
if (bwl == bhl) {
av1_predict_intra_block(xd, pd->width, pd->height, max_tx_size, mode, ref,
ref_stride, dst, dst_stride, 0, 0, plane);
-
+#if !USE_RECT_INTERINTRA
+ } else {
+ assert(0);
+ }
+#else
} else if (bwl < bhl) {
uint8_t *src_2 = ref + pxbw * ref_stride;
uint8_t *dst_2 = dst + pxbw * dst_stride;
@@ -1873,15 +1917,28 @@
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
uint16_t *src_216 = CONVERT_TO_SHORTPTR(src_2);
uint16_t *dst_216 = CONVERT_TO_SHORTPTR(dst_2);
+ memcpy(tmp16, src_216 - ref_stride, sizeof(*src_216) * pxbw);
memcpy(src_216 - ref_stride, dst_216 - dst_stride,
sizeof(*src_216) * pxbw);
- } else
+ } else {
#endif // CONFIG_AOM_HIGHBITDEPTH
- {
+ memcpy(tmp, src_2 - ref_stride, sizeof(*src_2) * pxbw);
memcpy(src_2 - ref_stride, dst_2 - dst_stride, sizeof(*src_2) * pxbw);
+#if CONFIG_AOM_HIGHBITDEPTH
}
+#endif
av1_predict_intra_block(xd, pd->width, pd->height, max_tx_size, mode, src_2,
ref_stride, dst_2, dst_stride, 0, 1 << bwl, plane);
+#if CONFIG_AOM_HIGHBITDEPTH
+ if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+ uint16_t *src_216 = CONVERT_TO_SHORTPTR(src_2);
+ memcpy(src_216 - ref_stride, tmp16, sizeof(*src_216) * pxbw);
+ } else {
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ memcpy(src_2 - ref_stride, tmp, sizeof(*src_2) * pxbw);
+#if CONFIG_AOM_HIGHBITDEPTH
+ }
+#endif
} else { // bwl > bhl
int i;
uint8_t *src_2 = ref + pxbh;
@@ -1892,26 +1949,42 @@
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
uint16_t *src_216 = CONVERT_TO_SHORTPTR(src_2);
uint16_t *dst_216 = CONVERT_TO_SHORTPTR(dst_2);
- for (i = 0; i < pxbh; ++i)
+ for (i = 0; i < pxbh; ++i) {
+ tmp16[i] = src_216[i * ref_stride - 1];
src_216[i * ref_stride - 1] = dst_216[i * dst_stride - 1];
- } else
+ }
+ } else {
#endif // CONFIG_AOM_HIGHBITDEPTH
- {
- for (i = 0; i < pxbh; ++i)
+ for (i = 0; i < pxbh; ++i) {
+ tmp[i] = src_2[i * ref_stride - 1];
src_2[i * ref_stride - 1] = dst_2[i * dst_stride - 1];
+ }
+#if CONFIG_AOM_HIGHBITDEPTH
}
+#endif
av1_predict_intra_block(xd, pd->width, pd->height, max_tx_size, mode, src_2,
ref_stride, dst_2, dst_stride, 1 << bhl, 0, plane);
+#if CONFIG_AOM_HIGHBITDEPTH
+ if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
+ uint16_t *src_216 = CONVERT_TO_SHORTPTR(src_2);
+ for (i = 0; i < pxbh; ++i) src_216[i * ref_stride - 1] = tmp16[i];
+ } else {
+#endif // CONFIG_AOM_HIGHBITDEPTH
+ for (i = 0; i < pxbh; ++i) src_2[i * ref_stride - 1] = tmp[i];
+#if CONFIG_AOM_HIGHBITDEPTH
+ }
+#endif
}
+#endif
}
void av1_build_intra_predictors_for_interintra(MACROBLOCKD *xd,
BLOCK_SIZE bsize, int plane,
- uint8_t *dst, int dst_stride) {
+ BUFFER_SET *ctx, uint8_t *dst,
+ int dst_stride) {
build_intra_predictors_for_interintra(
- xd, xd->plane[plane].dst.buf, xd->plane[plane].dst.stride, dst,
- dst_stride, interintra_to_intra_mode[xd->mi[0]->mbmi.interintra_mode],
- bsize, plane);
+ xd, ctx->plane[plane], ctx->stride[plane], dst, dst_stride,
+ interintra_to_intra_mode[xd->mi[0]->mbmi.interintra_mode], bsize, plane);
}
void av1_combine_interintra(MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
@@ -1938,12 +2011,13 @@
}
void av1_build_interintra_predictors_sby(MACROBLOCKD *xd, uint8_t *ypred,
- int ystride, BLOCK_SIZE bsize) {
+ int ystride, BUFFER_SET *ctx,
+ BLOCK_SIZE bsize) {
#if CONFIG_AOM_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
DECLARE_ALIGNED(16, uint16_t, intrapredictor[MAX_SB_SQUARE]);
av1_build_intra_predictors_for_interintra(
- xd, bsize, 0, CONVERT_TO_BYTEPTR(intrapredictor), MAX_SB_SIZE);
+ xd, bsize, 0, ctx, CONVERT_TO_BYTEPTR(intrapredictor), MAX_SB_SIZE);
av1_combine_interintra(xd, bsize, 0, ypred, ystride,
CONVERT_TO_BYTEPTR(intrapredictor), MAX_SB_SIZE);
return;
@@ -1951,7 +2025,7 @@
#endif // CONFIG_AOM_HIGHBITDEPTH
{
DECLARE_ALIGNED(16, uint8_t, intrapredictor[MAX_SB_SQUARE]);
- av1_build_intra_predictors_for_interintra(xd, bsize, 0, intrapredictor,
+ av1_build_intra_predictors_for_interintra(xd, bsize, 0, ctx, intrapredictor,
MAX_SB_SIZE);
av1_combine_interintra(xd, bsize, 0, ypred, ystride, intrapredictor,
MAX_SB_SIZE);
@@ -1959,13 +2033,14 @@
}
void av1_build_interintra_predictors_sbc(MACROBLOCKD *xd, uint8_t *upred,
- int ustride, int plane,
- BLOCK_SIZE bsize) {
+ int ustride, BUFFER_SET *ctx,
+ int plane, BLOCK_SIZE bsize) {
#if CONFIG_AOM_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
DECLARE_ALIGNED(16, uint16_t, uintrapredictor[MAX_SB_SQUARE]);
av1_build_intra_predictors_for_interintra(
- xd, bsize, plane, CONVERT_TO_BYTEPTR(uintrapredictor), MAX_SB_SIZE);
+ xd, bsize, plane, ctx, CONVERT_TO_BYTEPTR(uintrapredictor),
+ MAX_SB_SIZE);
av1_combine_interintra(xd, bsize, plane, upred, ustride,
CONVERT_TO_BYTEPTR(uintrapredictor), MAX_SB_SIZE);
return;
@@ -1973,8 +2048,8 @@
#endif // CONFIG_AOM_HIGHBITDEPTH
{
DECLARE_ALIGNED(16, uint8_t, uintrapredictor[MAX_SB_SQUARE]);
- av1_build_intra_predictors_for_interintra(xd, bsize, plane, uintrapredictor,
- MAX_SB_SIZE);
+ av1_build_intra_predictors_for_interintra(xd, bsize, plane, ctx,
+ uintrapredictor, MAX_SB_SIZE);
av1_combine_interintra(xd, bsize, plane, upred, ustride, uintrapredictor,
MAX_SB_SIZE);
}
@@ -1982,17 +2057,18 @@
void av1_build_interintra_predictors_sbuv(MACROBLOCKD *xd, uint8_t *upred,
uint8_t *vpred, int ustride,
- int vstride, BLOCK_SIZE bsize) {
- av1_build_interintra_predictors_sbc(xd, upred, ustride, 1, bsize);
- av1_build_interintra_predictors_sbc(xd, vpred, vstride, 2, bsize);
+ int vstride, BUFFER_SET *ctx,
+ BLOCK_SIZE bsize) {
+ av1_build_interintra_predictors_sbc(xd, upred, ustride, ctx, 1, bsize);
+ av1_build_interintra_predictors_sbc(xd, vpred, vstride, ctx, 2, bsize);
}
void av1_build_interintra_predictors(MACROBLOCKD *xd, uint8_t *ypred,
uint8_t *upred, uint8_t *vpred,
int ystride, int ustride, int vstride,
- BLOCK_SIZE bsize) {
- av1_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
- av1_build_interintra_predictors_sbuv(xd, upred, vpred, ustride, vstride,
+ BUFFER_SET *ctx, BLOCK_SIZE bsize) {
+ av1_build_interintra_predictors_sby(xd, ypred, ystride, ctx, bsize);
+ av1_build_interintra_predictors_sbuv(xd, upred, vpred, ustride, vstride, ctx,
bsize);
}
diff --git a/av1/common/reconinter.h b/av1/common/reconinter.h
index 62a196f..db0b697 100644
--- a/av1/common/reconinter.h
+++ b/av1/common/reconinter.h
@@ -333,16 +333,17 @@
int ic, int mi_row, int mi_col);
void av1_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize);
+ BUFFER_SET *ctx, BLOCK_SIZE bsize);
void av1_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize, int plane);
+ BUFFER_SET *ctx, BLOCK_SIZE bsize,
+ int plane);
void av1_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize);
+ BUFFER_SET *ctx, BLOCK_SIZE bsize);
void av1_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
- BLOCK_SIZE bsize);
+ BUFFER_SET *ctx, BLOCK_SIZE bsize);
#if CONFIG_SUPERTX
void av1_build_inter_predictors_sb_sub8x8_extend(MACROBLOCKD *xd,
@@ -529,28 +530,26 @@
void av1_build_interintra_predictors(MACROBLOCKD *xd, uint8_t *ypred,
uint8_t *upred, uint8_t *vpred,
int ystride, int ustride, int vstride,
- BLOCK_SIZE bsize);
+ BUFFER_SET *ctx, BLOCK_SIZE bsize);
void av1_build_interintra_predictors_sby(MACROBLOCKD *xd, uint8_t *ypred,
- int ystride, BLOCK_SIZE bsize);
-void av1_build_interintra_predictors_sbc(MACROBLOCKD *xd, uint8_t *upred,
- int ustride, int plane,
+ int ystride, BUFFER_SET *ctx,
BLOCK_SIZE bsize);
+void av1_build_interintra_predictors_sbc(MACROBLOCKD *xd, uint8_t *upred,
+ int ustride, BUFFER_SET *ctx,
+ int plane, BLOCK_SIZE bsize);
void av1_build_interintra_predictors_sbuv(MACROBLOCKD *xd, uint8_t *upred,
uint8_t *vpred, int ustride,
- int vstride, BLOCK_SIZE bsize);
+ int vstride, BUFFER_SET *ctx,
+ BLOCK_SIZE bsize);
void av1_build_intra_predictors_for_interintra(MACROBLOCKD *xd,
BLOCK_SIZE bsize, int plane,
+ BUFFER_SET *ctx,
uint8_t *intra_pred,
int intra_stride);
void av1_combine_interintra(MACROBLOCKD *xd, BLOCK_SIZE bsize, int plane,
const uint8_t *inter_pred, int inter_stride,
const uint8_t *intra_pred, int intra_stride);
-void av1_build_interintra_predictors_sbuv(MACROBLOCKD *xd, uint8_t *upred,
- uint8_t *vpred, int ustride,
- int vstride, BLOCK_SIZE bsize);
-void av1_build_interintra_predictors_sby(MACROBLOCKD *xd, uint8_t *ypred,
- int ystride, BLOCK_SIZE bsize);
// Encoder only
void av1_build_inter_predictors_for_planes_single_buf(
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index b44d5be..89ec602 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1502,7 +1502,7 @@
}
} else {
// Prediction
- av1_build_inter_predictors_sb(xd, mi_row, mi_col,
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, NULL,
AOMMAX(bsize, BLOCK_8X8));
// Reconstruction
@@ -1601,7 +1601,7 @@
}
} else {
#endif // CONFIG_WARPED_MOTION
- av1_build_inter_predictors_sb(xd, mi_row, mi_col,
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, NULL,
AOMMAX(bsize, BLOCK_8X8));
#if CONFIG_WARPED_MOTION
}
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index d26f65f..7e39cc5 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -919,7 +919,7 @@
x->pred_mv[LAST_FRAME] = mbmi->mv[0].as_mv;
}
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, cm->sb_size);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, NULL, cm->sb_size);
ref = xd->plane[0].dst.buf;
ref_stride = xd->plane[0].dst.stride;
@@ -5550,10 +5550,10 @@
} else {
#endif // CONFIG_WARPED_MOTION
if (!(cpi->sf.reuse_inter_pred_sby && ctx->pred_pixel_ready) || seg_skip)
- av1_build_inter_predictors_sby(xd, mi_row, mi_col,
+ av1_build_inter_predictors_sby(xd, mi_row, mi_col, NULL,
AOMMAX(bsize, BLOCK_8X8));
- av1_build_inter_predictors_sbuv(xd, mi_row, mi_col,
+ av1_build_inter_predictors_sbuv(xd, mi_row, mi_col, NULL,
AOMMAX(bsize, BLOCK_8X8));
#if CONFIG_WARPED_MOTION
}
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index cb577c5..f066b46 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -853,7 +853,8 @@
xd->mi[0]->mbmi.tx_size = TX_4X4;
xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME;
xd->mi[0]->mbmi.ref_frame[1] = NONE;
- av1_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
+ av1_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, NULL,
+ bsize);
av1_encode_sby_pass1(cm, x, bsize);
sum_mvr += mv.row;
sum_mvr_abs += abs(mv.row);
diff --git a/av1/encoder/mbgraph.c b/av1/encoder/mbgraph.c
index 1fd1682..1f63222 100644
--- a/av1/encoder/mbgraph.c
+++ b/av1/encoder/mbgraph.c
@@ -74,7 +74,7 @@
xd->mi[0]->mbmi.ref_frame[1] = NONE;
#endif // CONFIG_EXT_INTER
- av1_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_16X16);
+ av1_build_inter_predictors_sby(xd, mb_row, mb_col, NULL, BLOCK_16X16);
/* restore UMV window */
x->mv_col_min = tmp_col_min;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 941f465..ecdd04d 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -6371,13 +6371,11 @@
}
}
-static INLINE void restore_dst_buf(MACROBLOCKD *xd,
- uint8_t *orig_dst[MAX_MB_PLANE],
- int orig_dst_stride[MAX_MB_PLANE]) {
+static INLINE void restore_dst_buf(MACROBLOCKD *xd, BUFFER_SET dst) {
int i;
for (i = 0; i < MAX_MB_PLANE; i++) {
- xd->plane[i].dst.buf = orig_dst[i];
- xd->plane[i].dst.stride = orig_dst_stride[i];
+ xd->plane[i].dst.buf = dst.plane[i];
+ xd->plane[i].dst.stride = dst.stride[i];
}
}
@@ -6934,8 +6932,8 @@
static int64_t build_and_cost_compound_wedge(
const AV1_COMP *const cpi, MACROBLOCK *x, const int_mv *const cur_mv,
const BLOCK_SIZE bsize, const int this_mode, int rs2, int rate_mv,
- int *out_rate_mv, uint8_t **preds0, uint8_t **preds1, int *strides,
- int mi_row, int mi_col) {
+ BUFFER_SET *ctx, int *out_rate_mv, uint8_t **preds0, uint8_t **preds1,
+ int *strides, int mi_row, int mi_col) {
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi[0]->mbmi;
int rate_sum;
@@ -6951,7 +6949,7 @@
if (have_newmv_in_inter_mode(this_mode)) {
*out_rate_mv = interinter_compound_motion_search(cpi, x, bsize, this_mode,
mi_row, mi_col);
- av1_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sby(xd, mi_row, mi_col, ctx, bsize);
model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
&tmp_skip_txfm_sb, &tmp_skip_sse_sb);
rd = RDCOST(x->rdmult, x->rddiv, rs2 + *out_rate_mv + rate_sum, dist_sum);
@@ -7056,10 +7054,7 @@
double pts[144], pts_inref[144];
#endif // CONFIG_WARPED_MOTION
int64_t rd = INT64_MAX;
- uint8_t *orig_dst[MAX_MB_PLANE];
- int orig_dst_stride[MAX_MB_PLANE];
- uint8_t *tmp_dst[MAX_MB_PLANE];
- int tmp_dst_stride[MAX_MB_PLANE];
+ BUFFER_SET orig_dst, tmp_dst;
int rs = 0;
InterpFilter assign_filter = SWITCHABLE;
@@ -7312,12 +7307,12 @@
// one for future predictions. In the end, copy from tmp_buf to
// dst if necessary.
for (i = 0; i < MAX_MB_PLANE; i++) {
- tmp_dst[i] = tmp_buf + i * MAX_SB_SQUARE;
- tmp_dst_stride[i] = MAX_SB_SIZE;
+ tmp_dst.plane[i] = tmp_buf + i * MAX_SB_SQUARE;
+ tmp_dst.stride[i] = MAX_SB_SIZE;
}
for (i = 0; i < MAX_MB_PLANE; i++) {
- orig_dst[i] = xd->plane[i].dst.buf;
- orig_dst_stride[i] = xd->plane[i].dst.stride;
+ orig_dst.plane[i] = xd->plane[i].dst.buf;
+ orig_dst.stride[i] = xd->plane[i].dst.stride;
}
// We don't include the cost of the second reference here, because there
@@ -7383,7 +7378,7 @@
assign_filter == SWITCHABLE ? EIGHTTAP_REGULAR : assign_filter;
#endif
rs = av1_get_switchable_rate(cpi, xd);
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, &orig_dst, bsize);
model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
&tmp_dist, &skip_txfm_sb, &skip_sse_sb);
rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate, tmp_dist);
@@ -7403,7 +7398,7 @@
#else
InterpFilter best_filter = mbmi->interp_filter;
#endif
- restore_dst_buf(xd, tmp_dst, tmp_dst_stride);
+ restore_dst_buf(xd, tmp_dst);
// EIGHTTAP_REGULAR mode is calculated beforehand
for (i = 1; i < filter_set_size; ++i) {
int tmp_skip_sb = 0;
@@ -7419,7 +7414,7 @@
mbmi->interp_filter = i;
#endif
tmp_rs = av1_get_switchable_rate(cpi, xd);
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, &orig_dst, bsize);
model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
&tmp_dist, &tmp_skip_sb, &tmp_skip_sse);
tmp_rd = RDCOST(x->rdmult, x->rddiv, tmp_rs + tmp_rate, tmp_dist);
@@ -7436,16 +7431,16 @@
skip_sse_sb = tmp_skip_sse;
best_in_temp = !best_in_temp;
if (best_in_temp) {
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
} else {
- restore_dst_buf(xd, tmp_dst, tmp_dst_stride);
+ restore_dst_buf(xd, tmp_dst);
}
}
}
if (best_in_temp) {
- restore_dst_buf(xd, tmp_dst, tmp_dst_stride);
+ restore_dst_buf(xd, tmp_dst);
} else {
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
}
#if CONFIG_DUAL_FILTER
av1_copy(mbmi->interp_filter, best_filter);
@@ -7523,7 +7518,7 @@
switch (cur_type) {
case COMPOUND_AVERAGE:
- av1_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sby(xd, mi_row, mi_col, &orig_dst, bsize);
av1_subtract_plane(x, bsize, 0);
rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
&tmp_skip_txfm_sb, &tmp_skip_sse_sb,
@@ -7539,8 +7534,8 @@
best_rd_compound / 3 < ref_best_rd) {
int tmp_rate_mv = 0;
best_rd_cur = build_and_cost_compound_wedge(
- cpi, x, cur_mv, bsize, this_mode, rs2, rate_mv, &tmp_rate_mv,
- preds0, preds1, strides, mi_row, mi_col);
+ cpi, x, cur_mv, bsize, this_mode, rs2, rate_mv, &orig_dst,
+ &tmp_rate_mv, preds0, preds1, strides, mi_row, mi_col);
if (best_rd_cur < best_rd_compound) {
best_rd_compound = best_rd_cur;
@@ -7574,7 +7569,7 @@
}
if (ref_best_rd < INT64_MAX && best_rd_compound / 3 > ref_best_rd) {
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return INT64_MAX;
}
@@ -7614,15 +7609,16 @@
xd->plane[j].dst.buf = tmp_buf + j * MAX_SB_SQUARE;
xd->plane[j].dst.stride = bw;
}
- av1_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ av1_build_inter_predictors_sby(xd, mi_row, mi_col, &orig_dst, bsize);
+ restore_dst_buf(xd, orig_dst);
mbmi->ref_frame[1] = INTRA_FRAME;
mbmi->use_wedge_interintra = 0;
for (j = 0; j < INTERINTRA_MODES; ++j) {
mbmi->interintra_mode = (INTERINTRA_MODE)j;
rmode = interintra_mode_cost[mbmi->interintra_mode];
- av1_build_intra_predictors_for_interintra(xd, bsize, 0, intrapred, bw);
+ av1_build_intra_predictors_for_interintra(xd, bsize, 0, &orig_dst,
+ intrapred, bw);
av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
&tmp_skip_txfm_sb, &tmp_skip_sse_sb);
@@ -7634,7 +7630,8 @@
}
mbmi->interintra_mode = best_interintra_mode;
rmode = interintra_mode_cost[mbmi->interintra_mode];
- av1_build_intra_predictors_for_interintra(xd, bsize, 0, intrapred, bw);
+ av1_build_intra_predictors_for_interintra(xd, bsize, 0, &orig_dst,
+ intrapred, bw);
av1_combine_interintra(xd, bsize, 0, tmp_buf, bw, intrapred, bw);
av1_subtract_plane(x, bsize, 0);
rd = estimate_yrd_for_sb(cpi, bsize, x, &rate_sum, &dist_sum,
@@ -7674,7 +7671,7 @@
do_masked_motion_search(cpi, x, mask, bw, bsize, mi_row, mi_col,
&tmp_mv, &tmp_rate_mv, 0, mv_idx);
mbmi->mv[0].as_int = tmp_mv.as_int;
- av1_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sby(xd, mi_row, mi_col, &orig_dst, bsize);
model_rd_for_sb(cpi, bsize, x, xd, 0, 0, &rate_sum, &dist_sum,
&tmp_skip_txfm_sb, &tmp_skip_sse_sb);
rd = RDCOST(x->rdmult, x->rddiv,
@@ -7746,7 +7743,7 @@
if (pred_exists == 0) {
int tmp_rate;
int64_t tmp_dist;
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, &orig_dst, bsize);
model_rd_for_sb(cpi, bsize, x, xd, 0, MAX_MB_PLANE - 1, &tmp_rate,
&tmp_dist, &skip_txfm_sb, &skip_sse_sb);
rd = RDCOST(x->rdmult, x->rddiv, rs + tmp_rate, tmp_dist);
@@ -7767,7 +7764,7 @@
int64_t mrd =
AOMMIN(modelled_rd[mode0][refs[0]], modelled_rd[mode1][refs[1]]);
if (rd / 4 * 3 > mrd && ref_best_rd < INT64_MAX) {
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return INT64_MAX;
}
} else if (!is_comp_interintra_pred) {
@@ -7780,7 +7777,7 @@
// if current pred_error modeled rd is substantially more than the best
// so far, do not bother doing full rd
if (rd / 2 > ref_best_rd) {
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return INT64_MAX;
}
}
@@ -7849,10 +7846,10 @@
// is needed in only one direction
if (!av1_is_interp_needed(xd)) tmp_rate2 -= rs;
#endif // CONFIG_EXT_INTERP
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, &orig_dst, bsize);
#if CONFIG_EXT_INTER
} else {
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, &orig_dst, bsize);
#endif // CONFIG_EXT_INTER
}
av1_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, above_pred_buf,
@@ -7965,7 +7962,7 @@
continue;
} else {
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return INT64_MAX;
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
}
@@ -7988,7 +7985,7 @@
#if CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
continue;
#else
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return INT64_MAX;
#endif // CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION
}
@@ -8091,7 +8088,7 @@
if (best_rd == INT64_MAX) {
av1_invalid_rd_stats(rd_stats);
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return INT64_MAX;
}
*mbmi = best_mbmi;
@@ -8124,7 +8121,7 @@
#endif // CONFIG_AOM_HIGHBITDEPTH
#endif // !(CONFIG_MOTION_VAR || CONFIG_WARPED_MOTION)
- restore_dst_buf(xd, orig_dst, orig_dst_stride);
+ restore_dst_buf(xd, orig_dst);
return 0; // The rate-distortion cost will be re-calculated by caller.
}
@@ -8912,6 +8909,15 @@
// Mode must by compatible
assert(is_interintra_allowed_mode(this_mode));
+#if !USE_RECT_INTERINTRA
+ // Note: If the subsampling is unequal, any block size we pick
+ // either a rectangular luma block or a rectangular chroma block.
+ // So in this case, we can't use any interintra modes
+ if (xd->plane[1].subsampling_x != xd->plane[1].subsampling_y ||
+ xd->plane[2].subsampling_x != xd->plane[2].subsampling_y)
+ continue;
+#endif
+
if (!is_interintra_allowed_bsize(bsize)) continue;
}
@@ -9715,7 +9721,7 @@
}
} else {
#endif // CONFIG_WARPED_MOTION
- av1_build_inter_predictors_sb(xd, mi_row, mi_col, bsize);
+ av1_build_inter_predictors_sb(xd, mi_row, mi_col, NULL, bsize);
#if CONFIG_WARPED_MOTION
}
#endif // CONFIG_WARPED_MOTION
@@ -10901,7 +10907,8 @@
// then dont bother looking at UV
int is_cost_valid_uv;
RD_STATS rd_stats_uv;
- av1_build_inter_predictors_sbuv(&x->e_mbd, mi_row, mi_col, BLOCK_8X8);
+ av1_build_inter_predictors_sbuv(&x->e_mbd, mi_row, mi_col, NULL,
+ BLOCK_8X8);
#if CONFIG_VAR_TX
is_cost_valid_uv =
inter_block_uvrd(cpi, x, &rd_stats_uv, BLOCK_8X8, tmp_best_rdu);