X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=nihav-game%2Fsrc%2Fcodecs%2Fvmd.rs;h=e05899de67f2e4fe93feadcfa7825538e3021cb3;hb=b7c882c1ce6f86c07c2340751200e3a060942826;hp=ce40b95796c14712fe9a9fd9bfbe648ee395f886;hpb=e63a772067515d8d69883ba54aa7809e61b37057;p=nihav.git diff --git a/nihav-game/src/codecs/vmd.rs b/nihav-game/src/codecs/vmd.rs index ce40b95..e05899d 100644 --- a/nihav-game/src/codecs/vmd.rs +++ b/nihav-game/src/codecs/vmd.rs @@ -335,6 +335,12 @@ impl NADecoder for VMDVideoDecoder { } } +impl NAOptionHandler for VMDVideoDecoder { + 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(VMDVideoDecoder::new()) @@ -445,7 +451,7 @@ impl NADecoder for VMDAudioDecoder { let edata = info.get_extradata(); let flags = if let Some(ref buf) = edata { validate!(buf.len() >= 2); - (buf[0] as u16) | ((buf[1] as u16) << 8) + u16::from(buf[0]) | (u16::from(buf[1]) << 8) } else { 0 }; @@ -462,24 +468,27 @@ impl NADecoder for VMDAudioDecoder { self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0); } } else { - fmt = SND_S16P_FORMAT; self.blk_align = ainfo.get_block_len(); if (flags & 0x10) == 0 { + fmt = SND_S16P_FORMAT; self.blk_size = (ainfo.get_block_len() + 1) * channels; self.mode = VMDAudioMode::DPCM; } else { - self.blk_size = (ainfo.get_block_len() + 1) / 2 + 3; + fmt = SND_S16_FORMAT; + self.blk_size = (ainfo.get_block_len() * channels + 1) / 2 + 3 * channels; self.mode = VMDAudioMode::ADPCM; } }; self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len()); - self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone())); + self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo)); self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap(); Ok(()) } else { Err(DecoderError::InvalidData) } } + #[allow(clippy::identity_op)] + #[allow(clippy::cognitive_complexity)] fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult { let info = pkt.get_stream().get_info(); if let NACodecTypeInfo::Audio(_) = info.get_properties() { @@ -597,6 +606,9 @@ impl NADecoder for VMDAudioDecoder { let mut ima = IMAState::new(); for _ in 0..nblocks { if (mask & 1) != 0 { + for i in 0..self.blk_align { + dst[doff + i] = 0; + } doff += self.blk_align; mask >>= 1; continue; @@ -618,7 +630,35 @@ impl NADecoder for VMDAudioDecoder { mask >>= 1; } } else { - return Err(DecoderError::InvalidData); + let mut mask = mask; + let mut ima1 = IMAState::new(); + let mut ima2 = IMAState::new(); + for _ in 0..nblocks { + if (mask & 1) != 0 { + for i in 0..self.blk_align * 2 { + dst[doff + i] = 0; + } + doff += self.blk_align * 2; + mask >>= 1; + continue; + } + let pred1 = br.read_u16le()? as i16; + let pred2 = br.read_u16le()? as i16; + let step1 = br.read_byte()?; + let step2 = br.read_byte()?; + validate!((step1 as usize) < IMA_STEP_TABLE.len()); + validate!((step2 as usize) < IMA_STEP_TABLE.len()); + ima1.reset(pred1, step1); + ima2.reset(pred2, step2); + for _ in 0..self.blk_align { + let b = br.read_byte()?; + dst[doff] = ima1.expand_sample(b >> 4); + doff += 1; + dst[doff] = ima2.expand_sample(b & 0xF); + doff += 1; + } + mask >>= 1; + } } }, }; @@ -635,6 +675,12 @@ impl NADecoder for VMDAudioDecoder { } } +impl NAOptionHandler for VMDAudioDecoder { + 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(VMDAudioDecoder::new()) } @@ -644,14 +690,14 @@ mod test { use nihav_core::codecs::RegisteredDecoders; use nihav_core::demuxers::RegisteredDemuxers; use nihav_codec_support::test::dec_video::*; - use crate::game_register_all_codecs; + use crate::game_register_all_decoders; use crate::game_register_all_demuxers; #[test] fn test_vmd_video() { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![ @@ -672,7 +718,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-video", "assets/Game/HLP1000.VMD", Some(10), &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![ @@ -688,7 +734,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-video", "assets/Game/02C.VMD", None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0xb580782c, 0xd7fb98c0, 0xaf9b83cc, 0xaea0846b])); @@ -698,7 +744,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c])); @@ -708,7 +754,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a])); @@ -718,7 +764,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b])); @@ -728,7 +774,7 @@ mod test { let mut dmx_reg = RegisteredDemuxers::new(); game_register_all_demuxers(&mut dmx_reg); let mut dec_reg = RegisteredDecoders::new(); - game_register_all_codecs(&mut dec_reg); + game_register_all_decoders(&mut dec_reg); test_decoding("vmd", "vmd-audio", "assets/Game/HLP1000.VMD", None, &dmx_reg, &dec_reg, ExpectedTestResult::MD5([0x76a00405, 0xe4e5378d, 0x495b2a68, 0x4dffe042]));