1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_core::io::bitreader::*;
4 use nihav_core::io::codebook::*;
7 const PAL_SIZE: usize = 768;
8 const SMK_FLAG_INTERLACED: u32 = 0x02;
9 const SMK_FLAG_SCALED: u32 = 0x04;
12 cb: Option<Codebook<u8>>,
16 fn get_tree8(br: &mut BitReader, bits: &mut [u8; 256], codes: &mut [u32; 256], syms: &mut [u8; 256], count: &mut usize, len: u8, prefix: u32) -> DecoderResult<()> {
19 codes[*count] = prefix;
20 syms[*count] = br.read(8)? as u8;
23 validate!((*count <= 256 - 2) && (len <= 31));
24 get_tree8(br, bits, codes, syms, count, len + 1, prefix)?;
25 get_tree8(br, bits, codes, syms, count, len + 1, prefix | (1 << len))?;
30 pub struct FullTableCodebookDescReader<'a> {
36 impl<'a> FullTableCodebookDescReader<'a> {
37 pub fn new(codes: &'a [u32], bits: &'a [u8], syms: &'a [u8]) -> Self {
38 Self { bits, codes, syms }
41 impl<'a> CodebookDescReader<u8> for FullTableCodebookDescReader<'a>
43 fn bits(&mut self, idx: usize) -> u8 { self.bits[idx] }
44 fn code(&mut self, idx: usize) -> u32 { self.codes[idx] }
45 fn sym (&mut self, idx: usize) -> u8 { self.syms[idx] }
46 fn len(&mut self) -> usize { self.bits.len() }
56 fn decode(&mut self, br: &mut BitReader) -> DecoderResult<()> {
57 if !br.read_bool()? { return Ok(()); }
59 let mut bits: [u8; 256] = [0; 256];
60 let mut codes: [u32; 256] = [0; 256];
61 let mut syms: [u8; 256] = [0; 256];
64 get_tree8(br, &mut bits, &mut codes, &mut syms, &mut count, 0, 0)?;
65 validate!(!br.read_bool()?);
68 let mut cr = FullTableCodebookDescReader::new(&codes[0..count], &bits[0..count], &syms[0..count]);
69 let cb = Codebook::new(&mut cr, CodebookMode::LSB)?;
72 self.defsym = syms[0];
79 struct SmackerTree16 {
84 struct SmackerTree16Builder {
85 tree_lo: SmackerTree8,
86 tree_hi: SmackerTree8,
91 const SMK_BIGTREE_NODE: u32 = 0x80000000;
92 const SMK_LAST_UNINIT: usize = 0xFFFFFFFF;
94 impl SmackerTree16Builder {
95 fn get_tree16(&mut self, br: &mut BitReader, tree: &mut SmackerTree16, depth: usize) -> DecoderResult<u32> {
96 validate!(tree.tree.len() < self.nsyms);
97 validate!(depth <= 32);
99 let lo = br.read_tree8(&self.tree_lo)?;
100 let hi = br.read_tree8(&self.tree_hi)?;
101 let mut sym = (((hi as u16) << 8) | (lo as u16)) as u32;
102 if sym == self.esc[0] {
103 tree.last[0] = tree.tree.len();
105 } else if sym == self.esc[1] {
106 tree.last[1] = tree.tree.len();
108 } else if sym == self.esc[2] {
109 tree.last[2] = tree.tree.len();
115 let cur_idx = tree.tree.len();
117 let lcount = self.get_tree16(br, tree, depth + 1)?;
118 let rcount = self.get_tree16(br, tree, depth + 1)?;
119 tree.tree[cur_idx] = SMK_BIGTREE_NODE | lcount;
120 Ok(lcount + rcount + 1)
129 last: [SMK_LAST_UNINIT; 3],
132 fn decode(&mut self, br: &mut BitReader, size: u32) -> DecoderResult<()> {
133 if !br.read_bool()? { return Ok(()); }
135 let mut tree_lo = SmackerTree8::new();
137 let mut tree_hi = SmackerTree8::new();
140 let mut esc: [u32; 3] = [0; 3];
141 for esc in esc.iter_mut() {
145 let nsyms = (((size + 3) >> 2) + 4) as usize;
146 self.tree = Vec::with_capacity(nsyms);
148 let mut tb = SmackerTree16Builder { tree_lo, tree_hi, nsyms, esc };
150 tb.get_tree16(br, self, 0)?;
151 validate!(!br.read_bool()?);
153 for i in 0..self.last.len() {
154 if self.last[i] == SMK_LAST_UNINIT {
155 self.last[i] = self.tree.len();
159 validate!(self.tree.len() <= nsyms);
162 fn reset(&mut self) {
163 for i in 0..self.last.len() {
164 if self.last[i] != SMK_LAST_UNINIT {
165 self.tree[self.last[i]] = 0;
172 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>;
173 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>;
176 impl<'a> ReadTree for BitReader<'a> {
177 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8> {
178 if let Some(ref cb) = tree.cb {
179 Ok(self.read_cb(cb)?)
184 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16> {
186 while (tree.tree[pos] & SMK_BIGTREE_NODE) != 0 {
187 if self.read_bool()? {
188 pos += (tree.tree[pos] & !SMK_BIGTREE_NODE) as usize;
192 let val = tree.tree[pos];
193 if val != tree.tree[tree.last[0]] {
194 tree.tree[tree.last[2]] = tree.tree[tree.last[1]];
195 tree.tree[tree.last[1]] = tree.tree[tree.last[0]];
196 tree.tree[tree.last[0]] = val;
202 const SMK_BLOCK_RUNS: [usize; 64] = [
203 1, 2, 3, 4, 5, 6, 7, 8,
204 9, 10, 11, 12, 13, 14, 15, 16,
205 17, 18, 19, 20, 21, 22, 23, 24,
206 25, 26, 27, 28, 29, 30, 31, 32,
207 33, 34, 35, 36, 37, 38, 39, 40,
208 41, 42, 43, 44, 45, 46, 47, 48,
209 49, 50, 51, 52, 53, 54, 55, 56,
210 57, 58, 59, 128, 256, 512, 1024, 2048
213 struct SmackerVideoDecoder {
214 info: NACodecInfoRef,
215 mmap_tree: SmackerTree16,
216 mclr_tree: SmackerTree16,
217 full_tree: SmackerTree16,
218 type_tree: SmackerTree16,
229 impl SmackerVideoDecoder {
232 info: NACodecInfoRef::default(),
233 mmap_tree: SmackerTree16::new(),
234 mclr_tree: SmackerTree16::new(),
235 full_tree: SmackerTree16::new(),
236 type_tree: SmackerTree16::new(),
247 fn block_pos(&self, blk_no: usize) -> usize {
248 let bx = blk_no % self.bw;
249 let by = blk_no / self.bw;
250 bx * 4 + by * 4 * self.stride
252 #[allow(clippy::identity_op)]
253 fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<bool> {
254 let mut is_intra = true;
255 let blocks = self.bw * self.bh;
257 self.mmap_tree.reset();
258 self.mclr_tree.reset();
259 self.full_tree.reset();
260 self.type_tree.reset();
263 while block < blocks {
264 let btype = br.read_bigtree(&mut self.type_tree)?;
265 let run = SMK_BLOCK_RUNS[((btype as usize) >> 2) & 0x3F];
266 validate!(run <= blocks - block);
268 0 => { // two-colour pattern
270 let clr = br.read_bigtree(&mut self.mclr_tree)?;
271 let mut map = br.read_bigtree(&mut self.mmap_tree)?;
272 let hi = (clr >> 8) as u8;
273 let lo = (clr & 0xFF) as u8;
274 let mut doff = self.block_pos(block + i);
276 self.frame[doff + 0] = if (map & 1) != 0 { hi } else { lo };
277 self.frame[doff + 1] = if (map & 2) != 0 { hi } else { lo };
278 self.frame[doff + 2] = if (map & 4) != 0 { hi } else { lo };
279 self.frame[doff + 3] = if (map & 8) != 0 { hi } else { lo };
286 let mode = if !self.is_ver4 {
288 } else if br.read_bool()? {
290 } else if br.read_bool()? {
296 let mut doff = self.block_pos(block + i);
300 let clr0 = br.read_bigtree(&mut self.full_tree)?;
301 let clr1 = br.read_bigtree(&mut self.full_tree)?;
302 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
303 self.frame[doff + 1] = (clr1 >> 8) as u8;
304 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
305 self.frame[doff + 3] = (clr0 >> 8) as u8;
311 let clr = br.read_bigtree(&mut self.full_tree)?;
312 self.frame[doff + 0] = (clr & 0xFF) as u8;
313 self.frame[doff + 1] = (clr & 0xFF) as u8;
314 self.frame[doff + 2] = (clr >> 8) as u8;
315 self.frame[doff + 3] = (clr >> 8) as u8;
317 self.frame[doff + 0] = (clr & 0xFF) as u8;
318 self.frame[doff + 1] = (clr & 0xFF) as u8;
319 self.frame[doff + 2] = (clr >> 8) as u8;
320 self.frame[doff + 3] = (clr >> 8) as u8;
326 let clr0 = br.read_bigtree(&mut self.full_tree)?;
327 let clr1 = br.read_bigtree(&mut self.full_tree)?;
328 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
329 self.frame[doff + 1] = (clr1 >> 8) as u8;
330 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
331 self.frame[doff + 3] = (clr0 >> 8) as u8;
333 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
334 self.frame[doff + 1] = (clr1 >> 8) as u8;
335 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
336 self.frame[doff + 3] = (clr0 >> 8) as u8;
348 let clr = (btype >> 8) as u8;
350 let mut doff = self.block_pos(block + i);
352 self.frame[doff + 0] = clr;
353 self.frame[doff + 1] = clr;
354 self.frame[doff + 2] = clr;
355 self.frame[doff + 3] = clr;
366 fn output_frame(&self, buf: &mut NAVideoBuffer<u8>) {
367 let stride = buf.get_stride(0);
368 let data = buf.get_data_mut().unwrap();
369 let dst = data.as_mut_slice();
370 let is_scaled = (self.flags & SMK_FLAG_SCALED) != 0;
371 let is_interlaced = (self.flags & SMK_FLAG_INTERLACED) != 0;
375 dst[didx..][..self.w].copy_from_slice(&self.frame[sidx..][..self.w]);
379 for x in 0..self.w { dst[didx + x] = dst[didx - stride + x]; }
383 for x in 0..self.w { dst[didx + x] = 0; }
386 for x in 0..self.w { dst[didx + x] = 0; }
394 impl NADecoder for SmackerVideoDecoder {
395 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
396 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
397 let w = vinfo.get_width();
398 let h = vinfo.get_height();
399 let fmt = PAL8_FORMAT;
405 let edata = info.get_extradata().unwrap();
406 validate!(edata.len() > 24);
409 self.frame.resize(w * h, 0);
411 let mut mr = MemoryReader::new_read(&edata);
412 let mut br = ByteReader::new(&mut mr);
413 let magic = br.read_tag()?;
414 self.flags = br.read_u32le()?;
415 let mmap_size = br.read_u32le()?;
416 let mclr_size = br.read_u32le()?;
417 let full_size = br.read_u32le()?;
418 let type_size = br.read_u32le()?;
420 self.is_ver4 = &magic == b"SMK4";
421 let mut br = BitReader::new(&edata[24..], BitReaderMode::LE);
422 self.mmap_tree.decode(&mut br, mmap_size)?;
423 self.mclr_tree.decode(&mut br, mclr_size)?;
424 self.full_tree.decode(&mut br, full_size)?;
425 self.type_tree.decode(&mut br, type_size)?;
428 if (self.flags & SMK_FLAG_INTERLACED) != 0 {
431 if (self.flags & SMK_FLAG_SCALED) != 0 {
434 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, out_h, false, fmt));
435 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
439 Err(DecoderError::InvalidData)
442 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
443 let src = pkt.get_buffer();
444 validate!(src.len() >= PAL_SIZE);
449 if src.len() > PAL_SIZE {
450 let mut br = BitReader::new(&src[PAL_SIZE..], BitReaderMode::LE);
452 bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
453 let mut buf = bufinfo.get_vbuf().unwrap();
454 is_intra = self.decode_frame(&mut br)?;
455 self.output_frame(&mut buf);
456 let paloff = buf.get_offset(1);
457 let data = buf.get_data_mut().unwrap();
458 let dst = data.as_mut_slice();
459 let palout = &mut dst[paloff..][..PAL_SIZE];
460 palout.copy_from_slice(&src[0..PAL_SIZE]);
461 ftype = if is_intra { FrameType::I } else { FrameType::P };
463 bufinfo = NABufferType::None;
464 ftype = FrameType::Skip;
468 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
469 frm.set_keyframe(is_intra);
470 frm.set_frame_type(ftype);
473 fn flush(&mut self) {
477 impl NAOptionHandler for SmackerVideoDecoder {
478 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
479 fn set_options(&mut self, _options: &[NAOption]) { }
480 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
483 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
484 Box::new(SmackerVideoDecoder::new())
487 struct SmackerAudioDecoder {
494 impl SmackerAudioDecoder {
497 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
498 chmap: NAChannelMap::new(),
505 impl NADecoder for SmackerAudioDecoder {
506 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
507 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
508 self.bits = ainfo.get_format().get_bits();
509 let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16_FORMAT };
510 self.chans = ainfo.get_channels() as usize;
511 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, 0);
512 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 2 {"L,R"} else {"C"}).unwrap();
515 Err(DecoderError::InvalidData)
518 #[allow(clippy::identity_op)]
519 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
520 let info = pkt.get_stream().get_info();
521 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
522 let src = pkt.get_buffer();
523 validate!(src.len() > 4);
524 let mut br = BitReader::new(&src, BitReaderMode::LE);
525 let unp_size = br.read(32)? as usize;
526 if !br.read_bool()? {
527 let mut frm = NAFrame::new_from_pkt(pkt, info.clone(), NABufferType::None);
528 frm.set_frame_type(FrameType::Skip);
529 return Ok(frm.into_ref());
531 let stereo = br.read_bool()?;
532 let bits16 = br.read_bool()?;
533 validate!(!(stereo ^ (self.chans == 2)));
534 validate!(!(bits16 ^ (self.bits == 16)));
538 let nch = if stereo { 2 } else { 1 };
540 samples = unp_size / 2 / nch;
541 let mask = if stereo { 1 } else { 0 };
542 let mut trees: [SmackerTree8; 4] = [SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new()];
543 for tree in trees[..nch*2].iter_mut() {
544 tree.decode(&mut br)?;
546 let mut pred: [i16; 2] = [0; 2];
548 let hi = br.read(8)?;
549 let lo = br.read(8)?;
550 pred[nch - i - 1] = (lo | (hi << 8)) as i16;
553 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
554 let mut adata = abuf.get_abuf_i16().unwrap();
555 let dst = adata.get_data_mut().unwrap();
556 dst[..nch].copy_from_slice(&pred[..nch]);
557 for (i, out) in dst[nch..(unp_size >> 1)].iter_mut().enumerate() {
559 let lo = br.read_tree8(&trees[idx * 2 + 0])? as u16;
560 let hi = br.read_tree8(&trees[idx * 2 + 1])? as u16;
561 let diff = (lo | (hi << 8)) as i16;
562 pred[idx] = pred[idx].wrapping_add(diff);
566 samples = unp_size / nch;
567 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
568 let mut adata = abuf.get_abuf_u8().unwrap();
569 let dst = adata.get_data_mut().unwrap();
571 let mut trees: [SmackerTree8; 2] = [SmackerTree8::new(), SmackerTree8::new()];
572 trees[0].decode(&mut br)?;
573 trees[1].decode(&mut br)?;
574 let pred0 = br.read(8)? as u8;
575 let pred1 = br.read(8)? as u8;
576 let mut pred: [u8; 2] = [ pred1, pred0 ];
577 dst[..2].copy_from_slice(&pred);
578 for (i, out) in dst[2..unp_size].iter_mut().enumerate() {
579 let diff = br.read_tree8(&trees[i & 1])?;
580 pred[i & 1] = pred[i & 1].wrapping_add(diff);
584 let mut tree = SmackerTree8::new();
585 tree.decode(&mut br)?;
586 let mut pred = br.read(8)? as u8;
588 for out in dst[1..unp_size].iter_mut() {
589 let diff = br.read_tree8(&tree)?;
590 pred = pred.wrapping_add(diff);
595 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
596 frm.set_duration(Some(samples as u64));
597 frm.set_keyframe(false);
600 Err(DecoderError::InvalidData)
603 fn flush(&mut self) {
607 impl NAOptionHandler for SmackerAudioDecoder {
608 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
609 fn set_options(&mut self, _options: &[NAOption]) { }
610 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
613 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
614 Box::new(SmackerAudioDecoder::new())
619 use nihav_core::codecs::RegisteredDecoders;
620 use nihav_core::demuxers::RegisteredDemuxers;
621 use nihav_codec_support::test::dec_video::*;
622 use crate::rad_register_all_decoders;
623 use crate::rad_register_all_demuxers;
626 let mut dmx_reg = RegisteredDemuxers::new();
627 rad_register_all_demuxers(&mut dmx_reg);
628 let mut dec_reg = RegisteredDecoders::new();
629 rad_register_all_decoders(&mut dec_reg);
631 // sample from Heroes of Might and Magic 2
632 test_decoding("smacker", "smacker-video", "assets/RAD/credits.smk", None, &dmx_reg, &dec_reg,
633 ExpectedTestResult::MD5Frames(vec![
634 [0x0983944a, 0xa23503f8, 0x2602b589, 0x13b53480],
635 [0xb6c2bf1e, 0x2ee5fa60, 0x9896a6dc, 0x760b5737],
636 [0xc7c6d112, 0x2c3c5bac, 0x63684974, 0xa6573b1e],
637 [0x100e2871, 0xbc670db7, 0x54a802e5, 0xb5ba0b07],
638 [0xcd9d22ce, 0x7f195dc9, 0x93c47105, 0x6acf8aa7],
639 [0x84e82fdb, 0x304f24a8, 0x17466d73, 0x20182c33],
640 [0xfcae613f, 0xddab2bd4, 0x9d351ee5, 0x2d0aea24],
641 [0xea32a37c, 0x94d76dda, 0xbb34ca1d, 0xfc9d8a25],
642 [0x37855f28, 0xb508a386, 0x1f0bd981, 0x0f967e25],
643 [0x9b9f453a, 0xf6e34fe7, 0x9279fd71, 0x850a4f36]]));
647 let mut dmx_reg = RegisteredDemuxers::new();
648 rad_register_all_demuxers(&mut dmx_reg);
649 let mut dec_reg = RegisteredDecoders::new();
650 rad_register_all_decoders(&mut dec_reg);
652 // sample from Army Man: Air Tactics
653 test_decoding("smacker", "smacker-video", "assets/RAD/cine2.smk", Some(32000), &dmx_reg, &dec_reg,
654 ExpectedTestResult::MD5Frames(vec![
655 [0x9da29a47, 0xd61a31ef, 0xa0da6b39, 0xbcf48d01],
656 [0x604be492, 0x347854c0, 0xfeca481d, 0x98161276],
657 [0x3922ad4a, 0x21ac6633, 0xe2c62e0b, 0x11cf3db5],
658 [0xf1e58d8b, 0x539a6e41, 0x9ba5ebd6, 0x4129f62f],
659 [0x549c73f5, 0x5eecbbc4, 0xcf301c7f, 0x7dfad240]]));
662 fn test_smkaud_u8() {
663 let mut dmx_reg = RegisteredDemuxers::new();
664 rad_register_all_demuxers(&mut dmx_reg);
665 let mut dec_reg = RegisteredDecoders::new();
666 rad_register_all_decoders(&mut dec_reg);
668 // sample: https://samples.mplayerhq.hu/game-formats/smacker/wetlands/wetlogo.smk
669 test_decoding("smacker", "smacker-audio", "assets/RAD/wetlogo.smk", None, &dmx_reg, &dec_reg,
670 ExpectedTestResult::MD5([0xc686b833, 0x0a203038, 0x012f6d9b, 0xa4186d44]));
673 fn test_smkaud_s16() {
674 let mut dmx_reg = RegisteredDemuxers::new();
675 rad_register_all_demuxers(&mut dmx_reg);
676 let mut dec_reg = RegisteredDecoders::new();
677 rad_register_all_decoders(&mut dec_reg);
679 // sample: https://samples.mplayerhq.hu/game-formats/smacker/20130507_audio-distortion.smk
680 test_decoding("smacker", "smacker-audio", "assets/RAD/20130507_audio-distortion.smk", None, &dmx_reg, &dec_reg,
681 ExpectedTestResult::MD5([0x942a0922, 0x182bb5fd, 0x94ab7a59, 0x2028d810]));