RAD formats crate and Smacker demuxer and decoder
[nihav.git] / nihav-rad / src / codecs / smacker.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_core::io::bitreader::*;
4 use nihav_core::io::codebook::*;
5 use std::str::FromStr;
6
7 const PAL_SIZE: usize = 768;
8 const SMK_FLAG_INTERLACED: u32 = 0x02;
9 const SMK_FLAG_SCALED: u32 = 0x04;
10
11 struct SmackerTree8 {
12 cb: Option<Codebook<u8>>,
13 defsym: u8,
14 }
15
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<()> {
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
30 pub struct FullTableCodebookDescReader<'a> {
31 bits: &'a [u8],
32 codes: &'a [u32],
33 syms: &'a [u8],
34 }
35
36 impl<'a> FullTableCodebookDescReader<'a> {
37 pub fn new(codes: &'a [u32], bits: &'a [u8], syms: &'a [u8]) -> Self {
38 Self { bits, codes, syms }
39 }
40 }
41 impl<'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
49 impl 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
79 struct SmackerTree16 {
80 tree: Vec<u32>,
81 last: [usize; 3],
82 }
83
84 struct SmackerTree16Builder {
85 tree_lo: SmackerTree8,
86 tree_hi: SmackerTree8,
87 nsyms: usize,
88 esc: [u32; 3],
89 }
90
91 const SMK_BIGTREE_NODE: u32 = 0x80000000;
92 const SMK_LAST_UNINIT: usize = 0xFFFFFFFF;
93
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 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
124 impl 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() {
163 self.tree[self.last[i]] = 0;
164 }
165 }
166 }
167
168 trait ReadTree {
169 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>;
170 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>;
171 }
172
173 impl<'a> ReadTree for BitReader<'a> {
174 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8> {
175 if let Some(ref cb) = tree.cb {
176 Ok(self.read_cb(cb)?)
177 } else {
178 Ok(tree.defsym)
179 }
180 }
181 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16> {
182 let mut pos = 0;
183 while (tree.tree[pos] & SMK_BIGTREE_NODE) != 0 {
184 if self.read_bool()? {
185 pos += (tree.tree[pos] & !SMK_BIGTREE_NODE) as usize;
186 }
187 pos += 1;
188 }
189 let val = tree.tree[pos];
190 if val != tree.tree[tree.last[0]] {
191 tree.tree[tree.last[2]] = tree.tree[tree.last[1]];
192 tree.tree[tree.last[1]] = tree.tree[tree.last[0]];
193 tree.tree[tree.last[0]] = val;
194 }
195 Ok(val as u16)
196 }
197 }
198
199 const SMK_BLOCK_RUNS: [usize; 64] = [
200 1, 2, 3, 4, 5, 6, 7, 8,
201 9, 10, 11, 12, 13, 14, 15, 16,
202 17, 18, 19, 20, 21, 22, 23, 24,
203 25, 26, 27, 28, 29, 30, 31, 32,
204 33, 34, 35, 36, 37, 38, 39, 40,
205 41, 42, 43, 44, 45, 46, 47, 48,
206 49, 50, 51, 52, 53, 54, 55, 56,
207 57, 58, 59, 128, 256, 512, 1024, 2048
208 ];
209
210 struct SmackerVideoDecoder {
211 info: Rc<NACodecInfo>,
212 mmap_tree: SmackerTree16,
213 mclr_tree: SmackerTree16,
214 full_tree: SmackerTree16,
215 type_tree: SmackerTree16,
216 w: usize,
217 h: usize,
218 bw: usize,
219 bh: usize,
220 is_ver4: bool,
221 flags: u32,
222 frame: Vec<u8>,
223 stride: usize,
224 }
225
226 impl SmackerVideoDecoder {
227 fn new() -> Self {
228 let dummy_info = Rc::new(DUMMY_CODEC_INFO);
229 Self {
230 info: dummy_info,
231 mmap_tree: SmackerTree16::new(),
232 mclr_tree: SmackerTree16::new(),
233 full_tree: SmackerTree16::new(),
234 type_tree: SmackerTree16::new(),
235 w: 0,
236 h: 0,
237 bw: 0,
238 bh: 0,
239 is_ver4: false,
240 flags: 0,
241 frame: Vec::new(),
242 stride: 0,
243 }
244 }
245 fn block_pos(&self, blk_no: usize) -> usize {
246 let bx = blk_no % self.bw;
247 let by = blk_no / self.bw;
248 bx * 4 + by * 4 * self.stride
249 }
250 fn decode_frame(&mut self, br: &mut BitReader) -> DecoderResult<bool> {
251 let mut is_intra = true;
252 let blocks = self.bw * self.bh;
253
254 self.mmap_tree.reset();
255 self.mclr_tree.reset();
256 self.full_tree.reset();
257 self.type_tree.reset();
258
259 let mut block = 0;
260 while block < blocks {
261 let btype = br.read_bigtree(&mut self.type_tree)?;
262 let run = SMK_BLOCK_RUNS[((btype as usize) >> 2) & 0x3F];
263 validate!(run <= blocks - block);
264 match btype & 3 {
265 0 => { // two-colour pattern
266 for i in 0..run {
267 let clr = br.read_bigtree(&mut self.mclr_tree)?;
268 let mut map = br.read_bigtree(&mut self.mmap_tree)?;
269 let hi = (clr >> 8) as u8;
270 let lo = (clr & 0xFF) as u8;
271 let mut doff = self.block_pos(block + i);
272 for _ in 0..4 {
273 self.frame[doff + 0] = if (map & 1) != 0 { hi } else { lo };
274 self.frame[doff + 1] = if (map & 2) != 0 { hi } else { lo };
275 self.frame[doff + 2] = if (map & 4) != 0 { hi } else { lo };
276 self.frame[doff + 3] = if (map & 8) != 0 { hi } else { lo };
277 map >>= 4;
278 doff += self.stride;
279 }
280 }
281 },
282 1 => { // full
283 let mode;
284 if !self.is_ver4 || !br.read_bool()? {
285 mode = 0;
286 } else {
287 mode = 1 + br.read(1)?;
288 }
289 for i in 0..run {
290 let mut doff = self.block_pos(block + i);
291 match mode {
292 0 => {
293 for _ in 0..4 {
294 let clr0 = br.read_bigtree(&mut self.full_tree)?;
295 let clr1 = br.read_bigtree(&mut self.full_tree)?;
296 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
297 self.frame[doff + 1] = (clr1 >> 8) as u8;
298 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
299 self.frame[doff + 3] = (clr0 >> 8) as u8;
300 doff += self.stride;
301 }
302 },
303 1 => {
304 for _ in 0..2 {
305 let clr = br.read_bigtree(&mut self.full_tree)?;
306 self.frame[doff + 0] = (clr & 0xFF) as u8;
307 self.frame[doff + 1] = (clr & 0xFF) as u8;
308 self.frame[doff + 2] = (clr >> 8) as u8;
309 self.frame[doff + 3] = (clr >> 8) as u8;
310 doff += self.stride;
311 self.frame[doff + 0] = (clr & 0xFF) as u8;
312 self.frame[doff + 1] = (clr & 0xFF) as u8;
313 self.frame[doff + 2] = (clr >> 8) as u8;
314 self.frame[doff + 3] = (clr >> 8) as u8;
315 doff += self.stride;
316 }
317 },
318 2 => {
319 for _ in 0..2 {
320 let clr0 = br.read_bigtree(&mut self.full_tree)?;
321 let clr1 = br.read_bigtree(&mut self.full_tree)?;
322 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
323 self.frame[doff + 1] = (clr1 >> 8) as u8;
324 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
325 self.frame[doff + 3] = (clr0 >> 8) as u8;
326 doff += self.stride;
327 self.frame[doff + 0] = (clr1 & 0xFF) as u8;
328 self.frame[doff + 1] = (clr1 >> 8) as u8;
329 self.frame[doff + 2] = (clr0 & 0xFF) as u8;
330 self.frame[doff + 3] = (clr0 >> 8) as u8;
331 doff += self.stride;
332 }
333 },
334 _ => unreachable!(),
335 };
336 }
337 },
338 2 => { // skip
339 is_intra = false;
340 },
341 3 => { // fill
342 let clr = (btype >> 8) as u8;
343 for i in 0..run {
344 let mut doff = self.block_pos(block + i);
345 for _ in 0..4 {
346 self.frame[doff + 0] = clr;
347 self.frame[doff + 1] = clr;
348 self.frame[doff + 2] = clr;
349 self.frame[doff + 3] = clr;
350 doff += self.stride;
351 }
352 }
353 },
354 _ => unreachable!(),
355 };
356 block += run;
357 }
358 Ok(is_intra)
359 }
360 fn output_frame(&self, buf: &mut NAVideoBuffer<u8>) {
361 let stride = buf.get_stride(0);
362 let mut data = buf.get_data_mut();
363 let dst = data.as_mut_slice();
364 let is_scaled = (self.flags & SMK_FLAG_SCALED) != 0;
365 let is_interlaced = (self.flags & SMK_FLAG_INTERLACED) != 0;
366 let mut didx = 0;
367 let mut sidx = 0;
368 for _ in 0..self.h {
369 for x in 0..self.w { dst[didx + x] = self.frame[sidx + x]; }
370 sidx += self.stride;
371 didx += stride;
372 if is_scaled {
373 for x in 0..self.w { dst[didx + x] = dst[didx - stride + x]; }
374 didx += stride;
375 }
376 if is_interlaced {
377 for x in 0..self.w { dst[didx + x] = 0; }
378 didx += stride;
379 if is_scaled {
380 for x in 0..self.w { dst[didx + x] = 0; }
381 didx += stride;
382 }
383 }
384 }
385 }
386 }
387
388 impl NADecoder for SmackerVideoDecoder {
389 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
390 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
391 let w = vinfo.get_width();
392 let h = vinfo.get_height();
393 let fmt = PAL8_FORMAT;
394
395 self.w = w;
396 self.h = h;
397 self.bw = w >> 2;
398 self.bh = h >> 2;
399 let edata = info.get_extradata().unwrap();
400 validate!(edata.len() > 24);
401
402 self.stride = w;
403 self.frame.resize(w * h, 0);
404
405 let mut mr = MemoryReader::new_read(&edata);
406 let mut br = ByteReader::new(&mut mr);
407 let magic = br.read_u32be()?;
408 self.flags = br.read_u32le()?;
409 let mmap_size = br.read_u32le()?;
410 let mclr_size = br.read_u32le()?;
411 let full_size = br.read_u32le()?;
412 let type_size = br.read_u32le()?;
413
414 self.is_ver4 = (magic & 0xFF) == 0x34;
415 let mut br = BitReader::new(&edata[24..], edata.len() - 24, BitReaderMode::LE);
416 self.mmap_tree.decode(&mut br, mmap_size)?;
417 self.mclr_tree.decode(&mut br, mclr_size)?;
418 self.full_tree.decode(&mut br, full_size)?;
419 self.type_tree.decode(&mut br, type_size)?;
420
421 let mut out_h = h;
422 if (self.flags & SMK_FLAG_INTERLACED) != 0 {
423 out_h <<= 1;
424 }
425 if (self.flags & SMK_FLAG_SCALED) != 0 {
426 out_h <<= 1;
427 }
428 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, out_h, false, fmt));
429 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
430
431
432 Ok(())
433 } else {
434 Err(DecoderError::InvalidData)
435 }
436 }
437 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
438 let src = pkt.get_buffer();
439 validate!(src.len() >= PAL_SIZE);
440
441 let is_intra;
442 let ftype;
443 let mut bufinfo;
444 if src.len() > PAL_SIZE {
445 let mut br = BitReader::new(&src[PAL_SIZE..], src.len() - PAL_SIZE, BitReaderMode::LE);
446
447 let bufret = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2);
448 if let Err(_) = bufret { return Err(DecoderError::InvalidData); }
449 bufinfo = bufret.unwrap();
450 let mut buf = bufinfo.get_vbuf().unwrap();
451 is_intra = self.decode_frame(&mut br)?;
452 self.output_frame(&mut buf);
453 let paloff = buf.get_offset(1);
454 let mut data = buf.get_data_mut();
455 let dst = data.as_mut_slice();
456 let palout = &mut dst[paloff..][..PAL_SIZE];
457 palout.copy_from_slice(&src[0..PAL_SIZE]);
458 ftype = if is_intra { FrameType::I } else { FrameType::P };
459 } else {
460 bufinfo = NABufferType::None;
461 ftype = FrameType::Skip;
462 is_intra = false;
463 }
464
465 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
466 frm.set_keyframe(is_intra);
467 frm.set_frame_type(ftype);
468 Ok(Rc::new(RefCell::new(frm)))
469 }
470 }
471
472 pub fn get_decoder_video() -> Box<NADecoder> {
473 Box::new(SmackerVideoDecoder::new())
474 }
475
476 struct SmackerAudioDecoder {
477 ainfo: NAAudioInfo,
478 chmap: NAChannelMap,
479 chans: usize,
480 bits: u8,
481 }
482
483 impl SmackerAudioDecoder {
484 fn new() -> Self {
485 Self {
486 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
487 chmap: NAChannelMap::new(),
488 chans: 0,
489 bits: 0,
490 }
491 }
492 }
493
494 impl NADecoder for SmackerAudioDecoder {
495 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
496 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
497 self.bits = ainfo.get_format().get_bits();
498 let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16P_FORMAT };
499 self.chans = ainfo.get_channels() as usize;
500 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, 0);
501 self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 2 {"L,R"} else {"C"}).unwrap();
502 Ok(())
503 } else {
504 Err(DecoderError::InvalidData)
505 }
506 }
507 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
508 let info = pkt.get_stream().get_info();
509 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
510 let src = pkt.get_buffer();
511 validate!(src.len() > 4);
512 let mut br = BitReader::new(&src, src.len(), BitReaderMode::LE);
513 let unp_size = br.read(32)? as usize;
514 if !br.read_bool()? {
515 let mut frm = NAFrame::new_from_pkt(pkt, info.clone(), NABufferType::None);
516 frm.set_frame_type(FrameType::Skip);
517 return Ok(Rc::new(RefCell::new(frm)));
518 }
519 let stereo = br.read_bool()?;
520 let bits16 = br.read_bool()?;
521 validate!(!(stereo ^ (self.chans == 2)));
522 validate!(!(bits16 ^ (self.bits == 16)));
523
524 let mut abuf;
525 let samples;
526 let nch = if stereo { 2 } else { 1 };
527 if bits16 {
528 samples = unp_size / 2 / nch;
529 let mask = if stereo { 1 } else { 0 };
530 let mut trees: [SmackerTree8; 4] = [SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new()];
531 for i in 0..nch*2 {
532 trees[i].decode(&mut br)?;
533 }
534 let mut pred: [i16; 2] = [0; 2];
535 for i in 0..nch {
536 let hi = br.read(8)?;
537 let lo = br.read(8)?;
538 pred[nch - i - 1] = (lo | (hi << 8)) as i16;
539 }
540
541 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
542 let mut adata = abuf.get_abuf_i16().unwrap();
543 let offs: [usize; 2] = [0, adata.get_offset(1)];
544 let mut dst = adata.get_data_mut();
545 for ch in 0..nch {
546 dst[offs[ch]] = pred[ch];
547 }
548 for i in nch..(unp_size >> 1) {
549 let idx = i & mask;
550 let lo = br.read_tree8(&trees[idx * 2 + 0])? as u16;
551 let hi = br.read_tree8(&trees[idx * 2 + 1])? as u16;
552 let diff = (lo | (hi << 8)) as i16;
553 pred[idx] = pred[idx].wrapping_add(diff);
554 dst[offs[idx] + (i >> 1)] = pred[idx];
555 }
556 } else {
557 samples = unp_size / nch;
558 abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
559 let mut adata = abuf.get_abuf_u8().unwrap();
560 let mut dst = adata.get_data_mut();
561 if stereo {
562 let mut trees: [SmackerTree8; 2] = [SmackerTree8::new(), SmackerTree8::new()];
563 trees[0].decode(&mut br)?;
564 trees[1].decode(&mut br)?;
565 let pred0 = br.read(8)? as u8;
566 let pred1 = br.read(8)? as u8;
567 let mut pred: [u8; 2] = [ pred1, pred0 ];
568 for ch in 0..2 { dst[ch] = pred[ch]; }
569 for i in 2..unp_size {
570 let diff = br.read_tree8(&trees[i & 1])? as u8;
571 pred[i & 1] = pred[i & 1].wrapping_add(diff);
572 dst[i] = pred[i & 1];
573 }
574 } else {
575 let mut tree = SmackerTree8::new();
576 tree.decode(&mut br)?;
577 let mut pred = br.read(8)? as u8;
578 dst[0] = pred;
579 for i in 1..unp_size {
580 let diff = br.read_tree8(&tree)? as u8;
581 pred = pred.wrapping_add(diff);
582 dst[i] = pred;
583 }
584 }
585 }
586 let mut frm = NAFrame::new_from_pkt(pkt, info, abuf);
587 frm.set_duration(Some(samples as u64));
588 frm.set_keyframe(false);
589 Ok(Rc::new(RefCell::new(frm)))
590 } else {
591 Err(DecoderError::InvalidData)
592 }
593 }
594 }
595
596 pub fn get_decoder_audio() -> Box<NADecoder> {
597 Box::new(SmackerAudioDecoder::new())
598 }
599
600 #[cfg(test)]
601 mod test {
602 use nihav_core::codecs::RegisteredDecoders;
603 use nihav_core::demuxers::RegisteredDemuxers;
604 use nihav_core::test::dec_video::*;
605 use crate::codecs::rad_register_all_codecs;
606 use crate::demuxers::rad_register_all_demuxers;
607 #[test]
608 fn test_smkvid() {
609 let mut dmx_reg = RegisteredDemuxers::new();
610 rad_register_all_demuxers(&mut dmx_reg);
611 let mut dec_reg = RegisteredDecoders::new();
612 rad_register_all_codecs(&mut dec_reg);
613
614 //let file = "assets/RAD/20130507_audio-distortion.smk";
615 //let file = "assets/RAD/ajfstr1.smk";
616 //let file = "assets/RAD/credits.smk";
617 let file = "assets/RAD/wetlogo.smk";
618 test_file_decoding("smacker", file, Some(1000), true, false, None, &dmx_reg, &dec_reg);
619 }
620 #[test]
621 fn test_smkaud() {
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);
626
627 //let file = "assets/RAD/20130507_audio-distortion.smk";
628 let file = "assets/RAD/wetlogo.smk";
629 test_decode_audio("smacker", file, None, "smk", &dmx_reg, &dec_reg);
630 }
631 }