introduce option handling for decoders
[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 impl NAOptionHandler for VMDVideoDecoder {
339 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
340 fn set_options(&mut self, _options: &[NAOption]) { }
341 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
342 }
343
344
345 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
346 Box::new(VMDVideoDecoder::new())
347 }
348
349 #[derive(Clone,Copy,PartialEq)]
350 enum VMDAudioMode {
351 U8,
352 DPCM,
353 StereoDPCM,
354 ADPCM,
355 }
356
357 struct VMDAudioDecoder {
358 ainfo: NAAudioInfo,
359 info: Arc<NACodecInfo>,
360 chmap: NAChannelMap,
361 blk_align: usize,
362 blk_size: usize,
363 mode: VMDAudioMode,
364 pred: [i32; 2],
365 last_byte: Option<u8>,
366 is_odd: bool,
367 ch: usize,
368 }
369
370 const SOL_AUD_STEPS16: [i16; 128] = [
371 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
372 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
373 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
374 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
375 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
376 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
377 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
378 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
379 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
380 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
381 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
382 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
383 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
384 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
385 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
386 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
387 ];
388
389 impl VMDAudioDecoder {
390 fn new() -> Self {
391 Self {
392 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
393 info: NACodecInfo::new_dummy(),
394 chmap: NAChannelMap::new(),
395 blk_align: 0,
396 blk_size: 0,
397 mode: VMDAudioMode::U8,
398 pred: [0; 2],
399 last_byte: None,
400 is_odd: false,
401 ch: 0,
402 }
403 }
404 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
405 let channels = self.chmap.num_channels();
406 let mut off = [0, off1];
407 for _ in 0..nblocks {
408 if (mask & 1) != 0 {
409 for ch in 0..channels {
410 for i in 0..self.blk_align {
411 dst[off[ch] + i] = 0;
412 }
413 off[ch] += self.blk_align;
414 }
415 } else {
416 let mut pred: [i32; 2] = [0; 2];
417 for ch in 0..channels {
418 pred[ch] = i32::from(br.read_u16le()?);
419 dst[off[ch]] = pred[ch] as i16;
420 off[ch] += 1;
421 }
422 let mut ch = 0;
423 let flip_ch = if channels == 2 { 1 } else { 0 };
424 for _ in channels..self.blk_align*channels {
425 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
426 //pred[ch] = pred[ch].max(-32768).min(32767);
427 dst[off[ch]] = pred[ch] as i16;
428 off[ch] += 1;
429 ch ^= flip_ch;
430 }
431 }
432 mask >>= 1;
433 }
434 validate!(br.left() == 0);
435 Ok(())
436 }
437 fn pred16(pred: i32, val: u8) -> i32 {
438 if (val & 0x80) != 0 {
439 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
440 } else {
441 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
442 }
443 }
444 }
445
446 impl NADecoder for VMDAudioDecoder {
447 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
448 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
449 let fmt;
450 let channels = ainfo.get_channels() as usize;
451 let edata = info.get_extradata();
452 let flags = if let Some(ref buf) = edata {
453 validate!(buf.len() >= 2);
454 (buf[0] as u16) | ((buf[1] as u16) << 8)
455 } else {
456 0
457 };
458 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
459 if ainfo.get_format().get_bits() == 8 {
460 self.blk_size = ainfo.get_block_len();
461 self.blk_align = ainfo.get_block_len() / channels;
462 if (flags & 0x8000) == 0 {
463 fmt = SND_U8_FORMAT;
464 self.mode = VMDAudioMode::U8;
465 } else {
466 fmt = SND_S16_FORMAT;
467 self.mode = VMDAudioMode::StereoDPCM;
468 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
469 }
470 } else {
471 self.blk_align = ainfo.get_block_len();
472 if (flags & 0x10) == 0 {
473 fmt = SND_S16P_FORMAT;
474 self.blk_size = (ainfo.get_block_len() + 1) * channels;
475 self.mode = VMDAudioMode::DPCM;
476 } else {
477 fmt = SND_S16_FORMAT;
478 self.blk_size = (ainfo.get_block_len() * channels + 1) / 2 + 3 * channels;
479 self.mode = VMDAudioMode::ADPCM;
480 }
481 };
482 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
483 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
484 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
485 Ok(())
486 } else {
487 Err(DecoderError::InvalidData)
488 }
489 }
490 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
491 let info = pkt.get_stream().get_info();
492 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
493 let pktbuf = pkt.get_buffer();
494 validate!(pktbuf.len() >= 6);
495 let mut mr = MemoryReader::new_read(&pktbuf);
496 let mut br = ByteReader::new(&mut mr);
497 let blk_type = br.read_byte()?;
498 br.read_skip(9)?;
499 let mask;
500 let nblocks;
501 if blk_type == 2 { // initial
502 mask = br.read_u32le()?;
503 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
504 } else if blk_type == 3 { // silence
505 mask = 1;
506 nblocks = 1;
507 } else {
508 mask = 0;
509 nblocks = 1;
510 }
511 let mut samples = nblocks * self.blk_align;
512 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
513 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
514 }
515 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
516 match self.mode {
517 VMDAudioMode::DPCM => {
518 let mut adata = abuf.get_abuf_i16().unwrap();
519 let off1 = adata.get_offset(1);
520 let mut dst = adata.get_data_mut().unwrap();
521 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
522 },
523 VMDAudioMode::U8 => {
524 let mut adata = abuf.get_abuf_u8().unwrap();
525 let dst = adata.get_data_mut().unwrap();
526 let mut doff = 0;
527 let mut mask = mask;
528 let channels = self.chmap.num_channels();
529 for _ in 0..nblocks {
530 if (mask & 1) != 0 {
531 for i in 0..self.blk_align * channels {
532 dst[doff + i] = 128;
533 }
534 } else if channels == 1 {
535 for i in 0..self.blk_size {
536 dst[doff + i] = br.read_byte()?;
537 }
538 } else {
539 unreachable!();
540 }
541 doff += self.blk_align * channels;
542 mask >>= 1;
543 }
544 },
545 VMDAudioMode::StereoDPCM => {
546 let mut adata = abuf.get_abuf_i16().unwrap();
547 let dst = adata.get_data_mut().unwrap();
548 let mut doff = 0;
549 let mut mask = mask;
550 let mut ch = self.ch;
551 for _ in 0..nblocks {
552 let put_sample = self.last_byte.is_some();
553 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
554 self.pred[ch] = Self::pred16(self.pred[ch], val);
555 dst[doff] = self.pred[ch] as i16;
556 doff += 1;
557 ch ^= 1;
558 self.last_byte = None;
559 }
560 if (mask & 1) != 0 {
561 for i in 0..self.blk_align {
562 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
563 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
564 }
565 if self.is_odd {
566 if put_sample {
567 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
568 doff += 1;
569 ch ^= 1;
570 } else {
571 self.last_byte = Some(0);
572 }
573 }
574 } else {
575 for i in 0..self.blk_align {
576 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
577 dst[doff + i * 2] = self.pred[ch] as i16;
578 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
579 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
580 }
581 if self.is_odd {
582 let val = br.read_byte()?;
583 if put_sample {
584 self.pred[ch] = Self::pred16(self.pred[ch], val);
585 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
586 doff += 1;
587 ch ^= 1;
588 } else {
589 self.last_byte = Some(val);
590 }
591 }
592 }
593 doff += self.blk_align * 2;
594 mask >>= 1;
595 }
596 self.ch = ch;
597 },
598 VMDAudioMode::ADPCM => {
599 let mut adata = abuf.get_abuf_i16().unwrap();
600 let dst = adata.get_data_mut().unwrap();
601 let mut doff = 0;
602 if self.chmap.num_channels() == 1 {
603 let mut mask = mask;
604 let mut ima = IMAState::new();
605 for _ in 0..nblocks {
606 if (mask & 1) != 0 {
607 for i in 0..self.blk_align {
608 dst[doff + i] = 0;
609 }
610 doff += self.blk_align;
611 mask >>= 1;
612 continue;
613 }
614 let pred = br.read_u16le()? as i16;
615 let step = br.read_byte()?;
616 validate!((step as usize) < IMA_STEP_TABLE.len());
617 ima.reset(pred, step);
618 let mut b = 0;
619 for i in 0..self.blk_align {
620 if (i & 1) == 0 {
621 b = br.read_byte()?;
622 dst[doff] = ima.expand_sample(b >> 4);
623 } else {
624 dst[doff] = ima.expand_sample(b & 0xF);
625 }
626 doff += 1;
627 }
628 mask >>= 1;
629 }
630 } else {
631 let mut mask = mask;
632 let mut ima1 = IMAState::new();
633 let mut ima2 = IMAState::new();
634 for _ in 0..nblocks {
635 if (mask & 1) != 0 {
636 for i in 0..self.blk_align * 2 {
637 dst[doff + i] = 0;
638 }
639 doff += self.blk_align * 2;
640 mask >>= 1;
641 continue;
642 }
643 let pred1 = br.read_u16le()? as i16;
644 let pred2 = br.read_u16le()? as i16;
645 let step1 = br.read_byte()?;
646 let step2 = br.read_byte()?;
647 validate!((step1 as usize) < IMA_STEP_TABLE.len());
648 validate!((step2 as usize) < IMA_STEP_TABLE.len());
649 ima1.reset(pred1, step1);
650 ima2.reset(pred2, step2);
651 for _ in 0..self.blk_align {
652 let b = br.read_byte()?;
653 dst[doff] = ima1.expand_sample(b >> 4);
654 doff += 1;
655 dst[doff] = ima2.expand_sample(b & 0xF);
656 doff += 1;
657 }
658 mask >>= 1;
659 }
660 }
661 },
662 };
663
664 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
665 frm.set_duration(Some(samples as u64));
666 frm.set_keyframe(true);
667 Ok(frm.into_ref())
668 } else {
669 Err(DecoderError::InvalidData)
670 }
671 }
672 fn flush(&mut self) {
673 }
674 }
675
676 impl NAOptionHandler for VMDAudioDecoder {
677 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
678 fn set_options(&mut self, _options: &[NAOption]) { }
679 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
680 }
681
682 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
683 Box::new(VMDAudioDecoder::new())
684 }
685
686 #[cfg(test)]
687 mod test {
688 use nihav_core::codecs::RegisteredDecoders;
689 use nihav_core::demuxers::RegisteredDemuxers;
690 use nihav_codec_support::test::dec_video::*;
691 use crate::game_register_all_codecs;
692 use crate::game_register_all_demuxers;
693 #[test]
694 fn test_vmd_video() {
695 let mut dmx_reg = RegisteredDemuxers::new();
696 game_register_all_demuxers(&mut dmx_reg);
697 let mut dec_reg = RegisteredDecoders::new();
698 game_register_all_codecs(&mut dec_reg);
699
700 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
701 ExpectedTestResult::MD5Frames(vec![
702 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
703 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
704 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
705 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
706 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
707 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
708 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
709 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
710 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
711 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
712 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
713 }
714 #[test]
715 fn test_vmd_video_16bpp() {
716 let mut dmx_reg = RegisteredDemuxers::new();
717 game_register_all_demuxers(&mut dmx_reg);
718 let mut dec_reg = RegisteredDecoders::new();
719 game_register_all_codecs(&mut dec_reg);
720
721 test_decoding("vmd", "vmd-video", "assets/Game/HLP1000.VMD", Some(10), &dmx_reg, &dec_reg,
722 ExpectedTestResult::MD5Frames(vec![
723 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
724 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c],
725 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
726 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
727 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
728 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c]]));
729 }
730 #[test]
731 fn test_vmd_video_24bpp() {
732 let mut dmx_reg = RegisteredDemuxers::new();
733 game_register_all_demuxers(&mut dmx_reg);
734 let mut dec_reg = RegisteredDecoders::new();
735 game_register_all_codecs(&mut dec_reg);
736
737 test_decoding("vmd", "vmd-video", "assets/Game/02C.VMD", None, &dmx_reg, &dec_reg,
738 ExpectedTestResult::MD5([0xb580782c, 0xd7fb98c0, 0xaf9b83cc, 0xaea0846b]));
739 }
740 #[test]
741 fn test_vmd_audio_u8() {
742 let mut dmx_reg = RegisteredDemuxers::new();
743 game_register_all_demuxers(&mut dmx_reg);
744 let mut dec_reg = RegisteredDecoders::new();
745 game_register_all_codecs(&mut dec_reg);
746
747 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
748 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
749 }
750 #[test]
751 fn test_vmd_audio_s16_old() {
752 let mut dmx_reg = RegisteredDemuxers::new();
753 game_register_all_demuxers(&mut dmx_reg);
754 let mut dec_reg = RegisteredDecoders::new();
755 game_register_all_codecs(&mut dec_reg);
756
757 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
758 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
759 }
760 #[test]
761 fn test_vmd_audio_s16_new() {
762 let mut dmx_reg = RegisteredDemuxers::new();
763 game_register_all_demuxers(&mut dmx_reg);
764 let mut dec_reg = RegisteredDecoders::new();
765 game_register_all_codecs(&mut dec_reg);
766
767 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
768 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
769 }
770 #[test]
771 fn test_vmd_audio_ima_adpcm() {
772 let mut dmx_reg = RegisteredDemuxers::new();
773 game_register_all_demuxers(&mut dmx_reg);
774 let mut dec_reg = RegisteredDecoders::new();
775 game_register_all_codecs(&mut dec_reg);
776
777 test_decoding("vmd", "vmd-audio", "assets/Game/HLP1000.VMD", None, &dmx_reg, &dec_reg,
778 ExpectedTestResult::MD5([0x76a00405, 0xe4e5378d, 0x495b2a68, 0x4dffe042]));
779 }
780 }