1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_codec_support::codecs::HAMShuffler;
8 (read; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $br:expr, $dst_size:expr) => {
9 validate!($dpos < $dst_size);
10 let b = $br.read_byte()?;
14 $wpos = ($wpos + 1) & 0xFFF;
16 (copy; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $off:expr, $dst_size:expr) => {
17 let b = $window[$off];
18 validate!($dpos < $dst_size);
22 $wpos = ($wpos + 1) & 0xFFF;
23 $off = ($off + 1) & 0xFFF;
26 fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
27 let mut window: [u8; 0x1000] = [0x20; 0x1000];
29 let dst_size = br.read_u32le()? as usize;
30 validate!(dst_size <= dst.len());
33 if br.peek_u32le()? == 0x56781234 {
43 while br.left() > 0 && opos < dst_size {
44 let op = br.read_byte()?;
45 if (op == 0xFF) && (br.left() > 8) {
47 lz_op!(read; dst, opos, window, pos, br, dst_size);
51 if opos == dst_size { break; }
52 let is_literal = ((op >> i) & 1) != 0;
54 lz_op!(read; dst, opos, window, pos, br, dst_size);
56 let b0 = br.read_byte()? as usize;
57 let b1 = br.read_byte()? as usize;
58 let mut off = b0 | ((b1 & 0xF0) << 4);
59 let mut len = b1 & 0xF;
61 len = (br.read_byte()? as usize) + esc_len;
64 lz_op!(copy; dst, opos, window, pos, off, dst_size);
73 fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
74 let end = br.tell() + (len as u64);
77 dst[dpos] = br.read_byte()?;
80 while dpos < dst.len() && br.tell() < end {
81 let val = br.read_byte()?;
82 let len = ((val & 0x7F) as usize) * 2;
83 validate!(dpos + len <= dst.len());
84 if (val & 0x80) != 0 {
85 let dst = &mut dst[dpos..][..len];
88 let val = br.read_byte()?;
98 fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
104 let val = br.read_byte()?;
105 let len = ((val & 0x7F) as usize) + 1;
106 validate!(x + len <= w);
107 if (val & 0x80) != 0 {
108 let pix = &mut dst[dpos + x..][..len];
110 } // otherwise skip already existing data
119 let pix = &mut dst[dpos..][..w];
129 let val = br.read_byte()?;
130 let len = ((val & 0x7F) as usize) + 1;
131 validate!(x + len <= w);
132 if (val & 0x80) != 0 {
133 let pix = &mut dst[dpos + x..][..len];
134 if br.peek_byte()? == 0xFF {
136 rle_unpack(br, len, pix)?;
140 } // otherwise data is already there
147 _ => Err(DecoderError::InvalidData),
151 struct VMDVideoDecoder {
152 info: NACodecInfoRef,
160 impl VMDVideoDecoder {
163 info: NACodecInfoRef::default(),
168 hams: HAMShuffler::default(),
171 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
172 let paloff = buf.get_offset(1);
173 let stride = buf.get_stride(0);
174 let data = buf.get_data_mut().unwrap();
175 let dst = data.as_mut_slice();
177 let frame_x = br.read_u16le()? as usize;
178 let frame_y = br.read_u16le()? as usize;
179 let frame_l = br.read_u16le()? as usize;
180 let frame_d = br.read_u16le()? as usize;
182 let flags = br.read_byte()?;
183 let has_pal = (flags & 0x02) != 0;
184 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
187 validate!(frame_l >= frame_x && frame_d >= frame_y);
188 validate!(frame_l < self.width && frame_d < self.height);
192 for e in self.pal.iter_mut() {
193 let val = br.read_byte()?;
194 *e = (val << 2) | (val >> 4);
198 let dpal = &mut dst[paloff..][..768];
199 dpal.copy_from_slice(&self.pal[0..]);
201 if br.left() == 0 { return Ok(false); }
203 let w = frame_l + 1 - frame_x;
204 let h = frame_d + 1 - frame_y;
205 let dpos = frame_x + frame_y * stride;
207 let method = br.read_byte()?;
209 if (method & 0x80) != 0 {
210 validate!(!self.buf.is_empty());
211 lz_unpack(br, &mut self.buf)?;
212 let mut mr = MemoryReader::new_read(&self.buf);
213 let mut buf_br = ByteReader::new(&mut mr);
214 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
216 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
218 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
222 impl NADecoder for VMDVideoDecoder {
223 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
224 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
225 self.width = vinfo.get_width();
226 self.height = vinfo.get_height();
227 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
228 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
229 validate!(info.get_extradata().is_some());
231 if let Some(ref edata) = info.get_extradata() {
232 validate!(edata.len() == 0x330);
233 let unp_size = read_u32le(&edata[800..])? as usize;
234 validate!(unp_size < self.width * self.height * 3 + 64); // just for sanity
235 self.buf.resize(unp_size, 0);
237 let el = edata[28 + i];
238 self.pal[i] = (el << 2) | (el >> 4);
244 Err(DecoderError::InvalidData)
247 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
248 let src = pkt.get_buffer();
249 validate!(src.len() >= 10);
251 let mut mr = MemoryReader::new_read(&src);
252 let mut br = ByteReader::new(&mut mr);
255 let bufret = self.hams.clone_ref();
256 if let Some(bbuf) = bufret {
259 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
260 buf = bufinfo.get_vbuf().unwrap();
261 self.hams.add_frame(buf);
262 buf = self.hams.get_output_frame().unwrap();
265 let is_intra = self.decode_frame(&mut br, &mut buf)?;
267 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
268 frm.set_keyframe(is_intra);
269 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
272 fn flush(&mut self) {
278 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
279 Box::new(VMDVideoDecoder::new())
282 #[derive(Clone,Copy,PartialEq)]
289 struct VMDAudioDecoder {
291 info: Arc<NACodecInfo>,
297 last_byte: Option<u8>,
302 const SOL_AUD_STEPS16: [i16; 128] = [
303 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
304 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
305 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
306 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
307 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
308 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
309 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
310 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
311 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
312 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
313 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
314 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
315 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
316 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
317 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
318 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
321 impl VMDAudioDecoder {
324 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
325 info: NACodecInfo::new_dummy(),
326 chmap: NAChannelMap::new(),
329 mode: VMDAudioMode::U8,
336 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
337 let channels = self.chmap.num_channels();
338 let mut off = [0, off1];
339 for _ in 0..nblocks {
341 for ch in 0..channels {
342 for i in 0..self.blk_align {
343 dst[off[ch] + i] = 0;
345 off[ch] += self.blk_align;
348 let mut pred: [i32; 2] = [0; 2];
349 for ch in 0..channels {
350 pred[ch] = i32::from(br.read_u16le()?);
351 dst[off[ch]] = pred[ch] as i16;
355 let flip_ch = if channels == 2 { 1 } else { 0 };
356 for _ in channels..self.blk_align*channels {
357 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
358 //pred[ch] = pred[ch].max(-32768).min(32767);
359 dst[off[ch]] = pred[ch] as i16;
366 validate!(br.left() == 0);
369 fn pred16(pred: i32, val: u8) -> i32 {
370 if (val & 0x80) != 0 {
371 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
373 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
376 fn cvt_u8(val: u8) -> u8 {
381 impl NADecoder for VMDAudioDecoder {
382 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
383 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
385 let channels = ainfo.get_channels() as usize;
386 let edata = info.get_extradata();
387 let flags = if let Some(ref buf) = edata {
388 validate!(buf.len() >= 2);
389 (buf[0] as u16) | ((buf[1] as u16) << 8)
393 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
394 if ainfo.get_format().get_bits() == 8 {
395 self.blk_size = ainfo.get_block_len();
396 self.blk_align = ainfo.get_block_len() / channels;
397 if (flags & 0x8000) == 0 {
399 self.mode = VMDAudioMode::U8;
401 fmt = SND_S16_FORMAT;
402 self.mode = VMDAudioMode::StereoDPCM;
403 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
406 fmt = SND_S16P_FORMAT;
407 self.blk_size = (ainfo.get_block_len() + 1) * channels;
408 self.blk_align = ainfo.get_block_len();
409 self.mode = VMDAudioMode::DPCM;
411 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
412 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
413 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
416 Err(DecoderError::InvalidData)
419 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
420 let info = pkt.get_stream().get_info();
421 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
422 let pktbuf = pkt.get_buffer();
423 validate!(pktbuf.len() >= 6);
424 let mut mr = MemoryReader::new_read(&pktbuf);
425 let mut br = ByteReader::new(&mut mr);
426 let blk_type = br.read_byte()?;
430 if blk_type == 2 { // initial
431 mask = br.read_u32le()?;
432 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
433 } else if blk_type == 3 { // silence
440 let mut samples = nblocks * self.blk_align;
441 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
442 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
444 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
446 VMDAudioMode::DPCM => {
447 let mut adata = abuf.get_abuf_i16().unwrap();
448 let off1 = adata.get_offset(1);
449 let mut dst = adata.get_data_mut().unwrap();
450 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
452 VMDAudioMode::U8 => {
453 let mut adata = abuf.get_abuf_u8().unwrap();
454 let dst = adata.get_data_mut().unwrap();
457 let channels = self.chmap.num_channels();
458 for _ in 0..nblocks {
460 for i in 0..self.blk_align * channels {
463 } else if channels == 1 {
464 for i in 0..self.blk_size {
465 dst[doff + i] = br.read_byte()?;
468 for i in 0..self.blk_size {
469 let val = Self::cvt_u8(br.read_byte()?);
473 doff += self.blk_align * channels;
477 VMDAudioMode::StereoDPCM => {
478 let mut adata = abuf.get_abuf_i16().unwrap();
479 let dst = adata.get_data_mut().unwrap();
482 let mut ch = self.ch;
483 for _ in 0..nblocks {
484 let put_sample = self.last_byte.is_some();
485 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
486 self.pred[ch] = Self::pred16(self.pred[ch], val);
487 dst[doff] = self.pred[ch] as i16;
490 self.last_byte = None;
493 for i in 0..self.blk_align {
494 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
495 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
499 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
503 self.last_byte = Some(0);
507 for i in 0..self.blk_align {
508 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
509 dst[doff + i * 2] = self.pred[ch] as i16;
510 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
511 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
514 let val = br.read_byte()?;
516 self.pred[ch] = Self::pred16(self.pred[ch], val);
517 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
521 self.last_byte = Some(val);
525 doff += self.blk_align * 2;
532 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
533 frm.set_duration(Some(samples as u64));
534 frm.set_keyframe(true);
537 Err(DecoderError::InvalidData)
540 fn flush(&mut self) {
544 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
545 Box::new(VMDAudioDecoder::new())
550 use nihav_core::codecs::RegisteredDecoders;
551 use nihav_core::demuxers::RegisteredDemuxers;
552 use nihav_codec_support::test::dec_video::*;
553 use crate::game_register_all_codecs;
554 use crate::game_register_all_demuxers;
556 fn test_vmd_video() {
557 let mut dmx_reg = RegisteredDemuxers::new();
558 game_register_all_demuxers(&mut dmx_reg);
559 let mut dec_reg = RegisteredDecoders::new();
560 game_register_all_codecs(&mut dec_reg);
562 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
563 ExpectedTestResult::MD5Frames(vec![
564 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
565 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
566 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
567 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
568 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
569 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
570 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
571 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
572 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
573 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
574 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
577 fn test_vmd_audio_u8() {
578 let mut dmx_reg = RegisteredDemuxers::new();
579 game_register_all_demuxers(&mut dmx_reg);
580 let mut dec_reg = RegisteredDecoders::new();
581 game_register_all_codecs(&mut dec_reg);
583 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
584 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
587 fn test_vmd_audio_s16_old() {
588 let mut dmx_reg = RegisteredDemuxers::new();
589 game_register_all_demuxers(&mut dmx_reg);
590 let mut dec_reg = RegisteredDecoders::new();
591 game_register_all_codecs(&mut dec_reg);
593 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
594 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
597 fn test_vmd_audio_s16_new() {
598 let mut dmx_reg = RegisteredDemuxers::new();
599 game_register_all_demuxers(&mut dmx_reg);
600 let mut dec_reg = RegisteredDecoders::new();
601 game_register_all_codecs(&mut dec_reg);
603 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
604 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));