From: Kostya Shishkov Date: Wed, 18 Dec 2019 17:12:15 +0000 (+0100) Subject: vp3: fix motion compensation code X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=3cc76ad5da2772a179d6933695e84ec9212f84c2;p=nihav.git vp3: fix motion compensation code --- diff --git a/nihav-duck/src/codecs/vp3.rs b/nihav-duck/src/codecs/vp3.rs index 9473774..e52c940 100644 --- a/nihav-duck/src/codecs/vp3.rs +++ b/nihav-duck/src/codecs/vp3.rs @@ -552,6 +552,15 @@ fn vp31_loop_filter_h(frm: &mut NASimpleVideoFrame, x: usize, y: usize, plan vp31_loop_filter(frm.data, off, frm.stride[plane], 1, 8, loop_str); } +fn vp3_mv_mode(mvx: i16, mvy: i16) -> usize { + let mode = ((mvx & 1) + (mvy & 1) * 2) as usize; + if (mode == 3) && (mvx ^ mvy < 0) { + 4 + } else { + mode + } +} + impl VP34Decoder { fn new(version: u8) -> Self { let vt = alloc_video_buffer(NAVideoInfo::new(24, 24, false, YUV420_FORMAT), 4).unwrap(); @@ -1550,7 +1559,7 @@ println!("intra, ver {} (self {})", version, self.version); let xoff = (i & 1) * 8; let yoff = (i >> 1) * 8; - let mode = ((mvs[i].x & 1) + (mvs[i].y & 1) * 2) as usize; + let mode = vp3_mv_mode(mvs[i].x, mvs[i].y); if self.version != 4 { copy_block(frm, src.clone(), 0, bx * 8 + xoff, by * 8 + yoff, mvs[i].x >> 1, mvs[i].y >> 1, 8, 8, 0, 1, mode, VP3_INTERP_FUNCS); @@ -1563,7 +1572,7 @@ println!("intra, ver {} (self {})", version, self.version); let mx = (mv_sum.x >> 1) | (mv_sum.x & 1); let my = (mv_sum.y >> 1) | (mv_sum.y & 1); - let mode = ((mx & 1) + (my & 1) * 2) as usize; + let mode = vp3_mv_mode(mx, my); copy_block(frm, src.clone(), 1, bx * 4, by * 4, mx >> 1, my >> 1, 8, 8, 0, 1, mode, VP3_INTERP_FUNCS); copy_block(frm, src.clone(), 2, bx * 4, by * 4, mx >> 1, my >> 1, 8, 8, 0, 1, mode, VP3_INTERP_FUNCS); } @@ -1581,7 +1590,7 @@ println!("intra, ver {} (self {})", version, self.version); } else { self.shuf.get_golden().unwrap() }; - let mode = ((blk.mv.x & 1) + (blk.mv.y & 1) * 2) as usize; + let mode = vp3_mv_mode(blk.mv.x, blk.mv.y); if self.version != 4 { copy_block(frm, src.clone(), 0, bx * 8, by * 8, blk.mv.x >> 1, blk.mv.y >> 1, 16, 16, 0, 1, mode, VP3_INTERP_FUNCS); @@ -1601,7 +1610,7 @@ println!("intra, ver {} (self {})", version, self.version); } let mx = (blk.mv.x >> 1) | (blk.mv.x & 1); let my = (blk.mv.y >> 1) | (blk.mv.y & 1); - let mode = ((mx & 1) + (my & 1) * 2) as usize; + let mode = vp3_mv_mode(mx, my); if self.version != 4 { copy_block(frm, src.clone(), 1, bx * 4, by * 4, mx >> 1, my >> 1, 8, 8, 0, 1, mode, VP3_INTERP_FUNCS); diff --git a/nihav-duck/src/codecs/vpcommon.rs b/nihav-duck/src/codecs/vpcommon.rs index d1f6d44..bd7d1cf 100644 --- a/nihav-duck/src/codecs/vpcommon.rs +++ b/nihav-duck/src/codecs/vpcommon.rs @@ -432,21 +432,33 @@ fn vp3_interp10(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: } } -fn vp3_interp11(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize) +fn vp3_interp1x(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize) { let mut didx = 0; let mut sidx = 0; for _ in 0..bh { for x in 0..bw { dst[didx + x] = (((src[sidx + x] as u16) + - (src[sidx + x + 1] as u16) + - (src[sidx + x + sstride] as u16) + - (src[sidx + x + sstride + 1] as u16)) >> 2) as u8; + (src[sidx + x + sstride + 1] as u16)) >> 1) as u8; } didx += dstride; sidx += sstride; } } -pub const VP3_INTERP_FUNCS: &[blockdsp::BlkInterpFunc] = &[ vp3_interp00, vp3_interp01, vp3_interp10, vp3_interp11 ]; +fn vp3_interp1y(dst: &mut [u8], dstride: usize, src: &[u8], sstride: usize, bw: usize, bh: usize) +{ + let mut didx = 0; + let mut sidx = 0; + for _ in 0..bh { + for x in 0..bw { + dst[didx + x] = (((src[sidx + x + 1] as u16) + + (src[sidx + x + sstride] as u16)) >> 1) as u8; + } + didx += dstride; + sidx += sstride; + } +} + +pub const VP3_INTERP_FUNCS: &[blockdsp::BlkInterpFunc] = &[ vp3_interp00, vp3_interp01, vp3_interp10, vp3_interp1x, vp3_interp1y ];