move IMA ADPCM decoder into codec_support
[nihav.git] / nihav-game / src / codecs / vmd.rs
CommitLineData
9895bd7b
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
b4d5b851 3use nihav_codec_support::codecs::HAMShuffler;
9895bd7b 4use std::str::FromStr;
f45dfcf7 5use std::sync::Arc;
9895bd7b
KS
6
7macro_rules! lz_op {
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()?;
11 $dst[$dpos] = b;
12 $dpos += 1;
13 $window[$wpos] = b;
14 $wpos = ($wpos + 1) & 0xFFF;
15 };
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);
19 $dst[$dpos] = b;
20 $dpos += 1;
21 $window[$wpos] = b;
22 $wpos = ($wpos + 1) & 0xFFF;
23 $off = ($off + 1) & 0xFFF;
24 };
25}
26fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
27 let mut window: [u8; 0x1000] = [0x20; 0x1000];
28
29 let dst_size = br.read_u32le()? as usize;
30 validate!(dst_size <= dst.len());
31 let mut pos;
32 let esc_len;
33 if br.peek_u32le()? == 0x56781234 {
34 br.read_skip(4)?;
35 pos = 0x111;
36 esc_len = 15;
37 } else {
38 pos = 0xFEE;
39 esc_len = 255;
40 }
41
42 let mut opos = 0;
43 while br.left() > 0 && opos < dst_size {
44 let op = br.read_byte()?;
45 if (op == 0xFF) && (br.left() > 8) {
46 for _ in 0..8 {
47 lz_op!(read; dst, opos, window, pos, br, dst_size);
48 }
49 } else {
50 for i in 0..8 {
51 if opos == dst_size { break; }
52 let is_literal = ((op >> i) & 1) != 0;
53 if is_literal {
54 lz_op!(read; dst, opos, window, pos, br, dst_size);
55 } else {
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;
60 if len == esc_len {
61 len = (br.read_byte()? as usize) + esc_len;
62 }
63 for _ in 0..len+3 {
64 lz_op!(copy; dst, opos, window, pos, off, dst_size);
65 }
66 }
67 }
68 }
69 }
70 Ok(())
71}
72
73fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
74 let end = br.tell() + (len as u64);
75 let mut dpos = 0;
76 if (len & 1) != 0 {
77 dst[dpos] = br.read_byte()?;
78 dpos += 1;
79 }
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];
86 br.read_buf(dst)?;
87 } else {
771e522a
KS
88 let val1 = br.read_byte()?;
89 let val2 = br.read_byte()?;
90 for i in (0..len).step_by(2) {
91 dst[dpos + i] = val1;
92 dst[dpos + i + 1] = val2;
9895bd7b
KS
93 }
94 }
95 dpos += len;
96 }
97 Ok(())
98}
99
100fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
101 match method {
102 1 => {
103 for _ in 0..h {
104 let mut x = 0;
105 while x < w {
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];
111 br.read_buf(pix)?;
112 } // otherwise skip already existing data
113 x += len;
114 }
115 dpos += stride;
116 }
117 Ok(false)
118 },
119 2 => {
120 for _ in 0..h {
121 let pix = &mut dst[dpos..][..w];
122 br.read_buf(pix)?;
123 dpos += stride;
124 }
125 Ok(true)
126 },
127 3 => {
128 for _ in 0..h {
129 let mut x = 0;
130 while x < 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 {
137 br.read_skip(1)?;
138 rle_unpack(br, len, pix)?;
139 } else {
140 br.read_buf(pix)?;
141 }
142 } // otherwise data is already there
143 x += len;
144 }
145 dpos += stride;
146 }
147 Ok(false)
148 },
e69b1148 149 _ => Err(DecoderError::InvalidData),
9895bd7b
KS
150 }
151}
152
153struct VMDVideoDecoder {
2422d969 154 info: NACodecInfoRef,
9895bd7b
KS
155 pal: [u8; 768],
156 buf: Vec<u8>,
157 width: usize,
158 height: usize,
73a1eecd
KS
159 xoff: usize,
160 yoff: usize,
9895bd7b
KS
161 hams: HAMShuffler,
162}
163
164impl VMDVideoDecoder {
165 fn new() -> Self {
166 Self {
2422d969 167 info: NACodecInfoRef::default(),
9895bd7b
KS
168 pal: [0; 768],
169 buf: Vec::new(),
170 width: 0,
171 height: 0,
73a1eecd
KS
172 xoff: 0,
173 yoff: 0,
9895bd7b
KS
174 hams: HAMShuffler::default(),
175 }
176 }
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);
1a967e6b 180 let data = buf.get_data_mut().unwrap();
9895bd7b
KS
181 let dst = data.as_mut_slice();
182
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;
187 br.read_skip(1)?;
188 let flags = br.read_byte()?;
189 let has_pal = (flags & 0x02) != 0;
5961ae1d
KS
190 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
191 return Ok(false);
192 }
73a1eecd 193 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
9895bd7b 194 validate!(frame_l >= frame_x && frame_d >= frame_y);
73a1eecd 195 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
9895bd7b
KS
196
197 if has_pal {
198 br.read_skip(2)?;
199 for e in self.pal.iter_mut() {
200 let val = br.read_byte()?;
201 *e = (val << 2) | (val >> 4);
202 }
203 }
204
205 let dpal = &mut dst[paloff..][..768];
206 dpal.copy_from_slice(&self.pal[0..]);
207
208 if br.left() == 0 { return Ok(false); }
209
210 let w = frame_l + 1 - frame_x;
211 let h = frame_d + 1 - frame_y;
73a1eecd 212 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
9895bd7b
KS
213
214 let method = br.read_byte()?;
215 let is_intra;
216 if (method & 0x80) != 0 {
e69b1148 217 validate!(!self.buf.is_empty());
9895bd7b
KS
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)?;
222 } else {
223 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
224 }
225 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
226 }
227}
228
229impl NADecoder for VMDVideoDecoder {
01613464 230 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
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));
2422d969 235 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
9895bd7b
KS
236 validate!(info.get_extradata().is_some());
237
238 if let Some(ref edata) = info.get_extradata() {
239 validate!(edata.len() == 0x330);
240 let unp_size = read_u32le(&edata[800..])? as usize;
ed6c9f8a 241 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
9895bd7b
KS
242 self.buf.resize(unp_size, 0);
243 for i in 0..768 {
244 let el = edata[28 + i];
245 self.pal[i] = (el << 2) | (el >> 4);
246 }
73a1eecd
KS
247 self.xoff = read_u16le(&edata[8..])? as usize;
248 self.yoff = read_u16le(&edata[10..])? as usize;
9895bd7b
KS
249 }
250
251 Ok(())
252 } else {
253 Err(DecoderError::InvalidData)
254 }
255 }
01613464 256 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
257 let src = pkt.get_buffer();
258 validate!(src.len() >= 10);
259
260 let mut mr = MemoryReader::new_read(&src);
261 let mut br = ByteReader::new(&mut mr);
262
263 let mut buf;
264 let bufret = self.hams.clone_ref();
265 if let Some(bbuf) = bufret {
266 buf = bbuf;
267 } else {
e69b1148 268 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
9895bd7b
KS
269 buf = bufinfo.get_vbuf().unwrap();
270 self.hams.add_frame(buf);
271 buf = self.hams.get_output_frame().unwrap();
272 }
273
274 let is_intra = self.decode_frame(&mut br, &mut buf)?;
275
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 });
171860fc 279 Ok(frm.into_ref())
9895bd7b 280 }
f9be4e75
KS
281 fn flush(&mut self) {
282 self.hams.clear();
283 }
9895bd7b
KS
284}
285
286
08a1fab7 287pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
288 Box::new(VMDVideoDecoder::new())
289}
290
f45dfcf7
KS
291#[derive(Clone,Copy,PartialEq)]
292enum VMDAudioMode {
293 U8,
294 DPCM,
295 StereoDPCM,
296}
297
9895bd7b
KS
298struct VMDAudioDecoder {
299 ainfo: NAAudioInfo,
f45dfcf7 300 info: Arc<NACodecInfo>,
9895bd7b 301 chmap: NAChannelMap,
9895bd7b
KS
302 blk_align: usize,
303 blk_size: usize,
f45dfcf7
KS
304 mode: VMDAudioMode,
305 pred: [i32; 2],
306 last_byte: Option<u8>,
307 is_odd: bool,
308 ch: usize,
9895bd7b
KS
309}
310
311const 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
328];
329
330impl VMDAudioDecoder {
331 fn new() -> Self {
332 Self {
333 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
f45dfcf7 334 info: NACodecInfo::new_dummy(),
9895bd7b 335 chmap: NAChannelMap::new(),
9895bd7b
KS
336 blk_align: 0,
337 blk_size: 0,
f45dfcf7
KS
338 mode: VMDAudioMode::U8,
339 pred: [0; 2],
340 last_byte: None,
341 is_odd: false,
342 ch: 0,
9895bd7b
KS
343 }
344 }
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 {
349 if (mask & 1) != 0 {
350 for ch in 0..channels {
351 for i in 0..self.blk_align {
352 dst[off[ch] + i] = 0;
353 }
354 off[ch] += self.blk_align;
355 }
356 } else {
357 let mut pred: [i32; 2] = [0; 2];
358 for ch in 0..channels {
e69b1148 359 pred[ch] = i32::from(br.read_u16le()?);
9895bd7b
KS
360 dst[off[ch]] = pred[ch] as i16;
361 off[ch] += 1;
362 }
363 let mut ch = 0;
364 let flip_ch = if channels == 2 { 1 } else { 0 };
aa7e65d2 365 for _ in channels..self.blk_align*channels {
f45dfcf7 366 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
9895bd7b
KS
367 //pred[ch] = pred[ch].max(-32768).min(32767);
368 dst[off[ch]] = pred[ch] as i16;
369 off[ch] += 1;
370 ch ^= flip_ch;
371 }
372 }
373 mask >>= 1;
374 }
375 validate!(br.left() == 0);
376 Ok(())
377 }
f45dfcf7
KS
378 fn pred16(pred: i32, val: u8) -> i32 {
379 if (val & 0x80) != 0 {
380 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
381 } else {
382 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
383 }
384 }
385 fn cvt_u8(val: u8) -> u8 {
6eda3136 386 val ^ 0x80
f45dfcf7 387 }
9895bd7b
KS
388}
389
390impl NADecoder for VMDAudioDecoder {
01613464 391 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
392 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
393 let fmt;
f45dfcf7
KS
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)
399 } else {
400 0
401 };
402 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
9895bd7b 403 if ainfo.get_format().get_bits() == 8 {
9895bd7b 404 self.blk_size = ainfo.get_block_len();
f45dfcf7
KS
405 self.blk_align = ainfo.get_block_len() / channels;
406 if (flags & 0x8000) == 0 {
407 fmt = SND_U8_FORMAT;
408 self.mode = VMDAudioMode::U8;
409 } else {
410 fmt = SND_S16_FORMAT;
411 self.mode = VMDAudioMode::StereoDPCM;
412 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
413 }
9895bd7b
KS
414 } else {
415 fmt = SND_S16P_FORMAT;
f45dfcf7 416 self.blk_size = (ainfo.get_block_len() + 1) * channels;
aa7e65d2 417 self.blk_align = ainfo.get_block_len();
f45dfcf7 418 self.mode = VMDAudioMode::DPCM;
9895bd7b 419 };
9895bd7b 420 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
f45dfcf7
KS
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();
9895bd7b
KS
423 Ok(())
424 } else {
425 Err(DecoderError::InvalidData)
426 }
427 }
01613464 428 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
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()?;
436 br.read_skip(9)?;
437 let mask;
438 let nblocks;
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
443 mask = 1;
444 nblocks = 1;
445 } else {
446 mask = 0;
447 nblocks = 1;
448 }
f45dfcf7
KS
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;
452 }
9895bd7b 453 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
f45dfcf7
KS
454 match self.mode {
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)?;
460 },
461 VMDAudioMode::U8 => {
462 let mut adata = abuf.get_abuf_u8().unwrap();
463 let dst = adata.get_data_mut().unwrap();
464 let mut doff = 0;
465 let mut mask = mask;
466 let channels = self.chmap.num_channels();
467 for _ in 0..nblocks {
468 if (mask & 1) != 0 {
469 for i in 0..self.blk_align * channels {
470 dst[doff + i] = 128;
471 }
472 } else if channels == 1 {
473 for i in 0..self.blk_size {
474 dst[doff + i] = br.read_byte()?;
475 }
476 } else {
477 for i in 0..self.blk_size {
478 let val = Self::cvt_u8(br.read_byte()?);
479 dst[doff + i] = val;
480 }
9895bd7b 481 }
f45dfcf7
KS
482 doff += self.blk_align * channels;
483 mask >>= 1;
484 }
485 },
486 VMDAudioMode::StereoDPCM => {
487 let mut adata = abuf.get_abuf_i16().unwrap();
488 let dst = adata.get_data_mut().unwrap();
489 let mut doff = 0;
490 let mut mask = mask;
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;
497 doff += 1;
498 ch ^= 1;
499 self.last_byte = None;
9895bd7b 500 }
f45dfcf7
KS
501 if (mask & 1) != 0 {
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;
505 }
506 if self.is_odd {
507 if put_sample {
508 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
509 doff += 1;
510 ch ^= 1;
511 } else {
512 self.last_byte = Some(0);
513 }
514 }
515 } else {
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;
521 }
522 if self.is_odd {
523 let val = br.read_byte()?;
524 if put_sample {
525 self.pred[ch] = Self::pred16(self.pred[ch], val);
526 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
527 doff += 1;
528 ch ^= 1;
529 } else {
530 self.last_byte = Some(val);
531 }
aa7e65d2
KS
532 }
533 }
f45dfcf7
KS
534 doff += self.blk_align * 2;
535 mask >>= 1;
9895bd7b 536 }
f45dfcf7
KS
537 self.ch = ch;
538 },
539 };
9895bd7b 540
f45dfcf7 541 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
9895bd7b
KS
542 frm.set_duration(Some(samples as u64));
543 frm.set_keyframe(true);
171860fc 544 Ok(frm.into_ref())
9895bd7b
KS
545 } else {
546 Err(DecoderError::InvalidData)
547 }
548 }
f9be4e75
KS
549 fn flush(&mut self) {
550 }
9895bd7b
KS
551}
552
08a1fab7 553pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
554 Box::new(VMDAudioDecoder::new())
555}
556
557#[cfg(test)]
558mod test {
559 use nihav_core::codecs::RegisteredDecoders;
560 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 561 use nihav_codec_support::test::dec_video::*;
e64739f8
KS
562 use crate::game_register_all_codecs;
563 use crate::game_register_all_demuxers;
9895bd7b
KS
564 #[test]
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);
570
fe435580
KS
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]]));
9895bd7b
KS
584 }
585 #[test]
fe435580 586 fn test_vmd_audio_u8() {
9895bd7b
KS
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);
591
fe435580
KS
592 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
593 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
594 }
595 #[test]
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);
601
602 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
603 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
604 }
605 #[test]
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);
611
612 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
613 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
9895bd7b
KS
614 }
615}