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 i in 0..esc.len() {
142 esc[i] = br.read(16)?;
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 fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<bool> {
253 let mut is_intra = true;
254 let blocks = self.bw * self.bh;
256 self.mmap_tree.reset();
257 self.mclr_tree.reset();
258 self.full_tree.reset();
259 self.type_tree.reset();
262 while block < blocks {
263 let btype = br.read_bigtree(&mut self.type_tree)?;
264 let run = SMK_BLOCK_RUNS[((btype as usize) >> 2) & 0x3F];
265 validate!(run <= blocks - block);
267 0 => { // two-colour pattern
269 let clr = br.read_bigtree(&mut self.mclr_tree)?;
270 let mut map = br.read_bigtree(&mut self.mmap_tree)?;
271 let hi = (clr >> 8) as u8;
272 let lo = (clr & 0xFF) as u8;
273 let mut doff = self.block_pos(block + i);
275 self.frame[doff + 0] = if (map & 1) != 0 { hi } else { lo };
276 self.frame[doff + 1] = if (map & 2) != 0 { hi } else { lo };
277 self.frame[doff + 2] = if (map & 4) != 0 { hi } else { lo };
278 self.frame[doff + 3] = if (map & 8) != 0 { hi } else { lo };
286 if !self.is_ver4 || !br.read_bool()? {
289 mode = 1 + br.read(1)?;
292 let mut doff = self.block_pos(block + i);
296 let clr0 = br.read_bigtree(&mut self.full_tree)?;
297 let clr1 = br.read_bigtree(&mut self.full_tree)?;
298 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
299 self.frame[doff + 1] = (clr1 >> 8) as u8;
300 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
301 self.frame[doff + 3] = (clr0 >> 8) as u8;
307 let clr = br.read_bigtree(&mut self.full_tree)?;
308 self.frame[doff + 0] = (clr & 0xFF) as u8;
309 self.frame[doff + 1] = (clr & 0xFF) as u8;
310 self.frame[doff + 2] = (clr >> 8) as u8;
311 self.frame[doff + 3] = (clr >> 8) as u8;
313 self.frame[doff + 0] = (clr & 0xFF) as u8;
314 self.frame[doff + 1] = (clr & 0xFF) as u8;
315 self.frame[doff + 2] = (clr >> 8) as u8;
316 self.frame[doff + 3] = (clr >> 8) as u8;
322 let clr0 = br.read_bigtree(&mut self.full_tree)?;
323 let clr1 = br.read_bigtree(&mut self.full_tree)?;
324 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
325 self.frame[doff + 1] = (clr1 >> 8) as u8;
326 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
327 self.frame[doff + 3] = (clr0 >> 8) as u8;
329 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
330 self.frame[doff + 1] = (clr1 >> 8) as u8;
331 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
332 self.frame[doff + 3] = (clr0 >> 8) as u8;
344 let clr = (btype >> 8) as u8;
346 let mut doff = self.block_pos(block + i);
348 self.frame[doff + 0] = clr;
349 self.frame[doff + 1] = clr;
350 self.frame[doff + 2] = clr;
351 self.frame[doff + 3] = clr;
362 fn output_frame(&self, buf: &mut NAVideoBuffer<u8>) {
363 let stride = buf.get_stride(0);
364 let data = buf.get_data_mut().unwrap();
365 let dst = data.as_mut_slice();
366 let is_scaled = (self.flags & SMK_FLAG_SCALED) != 0;
367 let is_interlaced = (self.flags & SMK_FLAG_INTERLACED) != 0;
371 dst[didx..][..self.w].copy_from_slice(&self.frame[sidx..][..self.w]);
375 for x in 0..self.w { dst[didx + x] = dst[didx - stride + x]; }
379 for x in 0..self.w { dst[didx + x] = 0; }
382 for x in 0..self.w { dst[didx + x] = 0; }
390 impl NADecoder for SmackerVideoDecoder {
391 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
392 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
393 let w = vinfo.get_width();
394 let h = vinfo.get_height();
395 let fmt = PAL8_FORMAT;
401 let edata = info.get_extradata().unwrap();
402 validate!(edata.len() > 24);
405 self.frame.resize(w * h, 0);
407 let mut mr = MemoryReader::new_read(&edata);
408 let mut br = ByteReader::new(&mut mr);
409 let magic = br.read_u32be()?;
410 self.flags = br.read_u32le()?;
411 let mmap_size = br.read_u32le()?;
412 let mclr_size = br.read_u32le()?;
413 let full_size = br.read_u32le()?;
414 let type_size = br.read_u32le()?;
416 self.is_ver4 = (magic & 0xFF) == 0x34;
417 let mut br = BitReader::new(&edata[24..], BitReaderMode::LE);
418 self.mmap_tree.decode(&mut br, mmap_size)?;
419 self.mclr_tree.decode(&mut br, mclr_size)?;
420 self.full_tree.decode(&mut br, full_size)?;
421 self.type_tree.decode(&mut br, type_size)?;
424 if (self.flags & SMK_FLAG_INTERLACED) != 0 {
427 if (self.flags & SMK_FLAG_SCALED) != 0 {
430 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, out_h, false, fmt));
431 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
435 Err(DecoderError::InvalidData)
438 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
439 let src = pkt.get_buffer();
440 validate!(src.len() >= PAL_SIZE);
445 if src.len() > PAL_SIZE {
446 let mut br = BitReader::new(&src[PAL_SIZE..], BitReaderMode::LE);
448 bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
449 let mut buf = bufinfo.get_vbuf().unwrap();
450 is_intra = self.decode_frame(&mut br)?;
451 self.output_frame(&mut buf);
452 let paloff = buf.get_offset(1);
453 let data = buf.get_data_mut().unwrap();
454 let dst = data.as_mut_slice();
455 let palout = &mut dst[paloff..][..PAL_SIZE];
456 palout.copy_from_slice(&src[0..PAL_SIZE]);
457 ftype = if is_intra { FrameType::I } else { FrameType::P };
459 bufinfo = NABufferType::None;
460 ftype = FrameType::Skip;
464 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
465 frm.set_keyframe(is_intra);
466 frm.set_frame_type(ftype);
469 fn flush(&mut self) {
473 impl NAOptionHandler for SmackerVideoDecoder {
474 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
475 fn set_options(&mut self, _options: &[NAOption]) { }
476 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
479 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
480 Box::new(SmackerVideoDecoder::new())
483 struct SmackerAudioDecoder {
490 impl SmackerAudioDecoder {
493 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
494 chmap: NAChannelMap::new(),
501 impl NADecoder for SmackerAudioDecoder {
502 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
503 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
504 self.bits = ainfo.get_format().get_bits();
505 let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16_FORMAT };
506 self.chans = ainfo.get_channels() as usize;
507 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, 0);
508 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 2 {"L,R"} else {"C"}).unwrap();
511 Err(DecoderError::InvalidData)
514 #[allow(clippy::manual_memcpy)]
515 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
516 let info = pkt.get_stream().get_info();
517 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
518 let src = pkt.get_buffer();
519 validate!(src.len() > 4);
520 let mut br = BitReader::new(&src, BitReaderMode::LE);
521 let unp_size = br.read(32)? as usize;
522 if !br.read_bool()? {
523 let mut frm = NAFrame::new_from_pkt(pkt, info.clone(), NABufferType::None);
524 frm.set_frame_type(FrameType::Skip);
525 return Ok(frm.into_ref());
527 let stereo = br.read_bool()?;
528 let bits16 = br.read_bool()?;
529 validate!(!(stereo ^ (self.chans == 2)));
530 validate!(!(bits16 ^ (self.bits == 16)));
534 let nch = if stereo { 2 } else { 1 };
536 samples = unp_size / 2 / nch;
537 let mask = if stereo { 1 } else { 0 };
538 let mut trees: [SmackerTree8; 4] = [SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new()];
540 trees[i].decode(&mut br)?;
542 let mut pred: [i16; 2] = [0; 2];
544 let hi = br.read(8)?;
545 let lo = br.read(8)?;
546 pred[nch - i - 1] = (lo | (hi << 8)) as i16;
549 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
550 let mut adata = abuf.get_abuf_i16().unwrap();
551 let dst = adata.get_data_mut().unwrap();
555 for i in nch..(unp_size >> 1) {
557 let lo = br.read_tree8(&trees[idx * 2 + 0])? as u16;
558 let hi = br.read_tree8(&trees[idx * 2 + 1])? as u16;
559 let diff = (lo | (hi << 8)) as i16;
560 pred[idx] = pred[idx].wrapping_add(diff);
564 samples = unp_size / nch;
565 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
566 let mut adata = abuf.get_abuf_u8().unwrap();
567 let dst = adata.get_data_mut().unwrap();
569 let mut trees: [SmackerTree8; 2] = [SmackerTree8::new(), SmackerTree8::new()];
570 trees[0].decode(&mut br)?;
571 trees[1].decode(&mut br)?;
572 let pred0 = br.read(8)? as u8;
573 let pred1 = br.read(8)? as u8;
574 let mut pred: [u8; 2] = [ pred1, pred0 ];
575 for ch in 0..2 { dst[ch] = pred[ch]; }
576 for i in 2..unp_size {
577 let diff = br.read_tree8(&trees[i & 1])?;
578 pred[i & 1] = pred[i & 1].wrapping_add(diff);
579 dst[i] = pred[i & 1];
582 let mut tree = SmackerTree8::new();
583 tree.decode(&mut br)?;
584 let mut pred = br.read(8)? as u8;
586 for i in 1..unp_size {
587 let diff = br.read_tree8(&tree)?;
588 pred = pred.wrapping_add(diff);
593 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
594 frm.set_duration(Some(samples as u64));
595 frm.set_keyframe(false);
598 Err(DecoderError::InvalidData)
601 fn flush(&mut self) {
605 impl NAOptionHandler for SmackerAudioDecoder {
606 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
607 fn set_options(&mut self, _options: &[NAOption]) { }
608 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
611 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
612 Box::new(SmackerAudioDecoder::new())
617 use nihav_core::codecs::RegisteredDecoders;
618 use nihav_core::demuxers::RegisteredDemuxers;
619 use nihav_codec_support::test::dec_video::*;
620 use crate::rad_register_all_decoders;
621 use crate::rad_register_all_demuxers;
624 let mut dmx_reg = RegisteredDemuxers::new();
625 rad_register_all_demuxers(&mut dmx_reg);
626 let mut dec_reg = RegisteredDecoders::new();
627 rad_register_all_decoders(&mut dec_reg);
629 // sample from Heroes of Might and Magic 2
630 test_decoding("smacker", "smacker-video", "assets/RAD/credits.smk", None, &dmx_reg, &dec_reg,
631 ExpectedTestResult::MD5Frames(vec![
632 [0x0983944a, 0xa23503f8, 0x2602b589, 0x13b53480],
633 [0xb6c2bf1e, 0x2ee5fa60, 0x9896a6dc, 0x760b5737],
634 [0xc7c6d112, 0x2c3c5bac, 0x63684974, 0xa6573b1e],
635 [0x100e2871, 0xbc670db7, 0x54a802e5, 0xb5ba0b07],
636 [0xcd9d22ce, 0x7f195dc9, 0x93c47105, 0x6acf8aa7],
637 [0x84e82fdb, 0x304f24a8, 0x17466d73, 0x20182c33],
638 [0xfcae613f, 0xddab2bd4, 0x9d351ee5, 0x2d0aea24],
639 [0xea32a37c, 0x94d76dda, 0xbb34ca1d, 0xfc9d8a25],
640 [0x37855f28, 0xb508a386, 0x1f0bd981, 0x0f967e25],
641 [0x9b9f453a, 0xf6e34fe7, 0x9279fd71, 0x850a4f36]]));
644 fn test_smkaud_u8() {
645 let mut dmx_reg = RegisteredDemuxers::new();
646 rad_register_all_demuxers(&mut dmx_reg);
647 let mut dec_reg = RegisteredDecoders::new();
648 rad_register_all_decoders(&mut dec_reg);
650 // sample: https://samples.mplayerhq.hu/game-formats/smacker/wetlands/wetlogo.smk
651 test_decoding("smacker", "smacker-audio", "assets/RAD/wetlogo.smk", None, &dmx_reg, &dec_reg,
652 ExpectedTestResult::MD5([0xc686b833, 0x0a203038, 0x012f6d9b, 0xa4186d44]));
655 fn test_smkaud_s16() {
656 let mut dmx_reg = RegisteredDemuxers::new();
657 rad_register_all_demuxers(&mut dmx_reg);
658 let mut dec_reg = RegisteredDecoders::new();
659 rad_register_all_decoders(&mut dec_reg);
661 // sample: https://samples.mplayerhq.hu/game-formats/smacker/20130507_audio-distortion.smk
662 test_decoding("smacker", "smacker-audio", "assets/RAD/20130507_audio-distortion.smk", None, &dmx_reg, &dec_reg,
663 ExpectedTestResult::MD5([0x942a0922, 0x182bb5fd, 0x94ab7a59, 0x2028d810]));