vmdaudio: fix u8 silent blocks value
[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;
5961ae1d
KS
183 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
184 return Ok(false);
185 }
9895bd7b
KS
186 validate!(frame_l >= frame_x && frame_d >= frame_y);
187 validate!(frame_l < self.width && frame_d < self.height);
188
189 if has_pal {
190 br.read_skip(2)?;
191 for e in self.pal.iter_mut() {
192 let val = br.read_byte()?;
193 *e = (val << 2) | (val >> 4);
194 }
195 }
196
197 let dpal = &mut dst[paloff..][..768];
198 dpal.copy_from_slice(&self.pal[0..]);
199
200 if br.left() == 0 { return Ok(false); }
201
202 let w = frame_l + 1 - frame_x;
203 let h = frame_d + 1 - frame_y;
204 let dpos = frame_x + frame_y * stride;
205
206 let method = br.read_byte()?;
207 let is_intra;
208 if (method & 0x80) != 0 {
e69b1148 209 validate!(!self.buf.is_empty());
9895bd7b
KS
210 lz_unpack(br, &mut self.buf)?;
211 let mut mr = MemoryReader::new_read(&self.buf);
212 let mut buf_br = ByteReader::new(&mut mr);
213 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
214 } else {
215 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
216 }
217 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
218 }
219}
220
221impl NADecoder for VMDVideoDecoder {
01613464 222 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
223 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
224 self.width = vinfo.get_width();
225 self.height = vinfo.get_height();
226 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
2422d969 227 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
9895bd7b
KS
228 validate!(info.get_extradata().is_some());
229
230 if let Some(ref edata) = info.get_extradata() {
231 validate!(edata.len() == 0x330);
232 let unp_size = read_u32le(&edata[800..])? as usize;
233 validate!(unp_size < self.width * self.height * 3 + 64); // just for sanity
234 self.buf.resize(unp_size, 0);
235 for i in 0..768 {
236 let el = edata[28 + i];
237 self.pal[i] = (el << 2) | (el >> 4);
238 }
239 }
240
241 Ok(())
242 } else {
243 Err(DecoderError::InvalidData)
244 }
245 }
01613464 246 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
247 let src = pkt.get_buffer();
248 validate!(src.len() >= 10);
249
250 let mut mr = MemoryReader::new_read(&src);
251 let mut br = ByteReader::new(&mut mr);
252
253 let mut buf;
254 let bufret = self.hams.clone_ref();
255 if let Some(bbuf) = bufret {
256 buf = bbuf;
257 } else {
e69b1148 258 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
9895bd7b
KS
259 buf = bufinfo.get_vbuf().unwrap();
260 self.hams.add_frame(buf);
261 buf = self.hams.get_output_frame().unwrap();
262 }
263
264 let is_intra = self.decode_frame(&mut br, &mut buf)?;
265
266 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
267 frm.set_keyframe(is_intra);
268 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
171860fc 269 Ok(frm.into_ref())
9895bd7b 270 }
f9be4e75
KS
271 fn flush(&mut self) {
272 self.hams.clear();
273 }
9895bd7b
KS
274}
275
276
08a1fab7 277pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
278 Box::new(VMDVideoDecoder::new())
279}
280
281struct VMDAudioDecoder {
282 ainfo: NAAudioInfo,
283 chmap: NAChannelMap,
284 is16bit: bool,
285 blk_align: usize,
286 blk_size: usize,
287}
288
289const SOL_AUD_STEPS16: [i16; 128] = [
290 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
291 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
292 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
293 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
294 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
295 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
296 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
297 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
298 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
299 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
300 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
301 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
302 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
303 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
304 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
305 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
306];
307
308impl VMDAudioDecoder {
309 fn new() -> Self {
310 Self {
311 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
312 chmap: NAChannelMap::new(),
313 is16bit: false,
314 blk_align: 0,
315 blk_size: 0,
316 }
317 }
318 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
319 let channels = self.chmap.num_channels();
320 let mut off = [0, off1];
321 for _ in 0..nblocks {
322 if (mask & 1) != 0 {
323 for ch in 0..channels {
324 for i in 0..self.blk_align {
325 dst[off[ch] + i] = 0;
326 }
327 off[ch] += self.blk_align;
328 }
329 } else {
330 let mut pred: [i32; 2] = [0; 2];
331 for ch in 0..channels {
e69b1148 332 pred[ch] = i32::from(br.read_u16le()?);
9895bd7b
KS
333 dst[off[ch]] = pred[ch] as i16;
334 off[ch] += 1;
335 }
336 let mut ch = 0;
337 let flip_ch = if channels == 2 { 1 } else { 0 };
aa7e65d2 338 for _ in channels..self.blk_align*channels {
9895bd7b
KS
339 let b = br.read_byte()? as usize;
340 if (b & 0x80) != 0 {
e69b1148 341 pred[ch] -= i32::from(SOL_AUD_STEPS16[b & 0x7F]);
9895bd7b 342 } else {
e69b1148 343 pred[ch] += i32::from(SOL_AUD_STEPS16[b & 0x7F]);
9895bd7b
KS
344 }
345 //pred[ch] = pred[ch].max(-32768).min(32767);
346 dst[off[ch]] = pred[ch] as i16;
347 off[ch] += 1;
348 ch ^= flip_ch;
349 }
350 }
351 mask >>= 1;
352 }
353 validate!(br.left() == 0);
354 Ok(())
355 }
356}
357
358impl NADecoder for VMDAudioDecoder {
01613464 359 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
9895bd7b
KS
360 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
361 let fmt;
362 if ainfo.get_format().get_bits() == 8 {
363 fmt = SND_U8_FORMAT;
364 self.is16bit = false;
365 self.blk_size = ainfo.get_block_len();
aa7e65d2 366 self.blk_align = ainfo.get_block_len() / (ainfo.get_channels() as usize);
9895bd7b
KS
367 } else {
368 fmt = SND_S16P_FORMAT;
369 self.is16bit = true;
370 self.blk_size = (ainfo.get_block_len() + 1) * (ainfo.get_channels() as usize);
aa7e65d2 371 self.blk_align = ainfo.get_block_len();
9895bd7b 372 };
9895bd7b
KS
373 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
374 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 1 { "C" } else { "L,R" }).unwrap();
375 Ok(())
376 } else {
377 Err(DecoderError::InvalidData)
378 }
379 }
01613464 380 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
9895bd7b
KS
381 let info = pkt.get_stream().get_info();
382 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
383 let pktbuf = pkt.get_buffer();
384 validate!(pktbuf.len() >= 6);
385 let mut mr = MemoryReader::new_read(&pktbuf);
386 let mut br = ByteReader::new(&mut mr);
387 let blk_type = br.read_byte()?;
388 br.read_skip(9)?;
389 let mask;
390 let nblocks;
391 if blk_type == 2 { // initial
392 mask = br.read_u32le()?;
393 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
394 } else if blk_type == 3 { // silence
395 mask = 1;
396 nblocks = 1;
397 } else {
398 mask = 0;
399 nblocks = 1;
400 }
401 let samples = nblocks * self.blk_align;
402 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
403 if self.is16bit {
404 let mut adata = abuf.get_abuf_i16().unwrap();
405 let off1 = adata.get_offset(1);
1a967e6b 406 let mut dst = adata.get_data_mut().unwrap();
9895bd7b
KS
407 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
408 } else {
409 let mut adata = abuf.get_abuf_u8().unwrap();
1a967e6b 410 let dst = adata.get_data_mut().unwrap();
9895bd7b
KS
411 let mut doff = 0;
412 let mut mask = mask;
413 let channels = self.chmap.num_channels();
414 for _ in 0..nblocks {
415 if (mask & 1) != 0 {
416 for i in 0..self.blk_align * channels {
44f6395b 417 dst[doff + i] = 128;
9895bd7b 418 }
aa7e65d2
KS
419 } else if channels == 1 {
420 for i in 0..self.blk_size {
9895bd7b
KS
421 dst[doff + i] = br.read_byte()?;
422 }
aa7e65d2
KS
423 } else {
424 for i in 0..self.blk_size {
425 let val = br.read_byte()?;
426 if val < 128 {
427 dst[doff + i] = 127 - val;
428 } else {
429 dst[doff + i] = val;
430 }
431 }
9895bd7b 432 }
aa7e65d2 433 doff += self.blk_align * channels;
9895bd7b
KS
434 mask >>= 1;
435 }
436 }
437
438 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
439 frm.set_duration(Some(samples as u64));
440 frm.set_keyframe(true);
171860fc 441 Ok(frm.into_ref())
9895bd7b
KS
442 } else {
443 Err(DecoderError::InvalidData)
444 }
445 }
f9be4e75
KS
446 fn flush(&mut self) {
447 }
9895bd7b
KS
448}
449
08a1fab7 450pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
9895bd7b
KS
451 Box::new(VMDAudioDecoder::new())
452}
453
454#[cfg(test)]
455mod test {
456 use nihav_core::codecs::RegisteredDecoders;
457 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 458 use nihav_codec_support::test::dec_video::*;
e64739f8
KS
459 use crate::game_register_all_codecs;
460 use crate::game_register_all_demuxers;
9895bd7b
KS
461 #[test]
462 fn test_vmd_video() {
463 let mut dmx_reg = RegisteredDemuxers::new();
464 game_register_all_demuxers(&mut dmx_reg);
465 let mut dec_reg = RegisteredDecoders::new();
466 game_register_all_codecs(&mut dec_reg);
467
1678d59a
KS
468// let file = "assets/Game/1491.VMD";
469 let file = "assets/Game/128.vmd";
9895bd7b
KS
470 test_file_decoding("vmd", file, Some(10), true, false, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
471 }
472 #[test]
473 fn test_vmd_audio() {
474 let mut dmx_reg = RegisteredDemuxers::new();
475 game_register_all_demuxers(&mut dmx_reg);
476 let mut dec_reg = RegisteredDecoders::new();
477 game_register_all_codecs(&mut dec_reg);
478
1678d59a
KS
479// let file = "assets/Game/1491.VMD";
480 let file = "assets/Game/128.vmd";
481// let file = "assets/Game/1000.VMD";
482// let file = "assets/Game/235.VMD";
5580b11b 483 test_decode_audio("vmd", file, None, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
9895bd7b
KS
484 }
485}