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