aac: clear M/S flags
[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 validate!(depth <= 32);
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
125 impl 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() {
142 esc[i] = br.read(16)?;
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() {
164 if self.last[i] != SMK_LAST_UNINIT {
165 self.tree[self.last[i]] = 0;
166 }
167 }
168 }
169 }
170
171 trait ReadTree {
172 fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>;
173 fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>;
174 }
175
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)?)
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
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
211 ];
212
213 struct SmackerVideoDecoder {
214 info: NACodecInfoRef,
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
229 impl SmackerVideoDecoder {
230 fn new() -> Self {
231 Self {
232 info: NACodecInfoRef::default(),
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);
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;
368 let mut didx = 0;
369 let mut sidx = 0;
370 for _ in 0..self.h {
371 dst[didx..][..self.w].copy_from_slice(&self.frame[sidx..][..self.w]);
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
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;
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;
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)?;
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));
431 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
432
433 Ok(())
434 } else {
435 Err(DecoderError::InvalidData)
436 }
437 }
438 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
439 let src = pkt.get_buffer();
440 validate!(src.len() >= PAL_SIZE);
441
442 let is_intra;
443 let ftype;
444 let bufinfo;
445 if src.len() > PAL_SIZE {
446 let mut br = BitReader::new(&src[PAL_SIZE..], BitReaderMode::LE);
447
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 };
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);
467 Ok(frm.into_ref())
468 }
469 fn flush(&mut self) {
470 }
471 }
472
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 }
477 }
478
479 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
480 Box::new(SmackerVideoDecoder::new())
481 }
482
483 struct SmackerAudioDecoder {
484 ainfo: NAAudioInfo,
485 chmap: NAChannelMap,
486 chans: usize,
487 bits: u8,
488 }
489
490 impl 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
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();
509 Ok(())
510 } else {
511 Err(DecoderError::InvalidData)
512 }
513 }
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());
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
532 let abuf;
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();
551 let dst = adata.get_data_mut().unwrap();
552 for ch in 0..nch {
553 dst[ch] = pred[ch];
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);
561 dst[i] = pred[idx];
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();
567 let dst = adata.get_data_mut().unwrap();
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 {
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];
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 {
587 let diff = br.read_tree8(&tree)?;
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);
596 Ok(frm.into_ref())
597 } else {
598 Err(DecoderError::InvalidData)
599 }
600 }
601 fn flush(&mut self) {
602 }
603 }
604
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 }
609 }
610
611 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
612 Box::new(SmackerAudioDecoder::new())
613 }
614
615 #[cfg(test)]
616 mod test {
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;
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();
627 rad_register_all_decoders(&mut dec_reg);
628
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]]));
642 }
643 #[test]
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);
649
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]));
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();
659 rad_register_all_decoders(&mut dec_reg);
660
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]));
664 }
665 }