aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2019-12-18 18:12:15 +0100
committerKostya Shishkov <kostya.shishkov@gmail.com>2019-12-18 18:12:15 +0100
commit3cc76ad5da2772a179d6933695e84ec9212f84c2 (patch)
tree43d172e0bde7c7d23b54420923359e4d92dcd05b
parent72c6f2634b57fe73d101376602e21b81bebf3c1a (diff)
downloadnihav-3cc76ad5da2772a179d6933695e84ec9212f84c2.tar.gz
vp3: fix motion compensation code
-rw-r--r--nihav-duck/src/codecs/vp3.rs17
-rw-r--r--nihav-duck/src/codecs/vpcommon.rs22
2 files changed, 30 insertions, 9 deletions
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<u8>, 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 ];