From dda73ab08687ecd7bfa7ca0db40195ed490c5b84 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 30 Nov 2024 16:46:00 +0100 Subject: [PATCH] remove Actimagine VX format support It has been moved to na_game_tool. --- nihav-game/Cargo.toml | 6 +- nihav-game/src/codecs/mod.rs | 9 - nihav-game/src/codecs/vx.rs | 1802 -------------------------------- nihav-game/src/demuxers/mod.rs | 4 - nihav-game/src/demuxers/vx.rs | 269 ----- 5 files changed, 2 insertions(+), 2088 deletions(-) delete mode 100644 nihav-game/src/codecs/vx.rs delete mode 100644 nihav-game/src/demuxers/vx.rs diff --git a/nihav-game/Cargo.toml b/nihav-game/Cargo.toml index c32f7e2..ac34804 100644 --- a/nihav-game/Cargo.toml +++ b/nihav-game/Cargo.toml @@ -18,7 +18,7 @@ nihav_commonfmt = { path = "../nihav-commonfmt", default-features=false, feature [features] default = ["all_decoders", "all_demuxers", "all_muxers"] demuxers = [] -all_demuxers = ["demuxer_bmv", "demuxer_bmv3", "demuxer_fcmp", "demuxer_fst", "demuxer_gdv", "demuxer_seq", "demuxer_sga", "demuxer_siff", "demuxer_smush", "demuxer_vmd", "demuxer_vx"] +all_demuxers = ["demuxer_bmv", "demuxer_bmv3", "demuxer_fcmp", "demuxer_fst", "demuxer_gdv", "demuxer_seq", "demuxer_sga", "demuxer_siff", "demuxer_smush", "demuxer_vmd"] demuxer_bmv = ["demuxers"] demuxer_bmv3 = ["demuxers"] demuxer_cnm = ["demuxers"] @@ -30,12 +30,11 @@ demuxer_sga = ["demuxers"] demuxer_siff = ["demuxers"] demuxer_smush = ["demuxers"] demuxer_vmd = ["demuxers"] -demuxer_vx = ["demuxers"] all_decoders = ["all_video_decoders", "all_audio_decoders"] decoders = [] -all_video_decoders = ["decoder_beam_fcp", "decoder_beam_vbv", "decoder_bmv", "decoder_bmv3", "decoder_fstvid", "decoder_gdvvid", "decoder_ipma", "decoder_kmvc", "decoder_midivid", "decoder_midivid3", "decoder_seq", "decoder_sga", "decoder_smush_video", "decoder_vmd", "decoder_vx"] +all_video_decoders = ["decoder_beam_fcp", "decoder_beam_vbv", "decoder_bmv", "decoder_bmv3", "decoder_fstvid", "decoder_gdvvid", "decoder_ipma", "decoder_kmvc", "decoder_midivid", "decoder_midivid3", "decoder_seq", "decoder_sga", "decoder_smush_video", "decoder_vmd"] decoder_beam_fcp = ["decoders"] decoder_beam_vbv = ["decoders"] decoder_bmv = ["decoders"] @@ -50,7 +49,6 @@ decoder_seq = ["decoders"] decoder_sga = ["decoders"] decoder_smush_video = ["decoders"] decoder_vmd = ["decoders"] -decoder_vx = ["decoders"] all_audio_decoders = ["decoder_fstaud", "decoder_lhst500f22", "decoder_smush_audio"] decoder_fstaud = ["decoders"] diff --git a/nihav-game/src/codecs/mod.rs b/nihav-game/src/codecs/mod.rs index d29311f..5923919 100644 --- a/nihav-game/src/codecs/mod.rs +++ b/nihav-game/src/codecs/mod.rs @@ -39,11 +39,6 @@ pub mod sga; pub mod smush; #[cfg(feature="decoder_vmd")] pub mod vmd; -#[cfg(feature="decoder_vx")] -#[allow(clippy::collapsible_else_if)] -#[allow(clippy::erasing_op)] -#[allow(clippy::identity_op)] -pub mod vx; const GAME_CODECS: &[DecoderInfo] = &[ #[cfg(feature="decoder_gdvvid")] @@ -94,10 +89,6 @@ const GAME_CODECS: &[DecoderInfo] = &[ DecoderInfo { name: "midivid", get_decoder: midivid::get_decoder_video }, #[cfg(feature="decoder_midivid3")] DecoderInfo { name: "midivid3", get_decoder: midivid3::get_decoder_video }, -#[cfg(feature="decoder_vx")] - DecoderInfo { name: "vxaudio", get_decoder: vx::get_decoder_audio }, -#[cfg(feature="decoder_vx")] - DecoderInfo { name: "vxvideo", get_decoder: vx::get_decoder_video }, ]; /// Registers all available codecs provided by this crate. diff --git a/nihav-game/src/codecs/vx.rs b/nihav-game/src/codecs/vx.rs deleted file mode 100644 index 0a8de06..0000000 --- a/nihav-game/src/codecs/vx.rs +++ /dev/null @@ -1,1802 +0,0 @@ -use nihav_core::codecs::*; -use nihav_core::io::byteio::*; -use nihav_core::io::bitreader::*; -use nihav_core::io::codebook::*; -use nihav_core::io::intcode::*; -use std::str::FromStr; - -use std::ops::*; - -#[derive(Clone,Copy,Default,Debug,PartialEq)] -struct MV { - x: i8, - y: i8, -} - -impl Add for MV { - type Output = MV; - fn add(self, other: MV) -> MV { MV { x: self.x + other.x, y: self.y + other.y } } -} - -impl AddAssign for MV { - fn add_assign(&mut self, other: MV) { self.x += other.x; self.y += other.y; } -} - -impl Sub for MV { - type Output = MV; - fn sub(self, other: MV) -> MV { MV { x: self.x - other.x, y: self.y - other.y } } -} - -impl SubAssign for MV { - fn sub_assign(&mut self, other: MV) { self.x -= other.x; self.y -= other.y; } -} - -impl MV { - fn pred(t: MV, tl: MV, l: MV) -> MV { - let x0 = i16::from(t.x); - let x1 = i16::from(tl.x); - let x2 = i16::from(l.x); - let y0 = i16::from(t.y); - let y1 = i16::from(tl.y); - let y2 = i16::from(l.y); - let x = x0 + x1 + x2 - x0.min(x1).min(x2) - x0.max(x1).max(x2); - let y = y0 + y1 + y2 - y0.min(y1).min(y2) - y0.max(y1).max(y2); - MV{ x: x as i8, y: y as i8 } - } -} - -trait ReadCodes { - fn read_gammap(&mut self) -> BitReaderResult; - fn read_gammap_s(&mut self) -> BitReaderResult; - fn read_unary(&mut self) -> BitReaderResult; -} - -impl<'a> ReadCodes for BitReader<'a> { - fn read_gammap(&mut self) -> BitReaderResult { - Ok(self.read_code(UintCodeType::GammaP)? - 1) - } - fn read_gammap_s(&mut self) -> BitReaderResult { - let val = self.read_code(UintCodeType::GammaP)?; - if (val & 1) == 0 { - Ok((val >> 1) as i32) - } else { - Ok((1 - (val as i32)) >> 1) - } - } - fn read_unary(&mut self) -> BitReaderResult { - self.read_code(UintCodeType::UnaryZeroes) - } -} - -const CUR_BUF: usize = 3; -const CHROMA_OFF: usize = 256 * 256; - -macro_rules! mc { - ($bufs: expr, $src_id: expr, $dst_id: expr, $mx: expr, $my: expr, $xpos: expr, $ypos: expr, $w: expr, $h: expr, $ydelta: expr, $udelta: expr, $vdelta: expr, $width: expr, $height: expr) => { - if ($mx + ($xpos as isize) < 0) || ($mx + (($xpos + $w) as isize) > ($width as isize)) { - return Err(DecoderError::InvalidData); - } - if ($my + ($ypos as isize) < 0) || ($my + (($ypos + $h) as isize) > ($height as isize)) { - return Err(DecoderError::InvalidData); - } - - let sx = (($xpos as isize) + $mx) as usize; - let sy = (($ypos as isize) + $my) as usize; - - let mut soff = sx + sy * 256; - let mut doff = $xpos + $ypos * 256; - for _y in 0..$h { - for x in 0..$w { - $bufs[$dst_id][doff + x] = (i32::from($bufs[$src_id][soff + x]) + $ydelta).max(0).min(255) as u8; - } - soff += 256; - doff += 256; - } - let mut soff = CHROMA_OFF + sx / 2 + (sy / 2) * 256; - let mut doff = CHROMA_OFF + $xpos / 2 + $ypos / 2 * 256; - for _y in 0..$h / 2 { - for x in 0..$w / 2 { - $bufs[$dst_id][doff + x] = (i32::from($bufs[$src_id][soff + x]) + $udelta).max(0).min(255) as u8; - $bufs[$dst_id][doff + x + 128] = (i32::from($bufs[$src_id][soff + x + 128]) + $vdelta).max(0).min(255) as u8; - } - soff += 256; - doff += 256; - } - } -} - -fn pred_dc(buf: &mut [u8], mut pos: usize, x: usize, y: usize, w: usize, h: usize) { - let dc = if x == 0 && y == 0 { - 128 - } else if y == 0 { - let mut sum = 0; - let hh = h as u16; - for i in 0..h { - sum += u16::from(buf[pos - 1 + i * 256]); - } - ((sum + hh / 2) / hh) as u8 - } else if x == 0 { - let mut sum = 0; - let ww = w as u16; - for i in 0..w { - sum += u16::from(buf[pos - 256 + i]); - } - ((sum + ww / 2) / ww) as u8 - } else { - let mut sum = 0; - let ww = w as u16; - for i in 0..w { - sum += u16::from(buf[pos - 256 + i]); - } - let wdc = (sum + ww / 2) / ww; - - let mut sum = 0; - let hh = h as u16; - for i in 0..h { - sum += u16::from(buf[pos - 1 + i * 256]); - } - let hdc = (sum + hh / 2) / hh; - - ((wdc + hdc + 1) >> 1) as u8 - }; - for _ in 0..h { - for x in 0..w { - buf[pos + x] = dc; - } - pos += 256; - } -} -fn pred_dc4x4(buf: &mut [u8], pos: usize, x: usize, y: usize) { - if x == 0 && y == 0 { - for line in buf[pos..].chunks_mut(256).take(4) { - for el in line[..4].iter_mut() { - *el = 0x80; - } - } - return; - } - let mut sum = 0; - let mut shift = 1; - if y != 0 { - for i in 0..4 { - sum += u16::from(buf[pos - 256 + i]); - } - sum += 2; - shift += 1; - } - if x != 0 { - for i in 0..4 { - sum += u16::from(buf[pos + i * 256 - 1]); - } - sum += 2; - shift += 1; - } - let dc = (sum >> shift) as u8; - for line in buf[pos..].chunks_mut(256).take(4) { - for el in line[..4].iter_mut() { - *el = dc; - } - } -} - -fn pred_hor(buf: &mut [u8], mut pos: usize, w: usize, h: usize) { - for _ in 0..h { - for x in 0..w { - buf[pos + x] = buf[pos - 1]; - } - pos += 256; - } -} - -fn pred_ver(buf: &mut [u8], mut pos: usize, w: usize, h: usize) { - for _ in 0..h { - for x in 0..w { - buf[pos + x] = buf[pos + x - 256]; - } - pos += 256; - } -} - -fn avg(a: u8, b: u8) -> u8 { - ((u16::from(a) + u16::from(b) + 1) >> 1) as u8 -} -fn avg_nr(a: u8, b: u8) -> u8 { - ((u16::from(a) + u16::from(b)) >> 1) as u8 -} -fn interp2(a: u8, b: u8, c: u8) -> u8 { - ((u16::from(a) + 2 * u16::from(b) + u16::from(c) + 2) >> 2) as u8 -} - -fn pred_ddown_left(blk: &mut [u8], pos: usize) { - let (t0, t1, t2, t3) = (blk[pos - 256], blk[pos - 256 + 1], blk[pos - 256 + 2], blk[pos - 256 + 3]); - let (t4, t5, t6, t7) = (blk[pos - 256 + 4], blk[pos - 256 + 5], blk[pos - 256 + 6], blk[pos - 256 + 7]); - - blk[pos + 0 + 0 * 256] = interp2(t0, t1, t2); - let pix = interp2(t1, t2, t3); - blk[pos + 1 + 0 * 256] = pix; - blk[pos + 0 + 1 * 256] = pix; - let pix = interp2(t2, t3, t4); - blk[pos + 2 + 0 * 256] = pix; - blk[pos + 1 + 1 * 256] = pix; - blk[pos + 0 + 2 * 256] = pix; - let pix = interp2(t3, t4, t5); - blk[pos + 3 + 0 * 256] = pix; - blk[pos + 2 + 1 * 256] = pix; - blk[pos + 1 + 2 * 256] = pix; - blk[pos + 0 + 3 * 256] = pix; - let pix = interp2(t4, t5, t6); - blk[pos + 3 + 1 * 256] = pix; - blk[pos + 2 + 2 * 256] = pix; - blk[pos + 1 + 3 * 256] = pix; - let pix = interp2(t5, t6, t7); - blk[pos + 3 + 2 * 256] = pix; - blk[pos + 2 + 3 * 256] = pix; - blk[pos + 3 + 3 * 256] = interp2(t6, t7, t7); -} -fn pred_ddown_right(blk: &mut [u8], pos: usize) { - let (l0, l1, l2, l3) = (blk[pos - 1], blk[pos + 256 - 1], blk[pos + 256 * 2 - 1], blk[pos + 256 * 3 - 1]); - let (tl, t0, t1, t2) = (blk[pos - 256 - 1], blk[pos - 256], blk[pos - 256 + 1], blk[pos - 256 + 2]); - let t3 = blk[pos - 256 + 3]; - - blk[pos + 0 + 3 * 256] = interp2(l1, l2, l3); - let pix = interp2(l0, l1, l2); - blk[pos + 0 + 2 * 256] = pix; - blk[pos + 1 + 3 * 256] = pix; - let pix = interp2(tl, l0, l1); - blk[pos + 0 + 1 * 256] = pix; - blk[pos + 1 + 2 * 256] = pix; - blk[pos + 2 + 3 * 256] = pix; - let pix = interp2(l0, tl, t0); - blk[pos + 0 + 0 * 256] = pix; - blk[pos + 1 + 1 * 256] = pix; - blk[pos + 2 + 2 * 256] = pix; - blk[pos + 3 + 3 * 256] = pix; - let pix = interp2(tl, t0, t1); - blk[pos + 1 + 0 * 256] = pix; - blk[pos + 2 + 1 * 256] = pix; - blk[pos + 3 + 2 * 256] = pix; - let pix = interp2(t0, t1, t2); - blk[pos + 2 + 0 * 256] = pix; - blk[pos + 3 + 1 * 256] = pix; - blk[pos + 3 + 0 * 256] = interp2(t1, t2, t3); -} -fn pred_ver_right(blk: &mut [u8], pos: usize) { - let (l0, l1, l2) = (blk[pos - 1], blk[pos + 256 - 1], blk[pos + 256 * 2 - 1]); - let (tl, t0, t1, t2, t3) = (blk[pos - 256 - 1], blk[pos - 256], blk[pos - 256 + 1], blk[pos - 256 + 2], blk[pos - 256 + 3]); - - blk[pos + 0 + 3 * 256] = interp2(l0, l1, l2); - blk[pos + 0 + 2 * 256] = interp2(tl, l0, l1); - let pix = interp2(l0, tl, t0); - blk[pos + 0 + 1 * 256] = pix; - blk[pos + 1 + 3 * 256] = pix; - let pix = avg(tl, t0); - blk[pos + 0 + 0 * 256] = pix; - blk[pos + 1 + 2 * 256] = pix; - let pix = interp2(tl, t0, t1); - blk[pos + 1 + 1 * 256] = pix; - blk[pos + 2 + 3 * 256] = pix; - let pix = avg(t0, t1); - blk[pos + 1 + 0 * 256] = pix; - blk[pos + 2 + 2 * 256] = pix; - let pix = interp2(t0, t1, t2); - blk[pos + 2 + 1 * 256] = pix; - blk[pos + 3 + 3 * 256] = pix; - let pix = avg(t1, t2); - blk[pos + 2 + 0 * 256] = pix; - blk[pos + 3 + 2 * 256] = pix; - blk[pos + 3 + 1 * 256] = interp2(t1, t2, t3); - blk[pos + 3 + 0 * 256] = avg(t2, t3); -} -fn pred_hor_down(blk: &mut [u8], pos: usize) { - let (l0, l1, l2, l3) = (blk[pos - 1], blk[pos + 256 - 1], blk[pos + 256 * 2 - 1], blk[pos + 256 * 3 - 1]); - let (tl, t0, t1, t2) = (blk[pos - 256 - 1], blk[pos - 256], blk[pos - 256 + 1], blk[pos - 256 + 2]); - - blk[pos + 0 + 3 * 256] = avg(l2, l3); - blk[pos + 1 + 3 * 256] = interp2(l1, l2, l3); - let pix = avg(l1, l2); - blk[pos + 0 + 2 * 256] = pix; - blk[pos + 2 + 3 * 256] = pix; - let pix = interp2(l0, l1, l2); - blk[pos + 1 + 2 * 256] = pix; - blk[pos + 3 + 3 * 256] = pix; - let pix = avg(l0, l1); - blk[pos + 0 + 1 * 256] = pix; - blk[pos + 2 + 2 * 256] = pix; - let pix = interp2(tl, l0, l1); - blk[pos + 1 + 1 * 256] = pix; - blk[pos + 3 + 2 * 256] = pix; - let pix = avg(tl, l0); - blk[pos + 0 + 0 * 256] = pix; - blk[pos + 2 + 1 * 256] = pix; - let pix = interp2(l0, tl, t0); - blk[pos + 1 + 0 * 256] = pix; - blk[pos + 3 + 1 * 256] = pix; - blk[pos + 2 + 0 * 256] = interp2(tl, t0, t1); - blk[pos + 3 + 0 * 256] = interp2(t0, t1, t2); -} -fn pred_ver_left(blk: &mut [u8], pos: usize) { - let (t0, t1, t2, t3) = (blk[pos - 256], blk[pos - 256 + 1], blk[pos - 256 + 2], blk[pos - 256 + 3]); - let (t4, t5, t6) = (blk[pos - 256 + 4], blk[pos - 256 + 5], blk[pos - 256 + 6]); - - blk[pos + 3 + 3 * 256] = interp2(t4, t5, t6); - blk[pos + 3 + 2 * 256] = avg(t4, t5); - let pix = interp2(t3, t4, t5); - blk[pos + 3 + 1 * 256] = pix; - blk[pos + 2 + 3 * 256] = pix; - let pix = avg(t3, t4); - blk[pos + 3 + 0 * 256] = pix; - blk[pos + 2 + 2 * 256] = pix; - let pix = interp2(t2, t3, t4); - blk[pos + 2 + 1 * 256] = pix; - blk[pos + 1 + 3 * 256] = pix; - let pix = avg(t2, t3); - blk[pos + 2 + 0 * 256] = pix; - blk[pos + 1 + 2 * 256] = pix; - let pix = interp2(t1, t2, t3); - blk[pos + 1 + 1 * 256] = pix; - blk[pos + 0 + 3 * 256] = pix; - let pix = avg(t1, t2); - blk[pos + 1 + 0 * 256] = pix; - blk[pos + 0 + 2 * 256] = pix; - blk[pos + 0 + 1 * 256] = interp2(t0, t1, t2); - blk[pos + 0 + 0 * 256] = avg(t0, t1); -} -fn pred_hor_up(blk: &mut [u8], pos: usize) { - let (l0, l1, l2, l3) = (blk[pos - 1], blk[pos + 256 - 1], blk[pos + 256 * 2 - 1], blk[pos + 256 * 3 - 1]); - - blk[pos + 0 + 0 * 256] = avg(l0, l1); - blk[pos + 1 + 0 * 256] = interp2(l0, l1, l2); - let pix = avg(l1, l2); - blk[pos + 2 + 0 * 256] = pix; - blk[pos + 0 + 1 * 256] = pix; - let pix = interp2(l1, l2, l3); - blk[pos + 3 + 0 * 256] = pix; - blk[pos + 1 + 1 * 256] = pix; - let pix = avg(l2, l3); - blk[pos + 2 + 1 * 256] = pix; - blk[pos + 0 + 2 * 256] = pix; - let pix = interp2(l2, l3, l3); - blk[pos + 3 + 1 * 256] = pix; - blk[pos + 1 + 2 * 256] = pix; - blk[pos + 0 + 3 * 256] = l3; - blk[pos + 2 + 2 * 256] = l3; - blk[pos + 3 + 2 * 256] = l3; - blk[pos + 1 + 3 * 256] = l3; - blk[pos + 2 + 3 * 256] = l3; - blk[pos + 3 + 3 * 256] = l3; -} - -fn pred_plane(blk: &mut [u8], pos: usize, w: usize, h: usize) { - if w == 1 && h == 1 { - return; - } - if h == 1 { - blk[pos + w / 2 - 1] = avg_nr(blk[pos - 1], blk[pos + w - 1]); - if w > 2 { - pred_plane(blk, pos, w / 2, 1); - pred_plane(blk, pos + w / 2, w / 2, 1); - } - return; - } - if w == 1 { - blk[pos + (h / 2 - 1) * 256] = avg_nr(blk[pos - 256], blk[pos + (h - 1) * 256]); - if h > 2 { - pred_plane(blk, pos, 1, h / 2); - pred_plane(blk, pos + (h / 2) * 256, 1, h / 2); - } - return; - } - - let is_even_block = ((w.trailing_zeros() + h.trailing_zeros()) & 1) == 0; // i.e. w*h = 256/64/16/4 - - let hoff = (h - 1) * 256; - let h2off = (h / 2 - 1) * 256; - let woff = w - 1; - let w2off = w / 2 - 1; - let dr = blk[pos + woff + hoff]; - let tr = blk[pos + woff - 256]; - let dl = blk[pos - 1 + hoff]; - - let dm = avg_nr(dl, dr); - blk[pos + w2off + hoff] = dm; - blk[pos + woff + h2off] = avg_nr(tr, dr); - let (val1, val2) = if is_even_block { - (dm, blk[pos + w2off - 256]) - } else { - (blk[pos + woff + h2off], blk[pos - 1 + h2off]) - }; - blk[pos + w2off + h2off] = avg_nr(val1, val2); - - let hw = w / 2; - let hh = h / 2; - pred_plane(blk, pos, hw, hh); - pred_plane(blk, pos + hw, hw, hh); - pred_plane(blk, pos + hh * 256, hw, hh); - pred_plane(blk, pos + hw + hh * 256, hw, hh); -} -fn pred_plane_delta(blk: &mut [u8], pos: usize, w: usize, h: usize, delta: i32) { - let tr = blk[pos + w - 1 - 256]; - let dl = blk[pos + 256 * (h - 1) - 1]; - let pred = avg(tr, dl).wrapping_add(delta as u8); - blk[pos + 256 * (h - 1) + w - 1] = pred; - pred_plane(blk, pos, w, h); -} - -struct Codebooks { - nc_cb: [Codebook; 3], - num_zero_cb: [Codebook; 15], - zero_run_cb: [Codebook; 6], -} - -fn map_idx(idx: usize) -> u8 { idx as u8 } -macro_rules! create_cb { - ($bits_tab: expr, $lens_tab: expr) => {{ - let mut cbr = TableCodebookDescReader::new($bits_tab, $lens_tab, map_idx); - Codebook::new(&mut cbr, CodebookMode::MSB).unwrap() - }} -} - -impl Codebooks { - fn new() -> Self { - let nc_cb0 = create_cb!(&NC_BITS[0], &NC_LENS[0]); - let nc_cb1 = create_cb!(&NC_BITS[1], &NC_LENS[1]); - let nc_cb2 = create_cb!(&NC_BITS[2], &NC_LENS[2]); - - let nz0 = create_cb!(&NUM_ZERO_BITS[ 0], &NUM_ZERO_LENS[ 0]); - let nz1 = create_cb!(&NUM_ZERO_BITS[ 1], &NUM_ZERO_LENS[ 1]); - let nz2 = create_cb!(&NUM_ZERO_BITS[ 2], &NUM_ZERO_LENS[ 2]); - let nz3 = create_cb!(&NUM_ZERO_BITS[ 3], &NUM_ZERO_LENS[ 3]); - let nz4 = create_cb!(&NUM_ZERO_BITS[ 4], &NUM_ZERO_LENS[ 4]); - let nz5 = create_cb!(&NUM_ZERO_BITS[ 5], &NUM_ZERO_LENS[ 5]); - let nz6 = create_cb!(&NUM_ZERO_BITS[ 6], &NUM_ZERO_LENS[ 6]); - let nz7 = create_cb!(&NUM_ZERO_BITS[ 7], &NUM_ZERO_LENS[ 7]); - let nz8 = create_cb!(&NUM_ZERO_BITS[ 8], &NUM_ZERO_LENS[ 8]); - let nz9 = create_cb!(&NUM_ZERO_BITS[ 9], &NUM_ZERO_LENS[ 9]); - let nz10 = create_cb!(&NUM_ZERO_BITS[10], &NUM_ZERO_LENS[10]); - let nz11 = create_cb!(&NUM_ZERO_BITS[11], &NUM_ZERO_LENS[11]); - let nz12 = create_cb!(&NUM_ZERO_BITS[12], &NUM_ZERO_LENS[12]); - let nz13 = create_cb!(&NUM_ZERO_BITS[13], &NUM_ZERO_LENS[13]); - let nz14 = create_cb!(&NUM_ZERO_BITS[14], &NUM_ZERO_LENS[14]); - - let zcb0 = create_cb!(&ZERO_RUN_BITS[0], &ZERO_RUN_LENS[0]); - let zcb1 = create_cb!(&ZERO_RUN_BITS[1], &ZERO_RUN_LENS[1]); - let zcb2 = create_cb!(&ZERO_RUN_BITS[2], &ZERO_RUN_LENS[2]); - let zcb3 = create_cb!(&ZERO_RUN_BITS[3], &ZERO_RUN_LENS[3]); - let zcb4 = create_cb!(&ZERO_RUN_BITS[4], &ZERO_RUN_LENS[4]); - let zcb5 = create_cb!(&ZERO_RUN_BITS[5], &ZERO_RUN_LENS[5]); - Self { - nc_cb: [nc_cb0, nc_cb1, nc_cb2], - num_zero_cb: [nz0, nz1, nz2, nz3, nz4, nz5, nz6, nz7, nz8, nz9, nz10, nz11, nz12, nz13, nz14], - zero_run_cb: [zcb0, zcb1, zcb2, zcb3, zcb4, zcb5], - } - } -} - -macro_rules! transform { - ($a: expr, $b: expr, $c: expr, $d: expr, $q0: expr, $q1: expr) => { - let t0 = ($a + $c).wrapping_mul($q0); - let t1 = ($a - $c).wrapping_mul($q0); - let tb = $b.wrapping_mul($q1); - let td = $d.wrapping_mul($q1); - let t2 = tb + (td >> 1); - let t3 = (tb >> 1) - td; - $a = t0 + t2; - $b = t1 + t3; - $c = t1 - t3; - $d = t0 - t2; - } -} - -fn idct_add(qmat: &[i32; 8], blk: &mut [i32; 16], dst: &mut [u8]) { - for i in 0..4 { - transform!(blk[i + 0 * 4], blk[i + 1 * 4], blk[i + 2 * 4], blk[i + 3 * 4], qmat[i], qmat[i + 4]); - } - for (dline, row) in dst.chunks_mut(256).zip(blk.chunks_mut(4)) { - transform!(row[0], row[1], row[2], row[3], 1, 1); - for (out, coef) in dline.iter_mut().zip(row.iter_mut()) { - *out = (i32::from(*out) + ((*coef + 0x20) >> 6)).max(0).min(255) as u8; - } - } -} - -fn decode_coeffs(br: &mut BitReader, codebooks: &Codebooks, qmat: &[i32; 8], ctx: u8, dst: &mut [u8]) -> DecoderResult { - const ZIGZAG: [usize; 16] = [ - 0, 1, 4, 8, - 5, 2, 3, 6, - 9, 12, 13, 10, - 7, 11, 14, 15 - ]; - const MAX_LEVEL: [i32; 6] = [ 2, 5, 11, 23, 47, 0x8000 ]; - - let (ncoeffs, nones) = if ctx < 8 { - let sym = br.read_cb(&codebooks.nc_cb[NC_MAP[ctx as usize]])?; - if sym == 0 { - return Ok(0); - } - (sym >> 2, sym & 3) - } else { - let ncoeffs = (br.read(4)? + 1) as u8; - let nones = br.read(2)? as u8; - if ncoeffs < nones { - return Ok(0); - } - (ncoeffs, nones) - }; - let mut num_zero = if ncoeffs == 16 { 0 } else { - br.read_cb(&codebooks.num_zero_cb[ncoeffs as usize - 1])? - }; - validate!(ncoeffs + num_zero <= 16); - let mut blk = [0i32; 16]; - let mut level = 0usize; - let mut coef_left = ncoeffs; - let mut ones_left = nones; - let mut idx = ncoeffs + num_zero; - while coef_left > 0 { - let val = if ones_left > 0 { - ones_left -= 1; - if !br.read_bool()? { 1 } else { -1 } - } else { - let prefix = br.read_unary()?; - let val = if prefix < 15 { - (br.read(level as u8)? | (prefix << level)) as i32 - } else { - (br.read(11)? + (15 << level)) as i32 - }; - if val > MAX_LEVEL[level] { - level += 1; - } - if !br.read_bool()? { - val + 1 - } else { - -(val + 1) - } - }; - idx -= 1; - blk[ZIGZAG[idx as usize]] = val; - coef_left -= 1; - if num_zero > 0 && coef_left > 0 { - let run = if num_zero < 7 { - br.read_cb(&codebooks.zero_run_cb[num_zero as usize - 1])? - } else { - if br.peek(3) != 0 { - 7 - (br.read(3)? as u8) - } else { - (br.read_unary()? as u8) + 4 - } - }; - validate!(run <= num_zero); - idx -= run; - num_zero -= run; - } - } - idct_add(qmat, &mut blk, dst); - Ok(ncoeffs) -} - -const NCSTRIDE: usize = 64 + 1; - -struct VXVideoDecoder { - info: NACodecInfoRef, - width: usize, - height: usize, - buf: [[u8; 256 * 392]; 4], // layout is luma with stride 256 and at 256*256 chroma lines with two components starting at positions 0 and 128 and stride 256 - refs: [usize; 4], - ipred4x4: [u8; 25], - y_ncoeffs: [u8; NCSTRIDE * (256 / 4 + 1)], - c_ncoeffs: [u8; NCSTRIDE * (256 / 8 + 1)], - mvs: [MV; 16 * 16], - pred_mv: MV, - cur_mv: MV, - qmat: [i32; 8], - codebooks: Codebooks, -} - -impl VXVideoDecoder { - fn new() -> Self { - Self { - info: NACodecInfoRef::default(), - buf: [[0x80; 256 * 392]; 4], - width: 0, - height: 0, - refs: [0, 1, 2, 3], - ipred4x4: [9; 25], - y_ncoeffs: [0; NCSTRIDE * (256 / 4 + 1)], - c_ncoeffs: [0; NCSTRIDE * (256 / 8 + 1)], - mvs: [MV::default(); 16 * 16], - cur_mv: MV::default(), - pred_mv: MV::default(), - qmat: [0; 8], - codebooks: Codebooks::new(), - } - } - fn update_refs(&mut self) { - for el in self.refs.iter_mut() { - *el = (*el + 3) & 3; - } - } - fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<()> { - let mut mv_pos = 18; - for ypos in (0..self.height).step_by(16) { - for xpos in (0..self.width).step_by(16) { - let left_mv = self.mvs[mv_pos - 1]; - let top_mv = self.mvs[mv_pos - 17]; - let tl_mv = self.mvs[mv_pos - 18]; - self.pred_mv = MV::pred(top_mv, tl_mv, left_mv); - self.cur_mv = MV::default(); - self.decode_block(br, xpos, ypos, 16, 16)?; - self.mvs[mv_pos] = self.cur_mv; - mv_pos += 1; - } - mv_pos -= self.width / 16; - mv_pos += 18; - } - Ok(()) - } - fn copy_block(&mut self, xpos: usize, ypos: usize, w: usize, h: usize, ref_buf: usize) -> DecoderResult<()> { - let src = self.refs[ref_buf]; - let dst = self.refs[CUR_BUF]; - self.cur_mv = self.pred_mv; - let mx = self.pred_mv.x as isize; - let my = self.pred_mv.y as isize; - mc!(self.buf, src, dst, mx, my, xpos, ypos, w, h, 0, 0, 0, self.width, self.height); - Ok(()) - } - fn do_mc(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize, ref_buf: usize) -> DecoderResult<()> { - let src = self.refs[ref_buf]; - let dst = self.refs[CUR_BUF]; - let dx = br.read_gammap_s()? as i8; - let dy = br.read_gammap_s()? as i8; - self.cur_mv = self.pred_mv + MV { x: dx, y: dy }; - let mx = self.cur_mv.x as isize; - let my = self.cur_mv.y as isize; - mc!(self.buf, src, dst, mx, my, xpos, ypos, w, h, 0, 0, 0, self.width, self.height); - - Ok(()) - } - fn do_mc_bias(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - let src = self.refs[0]; - let dst = self.refs[CUR_BUF]; - let mx = br.read_gammap_s()? as isize; - let my = br.read_gammap_s()? as isize; - let ydelta = br.read_gammap_s()? * 2; - let udelta = br.read_gammap_s()? * 2; - let vdelta = br.read_gammap_s()? * 2; - mc!(self.buf, src, dst, mx, my, xpos, ypos, w, h, ydelta, udelta, vdelta, self.width, self.height); - - Ok(()) - } - fn pred_plane(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - let ydelta = br.read_gammap_s()? * 2; - let udelta = br.read_gammap_s()? * 2; - let vdelta = br.read_gammap_s()? * 2; - let yoff = xpos + ypos * 256; - let coff = CHROMA_OFF + xpos / 2 + ypos / 2 * 256; - pred_plane_delta(&mut self.buf[self.refs[CUR_BUF]], yoff, w, h, ydelta); - pred_plane_delta(&mut self.buf[self.refs[CUR_BUF]], coff, w / 2, h / 2, udelta); - pred_plane_delta(&mut self.buf[self.refs[CUR_BUF]], coff + 128, w / 2, h / 2, vdelta); - Ok(()) - } - fn intra_pred(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - let ymode = br.read_gammap()? as usize; - let cmode = br.read_gammap()? as usize; - let yoff = xpos + ypos * 256; - let coff = CHROMA_OFF + xpos / 2 + ypos / 2 * 256; - let blk = &mut self.buf[self.refs[CUR_BUF]]; - match ymode { - 0 => pred_ver(blk, yoff, w, h), - 1 => pred_hor(blk, yoff, w, h), - 2 => pred_dc (blk, yoff, xpos, ypos, w, h), - 3 => pred_plane_delta(blk, yoff, w, h, 0), - _ => return Err(DecoderError::InvalidData), - }; - match cmode { - 0 => { - pred_dc(blk, coff, xpos / 2, ypos / 2, w / 2, h / 2); - pred_dc(blk, coff + 128, xpos / 2, ypos / 2, w / 2, h / 2); - }, - 1 => { - pred_hor(blk, coff, w / 2, h / 2); - pred_hor(blk, coff + 128, w / 2, h / 2); - }, - 2 => { - pred_ver(blk, coff, w / 2, h / 2); - pred_ver(blk, coff + 128, w / 2, h / 2); - }, - 3 => { - pred_plane_delta(blk, coff, w / 2, h / 2, 0); - pred_plane_delta(blk, coff + 128, w / 2, h / 2, 0); - }, - _ => return Err(DecoderError::InvalidData), - }; - Ok(()) - } - fn intra_pred4x4(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - let mut yoff = xpos + ypos * 256; - let mut idx = 6; - let blk = &mut self.buf[self.refs[CUR_BUF]]; - for y in (0..h).step_by(4) { - for x in (0..w).step_by(4) { - let mut mode = self.ipred4x4[idx - 5].min(self.ipred4x4[idx - 1]); - if mode == 9 { - mode = 2; - } - if !br.read_bool()? { - let mode1 = br.read(3)? as u8; - mode = if mode1 >= mode { mode1 + 1 } else { mode1 }; - } - match mode { - 0 => pred_ver(blk, yoff + x, 4, 4), - 1 => pred_hor(blk, yoff + x, 4, 4), - 2 => pred_dc4x4(blk, yoff + x, xpos + x, ypos + y), - 3 => pred_ddown_left (blk, yoff + x), - 4 => pred_ddown_right(blk, yoff + x), - 5 => pred_ver_right (blk, yoff + x), - 6 => pred_hor_down (blk, yoff + x), - 7 => pred_ver_left (blk, yoff + x), - 8 => pred_hor_up (blk, yoff + x), - _ => unreachable!(), - }; - self.ipred4x4[idx] = mode; - idx += 1; - } - yoff += 256 * 4; - idx -= w / 4; - idx += 5; - } - let cmode = br.read_gammap()? as usize; - let coff = CHROMA_OFF + xpos / 2 + ypos / 2 * 256; - match cmode { - 0 => { - pred_dc(blk, coff, xpos / 2, ypos / 2, w / 2, h / 2); - pred_dc(blk, coff + 128, xpos / 2, ypos / 2, w / 2, h / 2); - }, - 1 => { - pred_hor(blk, coff, w / 2, h / 2); - pred_hor(blk, coff + 128, w / 2, h / 2); - }, - 2 => { - pred_ver(blk, coff, w / 2, h / 2); - pred_ver(blk, coff + 128, w / 2, h / 2); - }, - 3 => { - pred_plane_delta(blk, coff, w / 2, h / 2, 0); - pred_plane_delta(blk, coff + 128, w / 2, h / 2, 0); - }, - _ => return Err(DecoderError::InvalidData), - }; - Ok(()) - } - fn decode_residue(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - const CBP: [u8; 32] = [ - 0x00, 0x08, 0x04, 0x02, 0x01, 0x1F, 0x0F, 0x0A, - 0x05, 0x0C, 0x03, 0x10, 0x0E, 0x0D, 0x0B, 0x07, - 0x09, 0x06, 0x1E, 0x1B, 0x1A, 0x1D, 0x17, 0x15, - 0x18, 0x12, 0x11, 0x1C, 0x14, 0x13, 0x16, 0x19 - ]; - - let mut yoff = xpos + ypos * 256; - let mut coff = CHROMA_OFF + xpos / 2 + ypos / 2 * 256; - let blk = &mut self.buf[self.refs[CUR_BUF]]; - let mut yidx = (xpos / 4 + 1) + NCSTRIDE * (ypos / 4 + 1); - let mut cidx = (xpos / 8 + 1) + NCSTRIDE * (ypos / 8 + 1); - for _y in (0..h).step_by(8) { - for x in (0..w).step_by(8) { - let idx = br.read_gammap()? as usize; - validate!(idx < CBP.len()); - let cbp = CBP[idx]; - for bno in 0..4 { - let cur_yidx = yidx + x / 4 + (bno & 1) + (bno / 2) * NCSTRIDE; - if (cbp & (1 << bno)) != 0 { - let ctx = avg(self.y_ncoeffs[cur_yidx - 1], self.y_ncoeffs[cur_yidx - NCSTRIDE]); - self.y_ncoeffs[cur_yidx] = decode_coeffs(br, &self.codebooks, &self.qmat, ctx, &mut blk[yoff + x + (bno & 1) * 4 + (bno / 2) * 4 * 256..])?; - } else { - self.y_ncoeffs[cur_yidx] = 0; - } - } - if (cbp & 0x10) != 0 { - let ctx = avg(self.c_ncoeffs[cidx + x / 8 - 1], self.c_ncoeffs[cidx + x / 8 - NCSTRIDE]); - let unc = decode_coeffs(br, &self.codebooks, &self.qmat, ctx, &mut blk[coff + x / 2..])?; - let vnc = decode_coeffs(br, &self.codebooks, &self.qmat, ctx, &mut blk[coff + 128 + x / 2..])?; - self.c_ncoeffs[cidx + x / 8] = avg(unc, vnc); - } else { - self.c_ncoeffs[cidx + x / 8] = 0; - } - } - yidx += NCSTRIDE * 2; - cidx += NCSTRIDE; - yoff += 8 * 256; - coff += 4 * 256; - } - Ok(()) - } - fn decode_block(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - let mode = br.read_gammap()?; - let min_dim = w.min(h); - let large_block = min_dim >= 8; - if mode >= 16 && !large_block { - return Err(DecoderError::InvalidData); - } - match mode { - 0 if w > 2 => { - let hw = w / 2; - self.decode_block(br, xpos, ypos, hw, h)?; - self.decode_block(br, xpos + hw, ypos, hw, h)?; - }, - 1 => { self.copy_block(xpos, ypos, w, h, 0)?; }, - 2 if h > 2 => { - let hh = h / 2; - self.decode_block(br, xpos, ypos, w, hh)?; - self.decode_block(br, xpos, ypos + hh, w, hh)?; - }, - 3 => { self.do_mc_bias(br, xpos, ypos, w, h)?; }, - 4 | 5 | 6 => { - let ref_id = (mode - 4) as usize; - self.do_mc(br, xpos, ypos, w, h, ref_id)?; - }, - 7 => { self.pred_plane(br, xpos, ypos, w, h)?; }, - 8 if large_block => { - let hw = w / 2; - self.decode_block(br, xpos, ypos, hw, h)?; - self.decode_block(br, xpos + hw, ypos, hw, h)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 9 => { self.copy_block(xpos, ypos, w, h, 1)?; }, - 10 if large_block => { - self.do_mc_bias(br, xpos, ypos, w, h)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 11 => { - if min_dim >= 4 { - self.intra_pred(br, xpos, ypos, w, h)?; - } - }, - 12 if large_block => { - self.copy_block(xpos, ypos, w, h, 0)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 13 if large_block => { - let hh = h / 2; - self.decode_block(br, xpos, ypos, w, hh)?; - self.decode_block(br, xpos, ypos + hh, w, hh)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 14 => { self.copy_block(xpos, ypos, w, h, 2)?; }, - 15 => { - if min_dim >= 4 { - self.intra_pred4x4(br, xpos, ypos, w, h)?; - } - }, - 16 | 17 | 18 => { - let ref_id = (mode - 16) as usize; - self.do_mc(br, xpos, ypos, w, h, ref_id)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 19 => { - self.intra_pred4x4(br, xpos, ypos, w, h)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 20 => { - self.copy_block(xpos, ypos, w, h, 1)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 21 => { - self.copy_block(xpos, ypos, w, h, 2)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 22 => { - self.intra_pred(br, xpos, ypos, w, h)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - 23 => { - self.pred_plane(br, xpos, ypos, w, h)?; - self.decode_residue(br, xpos, ypos, w, h)?; - }, - _ => return Err(DecoderError::InvalidData), - }; - Ok(()) - } -} - -const QUANTISERS: [u8; 52] = [ - 10, 13, 10, 13, 13, 16, 13, 16, 11, 14, 11, 14, 14, 18, 14, 18, - 13, 16, 13, 16, 16, 20, 16, 20, 14, 18, 14, 18, 18, 23, 18, 23, - 16, 20, 16, 20, 20, 25, 20, 25, 18, 23, 18, 23, 23, 29, 23, 29, - 20, 14, 12, 10 -]; - -impl NADecoder for VXVideoDecoder { - fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { - if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { - self.width = vinfo.get_width(); - self.height = vinfo.get_height(); - validate!(self.width <= 256 && self.height <= 256); - - let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT)); - self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); - - if let Some(edata) = info.get_extradata() { - validate!(edata.len() > 0); - let fps = edata[0] as usize; - validate!(fps <= 60); - let base = &QUANTISERS[(fps % 6) * 8..][..8]; - let scale = fps / 6; - for (dq, iq) in self.qmat.iter_mut().zip(base.iter()) { - *dq = i32::from(*iq) << scale; - } - } else { - return Err(DecoderError::InvalidData); - } - - for frm in self.buf.iter_mut() { - let (ybuf, cbuf) = frm.split_at_mut(CHROMA_OFF); - for el in ybuf.iter_mut() { - *el = 0; - } - for el in cbuf.iter_mut() { - *el = 0x80; - } - } - - Ok(()) - } else { - Err(DecoderError::InvalidData) - } - } - fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { - let src = pkt.get_buffer(); - validate!(src.len() > 4); - - let mut br = BitReader::new(&src[4..], BitReaderMode::LE16MSB); - - self.y_ncoeffs = [0; NCSTRIDE * (256 / 4 + 1)]; - self.c_ncoeffs = [0; NCSTRIDE * (256 / 8 + 1)]; - self.mvs = [MV::default(); 16 * 16]; - self.decode_frame(&mut br)?; - - let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?; - let mut buf = bufinfo.get_vbuf().unwrap(); - let ystride = buf.get_stride(0); - let ustride = buf.get_stride(1); - let vstride = buf.get_stride(2); - let yoff = buf.get_offset(0); - let uoff = buf.get_offset(1); - let voff = buf.get_offset(2); - let data = buf.get_data_mut().unwrap(); - let cur = self.refs[CUR_BUF]; - for (sline, dline) in self.buf[cur][0..].chunks(256).take(self.height).zip(data[yoff..].chunks_mut(ystride)) { - dline[..self.width].copy_from_slice(&sline[..self.width]); - } - for (sline, dline) in self.buf[cur][CHROMA_OFF..].chunks(256).take(self.height / 2).zip(data[uoff..].chunks_mut(ustride)) { - dline[..self.width / 2].copy_from_slice(&sline[..self.width / 2]); - } - for (sline, dline) in self.buf[cur][CHROMA_OFF + 128..].chunks(256).take(self.height / 2).zip(data[voff..].chunks_mut(vstride)) { - dline[..self.width / 2].copy_from_slice(&sline[..self.width / 2]); - } - let videobuf = NABufferType::Video(buf); - self.update_refs(); - - let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), videobuf); - let is_intra = pkt.get_pts() == Some(0); - frm.set_keyframe(is_intra); - frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P }); - Ok(frm.into_ref()) - } - fn flush(&mut self) { - } -} - -impl NAOptionHandler for VXVideoDecoder { - fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } - fn set_options(&mut self, _options: &[NAOption]) { } - fn query_option_value(&self, _name: &str) -> Option { None } -} - - -pub fn get_decoder_video() -> Box { - Box::new(VXVideoDecoder::new()) -} - -fn parse_coeffs(br: &mut BitReader, codebooks: &Codebooks, ctx: u8) -> DecoderResult { - const MAX_LEVEL: [i32; 6] = [ 2, 5, 11, 23, 47, 0x8000 ]; - - let (ncoeffs, nones) = if ctx < 8 { - let sym = br.read_cb(&codebooks.nc_cb[NC_MAP[ctx as usize]])?; - if sym == 0 { - return Ok(0); - } - (sym >> 2, sym & 3) - } else { - let ncoeffs = (br.read(4)? + 1) as u8; - let nones = br.read(2)? as u8; - if ncoeffs < nones { - return Ok(0); - } - (ncoeffs, nones) - }; - let mut num_zero = if ncoeffs == 16 { 0 } else { - br.read_cb(&codebooks.num_zero_cb[ncoeffs as usize - 1])? - }; - validate!(ncoeffs + num_zero <= 16); - let mut level = 0usize; - let mut coef_left = ncoeffs; - let mut ones_left = nones; - while coef_left > 0 { - let _val = if ones_left > 0 { - ones_left -= 1; - if !br.read_bool()? { 1 } else { -1 } - } else { - let prefix = br.read_unary()?; - let val = if prefix < 15 { - (br.read(level as u8)? | (prefix << level)) as i32 - } else { - (br.read(11)? + (15 << level)) as i32 - }; - if val > MAX_LEVEL[level] { - level += 1; - } - if !br.read_bool()? { - val + 1 - } else { - -(val + 1) - } - }; - coef_left -= 1; - if num_zero > 0 && coef_left > 0 { - let run = if num_zero < 7 { - br.read_cb(&codebooks.zero_run_cb[num_zero as usize - 1])? - } else { - if br.peek(3) != 0 { - 7 - (br.read(3)? as u8) - } else { - (br.read_unary()? as u8) + 4 - } - }; - validate!(run <= num_zero); - num_zero -= run; - } - } - Ok(ncoeffs) -} - -#[cfg(feature="demuxer_vx")] -pub struct VXVideoParser { - width: usize, - height: usize, - ipred4x4: [u8; 25], - y_ncoeffs: [u8; NCSTRIDE * (256 / 4 + 1)], - c_ncoeffs: [u8; NCSTRIDE * (256 / 8 + 1)], - codebooks: Codebooks, -} - -#[cfg(feature="demuxer_vx")] -impl VXVideoParser { - pub fn new(width: usize, height: usize) -> Self { - Self { - width, height, - ipred4x4: [9; 25], - y_ncoeffs: [0; NCSTRIDE * (256 / 4 + 1)], - c_ncoeffs: [0; NCSTRIDE * (256 / 8 + 1)], - codebooks: Codebooks::new(), - } - } - pub fn parse_frame(&mut self, src: &[u8]) -> DecoderResult { - let mut br = BitReader::new(src, BitReaderMode::LE16MSB); - self.y_ncoeffs = [0; NCSTRIDE * (256 / 4 + 1)]; - self.c_ncoeffs = [0; NCSTRIDE * (256 / 8 + 1)]; - - for ypos in (0..self.height).step_by(16) { - for xpos in (0..self.width).step_by(16) { - self.parse_block(&mut br, xpos, ypos, 16, 16)?; - } - } - - Ok(br.tell()) - } - fn parse_mc(&mut self, br: &mut BitReader) -> DecoderResult<()> { - let _dx = br.read_gammap_s()? as i8; - let _dy = br.read_gammap_s()? as i8; - Ok(()) - } - fn parse_mc_bias(&mut self, br: &mut BitReader) -> DecoderResult<()> { - let _mx = br.read_gammap_s()? as isize; - let _my = br.read_gammap_s()? as isize; - let _ydelta = br.read_gammap_s()? * 2; - let _udelta = br.read_gammap_s()? * 2; - let _vdelta = br.read_gammap_s()? * 2; - Ok(()) - } - fn parse_plane_pred(&mut self, br: &mut BitReader) -> DecoderResult<()> { - let _ydelta = br.read_gammap_s()? * 2; - let _udelta = br.read_gammap_s()? * 2; - let _vdelta = br.read_gammap_s()? * 2; - Ok(()) - } - fn parse_intra_pred(&mut self, br: &mut BitReader) -> DecoderResult<()> { - let _ymode = br.read_gammap()? as usize; - let _cmode = br.read_gammap()? as usize; - Ok(()) - } - fn parse_intra_pred4x4(&mut self, br: &mut BitReader, w: usize, h: usize) -> DecoderResult<()> { - let mut idx = 6; - for _y in (0..h).step_by(4) { - for _x in (0..w).step_by(4) { - let mut mode = self.ipred4x4[idx - 5].min(self.ipred4x4[idx - 1]); - if mode == 9 { - mode = 2; - } - if !br.read_bool()? { - let mode1 = br.read(3)? as u8; - mode = if mode1 >= mode { mode1 + 1 } else { mode1 }; - } - self.ipred4x4[idx] = mode; - idx += 1; - } - } - let _cmode = br.read_gammap()? as usize; - Ok(()) - } - fn parse_residue(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - const CBP: [u8; 32] = [ - 0x00, 0x08, 0x04, 0x02, 0x01, 0x1F, 0x0F, 0x0A, - 0x05, 0x0C, 0x03, 0x10, 0x0E, 0x0D, 0x0B, 0x07, - 0x09, 0x06, 0x1E, 0x1B, 0x1A, 0x1D, 0x17, 0x15, - 0x18, 0x12, 0x11, 0x1C, 0x14, 0x13, 0x16, 0x19 - ]; - - let mut yidx = (xpos / 4 + 1) + NCSTRIDE * (ypos / 4 + 1); - let mut cidx = (xpos / 8 + 1) + NCSTRIDE * (ypos / 8 + 1); - for _y in (0..h).step_by(8) { - for x in (0..w).step_by(8) { - let idx = br.read_gammap()? as usize; - validate!(idx < CBP.len()); - let cbp = CBP[idx]; - for bno in 0..4 { - let cur_yidx = yidx + x / 4 + (bno & 1) + (bno / 2) * NCSTRIDE; - if (cbp & (1 << bno)) != 0 { - let ctx = avg(self.y_ncoeffs[cur_yidx - 1], self.y_ncoeffs[cur_yidx - NCSTRIDE]); - self.y_ncoeffs[cur_yidx] = parse_coeffs(br, &self.codebooks, ctx)?; - } else { - self.y_ncoeffs[cur_yidx] = 0; - } - } - if (cbp & 0x10) != 0 { - let ctx = avg(self.c_ncoeffs[cidx + x / 8 - 1], self.c_ncoeffs[cidx + x / 8 - NCSTRIDE]); - let unc = parse_coeffs(br, &self.codebooks, ctx)?; - let vnc = parse_coeffs(br, &self.codebooks, ctx)?; - self.c_ncoeffs[cidx + x / 8] = avg(unc, vnc); - } else { - self.c_ncoeffs[cidx + x / 8] = 0; - } - } - yidx += NCSTRIDE * 2; - cidx += NCSTRIDE; - } - Ok(()) - } - fn parse_block(&mut self, br: &mut BitReader, xpos: usize, ypos: usize, w: usize, h: usize) -> DecoderResult<()> { - let mode = br.read_gammap()?; - let min_dim = w.min(h); - let large_block = min_dim >= 8; - if mode >= 16 && !large_block { - return Err(DecoderError::InvalidData); - } - match mode { - 0 if w > 2 => { - let hw = w / 2; - self.parse_block(br, xpos, ypos, hw, h)?; - self.parse_block(br, xpos + hw, ypos, hw, h)?; - }, - 1 => {}, - 2 if h > 2 => { - let hh = h / 2; - self.parse_block(br, xpos, ypos, w, hh)?; - self.parse_block(br, xpos, ypos + hh, w, hh)?; - }, - 3 => { self.parse_mc_bias(br)?; }, - 4 | 5 | 6 => { - self.parse_mc(br)?; - }, - 7 => { self.parse_plane_pred(br)?; }, - 8 if large_block => { - let hw = w / 2; - self.parse_block(br, xpos, ypos, hw, h)?; - self.parse_block(br, xpos + hw, ypos, hw, h)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 9 => {}, - 10 if large_block => { - self.parse_mc_bias(br)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 11 => { - if min_dim >= 4 { - self.parse_intra_pred(br)?; - } - }, - 12 if large_block => { - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 13 if large_block => { - let hh = h / 2; - self.parse_block(br, xpos, ypos, w, hh)?; - self.parse_block(br, xpos, ypos + hh, w, hh)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 14 => {}, - 15 => { - if min_dim >= 4 { - self.parse_intra_pred4x4(br, w, h)?; - } - }, - 16 | 17 | 18 => { - self.parse_mc(br)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 19 => { - self.parse_intra_pred4x4(br, w, h)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 20 => { - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 21 => { - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 22 => { - self.parse_intra_pred(br)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - 23 => { - self.parse_plane_pred(br)?; - self.parse_residue(br, xpos, ypos, w, h)?; - }, - _ => return Err(DecoderError::InvalidData), - }; - Ok(()) - } -} - - -struct AudioState { - lpc0_idx: usize, - lpc1_idx: usize, - lpc2_idx: usize, - scale: i32, - frame_mode: usize, - lpc_coeffs: [i32; 8], - cur_filt: [i32; 8], - prev_filt: [i32; 8], - - pulse_buf: [i32; 128], - pulse_hist: [i32; 256], - lpc_hist: [i32; 8], - - lpc0_cb: [[i16; 8]; 64], - lpc1_cb: [[i16; 8]; 64], - lpc2_cb: [[i16; 8]; 64], - decays: [i32; 8], - base_filt: [i32; 8], - base_scale: i32, -} - -impl AudioState { - fn new() -> Self { - Self { - lpc0_idx: 0, - lpc1_idx: 0, - lpc2_idx: 0, - scale: 0, - frame_mode: 0, - lpc_coeffs: [0; 8], - cur_filt: [0; 8], - prev_filt: [0; 8], - - pulse_buf: [0; 128], - pulse_hist: [0; 256], - lpc_hist: [0; 8], - - lpc0_cb: [[0; 8]; 64], - lpc1_cb: [[0; 8]; 64], - lpc2_cb: [[0; 8]; 64], - decays: [0; 8], - base_filt: [0; 8], - base_scale: 0, - } - } - fn read_initial_params(&mut self, br: &mut ByteReader) -> DecoderResult<()> { - for entry in self.lpc0_cb.iter_mut() { - for el in entry.iter_mut() { - *el = br.read_u16le()? as i16; - } - } - for entry in self.lpc1_cb.iter_mut() { - for el in entry.iter_mut() { - *el = br.read_u16le()? as i16; - } - } - for entry in self.lpc2_cb.iter_mut() { - for el in entry.iter_mut() { - *el = br.read_u16le()? as i16; - } - } - for el in self.decays.iter_mut() { - *el = i32::from(br.read_u16le()? as i16); - } - for el in self.base_filt.iter_mut() { - *el = br.read_u32le()? as i32; - } - self.base_scale = br.read_u32le()? as i32; - Ok(()) - } - fn unpack_data(&mut self, br: &mut ByteReader, val: u16) -> DecoderResult<()> { - self.lpc0_idx = (val & 0x3F) as usize; - self.scale = (self.decays[((val >> 6) & 7) as usize] * self.scale) >> 13; - let val1 = br.read_u16le()?; - self.lpc1_idx = ((val1 >> 6) & 0x3F) as usize; - self.lpc2_idx = (val1 & 0x3F) as usize; - self.frame_mode = ((val1 >> 12) & 3) as usize; - let mut idx = (val1 >> 14) as usize; - if self.frame_mode == 0 { - let mut tail = 0; - for _ in 0..8 { - let val = br.read_u16le()?; - for i in 0..5 { - let add = i32::from((val >> (13 - i * 3)) & 7); - self.pulse_buf[idx] += self.scale * (add * 2 - 7); - idx += 3; - } - tail = tail * 2 + (val & 1); - } - let add = i32::from((tail >> 5) & 7); - self.pulse_buf[idx] += self.scale * (add * 2 - 7); - idx += 3; - let add = i32::from((tail >> 2) & 7); - self.pulse_buf[idx] += self.scale * (add * 2 - 7); - } else { - let (len, step) = match self.frame_mode { - 1 => (5, 3), - 2 => (4, 4), - 3 => (3, 5), - _ => unreachable!(), - }; - for _ in 0..len { - let val = br.read_u16le()?; - for i in 0..8 { - let add = i32::from((val >> (14 - i * 2)) & 3); - self.pulse_buf[idx] += self.scale * (add * 2 - 3); - idx += step; - } - } - } - Ok(()) - } - fn update_lpc_coeffs(&mut self) { - for i in 0..8 { - self.lpc_coeffs[i] += i32::from(self.lpc0_cb[self.lpc0_idx][i]); - self.lpc_coeffs[i] += i32::from(self.lpc1_cb[self.lpc1_idx][i]); - self.lpc_coeffs[i] += i32::from(self.lpc2_cb[self.lpc2_idx][i]); - } - - let mut tmp = [0; 8]; - - self.cur_filt = self.lpc_coeffs; - for i in 0..4 { - self.cur_filt.swap(i, 7 - i); - } - for len in 1..8 { - let scale = self.cur_filt[len]; - for (prod, &val) in tmp.iter_mut().zip(self.cur_filt.iter()).take(len) { - //*prod = (val * scale) >> 15; - *prod = val.wrapping_mul(scale) >> 15; - } - for (dst, &add) in self.cur_filt.iter_mut().zip(tmp[..len].iter()) { - *dst += add; - } - } - - for el in self.cur_filt.iter_mut() { - *el = -(*el >> 1); - } - } - fn decode_intra(&mut self, br: &mut ByteReader, val: u16, out: &mut [i32; 128]) -> DecoderResult<()> { - self.scale = self.base_scale; - self.lpc_hist = [0; 8]; - - for el in self.pulse_buf.iter_mut() { - *el = 0; - } - self.unpack_data(br, val)?; - - self.lpc_coeffs = self.base_filt; - self.update_lpc_coeffs(); - - apply_lpc(out, &self.pulse_buf, &mut self.lpc_hist, &self.cur_filt); - Ok(()) - } - #[allow(clippy::needless_range_loop)] - fn decode_inter(&mut self, br: &mut ByteReader, val: u16, mode: u16, out: &mut [i32; 128]) -> DecoderResult<()> { - let (part0, part1) = self.pulse_hist.split_at_mut(128); - part0.copy_from_slice(part1); - part1.copy_from_slice(&self.pulse_buf); - self.prev_filt = self.cur_filt; - - if mode == 0x7E { - for el in self.pulse_buf.iter_mut() { - *el = 0; - } - } else { - let src = &self.pulse_hist[127 - (mode as usize)..]; - let (src_head, body) = src.split_at(7); - let (src_body, src_tail) = body.split_at(128 - 7 * 2); - - let (dst_head, body) = self.pulse_buf.split_at_mut(7); - let (dst_body, dst_tail) = body.split_at_mut(128 - 7 * 2); - - for (i, (dst, &src)) in dst_head.iter_mut().zip(src_head.iter()).enumerate() { - *dst = (src * ((i + 1) as i32)) >> 4; - } - for (dst, &src) in dst_body.iter_mut().zip(src_body.iter()) { - *dst = src >> 1; - } - for (i, (dst, &src)) in dst_tail.iter_mut().zip(src_tail.iter()).enumerate() { - *dst = (src * ((7 - i) as i32)) >> 4; - } - } - - self.unpack_data(br, val)?; - self.update_lpc_coeffs(); - - let mut filters = [[0; 8]; 4]; - filters[3] = self.cur_filt; - let prev_filter = &self.prev_filt; - for i in 0..8 { - filters[1][i] = (prev_filter[i] + filters[3][i]) >> 1; - filters[0][i] = (prev_filter[i] + filters[1][i]) >> 1; - filters[2][i] = (filters[1][i] + filters[3][i]) >> 1; - } - for ((dst, src), filter) in out.chunks_exact_mut(32) - .zip(self.pulse_buf.chunks_exact(32)).zip(filters.iter()) { - apply_lpc(dst, src, &mut self.lpc_hist, filter); - } - Ok(()) - } -} - -fn apply_lpc(dst: &mut [i32], src: &[i32], hist: &mut [i32; 8], filt: &[i32; 8]) { - for (hidx, (out, src)) in dst.iter_mut().zip(src.iter()).enumerate() { - let mut sum = *src << 14; - for i in 0..8 { - //sum += hist[(hidx + i) & 7] * filt[i]; - sum = sum.wrapping_add(hist[(hidx + i) & 7].wrapping_mul(filt[i])); - } - let samp = sum >> 14; - *out = samp; - hist[hidx & 7] = samp; - } -} - -struct VXAudioDecoder { - ainfo: NAAudioInfo, - info: Arc, - chmap: NAChannelMap, - state: [AudioState; 2], - buf: [i32; 128], -} - -impl VXAudioDecoder { - fn new() -> Self { - Self { - ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), - info: NACodecInfo::new_dummy(), - chmap: NAChannelMap::new(), - state: [AudioState::new(), AudioState::new()], - buf: [0; 128], - } - } - fn output(&mut self, dst: &mut [i16]) { - for (dst, &src) in dst.iter_mut().zip(self.buf.iter()) { - *dst = src.max(-0x8000).min(0x7FFF) as i16; - } - } -} - -impl NADecoder for VXAudioDecoder { - fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { - if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { - if ainfo.channels != 1 && ainfo.channels != 2 { - return Err(DecoderError::NotImplemented); - } - if let Some(edata) = info.get_extradata() { - validate!(edata.len() == usize::from(ainfo.channels) * 3124); - let mut mr = MemoryReader::new_read(edata.as_slice()); - let mut br = ByteReader::new(&mut mr); - for state in self.state.iter_mut().take(usize::from(ainfo.channels)) { - state.read_initial_params(&mut br)?; - } - } else { - return Err(DecoderError::InvalidData); - } - self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.channels, SND_S16P_FORMAT, 128); - self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo)); - self.chmap = NAChannelMap::from_str(if ainfo.channels == 1 { "C" } else { "L,R" }).unwrap(); - Ok(()) - } else { - Err(DecoderError::InvalidData) - } - } - fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { - let info = pkt.get_stream().get_info(); - if let NACodecTypeInfo::Audio(_) = info.get_properties() { - let pktbuf = pkt.get_buffer(); - validate!(pktbuf.len() >= 10); - - let mut mr = MemoryReader::new_read(&pktbuf); - let mut br = ByteReader::new(&mut mr); - let nblocks = br.read_u16le()? as usize; - validate!(nblocks > 0); - - let samples = 128 * nblocks; - let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?; - let stride = abuf.get_audio_stride(); - let mut adata = abuf.get_abuf_i16().unwrap(); - let dst = adata.get_data_mut().unwrap(); - - if self.ainfo.channels == 1 { - for blk in dst.chunks_exact_mut(128) { - let val = br.read_u16le()?; - if val == 0x00 { continue; } - let mode = val >> 9; - if mode == 0x7F { - self.state[0].decode_intra(&mut br, val, &mut self.buf)?; - } else { - self.state[0].decode_inter(&mut br, val & 0x1FF, mode, &mut self.buf)?; - } - self.output(blk); - } - } else { - let (l, r) = dst.split_at_mut(stride); - for (lblk, rblk) in l.chunks_exact_mut(128).zip(r.chunks_exact_mut(128)) { - let val = br.read_u16le()?; - if val == 0x00 { continue; } - let mode = val >> 9; - if mode == 0x7F { - self.state[0].decode_intra(&mut br, val, &mut self.buf)?; - } else { - self.state[0].decode_inter(&mut br, val & 0x1FF, mode, &mut self.buf)?; - } - self.output(lblk); - let val = br.read_u16le()?; - if val == 0x00 { continue; } - let mode = val >> 9; - if mode == 0x7F { - self.state[1].decode_intra(&mut br, val, &mut self.buf)?; - } else { - self.state[1].decode_inter(&mut br, val & 0x1FF, mode, &mut self.buf)?; - } - self.output(rblk); - } - } - - let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf); - frm.set_duration(Some(samples as u64)); - frm.set_keyframe(true); - Ok(frm.into_ref()) - } else { - Err(DecoderError::InvalidData) - } - } - fn flush(&mut self) { - } -} - - -impl NAOptionHandler for VXAudioDecoder { - fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } - fn set_options(&mut self, _options: &[NAOption]) { } - fn query_option_value(&self, _name: &str) -> Option { None } -} - - -pub fn get_decoder_audio() -> Box { - Box::new(VXAudioDecoder::new()) -} - -#[cfg(test)] -mod test { - use nihav_core::codecs::RegisteredDecoders; - use nihav_core::demuxers::RegisteredDemuxers; - use nihav_codec_support::test::dec_video::*; - use crate::game_register_all_decoders; - use crate::game_register_all_demuxers; - #[test] - fn test_vx_video() { - let mut dmx_reg = RegisteredDemuxers::new(); - game_register_all_demuxers(&mut dmx_reg); - let mut dec_reg = RegisteredDecoders::new(); - game_register_all_decoders(&mut dec_reg); - - // sample from some game - test_decoding("vx", "vxvideo", "assets/Game/bioware.vx", Some(31), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5Frames(vec![ - [0x33de14fa, 0x00948eb7, 0x028141d7, 0x1d07abd6], - [0x77a96135, 0x0cc2d0b5, 0x45862c7c, 0xe27f5b10], - [0x3c3ed089, 0x3c643216, 0xe6aed381, 0x4d43c50f], - [0x09e86330, 0x37d3a766, 0xa8198ac5, 0x21fa089c], - [0xbcab34d7, 0xdffe234a, 0x6534709f, 0xc3050e32], - [0x2bab595d, 0x7a19937e, 0xccc97277, 0x91b32191], - [0xe082f77e, 0x6498fd0d, 0xa3828c0f, 0xb4f7a02a], - [0x8515f6e2, 0xc0cb8ab3, 0xf91a3483, 0xd54470fc], - [0x17b1b54a, 0x1b574323, 0xcdeec1ec, 0x7a00ae4e], - [0x773f1d47, 0x86188681, 0xb111bcb8, 0x80fe34e9], - [0xbc4a8e20, 0xca91d4b6, 0x7275a162, 0x9a73be7c], - [0x0d4992b5, 0xd12a985a, 0x929ebec2, 0x0653fbc7], - [0xc24691b7, 0xabd27a7a, 0xd62cbd73, 0xd72a49ea], - [0x9024f7f4, 0xbe707e73, 0x27b4b4a0, 0x33bb515e], - [0x31aee8fc, 0xd0a3fa6d, 0xea11ef6a, 0x53a5f031], - [0x4a83f326, 0xceff4329, 0x54fbe91e, 0xf98ee74b], - [0xe54b5450, 0x979f4b26, 0x910ee666, 0x05fd1996], - [0xe48d66d0, 0x0a69b963, 0x9917084e, 0xf4b0486d], - [0x624a8b32, 0x0d1ce036, 0x9de8ebf0, 0x472a77b9], - [0x5d307d48, 0x1168f3a9, 0xaa792fb2, 0x34430b20], - [0xf2d80474, 0xac6b0972, 0x500e569e, 0x3c8e7dde], - [0x481310b3, 0x70cdeb91, 0xed007972, 0x70cefff3], - [0x8b5b17ca, 0xca6f9a72, 0x0256908a, 0x4505cf85], - [0xb6222c1d, 0x7a9760cb, 0xb3276304, 0x2ff1595e], - [0xf98e3d89, 0xae957c83, 0xff849c05, 0x8ca54276], - [0xbcebda1c, 0x6f6e4ac6, 0x023e7f0f, 0x9578142f], - [0x399f5155, 0xd95b33e3, 0xf0b55af8, 0xe32db6b2], - [0x0c4d4347, 0x5f5061e4, 0xe2fa4690, 0xa340d294], - [0x6fcdddb5, 0xf101da80, 0x6f55ddd9, 0x0dfeead1], - [0xb9623043, 0x1dab8a93, 0x22fd5f7a, 0x2c2a6633], - [0xb3ac2652, 0xf474e49d, 0x7db51405, 0xcd1c13cc], - [0x6a901339, 0xda88b2be, 0x6d943e18, 0xda9b5926]])); - } - #[test] - fn test_vx_audio() { - let mut dmx_reg = RegisteredDemuxers::new(); - game_register_all_demuxers(&mut dmx_reg); - let mut dec_reg = RegisteredDecoders::new(); - game_register_all_decoders(&mut dec_reg); - - // sample from some game - test_decoding("vx", "vxaudio", "assets/Game/bioware.vx", Some(100), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5([0xf149848a, 0xd80054d2, 0x278535ff, 0x956ebed7])); - } -} - -const NC_MAP: [usize; 8] = [ 0, 0, 1, 1, 2, 2, 2, 2 ]; -const NC_BITS: [[u16; 68]; 3] = [ - [ - 0x0001, 0x0000, 0x0000, 0x0000, 0x0005, 0x0001, 0x0000, 0x0000, - 0x0007, 0x0004, 0x0001, 0x0000, 0x0007, 0x0006, 0x0005, 0x0003, - 0x0007, 0x0006, 0x0005, 0x0003, 0x0007, 0x0006, 0x0005, 0x0004, - 0x000F, 0x0006, 0x0005, 0x0004, 0x000B, 0x000E, 0x0005, 0x0004, - 0x0008, 0x000A, 0x000D, 0x0004, 0x000F, 0x000E, 0x0009, 0x0004, - 0x000B, 0x000A, 0x000D, 0x000C, 0x000F, 0x000E, 0x0009, 0x000C, - 0x000B, 0x000A, 0x000D, 0x0008, 0x000F, 0x0001, 0x0009, 0x000C, - 0x000B, 0x000E, 0x000D, 0x0008, 0x0007, 0x000A, 0x0009, 0x000C, - 0x0004, 0x0006, 0x0005, 0x0008 - ], [ - 0x0003, 0x0000, 0x0000, 0x0000, 0x000B, 0x0002, 0x0000, 0x0000, - 0x0007, 0x0007, 0x0003, 0x0000, 0x0007, 0x000A, 0x0009, 0x0005, - 0x0007, 0x0006, 0x0005, 0x0004, 0x0004, 0x0006, 0x0005, 0x0006, - 0x0007, 0x0006, 0x0005, 0x0008, 0x000F, 0x0006, 0x0005, 0x0004, - 0x000B, 0x000E, 0x000D, 0x0004, 0x000F, 0x000A, 0x0009, 0x0004, - 0x000B, 0x000E, 0x000D, 0x000C, 0x0008, 0x000A, 0x0009, 0x0008, - 0x000F, 0x000E, 0x000D, 0x000C, 0x000B, 0x000A, 0x0009, 0x000C, - 0x0007, 0x000B, 0x0006, 0x0008, 0x0009, 0x0008, 0x000A, 0x0001, - 0x0007, 0x0006, 0x0005, 0x0004 - ], [ - 0x000F, 0x0000, 0x0000, 0x0000, 0x000F, 0x000E, 0x0000, 0x0000, - 0x000B, 0x000F, 0x000D, 0x0000, 0x0008, 0x000C, 0x000E, 0x000C, - 0x000F, 0x000A, 0x000B, 0x000B, 0x000B, 0x0008, 0x0009, 0x000A, - 0x0009, 0x000E, 0x000D, 0x0009, 0x0008, 0x000A, 0x0009, 0x0008, - 0x000F, 0x000E, 0x000D, 0x000D, 0x000B, 0x000E, 0x000A, 0x000C, - 0x000F, 0x000A, 0x000D, 0x000C, 0x000B, 0x000E, 0x0009, 0x000C, - 0x0008, 0x000A, 0x000D, 0x0008, 0x000D, 0x0007, 0x0009, 0x000C, - 0x0009, 0x000C, 0x000B, 0x000A, 0x0005, 0x0008, 0x0007, 0x0006, - 0x0001, 0x0004, 0x0003, 0x0002 - ] -]; -const NC_LENS: [[u8; 68]; 3] = [ - [ - 1, 0, 0, 0, 6, 2, 0, 0, - 8, 6, 3, 0, 9, 8, 7, 5, - 10, 9, 8, 6, 11, 10, 9, 7, - 13, 11, 10, 8, 13, 13, 11, 9, - 13, 13, 13, 10, 14, 14, 13, 11, - 14, 14, 14, 13, 15, 15, 14, 14, - 15, 15, 15, 14, 16, 15, 15, 15, - 16, 16, 16, 15, 16, 16, 16, 16, - 16, 16, 16, 16 - ], [ - 2, 0, 0, 0, 6, 2, 0, 0, - 6, 5, 3, 0, 7, 6, 6, 4, - 8, 6, 6, 4, 8, 7, 7, 5, - 9, 8, 8, 6, 11, 9, 9, 6, - 11, 11, 11, 7, 12, 11, 11, 9, - 12, 12, 12, 11, 12, 12, 12, 11, - 13, 13, 13, 12, 13, 13, 13, 13, - 13, 14, 13, 13, 14, 14, 14, 13, - 14, 14, 14, 14 - ], [ - 4, 0, 0, 0, 6, 4, 0, 0, - 6, 5, 4, 0, 6, 5, 5, 4, - 7, 5, 5, 4, 7, 5, 5, 4, - 7, 6, 6, 4, 7, 6, 6, 4, - 8, 7, 7, 5, 8, 8, 7, 6, - 9, 8, 8, 7, 9, 9, 8, 8, - 9, 9, 9, 8, 10, 9, 9, 9, - 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10 - ] -]; - -const NUM_ZERO_BITS: [[u8; 16]; 15] = [ - [ - 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x01 - ], [ - 0x07, 0x06, 0x05, 0x04, 0x03, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x00 - ], [ - 0x05, 0x07, 0x06, 0x05, 0x04, 0x03, 0x04, 0x03, 0x02, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00 - ], [ - 0x03, 0x07, 0x05, 0x04, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x05, 0x04, 0x03, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x01, 0x01, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x01, 0x01, 0x05, 0x04, 0x03, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x01, 0x01, 0x01, 0x03, 0x03, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x01, 0x00, 0x01, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x00, 0x01, 0x01, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ], [ - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ] -]; -const NUM_ZERO_LENS: [[u8; 16]; 15] = [ - [ 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9 ], - [ 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 0 ], - [ 4, 3, 3, 3, 4, 4, 3, 3, 4, 5, 5, 6, 5, 6, 0, 0 ], - [ 5, 3, 4, 4, 3, 3, 3, 4, 3, 4, 5, 5, 5, 0, 0, 0 ], - [ 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 4, 5, 0, 0, 0, 0 ], - [ 6, 5, 3, 3, 3, 3, 3, 3, 4, 3, 6, 0, 0, 0, 0, 0 ], - [ 6, 5, 3, 3, 3, 2, 3, 4, 3, 6, 0, 0, 0, 0, 0, 0 ], - [ 6, 4, 5, 3, 2, 2, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0 ], - [ 6, 6, 4, 2, 2, 3, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 ], - [ 5, 5, 3, 2, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - [ 4, 4, 3, 3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - [ 4, 4, 2, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - [ 3, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - [ 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], - [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] -]; - -const ZERO_RUN_BITS: [[u8; 8]; 6] = [ - [ 1, 0, 0, 0, 0, 0, 0, 0 ], - [ 1, 1, 0, 0, 0, 0, 0, 0 ], - [ 3, 2, 1, 0, 0, 0, 0, 0 ], - [ 3, 2, 1, 1, 0, 0, 0, 0 ], - [ 3, 2, 3, 2, 1, 0, 0, 0 ], - [ 3, 0, 1, 3, 2, 5, 4, 0 ] -]; -const ZERO_RUN_LENS: [[u8; 8]; 6] = [ - [ 1, 1, 0, 0, 0, 0, 0, 0 ], - [ 1, 2, 2, 0, 0, 0, 0, 0 ], - [ 2, 2, 2, 2, 0, 0, 0, 0 ], - [ 2, 2, 2, 3, 3, 0, 0, 0 ], - [ 2, 2, 3, 3, 3, 3, 0, 0 ], - [ 2, 3, 3, 3, 3, 3, 3, 0 ] -]; - diff --git a/nihav-game/src/demuxers/mod.rs b/nihav-game/src/demuxers/mod.rs index 2fe9dd4..1fa4cef 100644 --- a/nihav-game/src/demuxers/mod.rs +++ b/nihav-game/src/demuxers/mod.rs @@ -27,8 +27,6 @@ mod siff; mod smush; #[cfg(feature="demuxer_vmd")] mod vmd; -#[cfg(feature="demuxer_vx")] -mod vx; const GAME_DEMUXERS: &[&dyn DemuxerCreator] = &[ #[cfg(feature="demuxer_bmv")] @@ -53,8 +51,6 @@ const GAME_DEMUXERS: &[&dyn DemuxerCreator] = &[ &smush::MCMPDemuxerCreator {}, #[cfg(feature="demuxer_vmd")] &vmd::VMDDemuxerCreator {}, -#[cfg(feature="demuxer_vx")] - &vx::VXDemuxerCreator {}, ]; /// Registers all available demuxers provided by this crate. diff --git a/nihav-game/src/demuxers/vx.rs b/nihav-game/src/demuxers/vx.rs deleted file mode 100644 index f46597e..0000000 --- a/nihav-game/src/demuxers/vx.rs +++ /dev/null @@ -1,269 +0,0 @@ -use nihav_core::frame::*; -use nihav_core::demuxers::*; -use std::io::SeekFrom; - -#[cfg(feature="decoder_vx")] -use super::super::codecs::vx::VXVideoParser; - -const AUDIO_EXTRADATA_LEN: usize = 3124; - -struct VXDemuxer<'a> { - src: &'a mut ByteReader<'a>, - vid_id: usize, - aud_id: usize, - fps: u32, - video_pos: u64, - vno: u64, - num_vfrm: u64, - num_aud: usize, - ano: u64, - num_afrm: u64, - seektab: Vec<(u32, u32)>, - #[cfg(feature="decoder_vx")] - parser: Option, - parse: bool, - apkt: Option, -} - -impl<'a> DemuxCore<'a> for VXDemuxer<'a> { - fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> { - let src = &mut self.src; - - let mut magic = [0u8; 4]; - src.read_buf(&mut magic)?; - validate!(&magic == b"VXDS"); - let nframes = src.read_u32le()? as usize; - let width = src.read_u32le()? as usize; - let height = src.read_u32le()? as usize; - let fps = src.read_u32le()?; - validate!(fps > (1 << 16) && fps < (100 << 16)); - let quant = src.read_u32le()?; - validate!(quant > 0 && quant < 256); - let srate = src.read_u32le()?; - let num_audio_tracks = src.read_u32le()? as usize; - let _max_frame_size = src.read_u32le()? as usize; - let audio_off = src.read_u32le()? as u64; - validate!(audio_off == 0 || audio_off >= 0x30); - let vinfo_off = src.read_u32le()? as u64; - validate!(vinfo_off == 0 || vinfo_off >= 0x30); - let num_keypos = src.read_u32le()? as usize; - - let vhdr = NAVideoInfo::new(width, height, false, YUV420_FORMAT); - let vci = NACodecTypeInfo::Video(vhdr); - let edata = vec![quant as u8, 0, 0, 0]; - let vinfo = NACodecInfo::new("vxvideo", vci, Some(edata)); - self.vid_id = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 65536, fps, nframes as u64)).unwrap(); - - if num_audio_tracks != 0 && self.parse { - validate!(audio_off + ((num_audio_tracks * AUDIO_EXTRADATA_LEN) as u64) == vinfo_off); - src.seek(SeekFrom::Start(audio_off))?; - let mut edata = vec![0u8; AUDIO_EXTRADATA_LEN * num_audio_tracks]; - src.read_buf(edata.as_mut_slice())?; - let ahdr = NAAudioInfo::new(srate, num_audio_tracks as u8, SND_S16P_FORMAT, 1); - let ainfo = NACodecInfo::new("vxaudio", NACodecTypeInfo::Audio(ahdr), Some(edata)); - self.aud_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 128, srate, 0)).unwrap(); - self.num_afrm = nframes as u64; - self.ano = 0; - self.num_aud = num_audio_tracks; - } else { - self.aud_id = self.vid_id + 1; - } - - if num_keypos > 0 { - src.seek(SeekFrom::Start(vinfo_off))?; - let mut last_frame = src.read_u32le()?; - let mut last_offset = src.read_u32le()?; - validate!(last_frame == 0 && last_offset == 0x30); - self.seektab.clear(); - self.seektab.push((last_frame, last_offset)); - for _ in 1..num_keypos { - let frameno = src.read_u32le()?; - let offset = src.read_u32le()?; - validate!(frameno > last_frame && offset > last_offset); - self.seektab.push((frameno, offset)); - last_frame = frameno; - last_offset = offset; - } - } - - #[cfg(not(feature="decoder_vx"))] - if self.parse == true { - println!("Frame parsing is not enabled in this build"); - } - - #[cfg(feature="decoder_vx")] - if self.parse { - self.parser = Some(VXVideoParser::new(width, height)); - } - - self.fps = fps; - self.video_pos = 0x30; - self.vno = 0; - self.num_vfrm = nframes as u64; - Ok(()) - } - - fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { - if self.apkt.is_some() { - let mut ret = None; - std::mem::swap(&mut self.apkt, &mut ret); - return Ok(ret.unwrap()); - } - if self.vno >= self.num_vfrm { return Err(DemuxerError::EOF); } - self.src.seek(SeekFrom::Start(self.video_pos))?; - let stream = strmgr.get_stream(self.vid_id); - if stream.is_none() { return Err(DemuxerError::InvalidData); } - let stream = stream.unwrap(); - let ts = stream.make_ts(Some(self.vno), None, None); - let size = self.src.read_u16le()? as usize; - validate!(size > 2); - let num_achunks = self.src.read_u16le()?; - let fsize = size - 2; - let mut buf = vec![0; fsize + 4]; - write_u32le(&mut buf, (fsize * 8) as u32)?; - self.src.read_buf(&mut buf[4..])?; - #[cfg(feature="decoder_vx")] - if self.num_aud > 0 { - if let Some(ref mut parser) = self.parser { - if let Ok(nbits) = parser.parse_frame(&buf[4..]) { - write_u32le(&mut buf, nbits as u32)?; - let vpart_size = 4 + ((nbits + 15) & !15) / 8; - - if let Some(astream) = strmgr.get_stream(self.aud_id) { - let mut audio = vec![0; buf.len() - vpart_size + 2]; - write_u16le(&mut audio, num_achunks)?; - audio[2..].copy_from_slice(&buf[vpart_size..]); - let ts_audio = astream.make_ts(Some(self.ano), None, None); - self.apkt = Some(NAPacket::new(astream, ts_audio, true, audio)); - self.ano += u64::from(num_achunks); - } - - buf.truncate(vpart_size); - } else { - println!("failed to parse video frame size, corrupted frame?"); - } - } - } - let keyframe = self.vno == 0 || - self.seektab.binary_search_by_key(&self.vno, |&(frm, _)| u64::from(frm)).is_ok(); - let pkt = NAPacket::new(stream, ts, keyframe, buf); - self.video_pos = self.src.tell(); - self.vno += 1; - Ok(pkt) - } - - fn seek(&mut self, time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> { - if self.seektab.len() < 2 { - Err(DemuxerError::NotPossible) - } else { - let fno = match time { - NATimePoint::Milliseconds(ms) => { - NATimeInfo::time_to_ts(ms, 1000, 65536, self.fps) - }, - NATimePoint::PTS(ts) => ts, - NATimePoint::None => return Err(DemuxerError::NotPossible) - }; - if fno >= self.num_vfrm { - return Err(DemuxerError::SeekError); - } - let idx = match self.seektab.binary_search_by_key(&fno, |&(frm, _)| u64::from(frm)) { - Ok(val) => val, - Err(val) => val - 1, - }; - self.vno = u64::from(self.seektab[idx].0); - self.video_pos = u64::from(self.seektab[idx].1); - Ok(()) - } - } - - fn get_duration(&self) -> u64 { 0 } -} - -const PARSE_FRAMES_OPT: &str = "parse_frames"; -const DEMUXER_OPTS: &[NAOptionDefinition] = &[ - NAOptionDefinition { - name: PARSE_FRAMES_OPT, - description: "parse frames to split them into video and audio parts", - opt_type: NAOptionDefinitionType::Bool }, -]; - -impl<'a> NAOptionHandler for VXDemuxer<'a> { - fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTS } - fn set_options(&mut self, options: &[NAOption]) { - for option in options.iter() { - for opt_def in DEMUXER_OPTS.iter() { - if opt_def.check(option).is_ok() { - if let (PARSE_FRAMES_OPT, NAValue::Bool(ref bval)) = (option.name, &option.value) { - self.parse = *bval; - } - } - } - } - } - fn query_option_value(&self, name: &str) -> Option { - match name { - PARSE_FRAMES_OPT => Some(NAValue::Bool(self.parse)), - _ => None, - } - } -} - -impl<'a> VXDemuxer<'a> { - fn new(io: &'a mut ByteReader<'a>) -> Self { - Self { - vid_id: 0, - aud_id: 0, - fps: 0, - video_pos: 0, - num_aud: 0, - vno: 0, - ano: 0, - num_vfrm: 0, - num_afrm: 0, - src: io, - seektab: Vec::new(), - #[cfg(feature="decoder_vx")] - parser: None, - parse: true, - apkt: None, - } - } -} - -pub struct VXDemuxerCreator { } - -impl DemuxerCreator for VXDemuxerCreator { - fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { - Box::new(VXDemuxer::new(br)) - } - fn get_name(&self) -> &'static str { "vx" } -} - -#[cfg(test)] -mod test { - use super::*; - use std::fs::File; - - #[test] - fn test_vx_demux() { - // sample from some game - let mut file = File::open("assets/Game/bioware.vx").unwrap(); - //let mut file = File::open("assets/Game/BS_01_Intro.vx").unwrap(); - //let mut file = File::open("assets/Game/sega.vx").unwrap(); - let mut fr = FileReader::new_read(&mut file); - let mut br = ByteReader::new(&mut fr); - let mut dmx = VXDemuxer::new(&mut br); - let mut sm = StreamManager::new(); - let mut si = SeekIndex::new(); - dmx.open(&mut sm, &mut si).unwrap(); - loop { - let pktres = dmx.get_frame(&mut sm); - if let Err(e) = pktres { - if (e as i32) == (DemuxerError::EOF as i32) { break; } - panic!("error"); - } - let pkt = pktres.unwrap(); - println!("Got {}", pkt); - } - } -} -- 2.39.5