]> git.nihav.org Git - nihav.git/blame - nihav-game/src/codecs/gremlinvideo.rs
mov: support segmented files
[nihav.git] / nihav-game / src / codecs / gremlinvideo.rs
CommitLineData
5641dccf
KS
1use nihav_core::frame::*;
2use nihav_core::formats;
3use nihav_core::formats::{NAChannelType, NAChannelMap};
4use nihav_core::codecs::*;
5use nihav_core::io::byteio::*;
e120f8fd
KS
6
7struct GremlinVideoDecoder {
2422d969 8 info: NACodecInfoRef,
e120f8fd
KS
9 pal: [u8; 768],
10 frame: Vec<u8>,
11 scale_v: bool,
12 scale_h: bool,
13}
14
8e652498
KS
15struct Bits8 {
16 queue: u8,
e120f8fd
KS
17 fill: u8,
18}
19
20struct Bits32 {
21 queue: u32,
22 fill: u8,
23}
24
25const PREAMBLE_SIZE: usize = 4096;
26
8e652498
KS
27impl Bits8 {
28 fn new() -> Self { Bits8 { queue: 0, fill: 0 } }
29 fn read_2bits(&mut self, br: &mut ByteReader) -> ByteIOResult<u8> {
e120f8fd 30 if self.fill == 0 {
8e652498 31 self.queue = br.read_byte()?;
e120f8fd
KS
32 self.fill += 8;
33 }
8e652498
KS
34 let res = self.queue >> 6;
35 self.queue <<= 2;
e120f8fd
KS
36 self.fill -= 2;
37 Ok(res)
38 }
39}
40
41impl Bits32 {
42 fn new() -> Self { Bits32 { queue: 0, fill: 0 } }
43 fn fill(&mut self, br: &mut ByteReader) -> ByteIOResult<()> {
44 self.queue = br.read_u32le()?;
45 self.fill = 32;
46 Ok(())
47 }
48 fn read_bits(&mut self, br: &mut ByteReader, nbits: u8) -> ByteIOResult<u32> {
49 let res = self.queue & ((1 << nbits) - 1);
50 self.queue >>= nbits;
51 self.fill -= nbits;
52 if self.fill <= 16 {
e69b1148 53 self.queue |= u32::from(br.read_u16le()?) << self.fill;
e120f8fd
KS
54 self.fill += 16;
55 }
56 Ok(res)
57 }
58}
59
60impl GremlinVideoDecoder {
61 fn new() -> Self {
e120f8fd 62 GremlinVideoDecoder {
2422d969 63 info: NACodecInfoRef::default(), pal: [0; 768], frame: Vec::new(),
e120f8fd
KS
64 scale_v: false, scale_h: false
65 }
66 }
67
68 fn lz_copy(&mut self, idx: usize, offset: isize, len: usize) -> DecoderResult<()> {
69 if idx + len > self.frame.len() { return Err(DecoderError::InvalidData); }
70 if offset == -1 {
71 let c = self.frame[idx - 1];
72 for i in 0..len { self.frame[idx + i] = c; }
73 } else if offset < 0 {
74 let start = idx - (-offset as usize);
75 for i in 0..len { self.frame[idx + i] = self.frame[start + i]; }
76 } else {
77 if idx + (offset as usize) + len > self.frame.len() { return Err(DecoderError::InvalidData); }
78 let start = idx + (offset as usize);
79 for i in 0..len { self.frame[idx + i] = self.frame[start + i]; }
80 }
81 Ok(())
82 }
83
84 fn rescale(&mut self, w: usize, h: usize, scale_v: bool, scale_h: bool) {
85 if (self.scale_v == scale_v) && (self.scale_h == scale_h) { return; }
86
87 if self.scale_h && self.scale_v {
88 for j in 0..h {
89 let y = h - j - 1;
90 for i in 0..w {
91 let x = w - i - 1;
92 self.frame[PREAMBLE_SIZE + x + y * w] = self.frame[PREAMBLE_SIZE + x/2 + (y/2) * (w/2)];
93 }
94 }
95 } else if self.scale_h {
96 for j in 0..h {
97 let y = h - j - 1;
98 for x in 0..w {
99 self.frame[PREAMBLE_SIZE + x + y * w] = self.frame[PREAMBLE_SIZE + x + (y/2) * w];
100 }
101 }
102 } else if self.scale_v {
103 for j in 0..h {
104 let y = h - j - 1;
105 for i in 0..w {
106 let x = w - i - 1;
107 self.frame[PREAMBLE_SIZE + x + y * w] = self.frame[PREAMBLE_SIZE + x/2 + y * (w/2)];
108 }
109 }
110 }
111
112 if scale_h && scale_v {
113 for y in 0..h/2 {
114 for x in 0..w/2 {
115 self.frame[PREAMBLE_SIZE + x + y * (w/2)] = self.frame[PREAMBLE_SIZE + x*2 + y*2 * w];
116 }
117 }
118 } else if scale_h {
119 for y in 0..h/2 {
120 for x in 0..w {
121 self.frame[PREAMBLE_SIZE + x + y * w] = self.frame[PREAMBLE_SIZE + x + y*2 * w];
122 }
123 }
124 } else if scale_v {
125 for y in 0..h {
126 for x in 0..w/2 {
127 self.frame[PREAMBLE_SIZE + x + y * w] = self.frame[PREAMBLE_SIZE + x*2 + y * w];
128 }
129 }
130 }
131
132 self.scale_v = scale_v;
133 self.scale_h = scale_h;
134 }
135
136 fn output_frame(&mut self, bufinfo: &mut NABufferType, w: usize, h: usize) {
137 let bufo = bufinfo.get_vbuf();
138 let mut buf = bufo.unwrap();
139 let paloff = buf.get_offset(1);
140 let stride = buf.get_stride(0);
1a967e6b 141 let data = buf.get_data_mut().unwrap();
9037cf6b 142 let dst = data.as_mut_slice();
e120f8fd
KS
143 let mut sidx = PREAMBLE_SIZE;
144 let mut didx = 0;
145
7450554d 146 dst[paloff..][..768].copy_from_slice(&self.pal);
e120f8fd
KS
147 if !self.scale_v && !self.scale_h {
148 for _ in 0..h {
7450554d 149 dst[didx..][..w].copy_from_slice(&self.frame[sidx..][..w]);
e120f8fd
KS
150 sidx += w;
151 didx += stride;
152 }
153 } else {
154 for y in 0..h {
155 if !self.scale_v {
7450554d 156 dst[didx..][..w].copy_from_slice(&self.frame[sidx..][..w]);
e120f8fd
KS
157 } else {
158 for x in 0..w { dst[didx + x] = self.frame[sidx + x/2]; }
159 }
160 if !self.scale_h || ((y & 1) == 1) {
161 sidx += if !self.scale_v { w } else { w/2 };
162 }
163 didx += stride;
164 }
165 }
166 }
167
168 fn decode_method2(&mut self, br: &mut ByteReader) -> DecoderResult<()> {
8e652498 169 let mut bits = Bits8::new();
e120f8fd
KS
170
171 let mut size = self.info.get_properties().get_video_info().unwrap().get_width() *
172 self.info.get_properties().get_video_info().unwrap().get_height();
173 let mut idx = PREAMBLE_SIZE;
8e652498
KS
174 if self.frame[8] != 0 {
175 for c in 0..256 {
176 for i in 0..16 { self.frame[c * 16 + i] = c as u8; }
177 }
e120f8fd
KS
178 }
179 while size > 0 {
180 let tag = bits.read_2bits(br)?;
181 if tag == 0 {
182 self.frame[idx] = br.read_byte()?;
183 size -= 1;
184 idx += 1;
185 } else if tag == 1 {
186 let b = br.read_byte()?;
187 let len = ((b & 0xF) as usize) + 3;
8e652498
KS
188 let bot = (b >> 4) as isize;
189 let off = ((br.read_byte()? as isize) << 4) + bot - 4096;
e120f8fd
KS
190 validate!(len <= size);
191 size -= len;
8e652498 192 self.lz_copy(idx, off, len)?;
e120f8fd
KS
193 idx += len;
194 } else if tag == 2 {
195 let len = (br.read_byte()? as usize) + 2;
196 validate!(len <= size);
197 size -= len;
198 idx += len;
199 } else {
200 break;
201 }
202 }
203 Ok(())
204 }
205
206 fn decode_method5(&mut self, br: &mut ByteReader, skip: usize) -> DecoderResult<()> {
8e652498 207 let mut bits = Bits8::new();
e120f8fd
KS
208
209 let mut size = self.info.get_properties().get_video_info().unwrap().get_width() *
210 self.info.get_properties().get_video_info().unwrap().get_height();
211 let mut idx = PREAMBLE_SIZE;
212 validate!(size >= skip);
213 size -= skip;
214 idx += skip;
215 while size > 0 {
216 let tag = bits.read_2bits(br)?;
217 if tag == 0 {
218 self.frame[idx] = br.read_byte()?;
219 size -= 1;
220 idx += 1;
221 } else if tag == 1 {
222 let b = br.read_byte()?;
223 let len = ((b & 0xF) as usize) + 3;
8e652498
KS
224 let bot = (b >> 4) as isize;
225 let off = ((br.read_byte()? as isize) << 4) + bot - 4096;
e120f8fd
KS
226 validate!(len <= size);
227 size -= len;
8e652498 228 self.lz_copy(idx, off, len)?;
e120f8fd
KS
229 idx += len;
230 } else if tag == 2 {
231 let b = br.read_byte()?;
232 if b == 0 { break; }
8e652498 233 let len: usize = (if b != 0xFF { b as usize } else { br.read_u16le()? as usize }) + 1;
e120f8fd
KS
234 validate!(len <= size);
235 size -= len;
236 idx += len;
237 } else {
238 let b = br.read_byte()?;
239 let len = ((b & 0x3) as usize) + 2;
240 let off = -((b >> 2) as isize) - 1;
241 validate!(len <= size);
242 size -= len;
1a151e53 243 self.lz_copy(idx, off, len)?;
e120f8fd
KS
244 idx += len;
245 }
246 }
247 Ok(())
248 }
249
7450554d 250 #[allow(clippy::identity_op)]
e120f8fd
KS
251 fn decode_method68(&mut self, br: &mut ByteReader,
252 skip: usize, use8: bool) -> DecoderResult<()> {
253 let mut bits = Bits32::new();
254
255 let mut size = self.info.get_properties().get_video_info().unwrap().get_width() *
256 self.info.get_properties().get_video_info().unwrap().get_height();
257 let mut idx = PREAMBLE_SIZE;
258 validate!(size >= skip);
259 size -= skip;
260 idx += skip;
261 bits.fill(br)?;
262 while size > 0 {
263 let tag = bits.read_bits(br, 2)?;
264 if tag == 0 { //draw
265 let b = bits.read_bits(br, 1)?;
266 if b == 0 {
267 self.frame[idx] = br.read_byte()?;
268 size -= 1;
269 idx += 1;
270 } else {
271 let mut len: usize = 2;
272 let mut lbits = 0;
273 loop {
274 lbits += 1;
275 let val = bits.read_bits(br, lbits)?;
276 len += val as usize;
277 if val != ((1 << lbits) - 1) { break; }
278 validate!(lbits < 16);
279 }
280 validate!(len <= size);
281 for i in 0..len { self.frame[idx + i] = br.read_byte()?; }
282 size -= len;
283 idx += len;
284 }
285 } else if tag == 1 { //skip
286 let b = bits.read_bits(br, 1)?;
287 let len: usize;
288 if b == 0 {
289 len = (bits.read_bits(br, 4)? as usize) + 2;
290 } else {
291 let bb = br.read_byte()?;
292 if (bb & 0x80) == 0 {
293 len = (bb as usize) + 18;
294 } else {
295 let top = ((bb & 0x7F) as usize) << 8;
296 len = top + (br.read_byte()? as usize) + 146;
297 }
298 }
299 validate!(len <= size);
300 size -= len;
301 idx += len;
302 } else if tag == 2 {
303 let subtag = bits.read_bits(br, 2)? as usize;
304 if subtag != 3 {
305 let top = (bits.read_bits(br, 4)? as usize) << 8;
306 let offs = top + (br.read_byte()? as usize);
307 if (subtag != 0) || (offs <= 0xF80) {
308 let len = (subtag as usize) + 3;
309 self.lz_copy(idx, (offs as isize) - 4096, len)?;
310 idx += len;
311 } else {
312 if offs == 0xFFF { return Ok(()); }
313 let real_off = ((offs >> 4) & 0x7) + 1;
314 let len = ((offs & 0xF) + 2) * 2;
315 validate!(len <= size);
316 size -= len;
317 let c1 = self.frame[idx - real_off];
318 let c2 = self.frame[idx - real_off + 1];
319 for i in 0..len/2 {
320 self.frame[idx + i*2 + 0] = c1;
321 self.frame[idx + i*2 + 1] = c2;
322 }
323 idx += len;
324 }
325 } else {
326 let b = br.read_byte()?;
327 let off = ((b & 0x7F) as usize) + 1;
328 let len = if (b & 0x80) == 0 { 2 } else { 3 };
329 validate!(len <= size);
330 size -= len;
1a151e53 331 self.lz_copy(idx, -(off as isize), len)?;
e120f8fd
KS
332 idx += len;
333 }
334 } else {
335 let len: usize;
336 let off: isize;
337 if use8 {
338 let b = br.read_byte()?;
339 if (b & 0xC0) == 0xC0 {
340 len = ((b & 0x3F) as usize) + 8;
341 let q = bits.read_bits(br, 4)? as isize;
342 off = (q << 8) + (br.read_byte()? as isize) + 1;
343 } else {
344 let ofs1: isize;
345 if (b & 0x80) == 0 {
346 len = ((b >> 4) as usize) + 6;
347 ofs1 = (b & 0xF) as isize;
348 } else {
349 len = ((b & 0x3F) as usize) + 14;
350 ofs1 = bits.read_bits(br, 4)? as isize;
351 }
352 off = (ofs1 << 8) + (br.read_byte()? as isize) - 4096;
353 }
354 } else {
355 let b = br.read_byte()?;
356 if (b >> 4) == 0xF {
357 len = (br.read_byte()? as usize) + 21;
358 } else {
359 len = ((b >> 4) as usize) + 6;
360 }
361 let ofs1 = (b & 0xF) as isize;
362 off = (ofs1 << 8) + (br.read_byte()? as isize) - 4096;
363 }
364 validate!(len <= size);
365 size -= len;
1a151e53 366 self.lz_copy(idx, off, len)?;
e120f8fd
KS
367 idx += len;
368 }
369 }
370 Ok(())
371 }
372}
373
374impl NADecoder for GremlinVideoDecoder {
01613464 375 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
e120f8fd
KS
376 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
377 let w = vinfo.get_width();
378 let h = vinfo.get_height();
379 if !vinfo.get_format().is_paletted() { return Err(DecoderError::NotImplemented); }
cbc3c7a2 380 let fmt = PAL8_FORMAT;
e120f8fd 381 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
2422d969 382 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
e120f8fd
KS
383
384 self.frame.resize(PREAMBLE_SIZE + w * h, 0);
385 for i in 0..2 {
386 for j in 0..256 {
387 for k in 0..8 {
388 self.frame[i * 2048 + j * 8 + k] = j as u8;
389 }
390 }
391 }
392 let edata = info.get_extradata().unwrap();
393 validate!(edata.len() == 768);
394 for c in 0..256 {
395 for i in 0..3 {
396 let cc = edata[c * 3 + i];
cbc3c7a2 397 self.pal[c * 3 + i] = (cc << 2) | (cc >> 4);
e120f8fd
KS
398 }
399 }
400 Ok(())
401 } else {
402 Err(DecoderError::InvalidData)
403 }
404 }
01613464 405 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
e120f8fd
KS
406 let src = pkt.get_buffer();
407 let mut mr = MemoryReader::new_read(&src);
408 let mut br = ByteReader::new(&mut mr);
409 let flags = br.read_u32le()?;
410 let w = self.info.get_properties().get_video_info().unwrap().get_width();
411 let h = self.info.get_properties().get_video_info().unwrap().get_height();
412
413 let cmethod = flags & 0xF;
414 let is_intra = (flags & 0x40) != 0;
415 let scale_v = (flags & 0x10) != 0;
416 let scale_h = (flags & 0x20) != 0;
417
418 self.rescale(w, h, scale_v, scale_h);
419
420 if (cmethod == 0) || (cmethod == 1) {
421 for c in 0..256 {
422 for i in 0..3 {
423 let b = br.read_byte()?;
cbc3c7a2 424 self.pal[c * 3 + i] = (b << 2) | (b >> 4);
e120f8fd
KS
425 }
426 }
427 if cmethod == 1 {
428 for i in PREAMBLE_SIZE..self.frame.len() { self.frame[i] = 0x00; }
429 }
430 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
431 frm.set_keyframe(false);
432 frm.set_frame_type(FrameType::Skip);
171860fc 433 return Ok(frm.into_ref())
e120f8fd
KS
434 } else if cmethod == 3 {
435 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
436 frm.set_keyframe(false);
437 frm.set_frame_type(FrameType::Skip);
171860fc 438 return Ok(frm.into_ref())
e120f8fd
KS
439 } else if cmethod == 2 {
440 self.decode_method2(&mut br)?;
441 } else if cmethod == 5 {
442 self.decode_method5(&mut br, (flags >> 8) as usize)?;
443 } else if cmethod == 6 {
444 self.decode_method68(&mut br, (flags >> 8) as usize, false)?;
445 } else if cmethod == 8 {
446 self.decode_method68(&mut br, (flags >> 8) as usize, true)?;
447 } else {
448 return Err(DecoderError::NotImplemented);
449 }
450
e69b1148 451 let mut bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
e120f8fd
KS
452
453 self.output_frame(&mut bufinfo, w, h);
454
455 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
456 frm.set_keyframe(is_intra);
457 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
171860fc 458 Ok(frm.into_ref())
e120f8fd 459 }
f9be4e75
KS
460 fn flush(&mut self) {
461 }
e120f8fd
KS
462}
463
7d57ae2f
KS
464impl NAOptionHandler for GremlinVideoDecoder {
465 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
466 fn set_options(&mut self, _options: &[NAOption]) { }
467 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
468}
469
08a1fab7 470pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
e120f8fd
KS
471 Box::new(GremlinVideoDecoder::new())
472}
473
b74ff9fa
KS
474struct GremlinAudioDecoder {
475 ainfo: NAAudioInfo,
476 chmap: NAChannelMap,
477 delta_tab: [i16; 256],
478 state0: i16,
479 state1: i16,
480}
481
482impl GremlinAudioDecoder {
483 fn new() -> Self {
484 let mut delta_tab: [i16; 256] = [0; 256];
485 let mut delta = 0;
486 let mut code = 64;
487 let mut step = 45;
488 for i in 0..127 {
489 delta += code >> 5;
490 code += step;
491 step += 2;
492 delta_tab[i * 2 + 1] = delta;
493 delta_tab[i * 2 + 2] = -delta;
494 }
495 delta_tab[255] = 32767;//delta + (code >> 5);
496 GremlinAudioDecoder {
497 ainfo: NAAudioInfo::new(0, 1, formats::SND_S16_FORMAT, 0),
498 chmap: NAChannelMap::new(),
499 delta_tab,
500 state0: 0,
501 state1: 0,
502 }
503 }
504}
505
506const CHMAP_MONO: [NAChannelType; 1] = [NAChannelType::C];
507const CHMAP_STEREO: [NAChannelType; 2] = [NAChannelType::L, NAChannelType::R];
508
509fn get_default_chmap(nch: u8) -> NAChannelMap {
510 let mut chmap = NAChannelMap::new();
511 match nch {
512 1 => chmap.add_channels(&CHMAP_MONO),
513 2 => chmap.add_channels(&CHMAP_STEREO),
514 _ => (),
515 }
516 chmap
517}
518
519impl NADecoder for GremlinAudioDecoder {
01613464 520 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
b74ff9fa
KS
521 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
522 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), formats::SND_S16P_FORMAT, ainfo.get_block_len());
523 self.chmap = get_default_chmap(ainfo.get_channels());
524 if self.chmap.num_channels() == 0 { return Err(DecoderError::InvalidData); }
525 Ok(())
526 } else {
527 Err(DecoderError::InvalidData)
528 }
529 }
01613464 530 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
b74ff9fa
KS
531 let info = pkt.get_stream().get_info();
532 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
533 let pktbuf = pkt.get_buffer();
534 let samples = pktbuf.len() / self.chmap.num_channels();
b70cc006 535 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
b74ff9fa
KS
536 let mut adata = abuf.get_abuf_i16().unwrap();
537 let off1 = adata.get_offset(1);
1a967e6b 538 let buf = adata.get_data_mut().unwrap();
b74ff9fa
KS
539 if self.chmap.num_channels() == 2 {
540 for (i, e) in pktbuf.chunks(2).enumerate() {
541 self.state0 = self.state0.wrapping_add(self.delta_tab[e[0] as usize]);
542 buf[i] = self.state0;
543 self.state1 = self.state1.wrapping_add(self.delta_tab[e[1] as usize]);
544 buf[off1 + i] = self.state1;
545 }
546 } else {
547 for (i, e) in pktbuf.iter().enumerate() {
548 self.state0 += self.delta_tab[*e as usize];
549 buf[i] = self.state0;
550 }
551 }
552 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
553 frm.set_duration(Some(samples as u64));
554 frm.set_keyframe(false);
171860fc 555 Ok(frm.into_ref())
b74ff9fa
KS
556 } else {
557 Err(DecoderError::InvalidData)
558 }
559 }
f9be4e75
KS
560 fn flush(&mut self) {
561 }
b74ff9fa
KS
562}
563
7d57ae2f
KS
564impl NAOptionHandler for GremlinAudioDecoder {
565 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
566 fn set_options(&mut self, _options: &[NAOption]) { }
567 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
568}
569
08a1fab7 570pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
b74ff9fa
KS
571 Box::new(GremlinAudioDecoder::new())
572}
573
e120f8fd
KS
574#[cfg(test)]
575mod test {
3167c45c
KS
576 use nihav_core::codecs::RegisteredDecoders;
577 use nihav_core::demuxers::RegisteredDemuxers;
8a790ba7 578 use nihav_codec_support::test::dec_video::*;
78fb6560 579 use crate::game_register_all_decoders;
e64739f8 580 use crate::game_register_all_demuxers;
8a790ba7
KS
581
582 #[test]
583 fn test_gdv_video() {
584 let mut dmx_reg = RegisteredDemuxers::new();
585 game_register_all_demuxers(&mut dmx_reg);
586 let mut dec_reg = RegisteredDecoders::new();
78fb6560 587 game_register_all_decoders(&mut dec_reg);
8a790ba7
KS
588
589 test_decoding("gdv", "gdv-video", "assets/Game/intro1.gdv", Some(10), &dmx_reg, &dec_reg,
590 ExpectedTestResult::MD5([0x7ea302bf, 0xc3e210cf, 0x6e341376, 0x9e976056]));
591 }
e120f8fd 592 #[test]
8a790ba7 593 fn test_gdv_audio() {
3167c45c
KS
594 let mut dmx_reg = RegisteredDemuxers::new();
595 game_register_all_demuxers(&mut dmx_reg);
596 let mut dec_reg = RegisteredDecoders::new();
78fb6560 597 game_register_all_decoders(&mut dec_reg);
3167c45c 598
8a790ba7
KS
599 test_decoding("gdv", "gdv-audio", "assets/Game/intro1.gdv", None, &dmx_reg, &dec_reg,
600 ExpectedTestResult::MD5([0xd41d8cd9, 0x8f00b204, 0xe9800998, 0xecf8427e]));
e120f8fd
KS
601 }
602}