make all codec crates export just register_all functions and document them
[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 266 }
f9be4e75
KS
267 fn flush(&mut self) {
268 self.hams.clear();
269 }
9895bd7b
KS
270}
271
272
08a1fab7 273pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
274 Box::new(VMDVideoDecoder::new())
275}
276
277struct VMDAudioDecoder {
278 ainfo: NAAudioInfo,
279 chmap: NAChannelMap,
280 is16bit: bool,
281 blk_align: usize,
282 blk_size: usize,
283}
284
285const SOL_AUD_STEPS16: [i16; 128] = [
286 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
287 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
288 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
289 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
290 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
291 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
292 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
293 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
294 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
295 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
296 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
297 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
298 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
299 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
300 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
301 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
302];
303
304impl VMDAudioDecoder {
305 fn new() -> Self {
306 Self {
307 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
308 chmap: NAChannelMap::new(),
309 is16bit: false,
310 blk_align: 0,
311 blk_size: 0,
312 }
313 }
314 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
315 let channels = self.chmap.num_channels();
316 let mut off = [0, off1];
317 for _ in 0..nblocks {
318 if (mask & 1) != 0 {
319 for ch in 0..channels {
320 for i in 0..self.blk_align {
321 dst[off[ch] + i] = 0;
322 }
323 off[ch] += self.blk_align;
324 }
325 } else {
326 let mut pred: [i32; 2] = [0; 2];
327 for ch in 0..channels {
e69b1148 328 pred[ch] = i32::from(br.read_u16le()?);
9895bd7b
KS
329 dst[off[ch]] = pred[ch] as i16;
330 off[ch] += 1;
331 }
332 let mut ch = 0;
333 let flip_ch = if channels == 2 { 1 } else { 0 };
aa7e65d2 334 for _ in channels..self.blk_align*channels {
9895bd7b
KS
335 let b = br.read_byte()? as usize;
336 if (b & 0x80) != 0 {
e69b1148 337 pred[ch] -= i32::from(SOL_AUD_STEPS16[b & 0x7F]);
9895bd7b 338 } else {
e69b1148 339 pred[ch] += i32::from(SOL_AUD_STEPS16[b & 0x7F]);
9895bd7b
KS
340 }
341 //pred[ch] = pred[ch].max(-32768).min(32767);
342 dst[off[ch]] = pred[ch] as i16;
343 off[ch] += 1;
344 ch ^= flip_ch;
345 }
346 }
347 mask >>= 1;
348 }
349 validate!(br.left() == 0);
350 Ok(())
351 }
352}
353
354impl NADecoder for VMDAudioDecoder {
01613464 355 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
356 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
357 let fmt;
358 if ainfo.get_format().get_bits() == 8 {
359 fmt = SND_U8_FORMAT;
360 self.is16bit = false;
361 self.blk_size = ainfo.get_block_len();
aa7e65d2 362 self.blk_align = ainfo.get_block_len() / (ainfo.get_channels() as usize);
9895bd7b
KS
363 } else {
364 fmt = SND_S16P_FORMAT;
365 self.is16bit = true;
366 self.blk_size = (ainfo.get_block_len() + 1) * (ainfo.get_channels() as usize);
aa7e65d2 367 self.blk_align = ainfo.get_block_len();
9895bd7b 368 };
9895bd7b
KS
369 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
370 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 1 { "C" } else { "L,R" }).unwrap();
371 Ok(())
372 } else {
373 Err(DecoderError::InvalidData)
374 }
375 }
01613464 376 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
377 let info = pkt.get_stream().get_info();
378 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
379 let pktbuf = pkt.get_buffer();
380 validate!(pktbuf.len() >= 6);
381 let mut mr = MemoryReader::new_read(&pktbuf);
382 let mut br = ByteReader::new(&mut mr);
383 let blk_type = br.read_byte()?;
384 br.read_skip(9)?;
385 let mask;
386 let nblocks;
387 if blk_type == 2 { // initial
388 mask = br.read_u32le()?;
389 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
390 } else if blk_type == 3 { // silence
391 mask = 1;
392 nblocks = 1;
393 } else {
394 mask = 0;
395 nblocks = 1;
396 }
397 let samples = nblocks * self.blk_align;
398 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
399 if self.is16bit {
400 let mut adata = abuf.get_abuf_i16().unwrap();
401 let off1 = adata.get_offset(1);
1a967e6b 402 let mut dst = adata.get_data_mut().unwrap();
9895bd7b
KS
403 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
404 } else {
405 let mut adata = abuf.get_abuf_u8().unwrap();
1a967e6b 406 let dst = adata.get_data_mut().unwrap();
9895bd7b
KS
407 let mut doff = 0;
408 let mut mask = mask;
409 let channels = self.chmap.num_channels();
410 for _ in 0..nblocks {
411 if (mask & 1) != 0 {
412 for i in 0..self.blk_align * channels {
413 dst[doff + i] = 0;
414 }
aa7e65d2
KS
415 } else if channels == 1 {
416 for i in 0..self.blk_size {
9895bd7b
KS
417 dst[doff + i] = br.read_byte()?;
418 }
aa7e65d2
KS
419 } else {
420 for i in 0..self.blk_size {
421 let val = br.read_byte()?;
422 if val < 128 {
423 dst[doff + i] = 127 - val;
424 } else {
425 dst[doff + i] = val;
426 }
427 }
9895bd7b 428 }
aa7e65d2 429 doff += self.blk_align * channels;
9895bd7b
KS
430 mask >>= 1;
431 }
432 }
433
434 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
435 frm.set_duration(Some(samples as u64));
436 frm.set_keyframe(true);
171860fc 437 Ok(frm.into_ref())
9895bd7b
KS
438 } else {
439 Err(DecoderError::InvalidData)
440 }
441 }
f9be4e75
KS
442 fn flush(&mut self) {
443 }
9895bd7b
KS
444}
445
08a1fab7 446pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
447 Box::new(VMDAudioDecoder::new())
448}
449
450#[cfg(test)]
451mod test {
452 use nihav_core::codecs::RegisteredDecoders;
453 use nihav_core::demuxers::RegisteredDemuxers;
454 use nihav_core::test::dec_video::*;
e64739f8
KS
455 use crate::game_register_all_codecs;
456 use crate::game_register_all_demuxers;
9895bd7b
KS
457 #[test]
458 fn test_vmd_video() {
459 let mut dmx_reg = RegisteredDemuxers::new();
460 game_register_all_demuxers(&mut dmx_reg);
461 let mut dec_reg = RegisteredDecoders::new();
462 game_register_all_codecs(&mut dec_reg);
463
1678d59a
KS
464// let file = "assets/Game/1491.VMD";
465 let file = "assets/Game/128.vmd";
9895bd7b
KS
466 test_file_decoding("vmd", file, Some(10), true, false, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
467 }
468 #[test]
469 fn test_vmd_audio() {
470 let mut dmx_reg = RegisteredDemuxers::new();
471 game_register_all_demuxers(&mut dmx_reg);
472 let mut dec_reg = RegisteredDecoders::new();
473 game_register_all_codecs(&mut dec_reg);
474
1678d59a
KS
475// let file = "assets/Game/1491.VMD";
476 let file = "assets/Game/128.vmd";
477// let file = "assets/Game/1000.VMD";
478// let file = "assets/Game/235.VMD";
5580b11b 479 test_decode_audio("vmd", file, None, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
9895bd7b
KS
480 }
481}