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,
162 impl VMDVideoDecoder {
165 info: NACodecInfoRef::default(),
172 hams: HAMShuffler::default(),
175 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
176 let paloff = buf.get_offset(1);
177 let stride = buf.get_stride(0);
178 let data = buf.get_data_mut().unwrap();
179 let dst = data.as_mut_slice();
181 let frame_x = br.read_u16le()? as usize;
182 let frame_y = br.read_u16le()? as usize;
183 let frame_l = br.read_u16le()? as usize;
184 let frame_d = br.read_u16le()? as usize;
186 let flags = br.read_byte()?;
187 let has_pal = (flags & 0x02) != 0;
188 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
191 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
192 validate!(frame_l >= frame_x && frame_d >= frame_y);
193 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
197 for e in self.pal.iter_mut() {
198 let val = br.read_byte()?;
199 *e = (val << 2) | (val >> 4);
203 let dpal = &mut dst[paloff..][..768];
204 dpal.copy_from_slice(&self.pal[0..]);
206 if br.left() == 0 { return Ok(false); }
208 let w = frame_l + 1 - frame_x;
209 let h = frame_d + 1 - frame_y;
210 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
212 let method = br.read_byte()?;
214 if (method & 0x80) != 0 {
215 validate!(!self.buf.is_empty());
216 lz_unpack(br, &mut self.buf)?;
217 let mut mr = MemoryReader::new_read(&self.buf);
218 let mut buf_br = ByteReader::new(&mut mr);
219 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
221 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
223 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
227 impl NADecoder for VMDVideoDecoder {
228 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
229 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
230 self.width = vinfo.get_width();
231 self.height = vinfo.get_height();
232 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
233 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
234 validate!(info.get_extradata().is_some());
236 if let Some(ref edata) = info.get_extradata() {
237 validate!(edata.len() == 0x330);
238 let unp_size = read_u32le(&edata[800..])? as usize;
239 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
240 self.buf.resize(unp_size, 0);
242 let el = edata[28 + i];
243 self.pal[i] = (el << 2) | (el >> 4);
245 self.xoff = read_u16le(&edata[8..])? as usize;
246 self.yoff = read_u16le(&edata[10..])? as usize;
251 Err(DecoderError::InvalidData)
254 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
255 let src = pkt.get_buffer();
256 validate!(src.len() >= 10);
258 let mut mr = MemoryReader::new_read(&src);
259 let mut br = ByteReader::new(&mut mr);
262 let bufret = self.hams.clone_ref();
263 if let Some(bbuf) = bufret {
266 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
267 buf = bufinfo.get_vbuf().unwrap();
268 self.hams.add_frame(buf);
269 buf = self.hams.get_output_frame().unwrap();
272 let is_intra = self.decode_frame(&mut br, &mut buf)?;
274 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
275 frm.set_keyframe(is_intra);
276 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
279 fn flush(&mut self) {
285 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
286 Box::new(VMDVideoDecoder::new())
289 #[derive(Clone,Copy,PartialEq)]
296 struct VMDAudioDecoder {
298 info: Arc<NACodecInfo>,
304 last_byte: Option<u8>,
309 const SOL_AUD_STEPS16: [i16; 128] = [
310 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
311 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
312 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
313 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
314 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
315 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
316 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
317 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
318 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
319 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
320 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
321 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
322 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
323 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
324 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
325 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
328 impl VMDAudioDecoder {
331 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
332 info: NACodecInfo::new_dummy(),
333 chmap: NAChannelMap::new(),
336 mode: VMDAudioMode::U8,
343 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
344 let channels = self.chmap.num_channels();
345 let mut off = [0, off1];
346 for _ in 0..nblocks {
348 for ch in 0..channels {
349 for i in 0..self.blk_align {
350 dst[off[ch] + i] = 0;
352 off[ch] += self.blk_align;
355 let mut pred: [i32; 2] = [0; 2];
356 for ch in 0..channels {
357 pred[ch] = i32::from(br.read_u16le()?);
358 dst[off[ch]] = pred[ch] as i16;
362 let flip_ch = if channels == 2 { 1 } else { 0 };
363 for _ in channels..self.blk_align*channels {
364 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
365 //pred[ch] = pred[ch].max(-32768).min(32767);
366 dst[off[ch]] = pred[ch] as i16;
373 validate!(br.left() == 0);
376 fn pred16(pred: i32, val: u8) -> i32 {
377 if (val & 0x80) != 0 {
378 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
380 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
383 fn cvt_u8(val: u8) -> u8 {
388 impl NADecoder for VMDAudioDecoder {
389 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
390 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
392 let channels = ainfo.get_channels() as usize;
393 let edata = info.get_extradata();
394 let flags = if let Some(ref buf) = edata {
395 validate!(buf.len() >= 2);
396 (buf[0] as u16) | ((buf[1] as u16) << 8)
400 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
401 if ainfo.get_format().get_bits() == 8 {
402 self.blk_size = ainfo.get_block_len();
403 self.blk_align = ainfo.get_block_len() / channels;
404 if (flags & 0x8000) == 0 {
406 self.mode = VMDAudioMode::U8;
408 fmt = SND_S16_FORMAT;
409 self.mode = VMDAudioMode::StereoDPCM;
410 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
413 fmt = SND_S16P_FORMAT;
414 self.blk_size = (ainfo.get_block_len() + 1) * channels;
415 self.blk_align = ainfo.get_block_len();
416 self.mode = VMDAudioMode::DPCM;
418 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
419 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
420 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
423 Err(DecoderError::InvalidData)
426 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
427 let info = pkt.get_stream().get_info();
428 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
429 let pktbuf = pkt.get_buffer();
430 validate!(pktbuf.len() >= 6);
431 let mut mr = MemoryReader::new_read(&pktbuf);
432 let mut br = ByteReader::new(&mut mr);
433 let blk_type = br.read_byte()?;
437 if blk_type == 2 { // initial
438 mask = br.read_u32le()?;
439 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
440 } else if blk_type == 3 { // silence
447 let mut samples = nblocks * self.blk_align;
448 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
449 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
451 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
453 VMDAudioMode::DPCM => {
454 let mut adata = abuf.get_abuf_i16().unwrap();
455 let off1 = adata.get_offset(1);
456 let mut dst = adata.get_data_mut().unwrap();
457 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
459 VMDAudioMode::U8 => {
460 let mut adata = abuf.get_abuf_u8().unwrap();
461 let dst = adata.get_data_mut().unwrap();
464 let channels = self.chmap.num_channels();
465 for _ in 0..nblocks {
467 for i in 0..self.blk_align * channels {
470 } else if channels == 1 {
471 for i in 0..self.blk_size {
472 dst[doff + i] = br.read_byte()?;
475 for i in 0..self.blk_size {
476 let val = Self::cvt_u8(br.read_byte()?);
480 doff += self.blk_align * channels;
484 VMDAudioMode::StereoDPCM => {
485 let mut adata = abuf.get_abuf_i16().unwrap();
486 let dst = adata.get_data_mut().unwrap();
489 let mut ch = self.ch;
490 for _ in 0..nblocks {
491 let put_sample = self.last_byte.is_some();
492 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
493 self.pred[ch] = Self::pred16(self.pred[ch], val);
494 dst[doff] = self.pred[ch] as i16;
497 self.last_byte = None;
500 for i in 0..self.blk_align {
501 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
502 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
506 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
510 self.last_byte = Some(0);
514 for i in 0..self.blk_align {
515 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
516 dst[doff + i * 2] = self.pred[ch] as i16;
517 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
518 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
521 let val = br.read_byte()?;
523 self.pred[ch] = Self::pred16(self.pred[ch], val);
524 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
528 self.last_byte = Some(val);
532 doff += self.blk_align * 2;
539 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
540 frm.set_duration(Some(samples as u64));
541 frm.set_keyframe(true);
544 Err(DecoderError::InvalidData)
547 fn flush(&mut self) {
551 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
552 Box::new(VMDAudioDecoder::new())
557 use nihav_core::codecs::RegisteredDecoders;
558 use nihav_core::demuxers::RegisteredDemuxers;
559 use nihav_codec_support::test::dec_video::*;
560 use crate::game_register_all_codecs;
561 use crate::game_register_all_demuxers;
563 fn test_vmd_video() {
564 let mut dmx_reg = RegisteredDemuxers::new();
565 game_register_all_demuxers(&mut dmx_reg);
566 let mut dec_reg = RegisteredDecoders::new();
567 game_register_all_codecs(&mut dec_reg);
569 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
570 ExpectedTestResult::MD5Frames(vec![
571 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
572 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
573 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
574 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
575 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
576 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
577 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
578 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
579 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
580 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
581 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
584 fn test_vmd_audio_u8() {
585 let mut dmx_reg = RegisteredDemuxers::new();
586 game_register_all_demuxers(&mut dmx_reg);
587 let mut dec_reg = RegisteredDecoders::new();
588 game_register_all_codecs(&mut dec_reg);
590 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
591 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
594 fn test_vmd_audio_s16_old() {
595 let mut dmx_reg = RegisteredDemuxers::new();
596 game_register_all_demuxers(&mut dmx_reg);
597 let mut dec_reg = RegisteredDecoders::new();
598 game_register_all_codecs(&mut dec_reg);
600 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
601 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
604 fn test_vmd_audio_s16_new() {
605 let mut dmx_reg = RegisteredDemuxers::new();
606 game_register_all_demuxers(&mut dmx_reg);
607 let mut dec_reg = RegisteredDecoders::new();
608 game_register_all_codecs(&mut dec_reg);
610 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
611 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));