smacker: add forgotten recursion depth check
[nihav.git] / nihav-rad / src / codecs / smacker.rs
CommitLineData
606c448e
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
3use nihav_core::io::bitreader::*;
4use nihav_core::io::codebook::*;
5use std::str::FromStr;
6
7const PAL_SIZE: usize = 768;
8const SMK_FLAG_INTERLACED: u32 = 0x02;
9const SMK_FLAG_SCALED: u32 = 0x04;
10
11struct SmackerTree8 {
12 cb: Option<Codebook<u8>>,
13 defsym: u8,
14}
15
16fn 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<()> {
17 if !br.read_bool()? {
18 bits[*count] = len;
19 codes[*count] = prefix;
20 syms[*count] = br.read(8)? as u8;
21 *count += 1;
22 } else {
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))?;
26 }
27 Ok(())
28}
29
30pub struct FullTableCodebookDescReader<'a> {
31 bits: &'a [u8],
32 codes: &'a [u32],
33 syms: &'a [u8],
34}
35
36impl<'a> FullTableCodebookDescReader<'a> {
37 pub fn new(codes: &'a [u32], bits: &'a [u8], syms: &'a [u8]) -> Self {
38 Self { bits, codes, syms }
39 }
40}
41impl<'a> CodebookDescReader<u8> for FullTableCodebookDescReader<'a>
42{
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() }
47}
48
49impl SmackerTree8 {
50 fn new() -> Self {
51 Self {
52 cb: None,
53 defsym: 0,
54 }
55 }
56 fn decode(&mut self, br: &mut BitReader) -> DecoderResult<()> {
57 if !br.read_bool()? { return Ok(()); }
58
59 let mut bits: [u8; 256] = [0; 256];
60 let mut codes: [u32; 256] = [0; 256];
61 let mut syms: [u8; 256] = [0; 256];
62 let mut count = 0;
63
64 get_tree8(br, &mut bits, &mut codes, &mut syms, &mut count, 0, 0)?;
65 validate!(!br.read_bool()?);
66
67 if count > 1 {
68 let mut cr = FullTableCodebookDescReader::new(&codes[0..count], &bits[0..count], &syms[0..count]);
69 let cb = Codebook::new(&mut cr, CodebookMode::LSB)?;
70 self.cb = Some(cb);
71 } else {
72 self.defsym = syms[0];
73 }
74
75 Ok(())
76 }
77}
78
79struct SmackerTree16 {
80 tree: Vec<u32>,
81 last: [usize; 3],
82}
83
84struct SmackerTree16Builder {
85 tree_lo: SmackerTree8,
86 tree_hi: SmackerTree8,
87 nsyms: usize,
88 esc: [u32; 3],
89}
90
91const SMK_BIGTREE_NODE: u32 = 0x80000000;
92const SMK_LAST_UNINIT: usize = 0xFFFFFFFF;
93
94impl SmackerTree16Builder {
95 fn get_tree16(&mut self, br: &mut BitReader, tree: &mut SmackerTree16, depth: usize) -> DecoderResult<u32> {
96 validate!(tree.tree.len() < self.nsyms);
2c031ed0 97 validate!(depth <= 32);
606c448e
KS
98 if !br.read_bool()? {
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();
104 sym = 0;
105 } else if sym == self.esc[1] {
106 tree.last[1] = tree.tree.len();
107 sym = 0;
108 } else if sym == self.esc[2] {
109 tree.last[2] = tree.tree.len();
110 sym = 0;
111 }
112 tree.tree.push(sym);
113 Ok(1)
114 } else {
115 let cur_idx = tree.tree.len();
116 tree.tree.push(0);
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)
121 }
122 }
123}
124
125impl SmackerTree16 {
126 fn new() -> Self {
127 Self {
128 tree: Vec::new(),
129 last: [SMK_LAST_UNINIT; 3],
130 }
131 }
132 fn decode(&mut self, br: &mut BitReader, size: u32) -> DecoderResult<()> {
133 if !br.read_bool()? { return Ok(()); }
134
135 let mut tree_lo = SmackerTree8::new();
136 tree_lo.decode(br)?;
137 let mut tree_hi = SmackerTree8::new();
138 tree_hi.decode(br)?;
139
140 let mut esc: [u32; 3] = [0; 3];
141 for i in 0..esc.len() {
e6aaad5c 142 esc[i] = br.read(16)?;
606c448e
KS
143 }
144
145 let nsyms = (((size + 3) >> 2) + 4) as usize;
146 self.tree = Vec::with_capacity(nsyms);
147
148 let mut tb = SmackerTree16Builder { tree_lo, tree_hi, nsyms, esc };
149
150 tb.get_tree16(br, self, 0)?;
151 validate!(!br.read_bool()?);
152
153 for i in 0..self.last.len() {
154 if self.last[i] == SMK_LAST_UNINIT {
155 self.last[i] = self.tree.len();
156 self.tree.push(0);
157 }
158 }
159 validate!(self.tree.len() <= nsyms);
160 Ok(())
161 }
162 fn reset(&mut self) {
163 for i in 0..self.last.len() {
af37e28a
KS
164 if self.last[i] != SMK_LAST_UNINIT {
165 self.tree[self.last[i]] = 0;
166 }
606c448e
KS
167 }
168 }
169}
170
171trait ReadTree {
172 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>;
173 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>;
174}
175
176impl<'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)?)
180 } else {
181 Ok(tree.defsym)
182 }
183 }
184 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16> {
185 let mut pos = 0;
186 while (tree.tree[pos] & SMK_BIGTREE_NODE) != 0 {
187 if self.read_bool()? {
188 pos += (tree.tree[pos] & !SMK_BIGTREE_NODE) as usize;
189 }
190 pos += 1;
191 }
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;
197 }
198 Ok(val as u16)
199 }
200}
201
202const 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
211];
212
213struct SmackerVideoDecoder {
2422d969 214 info: NACodecInfoRef,
606c448e
KS
215 mmap_tree: SmackerTree16,
216 mclr_tree: SmackerTree16,
217 full_tree: SmackerTree16,
218 type_tree: SmackerTree16,
219 w: usize,
220 h: usize,
221 bw: usize,
222 bh: usize,
223 is_ver4: bool,
224 flags: u32,
225 frame: Vec<u8>,
226 stride: usize,
227}
228
229impl SmackerVideoDecoder {
230 fn new() -> Self {
606c448e 231 Self {
2422d969 232 info: NACodecInfoRef::default(),
606c448e
KS
233 mmap_tree: SmackerTree16::new(),
234 mclr_tree: SmackerTree16::new(),
235 full_tree: SmackerTree16::new(),
236 type_tree: SmackerTree16::new(),
237 w: 0,
238 h: 0,
239 bw: 0,
240 bh: 0,
241 is_ver4: false,
242 flags: 0,
243 frame: Vec::new(),
244 stride: 0,
245 }
246 }
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
251 }
252 fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<bool> {
253 let mut is_intra = true;
254 let blocks = self.bw * self.bh;
255
256 self.mmap_tree.reset();
257 self.mclr_tree.reset();
258 self.full_tree.reset();
259 self.type_tree.reset();
260
261 let mut block = 0;
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);
266 match btype & 3 {
267 0 => { // two-colour pattern
268 for i in 0..run {
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);
274 for _ in 0..4 {
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 };
279 map >>= 4;
280 doff += self.stride;
281 }
282 }
283 },
284 1 => { // full
285 let mode;
286 if !self.is_ver4 || !br.read_bool()? {
287 mode = 0;
288 } else {
289 mode = 1 + br.read(1)?;
290 }
291 for i in 0..run {
292 let mut doff = self.block_pos(block + i);
293 match mode {
294 0 => {
295 for _ in 0..4 {
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;
302 doff += self.stride;
303 }
304 },
305 1 => {
306 for _ in 0..2 {
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;
312 doff += self.stride;
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;
317 doff += self.stride;
318 }
319 },
320 2 => {
321 for _ in 0..2 {
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;
328 doff += self.stride;
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;
333 doff += self.stride;
334 }
335 },
336 _ => unreachable!(),
337 };
338 }
339 },
340 2 => { // skip
341 is_intra = false;
342 },
343 3 => { // fill
344 let clr = (btype >> 8) as u8;
345 for i in 0..run {
346 let mut doff = self.block_pos(block + i);
347 for _ in 0..4 {
348 self.frame[doff + 0] = clr;
349 self.frame[doff + 1] = clr;
350 self.frame[doff + 2] = clr;
351 self.frame[doff + 3] = clr;
352 doff += self.stride;
353 }
354 }
355 },
356 _ => unreachable!(),
357 };
358 block += run;
359 }
360 Ok(is_intra)
361 }
362 fn output_frame(&self, buf: &mut NAVideoBuffer<u8>) {
363 let stride = buf.get_stride(0);
1a967e6b 364 let data = buf.get_data_mut().unwrap();
606c448e
KS
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;
368 let mut didx = 0;
369 let mut sidx = 0;
370 for _ in 0..self.h {
bf109afe 371 dst[didx..][..self.w].copy_from_slice(&self.frame[sidx..][..self.w]);
606c448e
KS
372 sidx += self.stride;
373 didx += stride;
374 if is_scaled {
375 for x in 0..self.w { dst[didx + x] = dst[didx - stride + x]; }
376 didx += stride;
377 }
378 if is_interlaced {
379 for x in 0..self.w { dst[didx + x] = 0; }
380 didx += stride;
381 if is_scaled {
382 for x in 0..self.w { dst[didx + x] = 0; }
383 didx += stride;
384 }
385 }
386 }
387 }
388}
389
390impl NADecoder for SmackerVideoDecoder {
01613464 391 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
606c448e
KS
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;
396
397 self.w = w;
398 self.h = h;
399 self.bw = w >> 2;
400 self.bh = h >> 2;
401 let edata = info.get_extradata().unwrap();
402 validate!(edata.len() > 24);
403
404 self.stride = w;
405 self.frame.resize(w * h, 0);
406
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()?;
415
416 self.is_ver4 = (magic & 0xFF) == 0x34;
fa90ccfb 417 let mut br = BitReader::new(&edata[24..], BitReaderMode::LE);
606c448e
KS
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)?;
422
423 let mut out_h = h;
424 if (self.flags & SMK_FLAG_INTERLACED) != 0 {
425 out_h <<= 1;
426 }
427 if (self.flags & SMK_FLAG_SCALED) != 0 {
428 out_h <<= 1;
429 }
430 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, out_h, false, fmt));
2422d969 431 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
606c448e
KS
432
433 Ok(())
434 } else {
435 Err(DecoderError::InvalidData)
436 }
437 }
01613464 438 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
606c448e
KS
439 let src = pkt.get_buffer();
440 validate!(src.len() >= PAL_SIZE);
441
442 let is_intra;
443 let ftype;
b70cc006 444 let bufinfo;
606c448e 445 if src.len() > PAL_SIZE {
fa90ccfb 446 let mut br = BitReader::new(&src[PAL_SIZE..], BitReaderMode::LE);
606c448e 447
7e6086e5 448 bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
606c448e
KS
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);
1a967e6b 453 let data = buf.get_data_mut().unwrap();
606c448e
KS
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 };
458 } else {
459 bufinfo = NABufferType::None;
460 ftype = FrameType::Skip;
461 is_intra = false;
462 }
463
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);
171860fc 467 Ok(frm.into_ref())
606c448e 468 }
f9be4e75
KS
469 fn flush(&mut self) {
470 }
606c448e
KS
471}
472
7d57ae2f
KS
473impl 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 }
477}
478
08a1fab7 479pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
606c448e
KS
480 Box::new(SmackerVideoDecoder::new())
481}
482
483struct SmackerAudioDecoder {
484 ainfo: NAAudioInfo,
485 chmap: NAChannelMap,
486 chans: usize,
487 bits: u8,
488}
489
490impl SmackerAudioDecoder {
491 fn new() -> Self {
492 Self {
493 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
494 chmap: NAChannelMap::new(),
495 chans: 0,
496 bits: 0,
497 }
498 }
499}
500
501impl NADecoder for SmackerAudioDecoder {
01613464 502 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
606c448e
KS
503 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
504 self.bits = ainfo.get_format().get_bits();
70e792a8 505 let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16_FORMAT };
606c448e
KS
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();
509 Ok(())
510 } else {
511 Err(DecoderError::InvalidData)
512 }
513 }
bf109afe 514 #[allow(clippy::manual_memcpy)]
01613464 515 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
606c448e
KS
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);
fa90ccfb 520 let mut br = BitReader::new(&src, BitReaderMode::LE);
606c448e
KS
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);
171860fc 525 return Ok(frm.into_ref());
606c448e
KS
526 }
527 let stereo = br.read_bool()?;
528 let bits16 = br.read_bool()?;
529 validate!(!(stereo ^ (self.chans == 2)));
530 validate!(!(bits16 ^ (self.bits == 16)));
531
b70cc006 532 let abuf;
606c448e
KS
533 let samples;
534 let nch = if stereo { 2 } else { 1 };
535 if bits16 {
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()];
539 for i in 0..nch*2 {
540 trees[i].decode(&mut br)?;
541 }
542 let mut pred: [i16; 2] = [0; 2];
543 for i in 0..nch {
544 let hi = br.read(8)?;
545 let lo = br.read(8)?;
546 pred[nch - i - 1] = (lo | (hi << 8)) as i16;
547 }
548
549 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
550 let mut adata = abuf.get_abuf_i16().unwrap();
1a967e6b 551 let dst = adata.get_data_mut().unwrap();
606c448e 552 for ch in 0..nch {
70e792a8 553 dst[ch] = pred[ch];
606c448e
KS
554 }
555 for i in nch..(unp_size >> 1) {
556 let idx = i & mask;
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);
70e792a8 561 dst[i] = pred[idx];
606c448e
KS
562 }
563 } else {
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();
1a967e6b 567 let dst = adata.get_data_mut().unwrap();
606c448e
KS
568 if stereo {
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 {
e6aaad5c 577 let diff = br.read_tree8(&trees[i & 1])?;
606c448e
KS
578 pred[i & 1] = pred[i & 1].wrapping_add(diff);
579 dst[i] = pred[i & 1];
580 }
581 } else {
582 let mut tree = SmackerTree8::new();
583 tree.decode(&mut br)?;
584 let mut pred = br.read(8)? as u8;
585 dst[0] = pred;
586 for i in 1..unp_size {
e6aaad5c 587 let diff = br.read_tree8(&tree)?;
606c448e
KS
588 pred = pred.wrapping_add(diff);
589 dst[i] = pred;
590 }
591 }
592 }
593 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
594 frm.set_duration(Some(samples as u64));
595 frm.set_keyframe(false);
171860fc 596 Ok(frm.into_ref())
606c448e
KS
597 } else {
598 Err(DecoderError::InvalidData)
599 }
600 }
f9be4e75
KS
601 fn flush(&mut self) {
602 }
606c448e
KS
603}
604
7d57ae2f
KS
605impl 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 }
609}
610
08a1fab7 611pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
606c448e
KS
612 Box::new(SmackerAudioDecoder::new())
613}
614
615#[cfg(test)]
616mod test {
617 use nihav_core::codecs::RegisteredDecoders;
618 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 619 use nihav_codec_support::test::dec_video::*;
78fb6560 620 use crate::rad_register_all_decoders;
e64739f8 621 use crate::rad_register_all_demuxers;
606c448e
KS
622 #[test]
623 fn test_smkvid() {
624 let mut dmx_reg = RegisteredDemuxers::new();
625 rad_register_all_demuxers(&mut dmx_reg);
626 let mut dec_reg = RegisteredDecoders::new();
78fb6560 627 rad_register_all_decoders(&mut dec_reg);
606c448e 628
886cde48 629 // sample from Heroes of Might and Magic 2
72be6d12
KS
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]]));
606c448e
KS
642 }
643 #[test]
72be6d12 644 fn test_smkaud_u8() {
606c448e
KS
645 let mut dmx_reg = RegisteredDemuxers::new();
646 rad_register_all_demuxers(&mut dmx_reg);
647 let mut dec_reg = RegisteredDecoders::new();
78fb6560 648 rad_register_all_decoders(&mut dec_reg);
606c448e 649
886cde48 650 // sample: https://samples.mplayerhq.hu/game-formats/smacker/wetlands/wetlogo.smk
72be6d12
KS
651 test_decoding("smacker", "smacker-audio", "assets/RAD/wetlogo.smk", None, &dmx_reg, &dec_reg,
652 ExpectedTestResult::MD5([0xc686b833, 0x0a203038, 0x012f6d9b, 0xa4186d44]));
653 }
654 #[test]
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();
78fb6560 659 rad_register_all_decoders(&mut dec_reg);
72be6d12 660
886cde48 661 // sample: https://samples.mplayerhq.hu/game-formats/smacker/20130507_audio-distortion.smk
72be6d12
KS
662 test_decoding("smacker", "smacker-audio", "assets/RAD/20130507_audio-distortion.smk", None, &dmx_reg, &dec_reg,
663 ExpectedTestResult::MD5([0x942a0922, 0x182bb5fd, 0x94ab7a59, 0x2028d810]));
606c448e
KS
664 }
665}