From: Kostya Shishkov Date: Sat, 30 Nov 2024 15:43:56 +0000 (+0100) Subject: remove Legend Entertainment Q format support X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=a1c3716e99542462aa3db6d71645bf32dd24a4db;p=nihav.git remove Legend Entertainment Q format support It has been moved to na_game_tool. --- diff --git a/nihav-game/Cargo.toml b/nihav-game/Cargo.toml index d7e66e5..c32f7e2 100644 --- a/nihav-game/Cargo.toml +++ b/nihav-game/Cargo.toml @@ -18,14 +18,13 @@ 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_q", "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_vx"] demuxer_bmv = ["demuxers"] demuxer_bmv3 = ["demuxers"] demuxer_cnm = ["demuxers"] demuxer_fcmp = ["demuxers"] demuxer_fst = ["demuxers"] demuxer_gdv = ["demuxers"] -demuxer_q = ["demuxers"] demuxer_seq = ["demuxers"] demuxer_sga = ["demuxers"] demuxer_siff = ["demuxers"] @@ -36,7 +35,7 @@ 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_q", "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_vx"] decoder_beam_fcp = ["decoders"] decoder_beam_vbv = ["decoders"] decoder_bmv = ["decoders"] @@ -47,7 +46,6 @@ decoder_ipma = ["decoders"] decoder_kmvc = ["decoders"] decoder_midivid = ["decoders"] decoder_midivid3 = ["decoders"] -decoder_q = ["decoders"] decoder_seq = ["decoders"] decoder_sga = ["decoders"] decoder_smush_video = ["decoders"] diff --git a/nihav-game/src/codecs/mod.rs b/nihav-game/src/codecs/mod.rs index 0614707..d29311f 100644 --- a/nihav-game/src/codecs/mod.rs +++ b/nihav-game/src/codecs/mod.rs @@ -31,8 +31,6 @@ pub mod lhst500f22; pub mod midivid; #[cfg(feature="decoder_midivid3")] pub mod midivid3; -#[cfg(feature="decoder_q")] -pub mod q; #[cfg(feature="decoder_seq")] pub mod seq; #[cfg(feature="decoder_sga")] @@ -74,8 +72,6 @@ const GAME_CODECS: &[DecoderInfo] = &[ DecoderInfo { name: "ipma2", get_decoder: ipma::get_decoder_v2 }, #[cfg(feature="decoder_kmvc")] DecoderInfo { name: "kmvc", get_decoder: kmvc::get_decoder }, -#[cfg(feature="decoder_q")] - DecoderInfo { name: "legend-q-video", get_decoder: q::get_decoder }, #[cfg(feature="decoder_seq")] DecoderInfo { name: "seq-video", get_decoder: seq::get_decoder }, #[cfg(feature="decoder_sga")] diff --git a/nihav-game/src/codecs/q.rs b/nihav-game/src/codecs/q.rs deleted file mode 100644 index 610370f..0000000 --- a/nihav-game/src/codecs/q.rs +++ /dev/null @@ -1,1157 +0,0 @@ -use nihav_core::frame::*; -use nihav_core::codecs::*; -use nihav_core::io::byteio::*; - -#[derive(Clone,Copy,Debug,PartialEq)] -enum TileMode { - Start, - Fill, - ShortPattern(u8, u8), - LongPattern(u8, u8), - Run, - Reuse, - FB, - MV(isize), - Absolute(usize), - Forward(u16), - Backward(u16), - Skip, -} - -struct QVideoDecoder { - info: NACodecInfoRef, - pal: [u8; 768], - frame: Vec, - w: usize, - h: usize, - tile_w: usize, - tile_h: usize, - tile_off: Vec, - mode: u8, - patterns: [u16; 128], - version: u8, - version2: u8, - f8_cache: [[u8; 16]; 240], -} - -macro_rules! copy_tile { - ($self: expr, $doff: expr, $soff: expr) => { - let mut doff = $doff; - let mut soff = $soff; - for _y in 0..$self.tile_h { - for x in 0..$self.tile_w { - $self.frame[doff + x] = $self.frame[soff + x]; - } - doff += $self.w; - soff += $self.w; - } - } -} - -impl QVideoDecoder { - fn new() -> Self { - QVideoDecoder { - info: NACodecInfoRef::default(), - pal: [0; 768], - frame: Vec::new(), - w: 0, - h: 0, - tile_off: Vec::new(), - mode: 0, - tile_w: 0, - tile_h: 0, - patterns: [0; 128], - version: 0, - version2: 0, - f8_cache: [[0; 16]; 240], - } - } - - fn decode_mode7_tile(dst: &mut [u8], stride: usize, br: &mut ByteReader) -> DecoderResult<()> { - let op = br.peek_byte()?; - if op < 0xF8 { - for dline in dst.chunks_mut(stride).take(4) { - br.read_buf(&mut dline[..4])?; - } - } else if op == 0xF8 || op == 0xFF { - br.read_byte()?; - } else { - br.read_byte()?; - let mut clr = [0; 8]; - let nclr = (op - 0xF6) as usize; - if nclr <= 4 { - let mut pattern = br.read_u32le()?; - br.read_buf(&mut clr[..nclr])?; - for dline in dst.chunks_mut(stride).take(4) { - for el in dline[..4].iter_mut() { - *el = clr[(pattern & 3) as usize]; - pattern >>= 2; - } - } - } else { - let mut pattern = br.read_u24le()?; - let pattern2 = br.read_u24le()?; - br.read_buf(&mut clr[..nclr])?; - for (y, dline) in dst.chunks_mut(stride).take(4).enumerate() { - for el in dline[..4].iter_mut() { - *el = clr[(pattern & 7) as usize]; - pattern >>= 3; - } - if y == 1 { - pattern = pattern2; - } - } - } - } - Ok(()) - } - - fn decode_frame_v3_0(&mut self, br: &mut ByteReader, _ctype: u16) -> DecoderResult<()> { - let mut titer = self.tile_off.iter().enumerate(); - let mut skip_mode = false; - while let Some((tile_no, &tile_off)) = titer.next() { - let op = br.read_byte()?; - if op < 0xF8 { - let clr0 = op; - let clr1 = br.read_byte()?; - if clr0 == clr1 { - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr0; - } - } - } else { - let mut pattern = br.read_u16le()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - } - } else { - match op { - 0xF8 => { - unimplemented!(); - }, - 0xF9 => { - let run = br.read_byte()? as usize; - validate!(run > 0); - - validate!(tile_no > 0); - let mut tile_off = tile_off; - for i in 0..run { - if !skip_mode { - copy_tile!(self, tile_off, self.tile_off[tile_no - 1]); - } - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - 0xFA => { - let off = br.read_u16le()? as usize; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - }, - 0xFB => { - let off = br.read_u16le()? as usize; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - }, - 0xFC => { - const MV_PART: [i8; 16] = [ 0, 4, 8, 12, 16, 20, 24, 28, -32, -4, -8, -12, -16, -20, -24, -28 ]; - - let idx = br.read_byte()? as usize; - let x = MV_PART[idx & 0xF] as isize; - let y = MV_PART[idx >> 4] as isize; - let src_off = (tile_off as isize) + x + y * (self.w as isize); - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - }, - 0xFD => { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - }, - 0xFE => { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - }, - _ => {}, - }; - } - skip_mode = op == 0xFF; - } - - Ok(()) - } - - fn decode_frame_v3_x(&mut self, br: &mut ByteReader, _ctype: u16) -> DecoderResult<()> { - const MV_X: [i8; 16] = [ 0, 1, 2, 3, 4, 5, 6, 7, -8, -1, -2, -3, -4, -5, -6, -7 ]; - const MV_Y: [i8; 16] = [ 8, 9, 2, 3, 4, 5, 6, 7, -8, -9, -2, -3, -4, -5, -6, -7 ]; - - let mut titer = self.tile_off.iter().enumerate(); - let mut skip_mode = false; - let mut last_mode = TileMode::Start; - while let Some((tile_no, &tile_off)) = titer.next() { - let op = br.read_byte()?; - if op < 0xF8 { - let clr0 = op; - let clr1 = br.read_byte()?; - if clr0 == clr1 { - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr0; - } - } - last_mode = TileMode::Fill; - } else { - let pat_idx = br.peek_byte()?; - if pat_idx & 0x80 == 0 { - br.read_byte()?; - let mut pattern = self.patterns[usize::from(pat_idx)]; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - last_mode = TileMode::ShortPattern(clr0, clr1); - } else { - let mut pattern = br.read_u16le()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - last_mode = TileMode::LongPattern(clr0, clr1); - } - } - } else { - match op { - 0xF8 => unimplemented!(), // skip+count? - 0xF9 => { - let run = br.read_byte()? as usize; - validate!(run > 0); - match last_mode { - TileMode::ShortPattern(_, _) | - TileMode::LongPattern(_, _) | - TileMode::Fill | - TileMode::Reuse => { - let mut tile_off = tile_off; - for i in 0..run { - if !skip_mode { - copy_tile!(self, tile_off, self.tile_off[tile_no - 1]); - } - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::Absolute(off) => { - let mut tile_off = tile_off; - for i in 0..run { - copy_tile!(self, tile_off, self.tile_off[off]); - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::MV(off) => { - let mut tile_off = tile_off; - for i in 0..run { - let src_off = tile_off as isize + off; - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::Forward(off) => { - let off = off as usize; - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - }, - TileMode::Backward(off) => { - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - copy_tile!(self, tile_off, self.tile_off[tile_no - (off as usize)]); - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - }, - TileMode::Skip => { - for _ in 0..run - 1 { - let (_tno, _toff) = titer.next().unwrap(); - } - } - _ => unimplemented!(), - } - - validate!(tile_no > 0); - last_mode = TileMode::Run; - }, - 0xFA => { - let off = br.read_u16le()? as usize; - validate!(off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[off]); - last_mode = TileMode::Absolute(off); - }, - 0xFB => { - let run = br.read_byte()? as usize; - validate!(run > 0 && tile_no + run <= self.tile_off.len()); - match last_mode { - TileMode::Fill => { - let mut tile_off = tile_off; - - for i in 0..run { - let clr0 = br.read_byte()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr0; - } - } - - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::ShortPattern(clr0, clr1) => { - let mut tile_off = tile_off; - for i in 0..run { - let mut pattern = if (br.peek_byte()? & 0x80) == 0 { - self.patterns[usize::from(br.read_byte()?)] - } else { - br.read_u16le()? - }; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::LongPattern(clr0, clr1) => { - let mut tile_off = tile_off; - for i in 0..run { - let mut pattern = br.read_u16le()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::Absolute(_) => { - let mut tile_off = tile_off; - for i in 0..run { - let off = br.read_u16le()? as usize; - validate!(off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[off]); - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::MV(_) => { - let mut tile_off = tile_off; - for i in 0..run { - let idx = br.read_byte()? as usize; - let x = MV_X[idx & 0xF] as isize * 4; - let y = MV_Y[idx >> 4] as isize * 4; - let src_off = (tile_off as isize) + x + y * (self.w as isize); - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - TileMode::Forward(_) => { - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - }, - TileMode::Backward(_) => { - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - }, - _ => unimplemented!(), - } - last_mode = TileMode::Reuse; - }, - 0xFC => { - let idx = br.read_byte()? as usize; - let x = MV_X[idx & 0xF] as isize * 4; - let y = MV_Y[idx >> 4] as isize * 4; - let src_off = (tile_off as isize) + x + y * (self.w as isize); - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - last_mode = TileMode::MV(x + y * (self.w as isize)); - }, - 0xFD => { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - last_mode = TileMode::Forward(off as u16); - }, - 0xFE => { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - last_mode = TileMode::Backward(off as u16); - }, - _ => { - last_mode = TileMode::Skip; - }, - }; - } - skip_mode = op == 0xFF; - } - - Ok(()) - } - - fn decode_frame_5(&mut self, br: &mut ByteReader, _ctype: u16) -> DecoderResult<()> { - let mut titer = self.tile_off.iter().enumerate(); - let mut last_mode = TileMode::Start; - - while let Some((tile_no, &tile_off)) = titer.next() { - let op = br.read_byte()?; - if op < 0xF8 { - let clr0 = op; - let clr1 = br.read_byte()?; - if clr0 == clr1 { - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr0; - } - } - last_mode = TileMode::Fill; - } else { - let pat = br.read_byte()?; - let mut pattern = if pat < 128 { - last_mode = TileMode::ShortPattern(clr0, clr1); - self.patterns[pat as usize] - } else { - last_mode = TileMode::LongPattern(clr0, clr1); - u16::from(pat) | (u16::from(br.read_byte()?) << 8) - }; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - } - } else { - match op { - 0xF8 => { - unimplemented!(); - }, - 0xF9 => { - let run = br.read_byte()? as usize; - validate!(run > 0); - - validate!(tile_no > 0); - validate!(last_mode != TileMode::Start); - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - let copy_off = match last_mode { - TileMode::Forward(off) => { - tile_no + (off as usize) - }, - TileMode::Backward(off) => { - validate!(tile_no >= (off as usize)); - tile_no - (off as usize) - }, - TileMode::Skip => self.tile_off.len(), - _ => tile_no - 1, - }; - if copy_off < self.tile_off.len() { - copy_tile!(self, tile_off, self.tile_off[copy_off]); - } - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - last_mode = TileMode::Run; - }, - 0xFA => { - let rtile = br.read_u16le()? as usize; - validate!(rtile < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[rtile]); - last_mode = TileMode::Reuse; - }, - 0xFB => { - match self.mode { - 6 => { - let run = br.read_byte()? as usize; - validate!(run >= 2); - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - match last_mode { - TileMode::Start => return Err(DecoderError::InvalidData), - TileMode::Fill => { - let clr = br.read_byte()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr; - } - } - }, - TileMode::ShortPattern(clr0, clr1) => { - let pat = br.read_byte()?; - let mut pattern = if pat < 128 { - self.patterns[pat as usize] - } else { - u16::from(pat) | (u16::from(br.read_byte()?) << 8) - }; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - }, - TileMode::LongPattern(clr0, clr1) => { - let mut pattern = br.read_u16le()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - }, - TileMode::Reuse => { - let rtile = br.read_u16le()? as usize; - validate!(rtile < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[rtile]); - }, - TileMode::MV(_) => { - let idx = br.read_byte()? as usize; - let (x, y) = DEF_MVS[idx]; - let src_off = (tile_off as isize) + (x as isize) * 4 + (y as isize) * 4 * (self.w as isize); - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - copy_tile!(self, tile_off, src_off as usize); - }, - TileMode::Forward(_) => { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - }, - TileMode::Backward(_) => { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - }, - _ => unimplemented!(), - }; - - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - }, - 7 => { - validate!(self.tile_w == 4 && self.tile_h == 4); - let run = br.read_byte()? as usize; - validate!(run > 0); - - let mut tile_off = tile_off; - for i in 0..run { - Self::decode_mode7_tile(&mut self.frame[tile_off..], self.w, br)?; - - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - _ => { - unimplemented!(); - }, - }; - last_mode = TileMode::FB; - }, - 0xFC => { - let idx = br.read_byte()? as usize; - let (x, y) = DEF_MVS[idx]; - let mv_off = (x as isize) * 4 + (y as isize) * 4 * (self.w as isize); - let src_off = (tile_off as isize) + mv_off; - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - last_mode = TileMode::MV(mv_off); - }, - 0xFD => { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - last_mode = TileMode::Forward(off as u16); - }, - 0xFE => { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - last_mode = TileMode::Backward(off as u16); - }, - _ => { - last_mode = TileMode::Skip; - }, - }; - } - } - - Ok(()) - } - fn decode_frame_7(&mut self, br: &mut ByteReader, _ctype: u16) -> DecoderResult<()> { - let mut titer = self.tile_off.iter().enumerate(); - let mut last_mode = TileMode::Start; - - let mut f8_mode = false; - let row_size = self.w / self.tile_w; - let mut next_row = 0; - let mut f8_data = [0; 16]; - let mut f8_pos = 0; - - while let Some((tile_no, &tile_off)) = titer.next() { - if tile_no == next_row { - f8_mode = false; - next_row += row_size; - } - while br.peek_byte()? == 0xF8 { - br.read_byte()?; - if f8_mode { - f8_mode = false; - } else { - let idx = br.read_byte()? as usize; - if idx < 0x10 { - validate!(f8_pos < self.f8_cache.len()); - br.peek_buf(&mut self.f8_cache[f8_pos])?; - if idx > 0 { - br.read_skip(idx)?; - } - f8_data = self.f8_cache[f8_pos]; - } else { - f8_data = self.f8_cache[idx - 0x10]; - self.f8_cache[f8_pos] = f8_data; - } - f8_pos += 1; - f8_mode = true; - } - } - - let op = br.read_byte()?; - if op < 0xF8 { - let (clr0, clr1) = if !f8_mode { - if br.peek_byte()? < 0xF8 { - (op, br.read_byte()?) - } else { - (op, op) - } - } else { - (f8_data[(op & 0xF) as usize], f8_data[(op >> 4) as usize]) - }; - if clr0 == clr1 && (!f8_mode || ((op & 0xF) == (op >> 4))) { - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr0; - } - } - last_mode = TileMode::Fill; - } else { - let pat = br.read_byte()?; - let mut pattern = if pat < 128 { - last_mode = TileMode::ShortPattern(clr0, clr1); - self.patterns[pat as usize] - } else { - last_mode = TileMode::LongPattern(clr0, clr1); - u16::from(pat) | (u16::from(br.read_byte()?) << 8) - }; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - } - } else { - match op { - 0xF8 => { - unreachable!(); - }, - 0xF9 => { - let run = br.read_byte()? as usize; - validate!(run > 0); - - validate!(tile_no > 0); - validate!(last_mode != TileMode::Start); - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - if let TileMode::MV(mv_off) = last_mode { - let src_off = (tile_off as isize) + mv_off; - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - continue; - } - let copy_off = match last_mode { - TileMode::Forward(off) => { - tile_no + (off as usize) - }, - TileMode::Backward(off) => { - validate!(tile_no >= (off as usize)); - tile_no - (off as usize) - }, - TileMode::Skip => self.tile_off.len(), - _ => tile_no - 1, - }; - if copy_off < self.tile_off.len() { - copy_tile!(self, tile_off, self.tile_off[copy_off]); - } - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - last_mode = TileMode::Run; - }, - 0xFA => { - let rtile = br.read_u16le()? as usize; - validate!(rtile < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[rtile]); - last_mode = TileMode::Reuse; - }, - 0xFB => { - match self.mode { - 6 => { - let run = br.read_byte()? as usize; - validate!(run >= 2); - let mut tile_no = tile_no; - let mut tile_off = tile_off; - for i in 0..run { - match last_mode { - TileMode::Start => return Err(DecoderError::InvalidData), - TileMode::Fill => { - let clr = br.read_byte()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = clr; - } - } - }, - TileMode::ShortPattern(clr0, clr1) => { - let pat = br.read_byte()?; - let mut pattern = if pat < 128 { - self.patterns[pat as usize] - } else { - u16::from(pat) | (u16::from(br.read_byte()?) << 8) - }; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - }, - TileMode::LongPattern(clr0, clr1) => { - let mut pattern = br.read_u16le()?; - for dline in self.frame[tile_off..].chunks_mut(self.w).take(self.tile_h) { - for el in dline[..self.tile_w].iter_mut() { - *el = if (pattern & 0x8000) == 0 { clr0 } else { clr1 }; - pattern <<= 1; - } - } - }, - TileMode::Reuse => { - let rtile = br.read_u16le()? as usize; - validate!(rtile < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[rtile]); - }, - TileMode::MV(_) => { - let idx = br.read_byte()? as usize; - let (x, y) = DEF_MVS[idx]; - let src_off = (tile_off as isize) + (x as isize) * 4 + (y as isize) * 4 * (self.w as isize); - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - copy_tile!(self, tile_off, src_off as usize); - }, - TileMode::Forward(_) => { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - }, - TileMode::Backward(_) => { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - }, - _ => unimplemented!(), - }; - - if i + 1 < run { - let (tno, &toff) = titer.next().unwrap(); - tile_no = tno; - tile_off = toff; - } - } - }, - 7 => { - validate!(self.tile_w == 4 && self.tile_h == 4); - let run = br.read_byte()? as usize; - validate!(run > 0); - - let mut tile_off = tile_off; - for i in 0..run { - Self::decode_mode7_tile(&mut self.frame[tile_off..], self.w, br)?; - - if i + 1 < run { - let (_tno, &toff) = titer.next().unwrap(); - tile_off = toff; - } - } - }, - _ => { - unimplemented!(); - }, - }; - last_mode = TileMode::FB; - }, - 0xFC => { - let idx = br.read_byte()? as usize; - let (x, y) = DEF_MVS[idx]; - let mv_off = (x as isize) * 4 + (y as isize) * 4 * (self.w as isize); - let src_off = (tile_off as isize) + mv_off; - validate!(src_off >= 0); - validate!((src_off as usize) + self.tile_w + (self.tile_h - 1) * self.w <= self.w * self.h); - - copy_tile!(self, tile_off, src_off as usize); - last_mode = TileMode::MV(mv_off); - }, - 0xFD => { - let off = (br.read_byte()? as usize) + 1; - validate!(tile_no + off < self.tile_off.len()); - copy_tile!(self, tile_off, self.tile_off[tile_no + off]); - last_mode = TileMode::Forward(off as u16); - }, - 0xFE => { - let off = (br.read_byte()? as usize) + 1; - validate!(off <= tile_no); - copy_tile!(self, tile_off, self.tile_off[tile_no - off]); - last_mode = TileMode::Backward(off as u16); - }, - _ => { - last_mode = TileMode::Skip; - }, - }; - } - } - - Ok(()) - } - - fn output_frame(&mut self, bufinfo: &mut NABufferType, w: usize, h: usize) { - let bufo = bufinfo.get_vbuf(); - let mut buf = bufo.unwrap(); - let paloff = buf.get_offset(1); - let stride = buf.get_stride(0); - let data = buf.get_data_mut().unwrap(); - let dst = data.as_mut_slice(); - - dst[paloff..][..768].copy_from_slice(&self.pal); - for (dline, sline) in dst.chunks_mut(stride).zip(self.frame.chunks(w)).take(h) { - dline[..w].copy_from_slice(sline); - } - } -} - -impl NADecoder for QVideoDecoder { - fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { - if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() { - let mut w; - let mut h; - if let Some(buf) = info.get_extradata() { - validate!(buf.len() >= 22); - w = read_u16le(&buf[4..])? as usize; - h = read_u16le(&buf[6..])? as usize; - self.tile_w = buf[8] as usize; - self.tile_h = buf[9] as usize; - validate!(self.tile_w > 0 && self.tile_h > 0); - if self.tile_w != 4 || self.tile_h != 4 { - return Err(DecoderError::NotImplemented); - } - self.version = buf[2]; - self.version2 = buf[3]; - if self.version != 3{ - w *= self.tile_w; - h *= self.tile_h; - } else { - validate!((w % self.tile_w) == 0); - validate!((h % self.tile_h) == 0); - } - } else { - return Err(DecoderError::InvalidData); - } - let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, PAL8_FORMAT)); - self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); - self.w = w; - self.h = h; - - self.mode = match self.version { - 4 => 6, - 5 => 7, - 6 => 7, - 7 => 7, - _ => 0, - }; - - self.frame.resize(w * h, 0); - self.pal = [0; 768]; - self.tile_off = Vec::with_capacity((w / self.tile_w) * (h / self.tile_h)); - let mut off = 0; - for _y in (0..h).step_by(self.tile_h) { - for x in (0..w).step_by(self.tile_w) { - self.tile_off.push(off + x); - } - off += w * self.tile_h; - } - Ok(()) - } else { - Err(DecoderError::InvalidData) - } - } - fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { - let src = pkt.get_buffer(); - validate!(!src.is_empty()); - - let mut mr = MemoryReader::new_read(&src); - let mut br = ByteReader::new(&mut mr); - - while br.left() >= 6 { - let ctype = br.read_u16le()?; - let csize = br.read_u32le()? as usize; - validate!(csize <= (br.left() as usize)); - match ctype { - 1 => { - validate!(csize <= 768); - br.read_buf(&mut self.pal[..csize])?; - for el in self.pal[..csize].iter_mut() { - *el = (*el << 2) | (*el >> 4); - } - }, - 2 | 3 | 4 | 9 | 11 => { - if self.version == 5 { - self.mode = if ctype == 9 || ctype == 11 { 7 } else { 6 }; - } - if self.version == 3 { - if self.version2 == 0 { - self.decode_frame_v3_0(&mut br, ctype)?; - } else { - self.decode_frame_v3_x(&mut br, ctype)?; - } - } else if self.version < 6 { - self.decode_frame_5(&mut br, ctype)?; - } else { - self.mode = if ctype == 11 { 7 } else { 6 }; - self.decode_frame_7(&mut br, ctype)?; - } - }, - 5 => { - validate!(csize <= 256 && (csize & 1) == 0); - for el in self.patterns[..csize/2].iter_mut() { - *el = br.read_u16le()?; - } - }, - 6 | 7 => { - self.mode = ctype as u8; - }, - _ => return Err(DecoderError::InvalidData), - }; - } - - let mut bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?; - - self.output_frame(&mut bufinfo, self.w, self.h); - - let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); - frm.set_frame_type(if pkt.is_keyframe() { FrameType::I } else { FrameType::P }); - Ok(frm.into_ref()) - } - fn flush(&mut self) { - } -} - -impl NAOptionHandler for QVideoDecoder { - 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() -> Box { - Box::new(QVideoDecoder::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; - - // samples from Callahan's Crosstime Saloon, Deathgate, Mission Critical and Shannara games - #[test] - fn test_q_video3() { - 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); - - test_decoding("legend-q", "legend-q-video", "assets/Game/dgate101.q", Some(31), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5([0x9cc0014c, 0xf6332802, 0xfabeb715, 0xdfaa11c0])); - } - #[test] - fn test_q_video4() { - 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); - - test_decoding("legend-q", "legend-q-video", "assets/Game/1925.Q", None, &dmx_reg, &dec_reg, - ExpectedTestResult::MD5([0xe1af971a, 0xfb509816, 0x9d60f5d6, 0xbcf48a3b])); - } - #[test] - fn test_q_video5() { - 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); - - test_decoding("legend-q", "legend-q-video", "assets/Game/mc703.q", Some(16), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5([0xf65ea3ce, 0x3052b2bb, 0xb10f8f69, 0x530d60f9])); - } - #[test] - fn test_q_video7() { - 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); - - test_decoding("legend-q", "legend-q-video", "assets/Game/CCS003.Q", Some(16), &dmx_reg, &dec_reg, - ExpectedTestResult::MD5([0x1be6ef08, 0xdbff6d2e, 0x9595ee10, 0x1dfda486])); - } -} - -const DEF_MVS: [(i8, i8); 256] = [ - ( 0, 8), ( 1, 8), ( 2, 8), ( 3, 8), ( 4, 8), ( 5, 8), ( 6, 8), ( 7, 8), - (-8, 8), (-1, 8), (-2, 8), (-3, 8), (-4, 8), (-5, 8), (-6, 8), (-7, 8), - ( 0, 9), ( 1, 9), ( 2, 9), ( 3, 9), ( 4, 9), ( 5, 9), ( 6, 9), ( 7, 9), - (-8, 9), (-1, 9), (-2, 9), (-3, 9), (-4, 9), (-5, 9), (-6, 9), (-7, 9), - ( 0, 2), ( 1, 2), ( 2, 2), ( 3, 2), ( 4, 2), ( 5, 2), ( 6, 2), ( 7, 2), - (-8, 2), (-1, 2), (-2, 2), (-3, 2), (-4, 2), (-5, 2), (-6, 2), (-7, 2), - ( 0, 3), ( 1, 3), ( 2, 3), ( 3, 3), ( 4, 3), ( 5, 3), ( 6, 3), ( 7, 3), - (-8, 3), (-1, 3), (-2, 3), (-3, 3), (-4, 3), (-5, 3), (-6, 3), (-7, 3), - ( 0, 4), ( 1, 4), ( 2, 4), ( 3, 4), ( 4, 4), ( 5, 4), ( 6, 4), ( 7, 4), - (-8, 4), (-1, 4), (-2, 4), (-3, 4), (-4, 4), (-5, 4), (-6, 4), (-7, 4), - ( 0, 5), ( 1, 5), ( 2, 5), ( 3, 5), ( 4, 5), ( 5, 5), ( 6, 5), ( 7, 5), - (-8, 5), (-1, 5), (-2, 5), (-3, 5), (-4, 5), (-5, 5), (-6, 5), (-7, 5), - ( 0, 6), ( 1, 6), ( 2, 6), ( 3, 6), ( 4, 6), ( 5, 6), ( 6, 6), ( 7, 6), - (-8, 6), (-1, 6), (-2, 6), (-3, 6), (-4, 6), (-5, 6), (-6, 6), (-7, 6), - ( 0, 7), ( 1, 7), ( 2, 7), ( 3, 7), ( 4, 7), ( 5, 7), ( 6, 7), ( 7, 7), - (-8, 7), (-1, 7), (-2, 7), (-3, 7), (-4, 7), (-5, 7), (-6, 7), (-7, 7), - ( 0,-8), ( 1,-8), ( 2,-8), ( 3,-8), ( 4,-8), ( 5,-8), ( 6,-8), ( 7,-8), - (-8,-8), (-1,-8), (-2,-8), (-3,-8), (-4,-8), (-5,-8), (-6,-8), (-7,-8), - ( 0,-9), ( 1,-9), ( 2,-9), ( 3,-9), ( 4,-9), ( 5,-9), ( 6,-9), ( 7,-9), - (-8,-9), (-1,-9), (-2,-9), (-3,-9), (-4,-9), (-5,-9), (-6,-9), (-7,-9), - ( 0,-2), ( 1,-2), ( 2,-2), ( 3,-2), ( 4,-2), ( 5,-2), ( 6,-2), ( 7,-2), - (-8,-2), (-1,-2), (-2,-2), (-3,-2), (-4,-2), (-5,-2), (-6,-2), (-7,-2), - ( 0,-3), ( 1,-3), ( 2,-3), ( 3,-3), ( 4,-3), ( 5,-3), ( 6,-3), ( 7,-3), - (-8,-3), (-1,-3), (-2,-3), (-3,-3), (-4,-3), (-5,-3), (-6,-3), (-7,-3), - ( 0,-4), ( 1,-4), ( 2,-4), ( 3,-4), ( 4,-4), ( 5,-4), ( 6,-4), ( 7,-4), - (-8,-4), (-1,-4), (-2,-4), (-3,-4), (-4,-4), (-5,-4), (-6,-4), (-7,-4), - ( 0,-5), ( 1,-5), ( 2,-5), ( 3,-5), ( 4,-5), ( 5,-5), ( 6,-5), ( 7,-5), - (-8,-5), (-1,-5), (-2,-5), (-3,-5), (-4,-5), (-5,-5), (-6,-5), (-7,-5), - ( 0,-6), ( 1,-6), ( 2,-6), ( 3,-6), ( 4,-6), ( 5,-6), ( 6,-6), ( 7,-6), - (-8,-6), (-1,-6), (-2,-6), (-3,-6), (-4,-6), (-5,-6), (-6,-6), (-7,-6), - ( 0,-7), ( 1,-7), ( 2,-7), ( 3,-7), ( 4,-7), ( 5,-7), ( 6,-7), ( 7,-7), - (-8,-7), (-1,-7), (-2,-7), (-3,-7), (-4,-7), (-5,-7), (-6,-7), (-7,-7) -]; diff --git a/nihav-game/src/demuxers/mod.rs b/nihav-game/src/demuxers/mod.rs index 36f903b..2fe9dd4 100644 --- a/nihav-game/src/demuxers/mod.rs +++ b/nihav-game/src/demuxers/mod.rs @@ -16,8 +16,6 @@ mod bmv; mod fst; #[cfg(feature="demuxer_gdv")] mod gdv; -#[cfg(feature="demuxer_q")] -mod q; #[cfg(feature="demuxer_seq")] mod seq; #[cfg(feature="demuxer_sga")] @@ -43,8 +41,6 @@ const GAME_DEMUXERS: &[&dyn DemuxerCreator] = &[ &fst::FSTDemuxerCreator {}, #[cfg(feature="demuxer_gdv")] &gdv::GDVDemuxerCreator {}, -#[cfg(feature="demuxer_q")] - &q::QDemuxerCreator {}, #[cfg(feature="demuxer_seq")] &seq::SequenceDemuxerCreator {}, #[cfg(feature="demuxer_sga")] diff --git a/nihav-game/src/demuxers/q.rs b/nihav-game/src/demuxers/q.rs deleted file mode 100644 index 977eff7..0000000 --- a/nihav-game/src/demuxers/q.rs +++ /dev/null @@ -1,248 +0,0 @@ -use nihav_core::frame::*; -use nihav_core::demuxers::*; - -struct QDemuxer<'a> { - src: &'a mut ByteReader<'a>, - vpts: u64, - apts: u64, - bps: usize, - a_id: Option, - v_id: Option, - nframes: usize, - duration: u64, - side_data: Vec, -} - -impl<'a> DemuxCore<'a> for QDemuxer<'a> { - fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> { - let src = &mut self.src; - - let mut hdr = [0; 22]; - src.read_buf(&mut hdr)?; - validate!(hdr[0] == 0x39); - validate!(hdr[1] == 0x68); - let version = hdr[2]; - validate!((3..=7).contains(&version)); - let mut width = read_u16le(&hdr[4..])? as usize; - let mut height = read_u16le(&hdr[6..])? as usize; - if version > 3 { - width *= hdr[8] as usize; - height *= hdr[9] as usize; - } - validate!(width > 0 && width <= 800); - validate!(height > 0 && height <= 600); - - self.nframes = read_u16le(&hdr[10..])? as usize; - validate!(self.nframes > 0); - let fps = if hdr[16] == 0 { 5 } else { hdr[16] as u32 }; - self.duration = (self.nframes as u64) * 1000 / u64::from(fps); - let asize = if version > 3 { - src.read_u32le()? - } else { 0 }; - - let vhdr = NAVideoInfo::new(width, height, false, PAL8_FORMAT); - let vci = NACodecTypeInfo::Video(vhdr); - let vinfo = NACodecInfo::new("legend-q-video", vci, Some(hdr.to_vec())); - self.v_id = strmgr.add_stream(NAStream::new(StreamType::Video, 0, vinfo, 1, fps, self.nframes as u64)); - if asize != 0 { - let ntype = self.src.peek_byte()?; - if ntype == 8 { - let _ = self.src.read_u16le()?; - let size = self.src.read_u32le()? as usize; - validate!(size >= 44); - let mut buf = vec![0; size]; - self.src.read_buf(&mut buf)?; - let arate = read_u32le(&buf[24..])?; - if arate > 0 { - let channels = buf[22]; - let abits = buf[34] as usize; - validate!(abits == 8 || abits == 16); - self.bps = (channels as usize) * abits / 8; - let bsize = read_u16le(&buf[32..])? as usize; - let ahdr = NAAudioInfo::new(arate, channels, if abits == 16 { SND_S16_FORMAT } else { SND_U8_FORMAT }, bsize); - let ainfo = NACodecInfo::new("pcm", NACodecTypeInfo::Audio(ahdr), None); - self.a_id = strmgr.add_stream(NAStream::new(StreamType::Audio, 1, ainfo, 1, arate, 2)); - } - } - } - self.apts = 0; - self.vpts = 0; - self.side_data.clear(); - Ok(()) - } - - fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult { - loop { - let ctype = self.src.read_u16le()?; - let size = self.src.read_u32le()? as usize; - match ctype { - 0xFFFF => return Err(DemuxerError::EOF), - 0 => { - if let Some(a_id) = self.a_id { - let stream = strmgr.get_stream(a_id).unwrap(); - let ts = stream.make_ts(Some(self.apts), None, None); - self.apts += (size / self.bps) as u64; - return self.src.read_packet(stream, ts, true, size); - } else { - self.src.read_skip(size)?; - } - }, - 1 => { - validate!(size <= 768); - let cur_len = self.side_data.len(); - self.side_data.resize(cur_len + size + 6, 0); - self.side_data[cur_len] = ctype as u8; - write_u32le(&mut self.side_data[cur_len + 2..], size as u32)?; - self.src.read_buf(&mut self.side_data[cur_len + 6..])?; - }, - 2 | 3 | 4 | 11 => { - validate!(self.v_id.is_some()); - let stream = strmgr.get_stream(self.v_id.unwrap_or(0)).unwrap(); - let ts = stream.make_ts(Some(self.vpts), None, None); - self.vpts += 1; - - let cur_len = self.side_data.len(); - self.side_data.resize(cur_len + size + 6, 0); - self.side_data[cur_len] = ctype as u8; - self.side_data[cur_len] = ctype as u8; - write_u32le(&mut self.side_data[cur_len + 2..], size as u32)?; - if let Err(err) = self.src.read_buf(&mut self.side_data[cur_len + 6..]) { - self.side_data.truncate(cur_len); - return Err(err.into()); - } - let mut buf = Vec::new(); - std::mem::swap(&mut buf, &mut self.side_data); - return Ok(NAPacket::new(stream, ts, self.vpts == 1, buf)); - }, - 5 => { - validate!(size <= 256); - let cur_len = self.side_data.len(); - self.side_data.resize(cur_len + size + 6, 0); - self.side_data[cur_len] = ctype as u8; - write_u32le(&mut self.side_data[cur_len + 2..], size as u32)?; - self.src.read_buf(&mut self.side_data[cur_len + 6..])?; - }, - 6 | 7 => { - self.side_data.push(ctype as u8); - self.side_data.push(0); - self.side_data.push(0); - self.side_data.push(0); - self.side_data.push(0); - self.side_data.push(0); - }, - 8 if size > 0 => return Err(DemuxerError::InvalidData), //should be handled before main loop - 9 => { // first part of interlaced frame - let cur_len = self.side_data.len(); - self.side_data.resize(cur_len + size + 6, 0); - self.side_data[cur_len] = ctype as u8; - write_u32le(&mut self.side_data[cur_len + 2..], size as u32)?; - self.src.read_buf(&mut self.side_data[cur_len + 6..])?; - }, - _ => { - self.src.read_skip(size)?; - }, - }; - } - } - - fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> { - Err(DemuxerError::NotPossible) - } - fn get_duration(&self) -> u64 { self.duration } -} -impl<'a> NAOptionHandler for QDemuxer<'a> { - fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } - fn set_options(&mut self, _options: &[NAOption]) { } - fn query_option_value(&self, _name: &str) -> Option { None } -} -impl<'a> QDemuxer<'a> { - fn new(io: &'a mut ByteReader<'a>) -> Self { - QDemuxer { - src: io, - vpts: 0, - apts: 0, - bps: 0, - a_id: None, - v_id: None, - nframes: 0, - duration: 0, - side_data: Vec::with_capacity(256 + 6), - } - } -} - -pub struct QDemuxerCreator { } - -impl DemuxerCreator for QDemuxerCreator { - fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box + 'a> { - Box::new(QDemuxer::new(br)) - } - fn get_name(&self) -> &'static str { "legend-q" } -} - -#[cfg(test)] -mod test { - use super::*; - use std::fs::File; - - // samples from Death Gate, Mission Critical and Shannara games - #[test] - fn test_q_demux_v3() { - let mut file = File::open("assets/Game/dgate101.q").unwrap(); - let mut fr = FileReader::new_read(&mut file); - let mut br = ByteReader::new(&mut fr); - let mut dmx = QDemuxer::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); - } - } - - #[test] - fn test_q_demux_v4() { - let mut file = File::open("assets/Game/1425A5.Q").unwrap(); - let mut fr = FileReader::new_read(&mut file); - let mut br = ByteReader::new(&mut fr); - let mut dmx = QDemuxer::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); - } - } - - #[test] - fn test_q_demux_v5() { - let mut file = File::open("assets/Game/mc703.q").unwrap(); - let mut fr = FileReader::new_read(&mut file); - let mut br = ByteReader::new(&mut fr); - let mut dmx = QDemuxer::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); - } - } -}