X-Git-Url: https://git.nihav.org/?p=nihav.git;a=blobdiff_plain;f=nihav-game%2Fsrc%2Fcodecs%2Fvmd.rs;h=40d8c5e9b8413ac37eecaafb9c9c12aa4aecb4e4;hp=904fe1fc998a0a027c617a6b8a4fdaf3ae7bab1f;hb=78fb6560c73965d834b215fb0b49505ae5443288;hpb=02c01d44e486b34dee5948f6d5821ea844014d70 diff --git a/nihav-game/src/codecs/vmd.rs b/nihav-game/src/codecs/vmd.rs index 904fe1f..40d8c5e 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()) @@ -435,9 +441,6 @@ impl VMDAudioDecoder { pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize]) } } - fn cvt_u8(val: u8) -> u8 { - val ^ 0x80 - } } impl NADecoder for VMDAudioDecoder { @@ -448,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 }; @@ -465,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() / 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::cyclomatic_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() { @@ -532,10 +538,7 @@ impl NADecoder for VMDAudioDecoder { dst[doff + i] = br.read_byte()?; } } else { - for i in 0..self.blk_size { - let val = Self::cvt_u8(br.read_byte()?); - dst[doff + i] = val; - } + unreachable!(); } doff += self.blk_align * channels; mask >>= 1; @@ -603,7 +606,10 @@ impl NADecoder for VMDAudioDecoder { let mut ima = IMAState::new(); for _ in 0..nblocks { if (mask & 1) != 0 { - doff += (self.blk_size - 3) * 2; + for i in 0..self.blk_align { + dst[doff + i] = 0; + } + doff += self.blk_align; mask >>= 1; continue; } @@ -611,17 +617,48 @@ impl NADecoder for VMDAudioDecoder { let step = br.read_byte()?; validate!((step as usize) < IMA_STEP_TABLE.len()); ima.reset(pred, step); - for _ in 3..self.blk_size { + let mut b = 0; + for i in 0..self.blk_align { + if (i & 1) == 0 { + b = br.read_byte()?; + dst[doff] = ima.expand_sample(b >> 4); + } else { + dst[doff] = ima.expand_sample(b & 0xF); + } + doff += 1; + } + mask >>= 1; + } + } else { + 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] = ima.expand_sample(b >> 4); + dst[doff] = ima1.expand_sample(b >> 4); doff += 1; - dst[doff] = ima.expand_sample(b & 0xF); + dst[doff] = ima2.expand_sample(b & 0xF); doff += 1; } mask >>= 1; } - } else { - return Err(DecoderError::InvalidData); } }, }; @@ -638,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()) } @@ -647,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![ @@ -675,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![ @@ -691,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])); @@ -701,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])); @@ -711,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])); @@ -721,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])); @@ -731,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]));