vp9: clip motion vectors in the same way as libvpx does.

The practical effect of this is that the scaling will wrongly not be
applied to the interpolation edge (the 3/4 constants in this patch).
In other words, we clip to the pre-scaling interpolation, even though
these should be clipped post-scaling. The resulting out-of-frame MVs
are thus automatically clipped within the visible portion of the frame,
which is probably not the intention, but is unfortunately what libvpx
does, so we need to copy that behaviour.
This commit is contained in:
Ronald S. Bultje 2015-05-14 22:13:46 -04:00
parent 96a58a8daa
commit 29045fbfd4
1 changed files with 20 additions and 10 deletions

View File

@ -2740,18 +2740,23 @@ static av_always_inline void mc_luma_scaled(VP9Context *s, vp9_scaled_mc_func sm
uint8_t *dst, ptrdiff_t dst_stride, uint8_t *dst, ptrdiff_t dst_stride,
const uint8_t *ref, ptrdiff_t ref_stride, const uint8_t *ref, ptrdiff_t ref_stride,
ThreadFrame *ref_frame, ThreadFrame *ref_frame,
ptrdiff_t y, ptrdiff_t x, const VP56mv *mv, ptrdiff_t y, ptrdiff_t x, const VP56mv *in_mv,
int bw, int bh, int w, int h, int bytesperpixel, int bw, int bh, int w, int h, int bytesperpixel,
const uint16_t *scale, const uint8_t *step) const uint16_t *scale, const uint8_t *step)
{ {
#define scale_mv(n, dim) (((int64_t)(n) * scale[dim]) >> 14) #define scale_mv(n, dim) (((int64_t)(n) * scale[dim]) >> 14)
int mx, my;
int refbw_m1, refbh_m1;
int th;
VP56mv mv;
mv.x = av_clip(in_mv->x, -(x + bw + 4) << 3, (s->cols * 8 - x + 3) << 3);
mv.y = av_clip(in_mv->y, -(y + bh + 4) << 3, (s->rows * 8 - y + 3) << 3);
// BUG libvpx seems to scale the two components separately. This introduces // BUG libvpx seems to scale the two components separately. This introduces
// rounding errors but we have to reproduce them to be exactly compatible // rounding errors but we have to reproduce them to be exactly compatible
// with the output from libvpx... // with the output from libvpx...
int mx = scale_mv(mv->x * 2, 0) + scale_mv(x * 16, 0); mx = scale_mv(mv.x * 2, 0) + scale_mv(x * 16, 0);
int my = scale_mv(mv->y * 2, 1) + scale_mv(y * 16, 1); my = scale_mv(mv.y * 2, 1) + scale_mv(y * 16, 1);
int refbw_m1, refbh_m1;
int th;
y = my >> 4; y = my >> 4;
x = mx >> 4; x = mx >> 4;
@ -2783,25 +2788,30 @@ static av_always_inline void mc_chroma_scaled(VP9Context *s, vp9_scaled_mc_func
const uint8_t *ref_u, ptrdiff_t src_stride_u, const uint8_t *ref_u, ptrdiff_t src_stride_u,
const uint8_t *ref_v, ptrdiff_t src_stride_v, const uint8_t *ref_v, ptrdiff_t src_stride_v,
ThreadFrame *ref_frame, ThreadFrame *ref_frame,
ptrdiff_t y, ptrdiff_t x, const VP56mv *mv, ptrdiff_t y, ptrdiff_t x, const VP56mv *in_mv,
int bw, int bh, int w, int h, int bytesperpixel, int bw, int bh, int w, int h, int bytesperpixel,
const uint16_t *scale, const uint8_t *step) const uint16_t *scale, const uint8_t *step)
{ {
int mx, my; int mx, my;
int refbw_m1, refbh_m1; int refbw_m1, refbh_m1;
int th; int th;
VP56mv mv;
if (s->ss_h) { if (s->ss_h) {
// BUG https://code.google.com/p/webm/issues/detail?id=820 // BUG https://code.google.com/p/webm/issues/detail?id=820
mx = scale_mv(mv->x, 0) + (scale_mv(x * 16, 0) & ~15) + (scale_mv(x * 32, 0) & 15); mv.x = av_clip(in_mv->x, -(x + bw + 4) << 4, (s->cols * 4 - x + 3) << 4);
mx = scale_mv(mv.x, 0) + (scale_mv(x * 16, 0) & ~15) + (scale_mv(x * 32, 0) & 15);
} else { } else {
mx = scale_mv(mv->x << 1, 0) + scale_mv(x * 16, 0); mv.x = av_clip(in_mv->x, -(x + bw + 4) << 3, (s->cols * 8 - x + 3) << 3);
mx = scale_mv(mv.x << 1, 0) + scale_mv(x * 16, 0);
} }
if (s->ss_v) { if (s->ss_v) {
// BUG https://code.google.com/p/webm/issues/detail?id=820 // BUG https://code.google.com/p/webm/issues/detail?id=820
my = scale_mv(mv->y, 1) + (scale_mv(y * 16, 1) & ~15) + (scale_mv(y * 32, 1) & 15); mv.y = av_clip(in_mv->y, -(y + bh + 4) << 4, (s->rows * 4 - y + 3) << 4);
my = scale_mv(mv.y, 1) + (scale_mv(y * 16, 1) & ~15) + (scale_mv(y * 32, 1) & 15);
} else { } else {
my = scale_mv(mv->y << 1, 1) + scale_mv(y * 16, 1); mv.y = av_clip(in_mv->y, -(y + bh + 4) << 3, (s->rows * 8 - y + 3) << 3);
my = scale_mv(mv.y << 1, 1) + scale_mv(y * 16, 1);
} }
#undef scale_mv #undef scale_mv
y = my >> 4; y = my >> 4;