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);
98 let lo = br.read_tree8(&self.tree_lo)?;
99 let hi = br.read_tree8(&self.tree_hi)?;
100 let mut sym = (((hi as u16) << 8) | (lo as u16)) as u32;
101 if sym == self.esc[0] {
102 tree.last[0] = tree.tree.len();
104 } else if sym == self.esc[1] {
105 tree.last[1] = tree.tree.len();
107 } else if sym == self.esc[2] {
108 tree.last[2] = tree.tree.len();
114 let cur_idx = tree.tree.len();
116 let lcount = self.get_tree16(br, tree, depth + 1)?;
117 let rcount = self.get_tree16(br, tree, depth + 1)?;
118 tree.tree[cur_idx] = SMK_BIGTREE_NODE | lcount;
119 Ok(lcount + rcount + 1)
128 last: [SMK_LAST_UNINIT; 3],
131 fn decode(&mut self, br: &mut BitReader, size: u32) -> DecoderResult<()> {
132 if !br.read_bool()? { return Ok(()); }
134 let mut tree_lo = SmackerTree8::new();
136 let mut tree_hi = SmackerTree8::new();
139 let mut esc: [u32; 3] = [0; 3];
140 for i in 0..esc.len() {
141 esc[i] = br.read(16)? as u32;
144 let nsyms = (((size + 3) >> 2) + 4) as usize;
145 self.tree = Vec::with_capacity(nsyms);
147 let mut tb = SmackerTree16Builder { tree_lo, tree_hi, nsyms, esc };
149 tb.get_tree16(br, self, 0)?;
150 validate!(!br.read_bool()?);
152 for i in 0..self.last.len() {
153 if self.last[i] == SMK_LAST_UNINIT {
154 self.last[i] = self.tree.len();
158 validate!(self.tree.len() <= nsyms);
161 fn reset(&mut self) {
162 for i in 0..self.last.len() {
163 if self.last[i] != SMK_LAST_UNINIT {
164 self.tree[self.last[i]] = 0;
171 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>;
172 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>;
175 impl<'a> ReadTree for BitReader<'a> {
176 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8> {
177 if let Some(ref cb) = tree.cb {
178 Ok(self.read_cb(cb)?)
183 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16> {
185 while (tree.tree[pos] & SMK_BIGTREE_NODE) != 0 {
186 if self.read_bool()? {
187 pos += (tree.tree[pos] & !SMK_BIGTREE_NODE) as usize;
191 let val = tree.tree[pos];
192 if val != tree.tree[tree.last[0]] {
193 tree.tree[tree.last[2]] = tree.tree[tree.last[1]];
194 tree.tree[tree.last[1]] = tree.tree[tree.last[0]];
195 tree.tree[tree.last[0]] = val;
201 const SMK_BLOCK_RUNS: [usize; 64] = [
202 1, 2, 3, 4, 5, 6, 7, 8,
203 9, 10, 11, 12, 13, 14, 15, 16,
204 17, 18, 19, 20, 21, 22, 23, 24,
205 25, 26, 27, 28, 29, 30, 31, 32,
206 33, 34, 35, 36, 37, 38, 39, 40,
207 41, 42, 43, 44, 45, 46, 47, 48,
208 49, 50, 51, 52, 53, 54, 55, 56,
209 57, 58, 59, 128, 256, 512, 1024, 2048
212 struct SmackerVideoDecoder {
213 info: NACodecInfoRef,
214 mmap_tree: SmackerTree16,
215 mclr_tree: SmackerTree16,
216 full_tree: SmackerTree16,
217 type_tree: SmackerTree16,
228 impl SmackerVideoDecoder {
231 info: NACodecInfoRef::default(),
232 mmap_tree: SmackerTree16::new(),
233 mclr_tree: SmackerTree16::new(),
234 full_tree: SmackerTree16::new(),
235 type_tree: SmackerTree16::new(),
246 fn block_pos(&self, blk_no: usize) -> usize {
247 let bx = blk_no % self.bw;
248 let by = blk_no / self.bw;
249 bx * 4 + by * 4 * self.stride
251 fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<bool> {
252 let mut is_intra = true;
253 let blocks = self.bw * self.bh;
255 self.mmap_tree.reset();
256 self.mclr_tree.reset();
257 self.full_tree.reset();
258 self.type_tree.reset();
261 while block < blocks {
262 let btype = br.read_bigtree(&mut self.type_tree)?;
263 let run = SMK_BLOCK_RUNS[((btype as usize) >> 2) & 0x3F];
264 validate!(run <= blocks - block);
266 0 => { // two-colour pattern
268 let clr = br.read_bigtree(&mut self.mclr_tree)?;
269 let mut map = br.read_bigtree(&mut self.mmap_tree)?;
270 let hi = (clr >> 8) as u8;
271 let lo = (clr & 0xFF) as u8;
272 let mut doff = self.block_pos(block + i);
274 self.frame[doff + 0] = if (map & 1) != 0 { hi } else { lo };
275 self.frame[doff + 1] = if (map & 2) != 0 { hi } else { lo };
276 self.frame[doff + 2] = if (map & 4) != 0 { hi } else { lo };
277 self.frame[doff + 3] = if (map & 8) != 0 { hi } else { lo };
285 if !self.is_ver4 || !br.read_bool()? {
288 mode = 1 + br.read(1)?;
291 let mut doff = self.block_pos(block + i);
295 let clr0 = br.read_bigtree(&mut self.full_tree)?;
296 let clr1 = br.read_bigtree(&mut self.full_tree)?;
297 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
298 self.frame[doff + 1] = (clr1 >> 8) as u8;
299 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
300 self.frame[doff + 3] = (clr0 >> 8) as u8;
306 let clr = br.read_bigtree(&mut self.full_tree)?;
307 self.frame[doff + 0] = (clr & 0xFF) as u8;
308 self.frame[doff + 1] = (clr & 0xFF) as u8;
309 self.frame[doff + 2] = (clr >> 8) as u8;
310 self.frame[doff + 3] = (clr >> 8) as u8;
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;
321 let clr0 = br.read_bigtree(&mut self.full_tree)?;
322 let clr1 = br.read_bigtree(&mut self.full_tree)?;
323 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
324 self.frame[doff + 1] = (clr1 >> 8) as u8;
325 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
326 self.frame[doff + 3] = (clr0 >> 8) as u8;
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;
343 let clr = (btype >> 8) as u8;
345 let mut doff = self.block_pos(block + i);
347 self.frame[doff + 0] = clr;
348 self.frame[doff + 1] = clr;
349 self.frame[doff + 2] = clr;
350 self.frame[doff + 3] = clr;
361 fn output_frame(&self, buf: &mut NAVideoBuffer<u8>) {
362 let stride = buf.get_stride(0);
363 let data = buf.get_data_mut().unwrap();
364 let dst = data.as_mut_slice();
365 let is_scaled = (self.flags & SMK_FLAG_SCALED) != 0;
366 let is_interlaced = (self.flags & SMK_FLAG_INTERLACED) != 0;
370 for x in 0..self.w { dst[didx + x] = self.frame[sidx + x]; }
374 for x in 0..self.w { dst[didx + x] = dst[didx - stride + x]; }
378 for x in 0..self.w { dst[didx + x] = 0; }
381 for x in 0..self.w { dst[didx + x] = 0; }
389 impl NADecoder for SmackerVideoDecoder {
390 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
391 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
392 let w = vinfo.get_width();
393 let h = vinfo.get_height();
394 let fmt = PAL8_FORMAT;
400 let edata = info.get_extradata().unwrap();
401 validate!(edata.len() > 24);
404 self.frame.resize(w * h, 0);
406 let mut mr = MemoryReader::new_read(&edata);
407 let mut br = ByteReader::new(&mut mr);
408 let magic = br.read_u32be()?;
409 self.flags = br.read_u32le()?;
410 let mmap_size = br.read_u32le()?;
411 let mclr_size = br.read_u32le()?;
412 let full_size = br.read_u32le()?;
413 let type_size = br.read_u32le()?;
415 self.is_ver4 = (magic & 0xFF) == 0x34;
416 let mut br = BitReader::new(&edata[24..], BitReaderMode::LE);
417 self.mmap_tree.decode(&mut br, mmap_size)?;
418 self.mclr_tree.decode(&mut br, mclr_size)?;
419 self.full_tree.decode(&mut br, full_size)?;
420 self.type_tree.decode(&mut br, type_size)?;
423 if (self.flags & SMK_FLAG_INTERLACED) != 0 {
426 if (self.flags & SMK_FLAG_SCALED) != 0 {
429 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, out_h, false, fmt));
430 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
434 Err(DecoderError::InvalidData)
437 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
438 let src = pkt.get_buffer();
439 validate!(src.len() >= PAL_SIZE);
444 if src.len() > PAL_SIZE {
445 let mut br = BitReader::new(&src[PAL_SIZE..], BitReaderMode::LE);
447 bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
448 let mut buf = bufinfo.get_vbuf().unwrap();
449 is_intra = self.decode_frame(&mut br)?;
450 self.output_frame(&mut buf);
451 let paloff = buf.get_offset(1);
452 let data = buf.get_data_mut().unwrap();
453 let dst = data.as_mut_slice();
454 let palout = &mut dst[paloff..][..PAL_SIZE];
455 palout.copy_from_slice(&src[0..PAL_SIZE]);
456 ftype = if is_intra { FrameType::I } else { FrameType::P };
458 bufinfo = NABufferType::None;
459 ftype = FrameType::Skip;
463 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
464 frm.set_keyframe(is_intra);
465 frm.set_frame_type(ftype);
468 fn flush(&mut self) {
472 impl NAOptionHandler for SmackerVideoDecoder {
473 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
474 fn set_options(&mut self, _options: &[NAOption]) { }
475 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
478 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
479 Box::new(SmackerVideoDecoder::new())
482 struct SmackerAudioDecoder {
489 impl SmackerAudioDecoder {
492 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
493 chmap: NAChannelMap::new(),
500 impl NADecoder for SmackerAudioDecoder {
501 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
502 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
503 self.bits = ainfo.get_format().get_bits();
504 let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16_FORMAT };
505 self.chans = ainfo.get_channels() as usize;
506 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, 0);
507 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 2 {"L,R"} else {"C"}).unwrap();
510 Err(DecoderError::InvalidData)
513 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
514 let info = pkt.get_stream().get_info();
515 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
516 let src = pkt.get_buffer();
517 validate!(src.len() > 4);
518 let mut br = BitReader::new(&src, BitReaderMode::LE);
519 let unp_size = br.read(32)? as usize;
520 if !br.read_bool()? {
521 let mut frm = NAFrame::new_from_pkt(pkt, info.clone(), NABufferType::None);
522 frm.set_frame_type(FrameType::Skip);
523 return Ok(frm.into_ref());
525 let stereo = br.read_bool()?;
526 let bits16 = br.read_bool()?;
527 validate!(!(stereo ^ (self.chans == 2)));
528 validate!(!(bits16 ^ (self.bits == 16)));
532 let nch = if stereo { 2 } else { 1 };
534 samples = unp_size / 2 / nch;
535 let mask = if stereo { 1 } else { 0 };
536 let mut trees: [SmackerTree8; 4] = [SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new()];
538 trees[i].decode(&mut br)?;
540 let mut pred: [i16; 2] = [0; 2];
542 let hi = br.read(8)?;
543 let lo = br.read(8)?;
544 pred[nch - i - 1] = (lo | (hi << 8)) as i16;
547 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
548 let mut adata = abuf.get_abuf_i16().unwrap();
549 let dst = adata.get_data_mut().unwrap();
553 for i in nch..(unp_size >> 1) {
555 let lo = br.read_tree8(&trees[idx * 2 + 0])? as u16;
556 let hi = br.read_tree8(&trees[idx * 2 + 1])? as u16;
557 let diff = (lo | (hi << 8)) as i16;
558 pred[idx] = pred[idx].wrapping_add(diff);
562 samples = unp_size / nch;
563 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
564 let mut adata = abuf.get_abuf_u8().unwrap();
565 let dst = adata.get_data_mut().unwrap();
567 let mut trees: [SmackerTree8; 2] = [SmackerTree8::new(), SmackerTree8::new()];
568 trees[0].decode(&mut br)?;
569 trees[1].decode(&mut br)?;
570 let pred0 = br.read(8)? as u8;
571 let pred1 = br.read(8)? as u8;
572 let mut pred: [u8; 2] = [ pred1, pred0 ];
573 for ch in 0..2 { dst[ch] = pred[ch]; }
574 for i in 2..unp_size {
575 let diff = br.read_tree8(&trees[i & 1])? as u8;
576 pred[i & 1] = pred[i & 1].wrapping_add(diff);
577 dst[i] = pred[i & 1];
580 let mut tree = SmackerTree8::new();
581 tree.decode(&mut br)?;
582 let mut pred = br.read(8)? as u8;
584 for i in 1..unp_size {
585 let diff = br.read_tree8(&tree)? as u8;
586 pred = pred.wrapping_add(diff);
591 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
592 frm.set_duration(Some(samples as u64));
593 frm.set_keyframe(false);
596 Err(DecoderError::InvalidData)
599 fn flush(&mut self) {
603 impl NAOptionHandler for SmackerAudioDecoder {
604 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
605 fn set_options(&mut self, _options: &[NAOption]) { }
606 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
609 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
610 Box::new(SmackerAudioDecoder::new())
615 use nihav_core::codecs::RegisteredDecoders;
616 use nihav_core::demuxers::RegisteredDemuxers;
617 use nihav_codec_support::test::dec_video::*;
618 use crate::rad_register_all_codecs;
619 use crate::rad_register_all_demuxers;
622 let mut dmx_reg = RegisteredDemuxers::new();
623 rad_register_all_demuxers(&mut dmx_reg);
624 let mut dec_reg = RegisteredDecoders::new();
625 rad_register_all_codecs(&mut dec_reg);
627 test_decoding("smacker", "smacker-video", "assets/RAD/credits.smk", None, &dmx_reg, &dec_reg,
628 ExpectedTestResult::MD5Frames(vec![
629 [0x0983944a, 0xa23503f8, 0x2602b589, 0x13b53480],
630 [0xb6c2bf1e, 0x2ee5fa60, 0x9896a6dc, 0x760b5737],
631 [0xc7c6d112, 0x2c3c5bac, 0x63684974, 0xa6573b1e],
632 [0x100e2871, 0xbc670db7, 0x54a802e5, 0xb5ba0b07],
633 [0xcd9d22ce, 0x7f195dc9, 0x93c47105, 0x6acf8aa7],
634 [0x84e82fdb, 0x304f24a8, 0x17466d73, 0x20182c33],
635 [0xfcae613f, 0xddab2bd4, 0x9d351ee5, 0x2d0aea24],
636 [0xea32a37c, 0x94d76dda, 0xbb34ca1d, 0xfc9d8a25],
637 [0x37855f28, 0xb508a386, 0x1f0bd981, 0x0f967e25],
638 [0x9b9f453a, 0xf6e34fe7, 0x9279fd71, 0x850a4f36]]));
641 fn test_smkaud_u8() {
642 let mut dmx_reg = RegisteredDemuxers::new();
643 rad_register_all_demuxers(&mut dmx_reg);
644 let mut dec_reg = RegisteredDecoders::new();
645 rad_register_all_codecs(&mut dec_reg);
647 test_decoding("smacker", "smacker-audio", "assets/RAD/wetlogo.smk", None, &dmx_reg, &dec_reg,
648 ExpectedTestResult::MD5([0xc686b833, 0x0a203038, 0x012f6d9b, 0xa4186d44]));
651 fn test_smkaud_s16() {
652 let mut dmx_reg = RegisteredDemuxers::new();
653 rad_register_all_demuxers(&mut dmx_reg);
654 let mut dec_reg = RegisteredDecoders::new();
655 rad_register_all_codecs(&mut dec_reg);
657 test_decoding("smacker", "smacker-audio", "assets/RAD/20130507_audio-distortion.smk", None, &dmx_reg, &dec_reg,
658 ExpectedTestResult::MD5([0x942a0922, 0x182bb5fd, 0x94ab7a59, 0x2028d810]));