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