]>
Commit | Line | Data |
---|---|---|
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 | if self.last[i] != SMK_LAST_UNINIT { | |
164 | self.tree[self.last[i]] = 0; | |
165 | } | |
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 { | |
213 | info: Rc<NACodecInfo>, | |
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 { | |
230 | let dummy_info = Rc::new(DUMMY_CODEC_INFO); | |
231 | Self { | |
232 | info: dummy_info, | |
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 | for x in 0..self.w { dst[didx + x] = self.frame[sidx + x]; } | |
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, info: Rc<NACodecInfo>) -> 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..], edata.len() - 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 = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata())); | |
432 | ||
433 | ||
434 | Ok(()) | |
435 | } else { | |
436 | Err(DecoderError::InvalidData) | |
437 | } | |
438 | } | |
439 | fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
440 | let src = pkt.get_buffer(); | |
441 | validate!(src.len() >= PAL_SIZE); | |
442 | ||
443 | let is_intra; | |
444 | let ftype; | |
445 | let bufinfo; | |
446 | if src.len() > PAL_SIZE { | |
447 | let mut br = BitReader::new(&src[PAL_SIZE..], src.len() - PAL_SIZE, BitReaderMode::LE); | |
448 | ||
449 | let bufret = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 2); | |
450 | if let Err(_) = bufret { return Err(DecoderError::InvalidData); } | |
451 | bufinfo = bufret.unwrap(); | |
452 | let mut buf = bufinfo.get_vbuf().unwrap(); | |
453 | is_intra = self.decode_frame(&mut br)?; | |
454 | self.output_frame(&mut buf); | |
455 | let paloff = buf.get_offset(1); | |
456 | let data = buf.get_data_mut().unwrap(); | |
457 | let dst = data.as_mut_slice(); | |
458 | let palout = &mut dst[paloff..][..PAL_SIZE]; | |
459 | palout.copy_from_slice(&src[0..PAL_SIZE]); | |
460 | ftype = if is_intra { FrameType::I } else { FrameType::P }; | |
461 | } else { | |
462 | bufinfo = NABufferType::None; | |
463 | ftype = FrameType::Skip; | |
464 | is_intra = false; | |
465 | } | |
466 | ||
467 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); | |
468 | frm.set_keyframe(is_intra); | |
469 | frm.set_frame_type(ftype); | |
470 | Ok(Rc::new(RefCell::new(frm))) | |
471 | } | |
472 | } | |
473 | ||
474 | pub fn get_decoder_video() -> Box<NADecoder> { | |
475 | Box::new(SmackerVideoDecoder::new()) | |
476 | } | |
477 | ||
478 | struct SmackerAudioDecoder { | |
479 | ainfo: NAAudioInfo, | |
480 | chmap: NAChannelMap, | |
481 | chans: usize, | |
482 | bits: u8, | |
483 | } | |
484 | ||
485 | impl SmackerAudioDecoder { | |
486 | fn new() -> Self { | |
487 | Self { | |
488 | ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0), | |
489 | chmap: NAChannelMap::new(), | |
490 | chans: 0, | |
491 | bits: 0, | |
492 | } | |
493 | } | |
494 | } | |
495 | ||
496 | impl NADecoder for SmackerAudioDecoder { | |
497 | fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> { | |
498 | if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() { | |
499 | self.bits = ainfo.get_format().get_bits(); | |
500 | let fmt = if self.bits == 8 { SND_U8_FORMAT } else { SND_S16P_FORMAT }; | |
501 | self.chans = ainfo.get_channels() as usize; | |
502 | self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, 0); | |
503 | self.chmap = NAChannelMap::from_str(if ainfo.get_channels() == 2 {"L,R"} else {"C"}).unwrap(); | |
504 | Ok(()) | |
505 | } else { | |
506 | Err(DecoderError::InvalidData) | |
507 | } | |
508 | } | |
509 | fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
510 | let info = pkt.get_stream().get_info(); | |
511 | if let NACodecTypeInfo::Audio(_) = info.get_properties() { | |
512 | let src = pkt.get_buffer(); | |
513 | validate!(src.len() > 4); | |
514 | let mut br = BitReader::new(&src, src.len(), BitReaderMode::LE); | |
515 | let unp_size = br.read(32)? as usize; | |
516 | if !br.read_bool()? { | |
517 | let mut frm = NAFrame::new_from_pkt(pkt, info.clone(), NABufferType::None); | |
518 | frm.set_frame_type(FrameType::Skip); | |
519 | return Ok(Rc::new(RefCell::new(frm))); | |
520 | } | |
521 | let stereo = br.read_bool()?; | |
522 | let bits16 = br.read_bool()?; | |
523 | validate!(!(stereo ^ (self.chans == 2))); | |
524 | validate!(!(bits16 ^ (self.bits == 16))); | |
525 | ||
526 | let abuf; | |
527 | let samples; | |
528 | let nch = if stereo { 2 } else { 1 }; | |
529 | if bits16 { | |
530 | samples = unp_size / 2 / nch; | |
531 | let mask = if stereo { 1 } else { 0 }; | |
532 | let mut trees: [SmackerTree8; 4] = [SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new(), SmackerTree8::new()]; | |
533 | for i in 0..nch*2 { | |
534 | trees[i].decode(&mut br)?; | |
535 | } | |
536 | let mut pred: [i16; 2] = [0; 2]; | |
537 | for i in 0..nch { | |
538 | let hi = br.read(8)?; | |
539 | let lo = br.read(8)?; | |
540 | pred[nch - i - 1] = (lo | (hi << 8)) as i16; | |
541 | } | |
542 | ||
543 | abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?; | |
544 | let mut adata = abuf.get_abuf_i16().unwrap(); | |
545 | let offs: [usize; 2] = [0, adata.get_offset(1)]; | |
546 | let dst = adata.get_data_mut().unwrap(); | |
547 | for ch in 0..nch { | |
548 | dst[offs[ch]] = pred[ch]; | |
549 | } | |
550 | for i in nch..(unp_size >> 1) { | |
551 | let idx = i & mask; | |
552 | let lo = br.read_tree8(&trees[idx * 2 + 0])? as u16; | |
553 | let hi = br.read_tree8(&trees[idx * 2 + 1])? as u16; | |
554 | let diff = (lo | (hi << 8)) as i16; | |
555 | pred[idx] = pred[idx].wrapping_add(diff); | |
556 | dst[offs[idx] + (i >> 1)] = pred[idx]; | |
557 | } | |
558 | } else { | |
559 | samples = unp_size / nch; | |
560 | abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?; | |
561 | let mut adata = abuf.get_abuf_u8().unwrap(); | |
562 | let dst = adata.get_data_mut().unwrap(); | |
563 | if stereo { | |
564 | let mut trees: [SmackerTree8; 2] = [SmackerTree8::new(), SmackerTree8::new()]; | |
565 | trees[0].decode(&mut br)?; | |
566 | trees[1].decode(&mut br)?; | |
567 | let pred0 = br.read(8)? as u8; | |
568 | let pred1 = br.read(8)? as u8; | |
569 | let mut pred: [u8; 2] = [ pred1, pred0 ]; | |
570 | for ch in 0..2 { dst[ch] = pred[ch]; } | |
571 | for i in 2..unp_size { | |
572 | let diff = br.read_tree8(&trees[i & 1])? as u8; | |
573 | pred[i & 1] = pred[i & 1].wrapping_add(diff); | |
574 | dst[i] = pred[i & 1]; | |
575 | } | |
576 | } else { | |
577 | let mut tree = SmackerTree8::new(); | |
578 | tree.decode(&mut br)?; | |
579 | let mut pred = br.read(8)? as u8; | |
580 | dst[0] = pred; | |
581 | for i in 1..unp_size { | |
582 | let diff = br.read_tree8(&tree)? as u8; | |
583 | pred = pred.wrapping_add(diff); | |
584 | dst[i] = pred; | |
585 | } | |
586 | } | |
587 | } | |
588 | let mut frm = NAFrame::new_from_pkt(pkt, info, abuf); | |
589 | frm.set_duration(Some(samples as u64)); | |
590 | frm.set_keyframe(false); | |
591 | Ok(Rc::new(RefCell::new(frm))) | |
592 | } else { | |
593 | Err(DecoderError::InvalidData) | |
594 | } | |
595 | } | |
596 | } | |
597 | ||
598 | pub fn get_decoder_audio() -> Box<NADecoder> { | |
599 | Box::new(SmackerAudioDecoder::new()) | |
600 | } | |
601 | ||
602 | #[cfg(test)] | |
603 | mod test { | |
604 | use nihav_core::codecs::RegisteredDecoders; | |
605 | use nihav_core::demuxers::RegisteredDemuxers; | |
606 | use nihav_core::test::dec_video::*; | |
607 | use crate::codecs::rad_register_all_codecs; | |
608 | use crate::demuxers::rad_register_all_demuxers; | |
609 | #[test] | |
610 | fn test_smkvid() { | |
611 | let mut dmx_reg = RegisteredDemuxers::new(); | |
612 | rad_register_all_demuxers(&mut dmx_reg); | |
613 | let mut dec_reg = RegisteredDecoders::new(); | |
614 | rad_register_all_codecs(&mut dec_reg); | |
615 | ||
616 | //let file = "assets/RAD/20130507_audio-distortion.smk"; | |
617 | //let file = "assets/RAD/ajfstr1.smk"; | |
618 | //let file = "assets/RAD/credits.smk"; | |
619 | let file = "assets/RAD/wetlogo.smk"; | |
620 | test_file_decoding("smacker", file, Some(1000), true, false, None, &dmx_reg, &dec_reg); | |
621 | } | |
622 | #[test] | |
623 | fn test_smkaud() { | |
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_codecs(&mut dec_reg); | |
628 | ||
629 | //let file = "assets/RAD/20130507_audio-distortion.smk"; | |
630 | let file = "assets/RAD/wetlogo.smk"; | |
631 | test_decode_audio("smacker", file, None, "smk", &dmx_reg, &dec_reg); | |
632 | } | |
633 | } |