]>
Commit | Line | Data |
---|---|---|
606c448e KS |
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() { | |
af37e28a KS |
163 | if self.last[i] != SMK_LAST_UNINIT { |
164 | self.tree[self.last[i]] = 0; | |
165 | } | |
606c448e KS |
166 | } |
167 | } | |
168 | } | |
169 | ||
170 | trait ReadTree { | |
171 | fn read_tree8(&mut self, tree: &SmackerTree8) -> DecoderResult<u8>; | |
172 | fn read_bigtree(&mut self, tree: &mut SmackerTree16) -> DecoderResult<u16>; | |
173 | } | |
174 | ||
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)?) | |
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 | ||
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 | |
210 | ]; | |
211 | ||
212 | struct 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 | ||
228 | impl 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 | ||
389 | impl 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 |
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 } | |
476 | } | |
477 | ||
08a1fab7 | 478 | pub fn get_decoder_video() -> Box<dyn NADecoder + Send> { |
606c448e KS |
479 | Box::new(SmackerVideoDecoder::new()) |
480 | } | |
481 | ||
482 | struct SmackerAudioDecoder { | |
483 | ainfo: NAAudioInfo, | |
484 | chmap: NAChannelMap, | |
485 | chans: usize, | |
486 | bits: u8, | |
487 | } | |
488 | ||
489 | impl 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 | ||
500 | impl 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 |
604 | impl 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 | 610 | pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> { |
606c448e KS |
611 | Box::new(SmackerAudioDecoder::new()) |
612 | } | |
613 | ||
614 | #[cfg(test)] | |
615 | mod 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 | } |