1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_codec_support::codecs::HAMShuffler;
4 use nihav_codec_support::codecs::imaadpcm::*;
9 (read; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $br:expr, $dst_size:expr) => {
10 validate!($dpos < $dst_size);
11 let b = $br.read_byte()?;
15 $wpos = ($wpos + 1) & 0xFFF;
17 (copy; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $off:expr, $dst_size:expr) => {
18 let b = $window[$off];
19 validate!($dpos < $dst_size);
23 $wpos = ($wpos + 1) & 0xFFF;
24 $off = ($off + 1) & 0xFFF;
27 fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
28 let mut window: [u8; 0x1000] = [0x20; 0x1000];
30 let dst_size = br.read_u32le()? as usize;
31 validate!(dst_size <= dst.len());
34 if br.peek_u32le()? == 0x56781234 {
44 while br.left() > 0 && opos < dst_size {
45 let op = br.read_byte()?;
46 if (op == 0xFF) && (br.left() > 8) {
48 lz_op!(read; dst, opos, window, pos, br, dst_size);
52 if opos == dst_size { break; }
53 let is_literal = ((op >> i) & 1) != 0;
55 lz_op!(read; dst, opos, window, pos, br, dst_size);
57 let b0 = br.read_byte()? as usize;
58 let b1 = br.read_byte()? as usize;
59 let mut off = b0 | ((b1 & 0xF0) << 4);
60 let mut len = b1 & 0xF;
62 len = (br.read_byte()? as usize) + esc_len;
65 lz_op!(copy; dst, opos, window, pos, off, dst_size);
74 fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
75 let end = br.tell() + (len as u64);
78 dst[dpos] = br.read_byte()?;
81 while dpos < dst.len() && br.tell() < end {
82 let val = br.read_byte()?;
83 let len = ((val & 0x7F) as usize) * 2;
84 validate!(dpos + len <= dst.len());
85 if (val & 0x80) != 0 {
86 let dst = &mut dst[dpos..][..len];
89 let val1 = br.read_byte()?;
90 let val2 = br.read_byte()?;
91 for i in (0..len).step_by(2) {
93 dst[dpos + i + 1] = val2;
101 fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
107 let val = br.read_byte()?;
108 let len = ((val & 0x7F) as usize) + 1;
109 validate!(x + len <= w);
110 if (val & 0x80) != 0 {
111 let pix = &mut dst[dpos + x..][..len];
113 } // otherwise skip already existing data
122 let pix = &mut dst[dpos..][..w];
132 let val = br.read_byte()?;
133 let len = ((val & 0x7F) as usize) + 1;
134 validate!(x + len <= w);
135 if (val & 0x80) != 0 {
136 let pix = &mut dst[dpos + x..][..len];
137 if br.peek_byte()? == 0xFF {
139 rle_unpack(br, len, pix)?;
143 } // otherwise data is already there
150 _ => Err(DecoderError::InvalidData),
154 struct VMDVideoDecoder {
155 info: NACodecInfoRef,
165 impl VMDVideoDecoder {
168 info: NACodecInfoRef::default(),
175 hams: HAMShuffler::default(),
178 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
179 let paloff = buf.get_offset(1);
180 let stride = buf.get_stride(0);
181 let data = buf.get_data_mut().unwrap();
182 let dst = data.as_mut_slice();
184 let frame_x = br.read_u16le()? as usize;
185 let frame_y = br.read_u16le()? as usize;
186 let frame_l = br.read_u16le()? as usize;
187 let frame_d = br.read_u16le()? as usize;
189 let flags = br.read_byte()?;
190 let has_pal = (flags & 0x02) != 0;
191 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
194 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
195 validate!(frame_l >= frame_x && frame_d >= frame_y);
196 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
200 for e in self.pal.iter_mut() {
201 let val = br.read_byte()?;
202 *e = (val << 2) | (val >> 4);
206 let dpal = &mut dst[paloff..][..768];
207 dpal.copy_from_slice(&self.pal[0..]);
209 if br.left() == 0 { return Ok(false); }
211 let w = frame_l + 1 - frame_x;
212 let h = frame_d + 1 - frame_y;
213 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
215 let method = br.read_byte()?;
217 if (method & 0x80) != 0 {
218 validate!(!self.buf.is_empty());
219 lz_unpack(br, &mut self.buf)?;
220 let mut mr = MemoryReader::new_read(&self.buf);
221 let mut buf_br = ByteReader::new(&mut mr);
222 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
224 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
226 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
230 impl NADecoder for VMDVideoDecoder {
231 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
232 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
233 self.width = vinfo.get_width();
234 self.height = vinfo.get_height();
235 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
236 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
237 validate!(info.get_extradata().is_some());
239 if let Some(ref edata) = info.get_extradata() {
240 validate!(edata.len() == 0x330);
241 let unp_size = read_u32le(&edata[800..])? as usize;
242 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
243 self.buf.resize(unp_size, 0);
245 let el = edata[28 + i];
246 self.pal[i] = (el << 2) | (el >> 4);
248 self.xoff = read_u16le(&edata[8..])? as usize;
249 self.yoff = read_u16le(&edata[10..])? as usize;
254 Err(DecoderError::InvalidData)
257 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
258 let src = pkt.get_buffer();
259 validate!(src.len() >= 10);
261 let mut mr = MemoryReader::new_read(&src);
262 let mut br = ByteReader::new(&mut mr);
265 let bufret = self.hams.clone_ref();
266 if let Some(bbuf) = bufret {
269 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
270 buf = bufinfo.get_vbuf().unwrap();
271 self.hams.add_frame(buf);
272 buf = self.hams.get_output_frame().unwrap();
275 let is_intra = self.decode_frame(&mut br, &mut buf)?;
277 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
278 frm.set_keyframe(is_intra);
279 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
282 fn flush(&mut self) {
288 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
289 Box::new(VMDVideoDecoder::new())
292 #[derive(Clone,Copy,PartialEq)]
300 struct VMDAudioDecoder {
302 info: Arc<NACodecInfo>,
308 last_byte: Option<u8>,
313 const SOL_AUD_STEPS16: [i16; 128] = [
314 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
315 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
316 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
317 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
318 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
319 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
320 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
321 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
322 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
323 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
324 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
325 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
326 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
327 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
328 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
329 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
332 impl VMDAudioDecoder {
335 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
336 info: NACodecInfo::new_dummy(),
337 chmap: NAChannelMap::new(),
340 mode: VMDAudioMode::U8,
347 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
348 let channels = self.chmap.num_channels();
349 let mut off = [0, off1];
350 for _ in 0..nblocks {
352 for ch in 0..channels {
353 for i in 0..self.blk_align {
354 dst[off[ch] + i] = 0;
356 off[ch] += self.blk_align;
359 let mut pred: [i32; 2] = [0; 2];
360 for ch in 0..channels {
361 pred[ch] = i32::from(br.read_u16le()?);
362 dst[off[ch]] = pred[ch] as i16;
366 let flip_ch = if channels == 2 { 1 } else { 0 };
367 for _ in channels..self.blk_align*channels {
368 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
369 //pred[ch] = pred[ch].max(-32768).min(32767);
370 dst[off[ch]] = pred[ch] as i16;
377 validate!(br.left() == 0);
380 fn pred16(pred: i32, val: u8) -> i32 {
381 if (val & 0x80) != 0 {
382 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
384 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
387 fn cvt_u8(val: u8) -> u8 {
392 impl NADecoder for VMDAudioDecoder {
393 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
394 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
396 let channels = ainfo.get_channels() as usize;
397 let edata = info.get_extradata();
398 let flags = if let Some(ref buf) = edata {
399 validate!(buf.len() >= 2);
400 (buf[0] as u16) | ((buf[1] as u16) << 8)
404 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
405 if ainfo.get_format().get_bits() == 8 {
406 self.blk_size = ainfo.get_block_len();
407 self.blk_align = ainfo.get_block_len() / channels;
408 if (flags & 0x8000) == 0 {
410 self.mode = VMDAudioMode::U8;
412 fmt = SND_S16_FORMAT;
413 self.mode = VMDAudioMode::StereoDPCM;
414 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
417 fmt = SND_S16P_FORMAT;
418 self.blk_align = ainfo.get_block_len();
419 if (flags & 0x10) == 0 {
420 self.blk_size = (ainfo.get_block_len() + 1) * channels;
421 self.mode = VMDAudioMode::DPCM;
423 self.blk_size = ainfo.get_block_len() / 2 + 3;
424 self.mode = VMDAudioMode::ADPCM;
427 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
428 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
429 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
432 Err(DecoderError::InvalidData)
435 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
436 let info = pkt.get_stream().get_info();
437 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
438 let pktbuf = pkt.get_buffer();
439 validate!(pktbuf.len() >= 6);
440 let mut mr = MemoryReader::new_read(&pktbuf);
441 let mut br = ByteReader::new(&mut mr);
442 let blk_type = br.read_byte()?;
446 if blk_type == 2 { // initial
447 mask = br.read_u32le()?;
448 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
449 } else if blk_type == 3 { // silence
456 let mut samples = nblocks * self.blk_align;
457 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
458 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
460 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
462 VMDAudioMode::DPCM => {
463 let mut adata = abuf.get_abuf_i16().unwrap();
464 let off1 = adata.get_offset(1);
465 let mut dst = adata.get_data_mut().unwrap();
466 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
468 VMDAudioMode::U8 => {
469 let mut adata = abuf.get_abuf_u8().unwrap();
470 let dst = adata.get_data_mut().unwrap();
473 let channels = self.chmap.num_channels();
474 for _ in 0..nblocks {
476 for i in 0..self.blk_align * channels {
479 } else if channels == 1 {
480 for i in 0..self.blk_size {
481 dst[doff + i] = br.read_byte()?;
484 for i in 0..self.blk_size {
485 let val = Self::cvt_u8(br.read_byte()?);
489 doff += self.blk_align * channels;
493 VMDAudioMode::StereoDPCM => {
494 let mut adata = abuf.get_abuf_i16().unwrap();
495 let dst = adata.get_data_mut().unwrap();
498 let mut ch = self.ch;
499 for _ in 0..nblocks {
500 let put_sample = self.last_byte.is_some();
501 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
502 self.pred[ch] = Self::pred16(self.pred[ch], val);
503 dst[doff] = self.pred[ch] as i16;
506 self.last_byte = None;
509 for i in 0..self.blk_align {
510 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
511 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
515 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
519 self.last_byte = Some(0);
523 for i in 0..self.blk_align {
524 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
525 dst[doff + i * 2] = self.pred[ch] as i16;
526 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
527 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
530 let val = br.read_byte()?;
532 self.pred[ch] = Self::pred16(self.pred[ch], val);
533 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
537 self.last_byte = Some(val);
541 doff += self.blk_align * 2;
546 VMDAudioMode::ADPCM => {
547 let mut adata = abuf.get_abuf_i16().unwrap();
548 let dst = adata.get_data_mut().unwrap();
550 if self.chmap.num_channels() == 1 {
552 let mut ima = IMAState::new();
553 for _ in 0..nblocks {
555 doff += (self.blk_size - 3) * 2;
559 let pred = br.read_u16le()? as i16;
560 let step = br.read_byte()?;
561 validate!((step as usize) < IMA_STEP_TABLE.len());
562 ima.reset(pred, step);
563 for _ in 3..self.blk_size {
564 let b = br.read_byte()?;
565 dst[doff] = ima.expand_sample(b >> 4);
567 dst[doff] = ima.expand_sample(b & 0xF);
573 return Err(DecoderError::InvalidData);
578 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
579 frm.set_duration(Some(samples as u64));
580 frm.set_keyframe(true);
583 Err(DecoderError::InvalidData)
586 fn flush(&mut self) {
590 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
591 Box::new(VMDAudioDecoder::new())
596 use nihav_core::codecs::RegisteredDecoders;
597 use nihav_core::demuxers::RegisteredDemuxers;
598 use nihav_codec_support::test::dec_video::*;
599 use crate::game_register_all_codecs;
600 use crate::game_register_all_demuxers;
602 fn test_vmd_video() {
603 let mut dmx_reg = RegisteredDemuxers::new();
604 game_register_all_demuxers(&mut dmx_reg);
605 let mut dec_reg = RegisteredDecoders::new();
606 game_register_all_codecs(&mut dec_reg);
608 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
609 ExpectedTestResult::MD5Frames(vec![
610 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
611 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
612 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
613 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
614 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
615 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
616 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
617 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
618 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
619 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
620 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
623 fn test_vmd_audio_u8() {
624 let mut dmx_reg = RegisteredDemuxers::new();
625 game_register_all_demuxers(&mut dmx_reg);
626 let mut dec_reg = RegisteredDecoders::new();
627 game_register_all_codecs(&mut dec_reg);
629 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
630 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
633 fn test_vmd_audio_s16_old() {
634 let mut dmx_reg = RegisteredDemuxers::new();
635 game_register_all_demuxers(&mut dmx_reg);
636 let mut dec_reg = RegisteredDecoders::new();
637 game_register_all_codecs(&mut dec_reg);
639 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
640 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
643 fn test_vmd_audio_s16_new() {
644 let mut dmx_reg = RegisteredDemuxers::new();
645 game_register_all_demuxers(&mut dmx_reg);
646 let mut dec_reg = RegisteredDecoders::new();
647 game_register_all_codecs(&mut dec_reg);
649 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
650 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));