65d5de318bfac07c5b859ce2eb793b9dd53bbbda
[nihav.git] / nihav-game / src / codecs / vmd.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_codec_support::codecs::imaadpcm::*;
4 use std::str::FromStr;
5 use std::sync::Arc;
6
7 macro_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 }
26 fn 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
73 fn 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 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;
93 }
94 }
95 dpos += len;
96 }
97 Ok(())
98 }
99
100 fn 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 },
149 _ => Err(DecoderError::InvalidData),
150 }
151 }
152
153 struct VMDVideoDecoder {
154 info: NACodecInfoRef,
155 pal: [u8; 768],
156 buf: Vec<u8>,
157 framebuf: Vec<u8>,
158 width: usize,
159 height: usize,
160 xoff: usize,
161 yoff: usize,
162 is_16bit: bool,
163 is_24bit: bool,
164 ver1: u8,
165 ver2: u8,
166 }
167
168 impl VMDVideoDecoder {
169 fn new() -> Self {
170 Self {
171 info: NACodecInfoRef::default(),
172 pal: [0; 768],
173 buf: Vec::new(),
174 framebuf: Vec::new(),
175 width: 0,
176 height: 0,
177 xoff: 0,
178 yoff: 0,
179 is_16bit: false,
180 is_24bit: false,
181 ver1: 0,
182 ver2: 0,
183 }
184 }
185 fn decode_frame(&mut self, br: &mut ByteReader) -> DecoderResult<bool> {
186 let frame_x = br.read_u16le()? as usize;
187 let frame_y = br.read_u16le()? as usize;
188 let frame_r = br.read_u16le()? as usize;
189 let frame_d = br.read_u16le()? as usize;
190 br.read_skip(1)?;
191 let flags = br.read_byte()?;
192 let has_pal = (flags & 0x02) != 0 && !self.is_16bit && !self.is_24bit;
193 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_r == 0xFFFF) && (frame_d == 0xFFFF) {
194 return Ok(false);
195 }
196 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
197 validate!(frame_r >= frame_x && frame_d >= frame_y);
198 validate!(frame_r - self.xoff < self.width && frame_d - self.yoff < self.height);
199
200 if has_pal {
201 br.read_skip(2)?;
202 for e in self.pal.iter_mut() {
203 let val = br.read_byte()?;
204 *e = (val << 2) | (val >> 4);
205 }
206 }
207
208 if br.left() == 0 { return Ok(false); }
209
210 let bpp = if (!self.is_16bit && !self.is_24bit) || self.ver1 < 2 {
211 1
212 } else if self.is_16bit {
213 2
214 } else {
215 3
216 };
217 let w = (frame_r + 1 - frame_x) * bpp;
218 let h = frame_d + 1 - frame_y;
219 let stride = self.width;
220 let dpos = (frame_x - self.xoff) * bpp + (frame_y - self.yoff) * stride;
221
222 let method = br.read_byte()?;
223 let is_intra;
224 if (method & 0x80) != 0 {
225 validate!(!self.buf.is_empty());
226 lz_unpack(br, &mut self.buf)?;
227 let mut mr = MemoryReader::new_read(&self.buf);
228 let mut buf_br = ByteReader::new(&mut mr);
229 is_intra = decode_frame_data(&mut buf_br, &mut self.framebuf, dpos, stride, w, h, method & 0x7F)?;
230 } else {
231 is_intra = decode_frame_data(br, &mut self.framebuf, dpos, stride, w, h, method & 0x7F)?;
232 }
233 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
234 }
235 }
236
237 const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
238 comp_info: [
239 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }),
240 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 1, next_elem: 2 }),
241 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 2, next_elem: 2 }),
242 None, None],
243 elem_size: 2, be: false, alpha: false, palette: false };
244
245 impl NADecoder for VMDVideoDecoder {
246 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
247 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
248 self.width = vinfo.get_width();
249 self.height = vinfo.get_height();
250 validate!(info.get_extradata().is_some());
251
252 if let Some(ref edata) = info.get_extradata() {
253 validate!(edata.len() == 0x330);
254 let unp_size = read_u32le(&edata[800..])? as usize;
255 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
256 self.buf.resize(unp_size, 0);
257 for i in 0..768 {
258 let el = edata[28 + i];
259 self.pal[i] = (el << 2) | (el >> 4);
260 }
261 self.xoff = read_u16le(&edata[8..])? as usize;
262 self.yoff = read_u16le(&edata[10..])? as usize;
263 self.ver1 = edata[2];
264 self.ver2 = edata[4];
265 } else {
266 unreachable!();
267 }
268 let (disp_width, fmt) = if self.ver2 < 5 {
269 (self.width, PAL8_FORMAT)
270 } else if self.ver2 < 13 {
271 self.is_24bit = true;
272 if self.ver1 >= 2 {
273 self.width *= 3;
274 }
275 validate!(self.width % 3 == 0);
276 (self.width / 3, RGB24_FORMAT)
277 } else {
278 self.is_16bit = true;
279 if self.ver1 >= 2 {
280 self.width *= 2;
281 }
282 (self.width / 2, RGB555_FORMAT)
283 };
284 self.framebuf = vec!(0; self.width * self.height);
285
286 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(disp_width, self.height, false, fmt));
287 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
288
289 Ok(())
290 } else {
291 Err(DecoderError::InvalidData)
292 }
293 }
294 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
295 let src = pkt.get_buffer();
296 validate!(src.len() >= 10);
297
298 let mut mr = MemoryReader::new_read(&src);
299 let mut br = ByteReader::new(&mut mr);
300
301 let is_intra = self.decode_frame(&mut br)?;
302
303 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
304 let videobuf;
305 if !self.is_16bit {
306 let mut buf = bufinfo.get_vbuf().unwrap();
307 let stride = buf.get_stride(0);
308 let paloff = buf.get_offset(1);
309 let data = buf.get_data_mut().unwrap();
310 for (inrow, outrow) in self.framebuf.chunks(self.width).zip(data.chunks_mut(stride)) {
311 (&mut outrow[..self.width]).copy_from_slice(inrow);
312 }
313 if !self.is_24bit {
314 (&mut data[paloff..][..768]).copy_from_slice(&self.pal);
315 }
316 videobuf = if !self.is_24bit { NABufferType::Video(buf) } else { NABufferType::VideoPacked(buf) };
317 } else {
318 let mut buf = bufinfo.get_vbuf16().unwrap();
319 let stride = buf.get_stride(0);
320 let data = buf.get_data_mut().unwrap();
321 for (inrow, outrow) in self.framebuf.chunks(self.width).zip(data.chunks_mut(stride)) {
322 for i in (0..self.width).step_by(2) {
323 outrow[i >> 1] = read_u16le(&inrow[i..])?;
324 }
325 }
326 videobuf = NABufferType::Video16(buf);
327 }
328
329 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), videobuf);
330 frm.set_keyframe(is_intra);
331 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
332 Ok(frm.into_ref())
333 }
334 fn flush(&mut self) {
335 }
336 }
337
338
339 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
340 Box::new(VMDVideoDecoder::new())
341 }
342
343 #[derive(Clone,Copy,PartialEq)]
344 enum VMDAudioMode {
345 U8,
346 DPCM,
347 StereoDPCM,
348 ADPCM,
349 }
350
351 struct VMDAudioDecoder {
352 ainfo: NAAudioInfo,
353 info: Arc<NACodecInfo>,
354 chmap: NAChannelMap,
355 blk_align: usize,
356 blk_size: usize,
357 mode: VMDAudioMode,
358 pred: [i32; 2],
359 last_byte: Option<u8>,
360 is_odd: bool,
361 ch: usize,
362 }
363
364 const SOL_AUD_STEPS16: [i16; 128] = [
365 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
366 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
367 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
368 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
369 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
370 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
371 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
372 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
373 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
374 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
375 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
376 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
377 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
378 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
379 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
380 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
381 ];
382
383 impl VMDAudioDecoder {
384 fn new() -> Self {
385 Self {
386 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
387 info: NACodecInfo::new_dummy(),
388 chmap: NAChannelMap::new(),
389 blk_align: 0,
390 blk_size: 0,
391 mode: VMDAudioMode::U8,
392 pred: [0; 2],
393 last_byte: None,
394 is_odd: false,
395 ch: 0,
396 }
397 }
398 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
399 let channels = self.chmap.num_channels();
400 let mut off = [0, off1];
401 for _ in 0..nblocks {
402 if (mask & 1) != 0 {
403 for ch in 0..channels {
404 for i in 0..self.blk_align {
405 dst[off[ch] + i] = 0;
406 }
407 off[ch] += self.blk_align;
408 }
409 } else {
410 let mut pred: [i32; 2] = [0; 2];
411 for ch in 0..channels {
412 pred[ch] = i32::from(br.read_u16le()?);
413 dst[off[ch]] = pred[ch] as i16;
414 off[ch] += 1;
415 }
416 let mut ch = 0;
417 let flip_ch = if channels == 2 { 1 } else { 0 };
418 for _ in channels..self.blk_align*channels {
419 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
420 //pred[ch] = pred[ch].max(-32768).min(32767);
421 dst[off[ch]] = pred[ch] as i16;
422 off[ch] += 1;
423 ch ^= flip_ch;
424 }
425 }
426 mask >>= 1;
427 }
428 validate!(br.left() == 0);
429 Ok(())
430 }
431 fn pred16(pred: i32, val: u8) -> i32 {
432 if (val & 0x80) != 0 {
433 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
434 } else {
435 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
436 }
437 }
438 }
439
440 impl NADecoder for VMDAudioDecoder {
441 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
442 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
443 let fmt;
444 let channels = ainfo.get_channels() as usize;
445 let edata = info.get_extradata();
446 let flags = if let Some(ref buf) = edata {
447 validate!(buf.len() >= 2);
448 (buf[0] as u16) | ((buf[1] as u16) << 8)
449 } else {
450 0
451 };
452 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
453 if ainfo.get_format().get_bits() == 8 {
454 self.blk_size = ainfo.get_block_len();
455 self.blk_align = ainfo.get_block_len() / channels;
456 if (flags & 0x8000) == 0 {
457 fmt = SND_U8_FORMAT;
458 self.mode = VMDAudioMode::U8;
459 } else {
460 fmt = SND_S16_FORMAT;
461 self.mode = VMDAudioMode::StereoDPCM;
462 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
463 }
464 } else {
465 self.blk_align = ainfo.get_block_len();
466 if (flags & 0x10) == 0 {
467 fmt = SND_S16P_FORMAT;
468 self.blk_size = (ainfo.get_block_len() + 1) * channels;
469 self.mode = VMDAudioMode::DPCM;
470 } else {
471 fmt = SND_S16_FORMAT;
472 self.blk_size = (ainfo.get_block_len() * channels + 1) / 2 + 3 * channels;
473 self.mode = VMDAudioMode::ADPCM;
474 }
475 };
476 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
477 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
478 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
479 Ok(())
480 } else {
481 Err(DecoderError::InvalidData)
482 }
483 }
484 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
485 let info = pkt.get_stream().get_info();
486 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
487 let pktbuf = pkt.get_buffer();
488 validate!(pktbuf.len() >= 6);
489 let mut mr = MemoryReader::new_read(&pktbuf);
490 let mut br = ByteReader::new(&mut mr);
491 let blk_type = br.read_byte()?;
492 br.read_skip(9)?;
493 let mask;
494 let nblocks;
495 if blk_type == 2 { // initial
496 mask = br.read_u32le()?;
497 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
498 } else if blk_type == 3 { // silence
499 mask = 1;
500 nblocks = 1;
501 } else {
502 mask = 0;
503 nblocks = 1;
504 }
505 let mut samples = nblocks * self.blk_align;
506 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
507 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
508 }
509 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
510 match self.mode {
511 VMDAudioMode::DPCM => {
512 let mut adata = abuf.get_abuf_i16().unwrap();
513 let off1 = adata.get_offset(1);
514 let mut dst = adata.get_data_mut().unwrap();
515 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
516 },
517 VMDAudioMode::U8 => {
518 let mut adata = abuf.get_abuf_u8().unwrap();
519 let dst = adata.get_data_mut().unwrap();
520 let mut doff = 0;
521 let mut mask = mask;
522 let channels = self.chmap.num_channels();
523 for _ in 0..nblocks {
524 if (mask & 1) != 0 {
525 for i in 0..self.blk_align * channels {
526 dst[doff + i] = 128;
527 }
528 } else if channels == 1 {
529 for i in 0..self.blk_size {
530 dst[doff + i] = br.read_byte()?;
531 }
532 } else {
533 unreachable!();
534 }
535 doff += self.blk_align * channels;
536 mask >>= 1;
537 }
538 },
539 VMDAudioMode::StereoDPCM => {
540 let mut adata = abuf.get_abuf_i16().unwrap();
541 let dst = adata.get_data_mut().unwrap();
542 let mut doff = 0;
543 let mut mask = mask;
544 let mut ch = self.ch;
545 for _ in 0..nblocks {
546 let put_sample = self.last_byte.is_some();
547 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
548 self.pred[ch] = Self::pred16(self.pred[ch], val);
549 dst[doff] = self.pred[ch] as i16;
550 doff += 1;
551 ch ^= 1;
552 self.last_byte = None;
553 }
554 if (mask & 1) != 0 {
555 for i in 0..self.blk_align {
556 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
557 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
558 }
559 if self.is_odd {
560 if put_sample {
561 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
562 doff += 1;
563 ch ^= 1;
564 } else {
565 self.last_byte = Some(0);
566 }
567 }
568 } else {
569 for i in 0..self.blk_align {
570 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
571 dst[doff + i * 2] = self.pred[ch] as i16;
572 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
573 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
574 }
575 if self.is_odd {
576 let val = br.read_byte()?;
577 if put_sample {
578 self.pred[ch] = Self::pred16(self.pred[ch], val);
579 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
580 doff += 1;
581 ch ^= 1;
582 } else {
583 self.last_byte = Some(val);
584 }
585 }
586 }
587 doff += self.blk_align * 2;
588 mask >>= 1;
589 }
590 self.ch = ch;
591 },
592 VMDAudioMode::ADPCM => {
593 let mut adata = abuf.get_abuf_i16().unwrap();
594 let dst = adata.get_data_mut().unwrap();
595 let mut doff = 0;
596 if self.chmap.num_channels() == 1 {
597 let mut mask = mask;
598 let mut ima = IMAState::new();
599 for _ in 0..nblocks {
600 if (mask & 1) != 0 {
601 for i in 0..self.blk_align {
602 dst[doff + i] = 0;
603 }
604 doff += self.blk_align;
605 mask >>= 1;
606 continue;
607 }
608 let pred = br.read_u16le()? as i16;
609 let step = br.read_byte()?;
610 validate!((step as usize) < IMA_STEP_TABLE.len());
611 ima.reset(pred, step);
612 let mut b = 0;
613 for i in 0..self.blk_align {
614 if (i & 1) == 0 {
615 b = br.read_byte()?;
616 dst[doff] = ima.expand_sample(b >> 4);
617 } else {
618 dst[doff] = ima.expand_sample(b & 0xF);
619 }
620 doff += 1;
621 }
622 mask >>= 1;
623 }
624 } else {
625 let mut mask = mask;
626 let mut ima1 = IMAState::new();
627 let mut ima2 = IMAState::new();
628 for _ in 0..nblocks {
629 if (mask & 1) != 0 {
630 for i in 0..self.blk_align * 2 {
631 dst[doff + i] = 0;
632 }
633 doff += self.blk_align * 2;
634 mask >>= 1;
635 continue;
636 }
637 let pred1 = br.read_u16le()? as i16;
638 let pred2 = br.read_u16le()? as i16;
639 let step1 = br.read_byte()?;
640 let step2 = br.read_byte()?;
641 validate!((step1 as usize) < IMA_STEP_TABLE.len());
642 validate!((step2 as usize) < IMA_STEP_TABLE.len());
643 ima1.reset(pred1, step1);
644 ima2.reset(pred2, step2);
645 for _ in 0..self.blk_align {
646 let b = br.read_byte()?;
647 dst[doff] = ima1.expand_sample(b >> 4);
648 doff += 1;
649 dst[doff] = ima2.expand_sample(b & 0xF);
650 doff += 1;
651 }
652 mask >>= 1;
653 }
654 }
655 },
656 };
657
658 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
659 frm.set_duration(Some(samples as u64));
660 frm.set_keyframe(true);
661 Ok(frm.into_ref())
662 } else {
663 Err(DecoderError::InvalidData)
664 }
665 }
666 fn flush(&mut self) {
667 }
668 }
669
670 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
671 Box::new(VMDAudioDecoder::new())
672 }
673
674 #[cfg(test)]
675 mod test {
676 use nihav_core::codecs::RegisteredDecoders;
677 use nihav_core::demuxers::RegisteredDemuxers;
678 use nihav_codec_support::test::dec_video::*;
679 use crate::game_register_all_codecs;
680 use crate::game_register_all_demuxers;
681 #[test]
682 fn test_vmd_video() {
683 let mut dmx_reg = RegisteredDemuxers::new();
684 game_register_all_demuxers(&mut dmx_reg);
685 let mut dec_reg = RegisteredDecoders::new();
686 game_register_all_codecs(&mut dec_reg);
687
688 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
689 ExpectedTestResult::MD5Frames(vec![
690 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
691 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
692 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
693 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
694 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
695 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
696 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
697 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
698 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
699 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
700 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
701 }
702 #[test]
703 fn test_vmd_video_16bpp() {
704 let mut dmx_reg = RegisteredDemuxers::new();
705 game_register_all_demuxers(&mut dmx_reg);
706 let mut dec_reg = RegisteredDecoders::new();
707 game_register_all_codecs(&mut dec_reg);
708
709 test_decoding("vmd", "vmd-video", "assets/Game/HLP1000.VMD", Some(10), &dmx_reg, &dec_reg,
710 ExpectedTestResult::MD5Frames(vec![
711 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
712 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c],
713 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
714 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
715 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
716 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c]]));
717 }
718 #[test]
719 fn test_vmd_video_24bpp() {
720 let mut dmx_reg = RegisteredDemuxers::new();
721 game_register_all_demuxers(&mut dmx_reg);
722 let mut dec_reg = RegisteredDecoders::new();
723 game_register_all_codecs(&mut dec_reg);
724
725 test_decoding("vmd", "vmd-video", "assets/Game/02C.VMD", None, &dmx_reg, &dec_reg,
726 ExpectedTestResult::MD5([0xb580782c, 0xd7fb98c0, 0xaf9b83cc, 0xaea0846b]));
727 }
728 #[test]
729 fn test_vmd_audio_u8() {
730 let mut dmx_reg = RegisteredDemuxers::new();
731 game_register_all_demuxers(&mut dmx_reg);
732 let mut dec_reg = RegisteredDecoders::new();
733 game_register_all_codecs(&mut dec_reg);
734
735 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
736 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
737 }
738 #[test]
739 fn test_vmd_audio_s16_old() {
740 let mut dmx_reg = RegisteredDemuxers::new();
741 game_register_all_demuxers(&mut dmx_reg);
742 let mut dec_reg = RegisteredDecoders::new();
743 game_register_all_codecs(&mut dec_reg);
744
745 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
746 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
747 }
748 #[test]
749 fn test_vmd_audio_s16_new() {
750 let mut dmx_reg = RegisteredDemuxers::new();
751 game_register_all_demuxers(&mut dmx_reg);
752 let mut dec_reg = RegisteredDecoders::new();
753 game_register_all_codecs(&mut dec_reg);
754
755 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
756 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
757 }
758 #[test]
759 fn test_vmd_audio_ima_adpcm() {
760 let mut dmx_reg = RegisteredDemuxers::new();
761 game_register_all_demuxers(&mut dmx_reg);
762 let mut dec_reg = RegisteredDecoders::new();
763 game_register_all_codecs(&mut dec_reg);
764
765 test_decoding("vmd", "vmd-audio", "assets/Game/HLP1000.VMD", None, &dmx_reg, &dec_reg,
766 ExpectedTestResult::MD5([0x76a00405, 0xe4e5378d, 0x495b2a68, 0x4dffe042]));
767 }
768 }