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 val1 = br.read_byte()?;
89 let val2 = br.read_byte()?;
90 for i in (0..len).step_by(2) {
92 dst[dpos + i + 1] = val2;
100 fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
106 let val = br.read_byte()?;
107 let len = ((val & 0x7F) as usize) + 1;
108 validate!(x + len <= w);
109 if (val & 0x80) != 0 {
110 let pix = &mut dst[dpos + x..][..len];
112 } // otherwise skip already existing data
121 let pix = &mut dst[dpos..][..w];
131 let val = br.read_byte()?;
132 let len = ((val & 0x7F) as usize) + 1;
133 validate!(x + len <= w);
134 if (val & 0x80) != 0 {
135 let pix = &mut dst[dpos + x..][..len];
136 if br.peek_byte()? == 0xFF {
138 rle_unpack(br, len, pix)?;
142 } // otherwise data is already there
149 _ => Err(DecoderError::InvalidData),
153 struct VMDVideoDecoder {
154 info: NACodecInfoRef,
164 impl VMDVideoDecoder {
167 info: NACodecInfoRef::default(),
174 hams: HAMShuffler::default(),
177 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
178 let paloff = buf.get_offset(1);
179 let stride = buf.get_stride(0);
180 let data = buf.get_data_mut().unwrap();
181 let dst = data.as_mut_slice();
183 let frame_x = br.read_u16le()? as usize;
184 let frame_y = br.read_u16le()? as usize;
185 let frame_l = br.read_u16le()? as usize;
186 let frame_d = br.read_u16le()? as usize;
188 let flags = br.read_byte()?;
189 let has_pal = (flags & 0x02) != 0;
190 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
193 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
194 validate!(frame_l >= frame_x && frame_d >= frame_y);
195 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
199 for e in self.pal.iter_mut() {
200 let val = br.read_byte()?;
201 *e = (val << 2) | (val >> 4);
205 let dpal = &mut dst[paloff..][..768];
206 dpal.copy_from_slice(&self.pal[0..]);
208 if br.left() == 0 { return Ok(false); }
210 let w = frame_l + 1 - frame_x;
211 let h = frame_d + 1 - frame_y;
212 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
214 let method = br.read_byte()?;
216 if (method & 0x80) != 0 {
217 validate!(!self.buf.is_empty());
218 lz_unpack(br, &mut self.buf)?;
219 let mut mr = MemoryReader::new_read(&self.buf);
220 let mut buf_br = ByteReader::new(&mut mr);
221 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
223 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
225 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
229 impl NADecoder for VMDVideoDecoder {
230 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
231 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
232 self.width = vinfo.get_width();
233 self.height = vinfo.get_height();
234 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
235 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
236 validate!(info.get_extradata().is_some());
238 if let Some(ref edata) = info.get_extradata() {
239 validate!(edata.len() == 0x330);
240 let unp_size = read_u32le(&edata[800..])? as usize;
241 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
242 self.buf.resize(unp_size, 0);
244 let el = edata[28 + i];
245 self.pal[i] = (el << 2) | (el >> 4);
247 self.xoff = read_u16le(&edata[8..])? as usize;
248 self.yoff = read_u16le(&edata[10..])? as usize;
253 Err(DecoderError::InvalidData)
256 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
257 let src = pkt.get_buffer();
258 validate!(src.len() >= 10);
260 let mut mr = MemoryReader::new_read(&src);
261 let mut br = ByteReader::new(&mut mr);
264 let bufret = self.hams.clone_ref();
265 if let Some(bbuf) = bufret {
268 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
269 buf = bufinfo.get_vbuf().unwrap();
270 self.hams.add_frame(buf);
271 buf = self.hams.get_output_frame().unwrap();
274 let is_intra = self.decode_frame(&mut br, &mut buf)?;
276 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
277 frm.set_keyframe(is_intra);
278 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
281 fn flush(&mut self) {
287 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
288 Box::new(VMDVideoDecoder::new())
291 #[derive(Clone,Copy,PartialEq)]
298 struct VMDAudioDecoder {
300 info: Arc<NACodecInfo>,
306 last_byte: Option<u8>,
311 const SOL_AUD_STEPS16: [i16; 128] = [
312 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
313 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
314 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
315 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
316 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
317 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
318 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
319 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
320 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
321 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
322 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
323 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
324 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
325 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
326 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
327 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
330 impl VMDAudioDecoder {
333 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
334 info: NACodecInfo::new_dummy(),
335 chmap: NAChannelMap::new(),
338 mode: VMDAudioMode::U8,
345 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
346 let channels = self.chmap.num_channels();
347 let mut off = [0, off1];
348 for _ in 0..nblocks {
350 for ch in 0..channels {
351 for i in 0..self.blk_align {
352 dst[off[ch] + i] = 0;
354 off[ch] += self.blk_align;
357 let mut pred: [i32; 2] = [0; 2];
358 for ch in 0..channels {
359 pred[ch] = i32::from(br.read_u16le()?);
360 dst[off[ch]] = pred[ch] as i16;
364 let flip_ch = if channels == 2 { 1 } else { 0 };
365 for _ in channels..self.blk_align*channels {
366 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
367 //pred[ch] = pred[ch].max(-32768).min(32767);
368 dst[off[ch]] = pred[ch] as i16;
375 validate!(br.left() == 0);
378 fn pred16(pred: i32, val: u8) -> i32 {
379 if (val & 0x80) != 0 {
380 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
382 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
385 fn cvt_u8(val: u8) -> u8 {
390 impl NADecoder for VMDAudioDecoder {
391 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
392 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
394 let channels = ainfo.get_channels() as usize;
395 let edata = info.get_extradata();
396 let flags = if let Some(ref buf) = edata {
397 validate!(buf.len() >= 2);
398 (buf[0] as u16) | ((buf[1] as u16) << 8)
402 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
403 if ainfo.get_format().get_bits() == 8 {
404 self.blk_size = ainfo.get_block_len();
405 self.blk_align = ainfo.get_block_len() / channels;
406 if (flags & 0x8000) == 0 {
408 self.mode = VMDAudioMode::U8;
410 fmt = SND_S16_FORMAT;
411 self.mode = VMDAudioMode::StereoDPCM;
412 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
415 fmt = SND_S16P_FORMAT;
416 self.blk_size = (ainfo.get_block_len() + 1) * channels;
417 self.blk_align = ainfo.get_block_len();
418 self.mode = VMDAudioMode::DPCM;
420 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
421 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
422 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
425 Err(DecoderError::InvalidData)
428 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
429 let info = pkt.get_stream().get_info();
430 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
431 let pktbuf = pkt.get_buffer();
432 validate!(pktbuf.len() >= 6);
433 let mut mr = MemoryReader::new_read(&pktbuf);
434 let mut br = ByteReader::new(&mut mr);
435 let blk_type = br.read_byte()?;
439 if blk_type == 2 { // initial
440 mask = br.read_u32le()?;
441 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
442 } else if blk_type == 3 { // silence
449 let mut samples = nblocks * self.blk_align;
450 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
451 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
453 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
455 VMDAudioMode::DPCM => {
456 let mut adata = abuf.get_abuf_i16().unwrap();
457 let off1 = adata.get_offset(1);
458 let mut dst = adata.get_data_mut().unwrap();
459 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
461 VMDAudioMode::U8 => {
462 let mut adata = abuf.get_abuf_u8().unwrap();
463 let dst = adata.get_data_mut().unwrap();
466 let channels = self.chmap.num_channels();
467 for _ in 0..nblocks {
469 for i in 0..self.blk_align * channels {
472 } else if channels == 1 {
473 for i in 0..self.blk_size {
474 dst[doff + i] = br.read_byte()?;
477 for i in 0..self.blk_size {
478 let val = Self::cvt_u8(br.read_byte()?);
482 doff += self.blk_align * channels;
486 VMDAudioMode::StereoDPCM => {
487 let mut adata = abuf.get_abuf_i16().unwrap();
488 let dst = adata.get_data_mut().unwrap();
491 let mut ch = self.ch;
492 for _ in 0..nblocks {
493 let put_sample = self.last_byte.is_some();
494 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
495 self.pred[ch] = Self::pred16(self.pred[ch], val);
496 dst[doff] = self.pred[ch] as i16;
499 self.last_byte = None;
502 for i in 0..self.blk_align {
503 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
504 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
508 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
512 self.last_byte = Some(0);
516 for i in 0..self.blk_align {
517 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
518 dst[doff + i * 2] = self.pred[ch] as i16;
519 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
520 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
523 let val = br.read_byte()?;
525 self.pred[ch] = Self::pred16(self.pred[ch], val);
526 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
530 self.last_byte = Some(val);
534 doff += self.blk_align * 2;
541 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
542 frm.set_duration(Some(samples as u64));
543 frm.set_keyframe(true);
546 Err(DecoderError::InvalidData)
549 fn flush(&mut self) {
553 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
554 Box::new(VMDAudioDecoder::new())
559 use nihav_core::codecs::RegisteredDecoders;
560 use nihav_core::demuxers::RegisteredDemuxers;
561 use nihav_codec_support::test::dec_video::*;
562 use crate::game_register_all_codecs;
563 use crate::game_register_all_demuxers;
565 fn test_vmd_video() {
566 let mut dmx_reg = RegisteredDemuxers::new();
567 game_register_all_demuxers(&mut dmx_reg);
568 let mut dec_reg = RegisteredDecoders::new();
569 game_register_all_codecs(&mut dec_reg);
571 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
572 ExpectedTestResult::MD5Frames(vec![
573 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
574 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
575 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
576 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
577 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
578 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
579 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
580 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
581 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
582 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
583 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
586 fn test_vmd_audio_u8() {
587 let mut dmx_reg = RegisteredDemuxers::new();
588 game_register_all_demuxers(&mut dmx_reg);
589 let mut dec_reg = RegisteredDecoders::new();
590 game_register_all_codecs(&mut dec_reg);
592 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
593 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
596 fn test_vmd_audio_s16_old() {
597 let mut dmx_reg = RegisteredDemuxers::new();
598 game_register_all_demuxers(&mut dmx_reg);
599 let mut dec_reg = RegisteredDecoders::new();
600 game_register_all_codecs(&mut dec_reg);
602 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
603 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
606 fn test_vmd_audio_s16_new() {
607 let mut dmx_reg = RegisteredDemuxers::new();
608 game_register_all_demuxers(&mut dmx_reg);
609 let mut dec_reg = RegisteredDecoders::new();
610 game_register_all_codecs(&mut dec_reg);
612 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
613 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));