vmd: take global picture offset into account when decoding frames
[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 {
88 let val = br.read_byte()?;
89 for i in 0..len {
90 dst[dpos + i] = val;
91 }
92 }
93 dpos += len;
94 }
95 Ok(())
96}
97
98fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
99 match method {
100 1 => {
101 for _ in 0..h {
102 let mut x = 0;
103 while x < w {
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];
109 br.read_buf(pix)?;
110 } // otherwise skip already existing data
111 x += len;
112 }
113 dpos += stride;
114 }
115 Ok(false)
116 },
117 2 => {
118 for _ in 0..h {
119 let pix = &mut dst[dpos..][..w];
120 br.read_buf(pix)?;
121 dpos += stride;
122 }
123 Ok(true)
124 },
125 3 => {
126 for _ in 0..h {
127 let mut x = 0;
128 while x < 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 {
135 br.read_skip(1)?;
136 rle_unpack(br, len, pix)?;
137 } else {
138 br.read_buf(pix)?;
139 }
140 } // otherwise data is already there
141 x += len;
142 }
143 dpos += stride;
144 }
145 Ok(false)
146 },
e69b1148 147 _ => Err(DecoderError::InvalidData),
9895bd7b
KS
148 }
149}
150
151struct VMDVideoDecoder {
2422d969 152 info: NACodecInfoRef,
9895bd7b
KS
153 pal: [u8; 768],
154 buf: Vec<u8>,
155 width: usize,
156 height: usize,
73a1eecd
KS
157 xoff: usize,
158 yoff: usize,
9895bd7b
KS
159 hams: HAMShuffler,
160}
161
162impl VMDVideoDecoder {
163 fn new() -> Self {
164 Self {
2422d969 165 info: NACodecInfoRef::default(),
9895bd7b
KS
166 pal: [0; 768],
167 buf: Vec::new(),
168 width: 0,
169 height: 0,
73a1eecd
KS
170 xoff: 0,
171 yoff: 0,
9895bd7b
KS
172 hams: HAMShuffler::default(),
173 }
174 }
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);
1a967e6b 178 let data = buf.get_data_mut().unwrap();
9895bd7b
KS
179 let dst = data.as_mut_slice();
180
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;
185 br.read_skip(1)?;
186 let flags = br.read_byte()?;
187 let has_pal = (flags & 0x02) != 0;
5961ae1d
KS
188 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
189 return Ok(false);
190 }
73a1eecd 191 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
9895bd7b 192 validate!(frame_l >= frame_x && frame_d >= frame_y);
73a1eecd 193 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
9895bd7b
KS
194
195 if has_pal {
196 br.read_skip(2)?;
197 for e in self.pal.iter_mut() {
198 let val = br.read_byte()?;
199 *e = (val << 2) | (val >> 4);
200 }
201 }
202
203 let dpal = &mut dst[paloff..][..768];
204 dpal.copy_from_slice(&self.pal[0..]);
205
206 if br.left() == 0 { return Ok(false); }
207
208 let w = frame_l + 1 - frame_x;
209 let h = frame_d + 1 - frame_y;
73a1eecd 210 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
9895bd7b
KS
211
212 let method = br.read_byte()?;
213 let is_intra;
214 if (method & 0x80) != 0 {
e69b1148 215 validate!(!self.buf.is_empty());
9895bd7b
KS
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)?;
220 } else {
221 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
222 }
223 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
224 }
225}
226
227impl NADecoder for VMDVideoDecoder {
01613464 228 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
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));
2422d969 233 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
9895bd7b
KS
234 validate!(info.get_extradata().is_some());
235
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 * 3 + 64); // just for sanity
240 self.buf.resize(unp_size, 0);
241 for i in 0..768 {
242 let el = edata[28 + i];
243 self.pal[i] = (el << 2) | (el >> 4);
244 }
73a1eecd
KS
245 self.xoff = read_u16le(&edata[8..])? as usize;
246 self.yoff = read_u16le(&edata[10..])? as usize;
9895bd7b
KS
247 }
248
249 Ok(())
250 } else {
251 Err(DecoderError::InvalidData)
252 }
253 }
01613464 254 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
255 let src = pkt.get_buffer();
256 validate!(src.len() >= 10);
257
258 let mut mr = MemoryReader::new_read(&src);
259 let mut br = ByteReader::new(&mut mr);
260
261 let mut buf;
262 let bufret = self.hams.clone_ref();
263 if let Some(bbuf) = bufret {
264 buf = bbuf;
265 } else {
e69b1148 266 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
9895bd7b
KS
267 buf = bufinfo.get_vbuf().unwrap();
268 self.hams.add_frame(buf);
269 buf = self.hams.get_output_frame().unwrap();
270 }
271
272 let is_intra = self.decode_frame(&mut br, &mut buf)?;
273
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 });
171860fc 277 Ok(frm.into_ref())
9895bd7b 278 }
f9be4e75
KS
279 fn flush(&mut self) {
280 self.hams.clear();
281 }
9895bd7b
KS
282}
283
284
08a1fab7 285pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
286 Box::new(VMDVideoDecoder::new())
287}
288
f45dfcf7
KS
289#[derive(Clone,Copy,PartialEq)]
290enum VMDAudioMode {
291 U8,
292 DPCM,
293 StereoDPCM,
294}
295
9895bd7b
KS
296struct VMDAudioDecoder {
297 ainfo: NAAudioInfo,
f45dfcf7 298 info: Arc<NACodecInfo>,
9895bd7b 299 chmap: NAChannelMap,
9895bd7b
KS
300 blk_align: usize,
301 blk_size: usize,
f45dfcf7
KS
302 mode: VMDAudioMode,
303 pred: [i32; 2],
304 last_byte: Option<u8>,
305 is_odd: bool,
306 ch: usize,
9895bd7b
KS
307}
308
309const 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
326];
327
328impl VMDAudioDecoder {
329 fn new() -> Self {
330 Self {
331 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
f45dfcf7 332 info: NACodecInfo::new_dummy(),
9895bd7b 333 chmap: NAChannelMap::new(),
9895bd7b
KS
334 blk_align: 0,
335 blk_size: 0,
f45dfcf7
KS
336 mode: VMDAudioMode::U8,
337 pred: [0; 2],
338 last_byte: None,
339 is_odd: false,
340 ch: 0,
9895bd7b
KS
341 }
342 }
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 {
347 if (mask & 1) != 0 {
348 for ch in 0..channels {
349 for i in 0..self.blk_align {
350 dst[off[ch] + i] = 0;
351 }
352 off[ch] += self.blk_align;
353 }
354 } else {
355 let mut pred: [i32; 2] = [0; 2];
356 for ch in 0..channels {
e69b1148 357 pred[ch] = i32::from(br.read_u16le()?);
9895bd7b
KS
358 dst[off[ch]] = pred[ch] as i16;
359 off[ch] += 1;
360 }
361 let mut ch = 0;
362 let flip_ch = if channels == 2 { 1 } else { 0 };
aa7e65d2 363 for _ in channels..self.blk_align*channels {
f45dfcf7 364 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
9895bd7b
KS
365 //pred[ch] = pred[ch].max(-32768).min(32767);
366 dst[off[ch]] = pred[ch] as i16;
367 off[ch] += 1;
368 ch ^= flip_ch;
369 }
370 }
371 mask >>= 1;
372 }
373 validate!(br.left() == 0);
374 Ok(())
375 }
f45dfcf7
KS
376 fn pred16(pred: i32, val: u8) -> i32 {
377 if (val & 0x80) != 0 {
378 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
379 } else {
380 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
381 }
382 }
383 fn cvt_u8(val: u8) -> u8 {
6eda3136 384 val ^ 0x80
f45dfcf7 385 }
9895bd7b
KS
386}
387
388impl NADecoder for VMDAudioDecoder {
01613464 389 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
390 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
391 let fmt;
f45dfcf7
KS
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)
397 } else {
398 0
399 };
400 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
9895bd7b 401 if ainfo.get_format().get_bits() == 8 {
9895bd7b 402 self.blk_size = ainfo.get_block_len();
f45dfcf7
KS
403 self.blk_align = ainfo.get_block_len() / channels;
404 if (flags & 0x8000) == 0 {
405 fmt = SND_U8_FORMAT;
406 self.mode = VMDAudioMode::U8;
407 } else {
408 fmt = SND_S16_FORMAT;
409 self.mode = VMDAudioMode::StereoDPCM;
410 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
411 }
9895bd7b
KS
412 } else {
413 fmt = SND_S16P_FORMAT;
f45dfcf7 414 self.blk_size = (ainfo.get_block_len() + 1) * channels;
aa7e65d2 415 self.blk_align = ainfo.get_block_len();
f45dfcf7 416 self.mode = VMDAudioMode::DPCM;
9895bd7b 417 };
9895bd7b 418 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
f45dfcf7
KS
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();
9895bd7b
KS
421 Ok(())
422 } else {
423 Err(DecoderError::InvalidData)
424 }
425 }
01613464 426 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
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()?;
434 br.read_skip(9)?;
435 let mask;
436 let nblocks;
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
441 mask = 1;
442 nblocks = 1;
443 } else {
444 mask = 0;
445 nblocks = 1;
446 }
f45dfcf7
KS
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;
450 }
9895bd7b 451 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
f45dfcf7
KS
452 match self.mode {
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)?;
458 },
459 VMDAudioMode::U8 => {
460 let mut adata = abuf.get_abuf_u8().unwrap();
461 let dst = adata.get_data_mut().unwrap();
462 let mut doff = 0;
463 let mut mask = mask;
464 let channels = self.chmap.num_channels();
465 for _ in 0..nblocks {
466 if (mask & 1) != 0 {
467 for i in 0..self.blk_align * channels {
468 dst[doff + i] = 128;
469 }
470 } else if channels == 1 {
471 for i in 0..self.blk_size {
472 dst[doff + i] = br.read_byte()?;
473 }
474 } else {
475 for i in 0..self.blk_size {
476 let val = Self::cvt_u8(br.read_byte()?);
477 dst[doff + i] = val;
478 }
9895bd7b 479 }
f45dfcf7
KS
480 doff += self.blk_align * channels;
481 mask >>= 1;
482 }
483 },
484 VMDAudioMode::StereoDPCM => {
485 let mut adata = abuf.get_abuf_i16().unwrap();
486 let dst = adata.get_data_mut().unwrap();
487 let mut doff = 0;
488 let mut mask = mask;
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;
495 doff += 1;
496 ch ^= 1;
497 self.last_byte = None;
9895bd7b 498 }
f45dfcf7
KS
499 if (mask & 1) != 0 {
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;
503 }
504 if self.is_odd {
505 if put_sample {
506 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
507 doff += 1;
508 ch ^= 1;
509 } else {
510 self.last_byte = Some(0);
511 }
512 }
513 } else {
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;
519 }
520 if self.is_odd {
521 let val = br.read_byte()?;
522 if put_sample {
523 self.pred[ch] = Self::pred16(self.pred[ch], val);
524 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
525 doff += 1;
526 ch ^= 1;
527 } else {
528 self.last_byte = Some(val);
529 }
aa7e65d2
KS
530 }
531 }
f45dfcf7
KS
532 doff += self.blk_align * 2;
533 mask >>= 1;
9895bd7b 534 }
f45dfcf7
KS
535 self.ch = ch;
536 },
537 };
9895bd7b 538
f45dfcf7 539 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
9895bd7b
KS
540 frm.set_duration(Some(samples as u64));
541 frm.set_keyframe(true);
171860fc 542 Ok(frm.into_ref())
9895bd7b
KS
543 } else {
544 Err(DecoderError::InvalidData)
545 }
546 }
f9be4e75
KS
547 fn flush(&mut self) {
548 }
9895bd7b
KS
549}
550
08a1fab7 551pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
552 Box::new(VMDAudioDecoder::new())
553}
554
555#[cfg(test)]
556mod test {
557 use nihav_core::codecs::RegisteredDecoders;
558 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 559 use nihav_codec_support::test::dec_video::*;
e64739f8
KS
560 use crate::game_register_all_codecs;
561 use crate::game_register_all_demuxers;
9895bd7b
KS
562 #[test]
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);
568
fe435580
KS
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]]));
9895bd7b
KS
582 }
583 #[test]
fe435580 584 fn test_vmd_audio_u8() {
9895bd7b
KS
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);
589
fe435580
KS
590 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
591 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
592 }
593 #[test]
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);
599
600 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
601 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
602 }
603 #[test]
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);
609
610 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
611 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
9895bd7b
KS
612 }
613}