]> git.nihav.org Git - nihav.git/blame - nihav-rad/src/codecs/smacker.rs
vp6enc: allow setting codec version
[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);
97 if !br.read_bool()? {
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();
103 sym = 0;
104 } else if sym == self.esc[1] {
105 tree.last[1] = tree.tree.len();
106 sym = 0;
107 } else if sym == self.esc[2] {
108 tree.last[2] = tree.tree.len();
109 sym = 0;
110 }
111 tree.tree.push(sym);
112 Ok(1)
113 } else {
114 let cur_idx = tree.tree.len();
115 tree.tree.push(0);
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)
120 }
121 }
122}
123
124impl SmackerTree16 {
125 fn new() -> Self {
126 Self {
127 tree: Vec::new(),
128 last: [SMK_LAST_UNINIT; 3],
129 }
130 }
131 fn decode(&mut self, br: &mut BitReader, size: u32) -> DecoderResult<()> {
132 if !br.read_bool()? { return Ok(()); }
133
134 let mut tree_lo = SmackerTree8::new();
135 tree_lo.decode(br)?;
136 let mut tree_hi = SmackerTree8::new();
137 tree_hi.decode(br)?;
138
139 let mut esc: [u32; 3] = [0; 3];
140 for i in 0..esc.len() {
141 esc[i] = br.read(16)? as u32;
142 }
143
144 let nsyms = (((size + 3) >> 2) + 4) as usize;
145 self.tree = Vec::with_capacity(nsyms);
146
147 let mut tb = SmackerTree16Builder { tree_lo, tree_hi, nsyms, esc };
148
149 tb.get_tree16(br, self, 0)?;
150 validate!(!br.read_bool()?);
151
152 for i in 0..self.last.len() {
153 if self.last[i] == SMK_LAST_UNINIT {
154 self.last[i] = self.tree.len();
155 self.tree.push(0);
156 }
157 }
158 validate!(self.tree.len() <= nsyms);
159 Ok(())
160 }
161 fn reset(&mut self) {
162 for i in 0..self.last.len() {
af37e28a
KS
163 if self.last[i] != SMK_LAST_UNINIT {
164 self.tree[self.last[i]] = 0;
165 }
606c448e
KS
166 }
167 }
168}
169
170trait ReadTree {
171 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>;
172 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>;
173}
174
175impl<'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)?)
179 } else {
180 Ok(tree.defsym)
181 }
182 }
183 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16> {
184 let mut pos = 0;
185 while (tree.tree[pos] & SMK_BIGTREE_NODE) != 0 {
186 if self.read_bool()? {
187 pos += (tree.tree[pos] & !SMK_BIGTREE_NODE) as usize;
188 }
189 pos += 1;
190 }
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;
196 }
197 Ok(val as u16)
198 }
199}
200
201const 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
210];
211
212struct SmackerVideoDecoder {
2422d969 213 info: NACodecInfoRef,
606c448e
KS
214 mmap_tree: SmackerTree16,
215 mclr_tree: SmackerTree16,
216 full_tree: SmackerTree16,
217 type_tree: SmackerTree16,
218 w: usize,
219 h: usize,
220 bw: usize,
221 bh: usize,
222 is_ver4: bool,
223 flags: u32,
224 frame: Vec<u8>,
225 stride: usize,
226}
227
228impl SmackerVideoDecoder {
229 fn new() -> Self {
606c448e 230 Self {
2422d969 231 info: NACodecInfoRef::default(),
606c448e
KS
232 mmap_tree: SmackerTree16::new(),
233 mclr_tree: SmackerTree16::new(),
234 full_tree: SmackerTree16::new(),
235 type_tree: SmackerTree16::new(),
236 w: 0,
237 h: 0,
238 bw: 0,
239 bh: 0,
240 is_ver4: false,
241 flags: 0,
242 frame: Vec::new(),
243 stride: 0,
244 }
245 }
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
250 }
251 fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<bool> {
252 let mut is_intra = true;
253 let blocks = self.bw * self.bh;
254
255 self.mmap_tree.reset();
256 self.mclr_tree.reset();
257 self.full_tree.reset();
258 self.type_tree.reset();
259
260 let mut block = 0;
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);
265 match btype & 3 {
266 0 => { // two-colour pattern
267 for i in 0..run {
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);
273 for _ in 0..4 {
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 };
278 map >>= 4;
279 doff += self.stride;
280 }
281 }
282 },
283 1 => { // full
284 let mode;
285 if !self.is_ver4 || !br.read_bool()? {
286 mode = 0;
287 } else {
288 mode = 1 + br.read(1)?;
289 }
290 for i in 0..run {
291 let mut doff = self.block_pos(block + i);
292 match mode {
293 0 => {
294 for _ in 0..4 {
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;
301 doff += self.stride;
302 }
303 },
304 1 => {
305 for _ in 0..2 {
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;
311 doff += self.stride;
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;
316 doff += self.stride;
317 }
318 },
319 2 => {
320 for _ in 0..2 {
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;
327 doff += self.stride;
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;
332 doff += self.stride;
333 }
334 },
335 _ => unreachable!(),
336 };
337 }
338 },
339 2 => { // skip
340 is_intra = false;
341 },
342 3 => { // fill
343 let clr = (btype >> 8) as u8;
344 for i in 0..run {
345 let mut doff = self.block_pos(block + i);
346 for _ in 0..4 {
347 self.frame[doff + 0] = clr;
348 self.frame[doff + 1] = clr;
349 self.frame[doff + 2] = clr;
350 self.frame[doff + 3] = clr;
351 doff += self.stride;
352 }
353 }
354 },
355 _ => unreachable!(),
356 };
357 block += run;
358 }
359 Ok(is_intra)
360 }
361 fn output_frame(&self, buf: &mut NAVideoBuffer<u8>) {
362 let stride = buf.get_stride(0);
1a967e6b 363 let data = buf.get_data_mut().unwrap();
606c448e
KS
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;
367 let mut didx = 0;
368 let mut sidx = 0;
369 for _ in 0..self.h {
bf109afe 370 dst[didx..][..self.w].copy_from_slice(&self.frame[sidx..][..self.w]);
606c448e
KS
371 sidx += self.stride;
372 didx += stride;
373 if is_scaled {
374 for x in 0..self.w { dst[didx + x] = dst[didx - stride + x]; }
375 didx += stride;
376 }
377 if is_interlaced {
378 for x in 0..self.w { dst[didx + x] = 0; }
379 didx += stride;
380 if is_scaled {
381 for x in 0..self.w { dst[didx + x] = 0; }
382 didx += stride;
383 }
384 }
385 }
386 }
387}
388
389impl NADecoder for SmackerVideoDecoder {
01613464 390 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
606c448e
KS
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;
395
396 self.w = w;
397 self.h = h;
398 self.bw = w >> 2;
399 self.bh = h >> 2;
400 let edata = info.get_extradata().unwrap();
401 validate!(edata.len() > 24);
402
403 self.stride = w;
404 self.frame.resize(w * h, 0);
405
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()?;
414
415 self.is_ver4 = (magic & 0xFF) == 0x34;
fa90ccfb 416 let mut br = BitReader::new(&edata[24..], BitReaderMode::LE);
606c448e
KS
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)?;
421
422 let mut out_h = h;
423 if (self.flags & SMK_FLAG_INTERLACED) != 0 {
424 out_h <<= 1;
425 }
426 if (self.flags & SMK_FLAG_SCALED) != 0 {
427 out_h <<= 1;
428 }
429 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, out_h, false, fmt));
2422d969 430 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
606c448e
KS
431
432 Ok(())
433 } else {
434 Err(DecoderError::InvalidData)
435 }
436 }
01613464 437 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
606c448e
KS
438 let src = pkt.get_buffer();
439 validate!(src.len() >= PAL_SIZE);
440
441 let is_intra;
442 let ftype;
b70cc006 443 let bufinfo;
606c448e 444 if src.len() > PAL_SIZE {
fa90ccfb 445 let mut br = BitReader::new(&src[PAL_SIZE..], BitReaderMode::LE);
606c448e 446
7e6086e5 447 bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2)?;
606c448e
KS
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);
1a967e6b 452 let data = buf.get_data_mut().unwrap();
606c448e
KS
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 };
457 } else {
458 bufinfo = NABufferType::None;
459 ftype = FrameType::Skip;
460 is_intra = false;
461 }
462
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);
171860fc 466 Ok(frm.into_ref())
606c448e 467 }
f9be4e75
KS
468 fn flush(&mut self) {
469 }
606c448e
KS
470}
471
7d57ae2f
KS
472impl 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 }
476}
477
08a1fab7 478pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
606c448e
KS
479 Box::new(SmackerVideoDecoder::new())
480}
481
482struct SmackerAudioDecoder {
483 ainfo: NAAudioInfo,
484 chmap: NAChannelMap,
485 chans: usize,
486 bits: u8,
487}
488
489impl SmackerAudioDecoder {
490 fn new() -> Self {
491 Self {
492 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
493 chmap: NAChannelMap::new(),
494 chans: 0,
495 bits: 0,
496 }
497 }
498}
499
500impl NADecoder for SmackerAudioDecoder {
01613464 501 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
606c448e
KS
502 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
503 self.bits = ainfo.get_format().get_bits();
70e792a8 504 let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16_FORMAT };
606c448e
KS
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();
508 Ok(())
509 } else {
510 Err(DecoderError::InvalidData)
511 }
512 }
bf109afe 513 #[allow(clippy::manual_memcpy)]
01613464 514 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
606c448e
KS
515 let info = pkt.get_stream().get_info();
516 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
517 let src = pkt.get_buffer();
518 validate!(src.len() > 4);
fa90ccfb 519 let mut br = BitReader::new(&src, BitReaderMode::LE);
606c448e
KS
520 let unp_size = br.read(32)? as usize;
521 if !br.read_bool()? {
522 let mut frm = NAFrame::new_from_pkt(pkt, info.clone(), NABufferType::None);
523 frm.set_frame_type(FrameType::Skip);
171860fc 524 return Ok(frm.into_ref());
606c448e
KS
525 }
526 let stereo = br.read_bool()?;
527 let bits16 = br.read_bool()?;
528 validate!(!(stereo ^ (self.chans == 2)));
529 validate!(!(bits16 ^ (self.bits == 16)));
530
b70cc006 531 let abuf;
606c448e
KS
532 let samples;
533 let nch = if stereo { 2 } else { 1 };
534 if bits16 {
535 samples = unp_size / 2 / nch;
536 let mask = if stereo { 1 } else { 0 };
537 let mut trees: [SmackerTree8; 4] = [SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new()];
538 for i in 0..nch*2 {
539 trees[i].decode(&mut br)?;
540 }
541 let mut pred: [i16; 2] = [0; 2];
542 for i in 0..nch {
543 let hi = br.read(8)?;
544 let lo = br.read(8)?;
545 pred[nch - i - 1] = (lo | (hi << 8)) as i16;
546 }
547
548 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
549 let mut adata = abuf.get_abuf_i16().unwrap();
1a967e6b 550 let dst = adata.get_data_mut().unwrap();
606c448e 551 for ch in 0..nch {
70e792a8 552 dst[ch] = pred[ch];
606c448e
KS
553 }
554 for i in nch..(unp_size >> 1) {
555 let idx = i & mask;
556 let lo = br.read_tree8(&trees[idx * 2 + 0])? as u16;
557 let hi = br.read_tree8(&trees[idx * 2 + 1])? as u16;
558 let diff = (lo | (hi << 8)) as i16;
559 pred[idx] = pred[idx].wrapping_add(diff);
70e792a8 560 dst[i] = pred[idx];
606c448e
KS
561 }
562 } else {
563 samples = unp_size / nch;
564 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
565 let mut adata = abuf.get_abuf_u8().unwrap();
1a967e6b 566 let dst = adata.get_data_mut().unwrap();
606c448e
KS
567 if stereo {
568 let mut trees: [SmackerTree8; 2] = [SmackerTree8::new(), SmackerTree8::new()];
569 trees[0].decode(&mut br)?;
570 trees[1].decode(&mut br)?;
571 let pred0 = br.read(8)? as u8;
572 let pred1 = br.read(8)? as u8;
573 let mut pred: [u8; 2] = [ pred1, pred0 ];
574 for ch in 0..2 { dst[ch] = pred[ch]; }
575 for i in 2..unp_size {
576 let diff = br.read_tree8(&trees[i & 1])? as u8;
577 pred[i & 1] = pred[i & 1].wrapping_add(diff);
578 dst[i] = pred[i & 1];
579 }
580 } else {
581 let mut tree = SmackerTree8::new();
582 tree.decode(&mut br)?;
583 let mut pred = br.read(8)? as u8;
584 dst[0] = pred;
585 for i in 1..unp_size {
586 let diff = br.read_tree8(&tree)? as u8;
587 pred = pred.wrapping_add(diff);
588 dst[i] = pred;
589 }
590 }
591 }
592 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
593 frm.set_duration(Some(samples as u64));
594 frm.set_keyframe(false);
171860fc 595 Ok(frm.into_ref())
606c448e
KS
596 } else {
597 Err(DecoderError::InvalidData)
598 }
599 }
f9be4e75
KS
600 fn flush(&mut self) {
601 }
606c448e
KS
602}
603
7d57ae2f
KS
604impl NAOptionHandler for SmackerAudioDecoder {
605 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
606 fn set_options(&mut self, _options: &[NAOption]) { }
607 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
608}
609
08a1fab7 610pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
606c448e
KS
611 Box::new(SmackerAudioDecoder::new())
612}
613
614#[cfg(test)]
615mod test {
616 use nihav_core::codecs::RegisteredDecoders;
617 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 618 use nihav_codec_support::test::dec_video::*;
78fb6560 619 use crate::rad_register_all_decoders;
e64739f8 620 use crate::rad_register_all_demuxers;
606c448e
KS
621 #[test]
622 fn test_smkvid() {
623 let mut dmx_reg = RegisteredDemuxers::new();
624 rad_register_all_demuxers(&mut dmx_reg);
625 let mut dec_reg = RegisteredDecoders::new();
78fb6560 626 rad_register_all_decoders(&mut dec_reg);
606c448e 627
72be6d12
KS
628 test_decoding("smacker", "smacker-video", "assets/RAD/credits.smk", None, &dmx_reg, &dec_reg,
629 ExpectedTestResult::MD5Frames(vec![
630 [0x0983944a, 0xa23503f8, 0x2602b589, 0x13b53480],
631 [0xb6c2bf1e, 0x2ee5fa60, 0x9896a6dc, 0x760b5737],
632 [0xc7c6d112, 0x2c3c5bac, 0x63684974, 0xa6573b1e],
633 [0x100e2871, 0xbc670db7, 0x54a802e5, 0xb5ba0b07],
634 [0xcd9d22ce, 0x7f195dc9, 0x93c47105, 0x6acf8aa7],
635 [0x84e82fdb, 0x304f24a8, 0x17466d73, 0x20182c33],
636 [0xfcae613f, 0xddab2bd4, 0x9d351ee5, 0x2d0aea24],
637 [0xea32a37c, 0x94d76dda, 0xbb34ca1d, 0xfc9d8a25],
638 [0x37855f28, 0xb508a386, 0x1f0bd981, 0x0f967e25],
639 [0x9b9f453a, 0xf6e34fe7, 0x9279fd71, 0x850a4f36]]));
606c448e
KS
640 }
641 #[test]
72be6d12 642 fn test_smkaud_u8() {
606c448e
KS
643 let mut dmx_reg = RegisteredDemuxers::new();
644 rad_register_all_demuxers(&mut dmx_reg);
645 let mut dec_reg = RegisteredDecoders::new();
78fb6560 646 rad_register_all_decoders(&mut dec_reg);
606c448e 647
72be6d12
KS
648 test_decoding("smacker", "smacker-audio", "assets/RAD/wetlogo.smk", None, &dmx_reg, &dec_reg,
649 ExpectedTestResult::MD5([0xc686b833, 0x0a203038, 0x012f6d9b, 0xa4186d44]));
650 }
651 #[test]
652 fn test_smkaud_s16() {
653 let mut dmx_reg = RegisteredDemuxers::new();
654 rad_register_all_demuxers(&mut dmx_reg);
655 let mut dec_reg = RegisteredDecoders::new();
78fb6560 656 rad_register_all_decoders(&mut dec_reg);
72be6d12
KS
657
658 test_decoding("smacker", "smacker-audio", "assets/RAD/20130507_audio-distortion.smk", None, &dmx_reg, &dec_reg,
659 ExpectedTestResult::MD5([0x942a0922, 0x182bb5fd, 0x94ab7a59, 0x2028d810]));
606c448e
KS
660 }
661}