X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-duck%2Fsrc%2Fcodecs%2Fvp6.rs;h=916711cddbc00b5392b75c4f1c7f6b28ba257f7e;hb=e6aaad5c5273cd814b5748b7faf3751835a37217;hp=b69930c8517920e0b11bb7558d9e11ecad09929b;hpb=44a1af4bd70e6d27e5e28f9758109dbca4fbcbbd;p=nihav.git diff --git a/nihav-duck/src/codecs/vp6.rs b/nihav-duck/src/codecs/vp6.rs index b69930c..916711c 100644 --- a/nihav-duck/src/codecs/vp6.rs +++ b/nihav-duck/src/codecs/vp6.rs @@ -1,10 +1,10 @@ use nihav_core::codecs::*; use nihav_core::io::bitreader::*; use nihav_codec_support::codecs::{MV, ZIGZAG}; -use nihav_codec_support::codecs::blockdsp::edge_emu; use super::vpcommon::*; use super::vp56::*; use super::vp6data::*; +use super::vp6dsp::*; #[derive(Default)] struct VP6BR { @@ -54,7 +54,6 @@ impl VP56Parser for VP6BR { hdr.multistream = true; } let bytes = br.tell() >> 3; - std::mem::drop(br); bc.skip_bytes(bytes); self.loop_mode = 0; if hdr.is_intra { @@ -473,138 +472,22 @@ fn decode_zero_run_huff(br: &mut BitReader, huff: &VP6Huff) -> DecoderResult, comp: usize, - dx: usize, dy: usize, mv_x: i16, mv_y: i16) -{ - let (w, h) = src.get_dimensions(comp); - let sx = (dx as isize) + (mv_x as isize); - let sy = (dy as isize) + (mv_y as isize); - - if (sx - 2 < 0) || (sx + 8 + 2 > (w as isize)) || - (sy - 2 < 0) || (sy + 8 + 2 > (h as isize)) { - edge_emu(&src, sx - 2, sy - 2, 8 + 2 + 2, 8 + 2 + 2, - dst, dstride, comp, 0); - } else { - let sstride = src.get_stride(comp); - let soff = src.get_offset(comp); - let sdta = src.get_data(); - let sbuf: &[u8] = sdta.as_slice(); - let saddr = soff + ((sx - 2) as usize) + ((sy - 2) as usize) * sstride; - let src = &sbuf[saddr..]; - for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(12) { - dline[..12].copy_from_slice(&sline[..12]); - } - } -} - -fn calc_variance(src: &[u8], stride: usize) -> u16 { - let mut sum = 0; - let mut ssum = 0; - for line in src.chunks(stride * 2).take(4) { - for el in line.iter().take(8).step_by(2) { - let pix = u32::from(*el); - sum += pix; - ssum += pix * pix; - } - } - ((ssum * 16 - sum * sum) >> 8) as u16 -} - -macro_rules! mc_filter { - (bilinear; $a: expr, $b: expr, $c: expr) => { - ((u16::from($a) * (8 - $c) + u16::from($b) * $c + 4) >> 3) as u8 - }; - (bicubic; $src: expr, $off: expr, $step: expr, $coeffs: expr) => { - ((i32::from($src[$off - $step] ) * i32::from($coeffs[0]) + - i32::from($src[$off] ) * i32::from($coeffs[1]) + - i32::from($src[$off + $step] ) * i32::from($coeffs[2]) + - i32::from($src[$off + $step * 2]) * i32::from($coeffs[3]) + 64) >> 7).min(255).max(0) as u8 - } -} - -//#[allow(snake_case)] -fn mc_bilinear(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, mx: u16, my: u16) { - if my == 0 { - for dline in dst.chunks_mut(dstride).take(8) { - for i in 0..8 { - dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx); - } - soff += sstride; - } - } else if mx == 0 { - for dline in dst.chunks_mut(dstride).take(8) { - for i in 0..8 { - dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + sstride], my); - } - soff += sstride; - } - } else { - let mut tmp = [0u8; 8]; - for i in 0..8 { - tmp[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx); - } - soff += sstride; - for dline in dst.chunks_mut(dstride).take(8) { - for i in 0..8 { - let cur = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx); - dline[i] = mc_filter!(bilinear; tmp[i], cur, my); - tmp[i] = cur; - } - soff += sstride; - } - } -} - -#[allow(clippy::trivially_copy_pass_by_ref)] -fn mc_bicubic(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, coeffs_w: &[i16; 4], coeffs_h: &[i16; 4]) { - if coeffs_h[1] == 128 { - for dline in dst.chunks_mut(dstride).take(8) { - for i in 0..8 { - dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w); - } - soff += sstride; - } - } else if coeffs_w[1] == 128 { // horizontal-only interpolation - for dline in dst.chunks_mut(dstride).take(8) { - for i in 0..8 { - dline[i] = mc_filter!(bicubic; src, soff + i, sstride, coeffs_h); - } - soff += sstride; - } - } else { - let mut buf = [0u8; 16 * 11]; - soff -= sstride; - for dline in buf.chunks_mut(16) { - for i in 0..8 { - dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w); - } - soff += sstride; - } - let mut soff = 16; - for dline in dst.chunks_mut(dstride).take(8) { - for i in 0..8 { - dline[i] = mc_filter!(bicubic; buf, soff + i, 16, coeffs_h); - } - soff += 16; - } - } -} - struct VP6Decoder { dec: VP56Decoder, info: NACodecInfoRef, br: VP6BR, has_alpha: bool, + flipped: bool, } impl VP6Decoder { - fn new(has_alpha: bool) -> Self { + fn new(flipped: bool, has_alpha: bool) -> Self { Self { - dec: VP56Decoder::new(6, has_alpha, true), + dec: VP56Decoder::new(6, has_alpha, flipped), info: NACodecInfoRef::default(), br: VP6BR::new(), has_alpha, + flipped, } } } @@ -617,7 +500,15 @@ impl NADecoder for VP6Decoder { } else { VP_YUVA420_FORMAT }; - let myvinfo = NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt); + let mut width = vinfo.get_width(); + let mut height = vinfo.get_height(); + if let (false, Some(edta)) = (self.flipped, info.get_extradata()) { + if (width & 0xF) == 0 && (height & 0xF) == 0 { + width -= usize::from(edta[0] >> 4); + height -= usize::from(edta[0] & 0xF); + } + } + let myvinfo = NAVideoInfo::new(width, height, self.flipped, fmt); let myinfo = NACodecTypeInfo::Video(myvinfo); self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); self.dec.init(supp, myvinfo)?; @@ -648,11 +539,15 @@ impl NAOptionHandler for VP6Decoder { } pub fn get_decoder_vp6() -> Box { - Box::new(VP6Decoder::new(false)) + Box::new(VP6Decoder::new(true, false)) +} + +pub fn get_decoder_vp6f() -> Box { + Box::new(VP6Decoder::new(false, false)) } pub fn get_decoder_vp6_alpha() -> Box { - Box::new(VP6Decoder::new(true)) + Box::new(VP6Decoder::new(false, true)) } #[cfg(test)] @@ -670,6 +565,7 @@ mod test { let mut dec_reg = RegisteredDecoders::new(); duck_register_all_decoders(&mut dec_reg); + // sample from a private collection test_decoding("avi", "vp6", "assets/Duck/selection_720x576_300kBit_vp60i.avi", Some(16), &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0x042c3e96, 0x8a9b26a2, 0x4dcbaf66, 0x1b788d03])); @@ -681,6 +577,7 @@ mod test { let mut dec_reg = RegisteredDecoders::new(); duck_register_all_decoders(&mut dec_reg); + // sample: https://samples.mplayerhq.hu/V-codecs/VP6/vp6_crash.avi test_decoding("avi", "vp6", "assets/Duck/vp6_crash.avi", Some(4), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![ [0xdcd70fa0, 0x0d075ce2, 0xc9e65077, 0xb003a92e], @@ -689,5 +586,41 @@ mod test { [0x11b048ac, 0xedb3e471, 0xd04e9399, 0x64e623e3], [0x182871b1, 0x2146893a, 0x2912210e, 0x6dd592e8]])); } - // todo find good sample for vp6a test + #[test] + fn test_vp6_alpha() { + let mut dmx_reg = RegisteredDemuxers::new(); + generic_register_all_demuxers(&mut dmx_reg); + let mut dec_reg = RegisteredDecoders::new(); + duck_register_all_decoders(&mut dec_reg); + + // sample created by remuxing some VP6A in FLV + test_decoding("avi", "vp6a", "assets/Duck/vp6a.avi", Some(25), + &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![ + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xaf903d79, 0x17ddb3c7, 0xf0a381e8, 0x26b36a7d], + [0xd3801a96, 0x1b5384ff, 0x422b228c, 0x9c4582c4], + [0x8ddb0dfe, 0x302eb1ed, 0x10e64e22, 0x5a5a62b9], + [0x79338328, 0x06113781, 0x8b116d18, 0xde56707e], + [0xdb58433b, 0x1de4ce67, 0x15fcbcee, 0x1df9de61]])); + } }