]> git.nihav.org Git - nihav.git/blame_incremental - nihav-game/src/codecs/vmd.rs
nihav-duck: require blockdsp feature from core
[nihav.git] / nihav-game / src / codecs / vmd.rs
... / ...
CommitLineData
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 _ => Err(DecoderError::InvalidData),
146 }
147}
148
149struct VMDVideoDecoder {
150 info: NACodecInfoRef,
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 {
161 info: NACodecInfoRef::default(),
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);
172 let data = buf.get_data_mut().unwrap();
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.is_empty());
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 {
218 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
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));
223 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
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, _supp: &mut NADecoderSupport, 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 bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
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 });
265 Ok(frm.into_ref())
266 }
267}
268
269
270pub fn get_decoder_video() -> Box<dyn NADecoder> {
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 {
325 pred[ch] = i32::from(br.read_u16le()?);
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 };
331 for _ in channels..self.blk_align*channels {
332 let b = br.read_byte()? as usize;
333 if (b & 0x80) != 0 {
334 pred[ch] -= i32::from(SOL_AUD_STEPS16[b & 0x7F]);
335 } else {
336 pred[ch] += i32::from(SOL_AUD_STEPS16[b & 0x7F]);
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 {
352 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
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();
359 self.blk_align = ainfo.get_block_len() / (ainfo.get_channels() as usize);
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);
364 self.blk_align = ainfo.get_block_len();
365 };
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 }
373 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
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);
399 let mut dst = adata.get_data_mut().unwrap();
400 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
401 } else {
402 let mut adata = abuf.get_abuf_u8().unwrap();
403 let dst = adata.get_data_mut().unwrap();
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 }
412 } else if channels == 1 {
413 for i in 0..self.blk_size {
414 dst[doff + i] = br.read_byte()?;
415 }
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 }
425 }
426 doff += self.blk_align * channels;
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);
434 Ok(frm.into_ref())
435 } else {
436 Err(DecoderError::InvalidData)
437 }
438 }
439}
440
441pub fn get_decoder_audio() -> Box<dyn NADecoder> {
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
459// let file = "assets/Game/1491.VMD";
460 let file = "assets/Game/128.vmd";
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
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";
474 test_decode_audio("vmd", file, None, "vmd", &dmx_reg, &dec_reg);
475 }
476}