diff options
author | Janne Grunau <janne-vlc@jannau.net> | 2018-10-15 23:01:23 +0300 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2018-10-18 09:14:39 +0300 |
commit | 5c416dce1a1cdc7a4b9d7537fa47500bfeab07fa (patch) | |
tree | 8caa8de9af26c65bd1b71ab38c067e2b0971499f /src/decode.c | |
parent | c38b3923bbb14fcdf00f6fa31104bf57d27150b3 (diff) |
intrabc: clip displacement vector to current tile
Reverts commit f17c5e084f9a983c00a48b25c4f6422b6c521435 "check IntraBC
displacement vector".
Fixes #63 and an overlapping memcpy in
clusterfuzz-testcase-minimized-dav1d_fuzzer-5675967192760320. Credits to
oss-fuzz and Tyson Smith.
Diffstat (limited to 'src/decode.c')
-rw-r--r-- | src/decode.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/src/decode.c b/src/decode.c index e2990be..f1a18c0 100644 --- a/src/decode.c +++ b/src/decode.c @@ -1189,12 +1189,66 @@ static int decode_b(Dav1dTileContext *const t, const struct mv ref = b->mv[0]; read_mv_residual(t, &b->mv[0], &ts->cdf.dmv, 0); + + // clip intrabc motion vector to decoded parts of current tile + int border_left = ts->tiling.col_start * 4; + int border_top = ts->tiling.row_start * 4; + if (has_chroma) { + if (bw4 < 2 && ss_hor) + border_left += 4; + if (bh4 < 2 && ss_ver) + border_top += 4; + } + int src_left = t->bx * 4 + (b->mv[0].x >> 3); + int src_top = t->by * 4 + (b->mv[0].y >> 3); + int src_right = src_left + bw4 * 4; + int src_bottom = src_top + bh4 * 4; + + // check against left or right tile boundary and adjust if necessary + if (src_left < border_left) { + src_right += border_left - src_left; + src_left += border_left - src_left; + } else if (src_right > ts->tiling.col_end * 4) { + src_left -= src_right - ts->tiling.col_end * 4; + src_right -= src_right - ts->tiling.col_end * 4; + } + // check against top tile boundary and adjust if necessary + if (src_top < border_top) { + src_bottom += border_top - src_top; + src_top += border_top - src_top; + } + + const int sbx = (t->bx >> (4 + f->seq_hdr.sb128)) << (6 + f->seq_hdr.sb128); + const int sby = (t->by >> (4 + f->seq_hdr.sb128)) << (6 + f->seq_hdr.sb128); + const int sb_size = 1 << (6 + f->seq_hdr.sb128); + // check for overlap with current superblock + if (src_bottom > sby && src_right > sbx) { + if (src_top - border_top >= src_bottom - sby) { + // if possible move src up into the previous suberblock row + src_top -= src_bottom - sby; + src_bottom -= src_bottom - sby; + } else if (src_left - border_left >= src_right - sbx) { + // if possible move src left into the previous suberblock + src_left -= src_right - sbx; + src_right -= src_right - sbx; + } + } + // move src up if it is below current superblock row + if (src_bottom > sby + sb_size) { + src_top -= src_bottom - (sby + sb_size); + src_bottom -= src_bottom - (sby + sb_size); + } + // error out if mv still overlaps with the current superblock + if (src_bottom > sby && src_right > sbx) + return -1; + + b->mv[0].x = (src_left - t->bx * 4) * 8; + b->mv[0].y = (src_top - t->by * 4) * 8; + if (DEBUG_BLOCK_INFO) printf("Post-dmv[%d/%d,ref=%d/%d|%d/%d]: r=%d\n", b->mv[0].y, b->mv[0].x, ref.y, ref.x, mvlist[0][0].y, mvlist[0][0].x, ts->msac.rng); - if (b->mv[0].x >= 0 && b->mv[0].y >= 0) - b->mv[0] = ref; read_vartx_tree(t, b, bs, bx4, by4); // reconstruction |