duck/avc: improve decoder a bit
[nihav.git] / nihav-game / src / codecs / vmd.rs
CommitLineData
9895bd7b
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
3use std::str::FromStr;
4
5macro_rules! lz_op {
6 (read; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $br:expr, $dst_size:expr) => {
7 validate!($dpos < $dst_size);
8 let b = $br.read_byte()?;
9 $dst[$dpos] = b;
10 $dpos += 1;
11 $window[$wpos] = b;
12 $wpos = ($wpos + 1) & 0xFFF;
13 };
14 (copy; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $off:expr, $dst_size:expr) => {
15 let b = $window[$off];
16 validate!($dpos < $dst_size);
17 $dst[$dpos] = b;
18 $dpos += 1;
19 $window[$wpos] = b;
20 $wpos = ($wpos + 1) & 0xFFF;
21 $off = ($off + 1) & 0xFFF;
22 };
23}
24fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
25 let mut window: [u8; 0x1000] = [0x20; 0x1000];
26
27 let dst_size = br.read_u32le()? as usize;
28 validate!(dst_size <= dst.len());
29 let mut pos;
30 let esc_len;
31 if br.peek_u32le()? == 0x56781234 {
32 br.read_skip(4)?;
33 pos = 0x111;
34 esc_len = 15;
35 } else {
36 pos = 0xFEE;
37 esc_len = 255;
38 }
39
40 let mut opos = 0;
41 while br.left() > 0 && opos < dst_size {
42 let op = br.read_byte()?;
43 if (op == 0xFF) && (br.left() > 8) {
44 for _ in 0..8 {
45 lz_op!(read; dst, opos, window, pos, br, dst_size);
46 }
47 } else {
48 for i in 0..8 {
49 if opos == dst_size { break; }
50 let is_literal = ((op >> i) & 1) != 0;
51 if is_literal {
52 lz_op!(read; dst, opos, window, pos, br, dst_size);
53 } else {
54 let b0 = br.read_byte()? as usize;
55 let b1 = br.read_byte()? as usize;
56 let mut off = b0 | ((b1 & 0xF0) << 4);
57 let mut len = b1 & 0xF;
58 if len == esc_len {
59 len = (br.read_byte()? as usize) + esc_len;
60 }
61 for _ in 0..len+3 {
62 lz_op!(copy; dst, opos, window, pos, off, dst_size);
63 }
64 }
65 }
66 }
67 }
68 Ok(())
69}
70
71fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
72 let end = br.tell() + (len as u64);
73 let mut dpos = 0;
74 if (len & 1) != 0 {
75 dst[dpos] = br.read_byte()?;
76 dpos += 1;
77 }
78 while dpos < dst.len() && br.tell() < end {
79 let val = br.read_byte()?;
80 let len = ((val & 0x7F) as usize) * 2;
81 validate!(dpos + len <= dst.len());
82 if (val & 0x80) != 0 {
83 let dst = &mut dst[dpos..][..len];
84 br.read_buf(dst)?;
85 } else {
86 let val = br.read_byte()?;
87 for i in 0..len {
88 dst[dpos + i] = val;
89 }
90 }
91 dpos += len;
92 }
93 Ok(())
94}
95
96fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
97 match method {
98 1 => {
99 for _ in 0..h {
100 let mut x = 0;
101 while x < w {
102 let val = br.read_byte()?;
103 let len = ((val & 0x7F) as usize) + 1;
104 validate!(x + len <= w);
105 if (val & 0x80) != 0 {
106 let pix = &mut dst[dpos + x..][..len];
107 br.read_buf(pix)?;
108 } // otherwise skip already existing data
109 x += len;
110 }
111 dpos += stride;
112 }
113 Ok(false)
114 },
115 2 => {
116 for _ in 0..h {
117 let pix = &mut dst[dpos..][..w];
118 br.read_buf(pix)?;
119 dpos += stride;
120 }
121 Ok(true)
122 },
123 3 => {
124 for _ in 0..h {
125 let mut x = 0;
126 while x < w {
127 let val = br.read_byte()?;
128 let len = ((val & 0x7F) as usize) + 1;
129 validate!(x + len <= w);
130 if (val & 0x80) != 0 {
131 let pix = &mut dst[dpos + x..][..len];
132 if br.peek_byte()? == 0xFF {
133 br.read_skip(1)?;
134 rle_unpack(br, len, pix)?;
135 } else {
136 br.read_buf(pix)?;
137 }
138 } // otherwise data is already there
139 x += len;
140 }
141 dpos += stride;
142 }
143 Ok(false)
144 },
e69b1148 145 _ => Err(DecoderError::InvalidData),
9895bd7b
KS
146 }
147}
148
149struct VMDVideoDecoder {
2422d969 150 info: NACodecInfoRef,
9895bd7b
KS
151 pal: [u8; 768],
152 buf: Vec<u8>,
153 width: usize,
154 height: usize,
155 hams: HAMShuffler,
156}
157
158impl VMDVideoDecoder {
159 fn new() -> Self {
160 Self {
2422d969 161 info: NACodecInfoRef::default(),
9895bd7b
KS
162 pal: [0; 768],
163 buf: Vec::new(),
164 width: 0,
165 height: 0,
166 hams: HAMShuffler::default(),
167 }
168 }
169 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
170 let paloff = buf.get_offset(1);
171 let stride = buf.get_stride(0);
1a967e6b 172 let data = buf.get_data_mut().unwrap();
9895bd7b
KS
173 let dst = data.as_mut_slice();
174
175 let frame_x = br.read_u16le()? as usize;
176 let frame_y = br.read_u16le()? as usize;
177 let frame_l = br.read_u16le()? as usize;
178 let frame_d = br.read_u16le()? as usize;
179 br.read_skip(1)?;
180 let flags = br.read_byte()?;
181 let has_pal = (flags & 0x02) != 0;
182 validate!(frame_l >= frame_x && frame_d >= frame_y);
183 validate!(frame_l < self.width && frame_d < self.height);
184
185 if has_pal {
186 br.read_skip(2)?;
187 for e in self.pal.iter_mut() {
188 let val = br.read_byte()?;
189 *e = (val << 2) | (val >> 4);
190 }
191 }
192
193 let dpal = &mut dst[paloff..][..768];
194 dpal.copy_from_slice(&self.pal[0..]);
195
196 if br.left() == 0 { return Ok(false); }
197
198 let w = frame_l + 1 - frame_x;
199 let h = frame_d + 1 - frame_y;
200 let dpos = frame_x + frame_y * stride;
201
202 let method = br.read_byte()?;
203 let is_intra;
204 if (method & 0x80) != 0 {
e69b1148 205 validate!(!self.buf.is_empty());
9895bd7b
KS
206 lz_unpack(br, &mut self.buf)?;
207 let mut mr = MemoryReader::new_read(&self.buf);
208 let mut buf_br = ByteReader::new(&mut mr);
209 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
210 } else {
211 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
212 }
213 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
214 }
215}
216
217impl NADecoder for VMDVideoDecoder {
01613464 218 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
219 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
220 self.width = vinfo.get_width();
221 self.height = vinfo.get_height();
222 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
2422d969 223 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
9895bd7b
KS
224 validate!(info.get_extradata().is_some());
225
226 if let Some(ref edata) = info.get_extradata() {
227 validate!(edata.len() == 0x330);
228 let unp_size = read_u32le(&edata[800..])? as usize;
229 validate!(unp_size < self.width * self.height * 3 + 64); // just for sanity
230 self.buf.resize(unp_size, 0);
231 for i in 0..768 {
232 let el = edata[28 + i];
233 self.pal[i] = (el << 2) | (el >> 4);
234 }
235 }
236
237 Ok(())
238 } else {
239 Err(DecoderError::InvalidData)
240 }
241 }
01613464 242 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
243 let src = pkt.get_buffer();
244 validate!(src.len() >= 10);
245
246 let mut mr = MemoryReader::new_read(&src);
247 let mut br = ByteReader::new(&mut mr);
248
249 let mut buf;
250 let bufret = self.hams.clone_ref();
251 if let Some(bbuf) = bufret {
252 buf = bbuf;
253 } else {
e69b1148 254 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
9895bd7b
KS
255 buf = bufinfo.get_vbuf().unwrap();
256 self.hams.add_frame(buf);
257 buf = self.hams.get_output_frame().unwrap();
258 }
259
260 let is_intra = self.decode_frame(&mut br, &mut buf)?;
261
262 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
263 frm.set_keyframe(is_intra);
264 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
171860fc 265 Ok(frm.into_ref())
9895bd7b
KS
266 }
267}
268
269
6011e201 270pub fn get_decoder_video() -> Box<dyn NADecoder> {
9895bd7b
KS
271 Box::new(VMDVideoDecoder::new())
272}
273
274struct VMDAudioDecoder {
275 ainfo: NAAudioInfo,
276 chmap: NAChannelMap,
277 is16bit: bool,
278 blk_align: usize,
279 blk_size: usize,
280}
281
282const SOL_AUD_STEPS16: [i16; 128] = [
283 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
284 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
285 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
286 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
287 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
288 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
289 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
290 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
291 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
292 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
293 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
294 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
295 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
296 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
297 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
298 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
299];
300
301impl VMDAudioDecoder {
302 fn new() -> Self {
303 Self {
304 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
305 chmap: NAChannelMap::new(),
306 is16bit: false,
307 blk_align: 0,
308 blk_size: 0,
309 }
310 }
311 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
312 let channels = self.chmap.num_channels();
313 let mut off = [0, off1];
314 for _ in 0..nblocks {
315 if (mask & 1) != 0 {
316 for ch in 0..channels {
317 for i in 0..self.blk_align {
318 dst[off[ch] + i] = 0;
319 }
320 off[ch] += self.blk_align;
321 }
322 } else {
323 let mut pred: [i32; 2] = [0; 2];
324 for ch in 0..channels {
e69b1148 325 pred[ch] = i32::from(br.read_u16le()?);
9895bd7b
KS
326 dst[off[ch]] = pred[ch] as i16;
327 off[ch] += 1;
328 }
329 let mut ch = 0;
330 let flip_ch = if channels == 2 { 1 } else { 0 };
aa7e65d2 331 for _ in channels..self.blk_align*channels {
9895bd7b
KS
332 let b = br.read_byte()? as usize;
333 if (b & 0x80) != 0 {
e69b1148 334 pred[ch] -= i32::from(SOL_AUD_STEPS16[b & 0x7F]);
9895bd7b 335 } else {
e69b1148 336 pred[ch] += i32::from(SOL_AUD_STEPS16[b & 0x7F]);
9895bd7b
KS
337 }
338 //pred[ch] = pred[ch].max(-32768).min(32767);
339 dst[off[ch]] = pred[ch] as i16;
340 off[ch] += 1;
341 ch ^= flip_ch;
342 }
343 }
344 mask >>= 1;
345 }
346 validate!(br.left() == 0);
347 Ok(())
348 }
349}
350
351impl NADecoder for VMDAudioDecoder {
01613464 352 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
353 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
354 let fmt;
355 if ainfo.get_format().get_bits() == 8 {
356 fmt = SND_U8_FORMAT;
357 self.is16bit = false;
358 self.blk_size = ainfo.get_block_len();
aa7e65d2 359 self.blk_align = ainfo.get_block_len() / (ainfo.get_channels() as usize);
9895bd7b
KS
360 } else {
361 fmt = SND_S16P_FORMAT;
362 self.is16bit = true;
363 self.blk_size = (ainfo.get_block_len() + 1) * (ainfo.get_channels() as usize);
aa7e65d2 364 self.blk_align = ainfo.get_block_len();
9895bd7b 365 };
9895bd7b
KS
366 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
367 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 1 { "C" } else { "L,R" }).unwrap();
368 Ok(())
369 } else {
370 Err(DecoderError::InvalidData)
371 }
372 }
01613464 373 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
374 let info = pkt.get_stream().get_info();
375 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
376 let pktbuf = pkt.get_buffer();
377 validate!(pktbuf.len() >= 6);
378 let mut mr = MemoryReader::new_read(&pktbuf);
379 let mut br = ByteReader::new(&mut mr);
380 let blk_type = br.read_byte()?;
381 br.read_skip(9)?;
382 let mask;
383 let nblocks;
384 if blk_type == 2 { // initial
385 mask = br.read_u32le()?;
386 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
387 } else if blk_type == 3 { // silence
388 mask = 1;
389 nblocks = 1;
390 } else {
391 mask = 0;
392 nblocks = 1;
393 }
394 let samples = nblocks * self.blk_align;
395 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
396 if self.is16bit {
397 let mut adata = abuf.get_abuf_i16().unwrap();
398 let off1 = adata.get_offset(1);
1a967e6b 399 let mut dst = adata.get_data_mut().unwrap();
9895bd7b
KS
400 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
401 } else {
402 let mut adata = abuf.get_abuf_u8().unwrap();
1a967e6b 403 let dst = adata.get_data_mut().unwrap();
9895bd7b
KS
404 let mut doff = 0;
405 let mut mask = mask;
406 let channels = self.chmap.num_channels();
407 for _ in 0..nblocks {
408 if (mask & 1) != 0 {
409 for i in 0..self.blk_align * channels {
410 dst[doff + i] = 0;
411 }
aa7e65d2
KS
412 } else if channels == 1 {
413 for i in 0..self.blk_size {
9895bd7b
KS
414 dst[doff + i] = br.read_byte()?;
415 }
aa7e65d2
KS
416 } else {
417 for i in 0..self.blk_size {
418 let val = br.read_byte()?;
419 if val < 128 {
420 dst[doff + i] = 127 - val;
421 } else {
422 dst[doff + i] = val;
423 }
424 }
9895bd7b 425 }
aa7e65d2 426 doff += self.blk_align * channels;
9895bd7b
KS
427 mask >>= 1;
428 }
429 }
430
431 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
432 frm.set_duration(Some(samples as u64));
433 frm.set_keyframe(true);
171860fc 434 Ok(frm.into_ref())
9895bd7b
KS
435 } else {
436 Err(DecoderError::InvalidData)
437 }
438 }
439}
440
6011e201 441pub fn get_decoder_audio() -> Box<dyn NADecoder> {
9895bd7b
KS
442 Box::new(VMDAudioDecoder::new())
443}
444
445#[cfg(test)]
446mod test {
447 use nihav_core::codecs::RegisteredDecoders;
448 use nihav_core::demuxers::RegisteredDemuxers;
449 use nihav_core::test::dec_video::*;
450 use crate::codecs::game_register_all_codecs;
451 use crate::demuxers::game_register_all_demuxers;
452 #[test]
453 fn test_vmd_video() {
454 let mut dmx_reg = RegisteredDemuxers::new();
455 game_register_all_demuxers(&mut dmx_reg);
456 let mut dec_reg = RegisteredDecoders::new();
457 game_register_all_codecs(&mut dec_reg);
458
1678d59a
KS
459// let file = "assets/Game/1491.VMD";
460 let file = "assets/Game/128.vmd";
9895bd7b
KS
461 test_file_decoding("vmd", file, Some(10), true, false, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
462 }
463 #[test]
464 fn test_vmd_audio() {
465 let mut dmx_reg = RegisteredDemuxers::new();
466 game_register_all_demuxers(&mut dmx_reg);
467 let mut dec_reg = RegisteredDecoders::new();
468 game_register_all_codecs(&mut dec_reg);
469
1678d59a
KS
470// let file = "assets/Game/1491.VMD";
471 let file = "assets/Game/128.vmd";
472// let file = "assets/Game/1000.VMD";
473// let file = "assets/Game/235.VMD";
9895bd7b
KS
474 test_decode_audio("vmd", file, None, "vmd", &dmx_reg, &dec_reg);
475 }
476}