]>
Commit | Line | Data |
---|---|---|
606c448e | 1 | use nihav_core::codecs::*; |
b83a3961 KS |
2 | use nihav_core::io::byteio::*; |
3 | use nihav_core::io::bitreader::*; | |
4 | use nihav_core::io::codebook::*; | |
b4d5b851 | 5 | use nihav_codec_support::codecs::{IPShuffler, HAMShuffler}; |
b83a3961 | 6 | |
94cebb38 KS |
7 | use super::binkviddata::*; |
8 | ||
b83a3961 KS |
9 | const SKIP_BLOCK: u8 = 0; |
10 | const SCALED_BLOCK: u8 = 1; | |
11 | const MOTION_BLOCK: u8 = 2; | |
12 | const RUN_BLOCK: u8 = 3; | |
13 | const RESIDUE_BLOCK: u8 = 4; | |
14 | const INTRA_BLOCK: u8 = 5; | |
15 | const FILL_BLOCK: u8 = 6; | |
16 | const INTER_BLOCK: u8 = 7; | |
17 | const PATTERN_BLOCK: u8 = 8; | |
18 | const RAW_BLOCK: u8 = 9; | |
19 | ||
20 | #[derive(Default, Clone,Copy)] | |
21 | struct Tree { | |
22 | id: usize, | |
23 | syms: [u8; 16], | |
24 | } | |
25 | ||
26 | impl Tree { | |
3687b8b3 | 27 | #[allow(clippy::collapsible_else_if)] |
b83a3961 KS |
28 | fn read_desc(&mut self, br: &mut BitReader) -> DecoderResult<()> { |
29 | self.id = br.read(4)? as usize; | |
30 | if self.id == 0 { | |
31 | for i in 0..16 { self.syms[i] = i as u8; } | |
32 | } else { | |
33 | if br.read_bool()? { | |
34 | let len = br.read(3)? as usize; | |
35 | let mut present: [bool; 16] = [false; 16]; | |
7e6086e5 | 36 | for i in 0..=len { |
b83a3961 KS |
37 | self.syms[i] = br.read(4)? as u8; |
38 | present[self.syms[i] as usize] = true; | |
39 | } | |
40 | let mut idx = len + 1; | |
3687b8b3 KS |
41 | for (i, &present) in present.iter().enumerate() { |
42 | if present { continue; } | |
b83a3961 KS |
43 | self.syms[idx] = i as u8; |
44 | idx += 1; | |
45 | } | |
46 | } else { | |
47 | let len = br.read(2)? as usize; | |
48 | let mut syms: [u8; 16] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; | |
49 | let mut tmp: [u8; 16] = [0; 16]; | |
7e6086e5 | 50 | for bits in 0..=len { |
b83a3961 KS |
51 | let size = 1 << bits; |
52 | for arr in syms.chunks_mut(size * 2) { | |
53 | let mut ptr0 = 0; | |
54 | let mut ptr1 = size; | |
55 | let mut optr = 0; | |
56 | while (ptr0 < size) && (ptr1 < size * 2) { | |
57 | if !br.read_bool()? { | |
58 | tmp[optr] = arr[ptr0]; | |
59 | ptr0 += 1; | |
60 | } else { | |
61 | tmp[optr] = arr[ptr1]; | |
62 | ptr1 += 1; | |
63 | } | |
64 | optr += 1; | |
65 | } | |
66 | while ptr0 < size { | |
67 | tmp[optr] = arr[ptr0]; | |
68 | ptr0 += 1; | |
69 | optr += 1; | |
70 | } | |
71 | while ptr1 < size * 2 { | |
72 | tmp[optr] = arr[ptr1]; | |
73 | ptr1 += 1; | |
74 | optr += 1; | |
75 | } | |
76 | arr.copy_from_slice(&tmp[0..size * 2]); | |
77 | } | |
78 | } | |
79 | self.syms = syms; | |
80 | } | |
81 | } | |
82 | Ok(()) | |
83 | } | |
84 | fn read_sym(&self, br: &mut BitReader, trees: &BinkTrees) -> DecoderResult<u8> { | |
85 | let idx = br.read_cb(&trees.cb[self.id])?; | |
86 | Ok(self.syms[idx as usize]) | |
87 | } | |
88 | } | |
89 | ||
90 | #[derive(Default)] | |
91 | struct Bundle<T: Copy> { | |
92 | tree: Tree, | |
93 | data: Vec<T>, | |
94 | dec_pos: usize, | |
95 | read_pos: usize, | |
96 | bits: u8, | |
97 | } | |
98 | ||
99 | impl<T:Copy> Bundle<T> { | |
100 | fn binkb_reset(&mut self, bits: u8) { | |
101 | self.bits = bits; | |
102 | self.dec_pos = 0; | |
103 | self.read_pos = 0; | |
104 | } | |
105 | fn reset(&mut self) { | |
106 | self.dec_pos = 0; | |
107 | self.read_pos = 0; | |
108 | } | |
109 | fn read_desc(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
110 | self.dec_pos = 0; | |
111 | self.read_pos = 0; | |
112 | self.tree.read_desc(br)?; | |
113 | Ok(()) | |
114 | } | |
115 | fn read_len(&mut self, br: &mut BitReader) -> DecoderResult<usize> { | |
116 | if self.read_pos < self.dec_pos { return Ok(0); } | |
117 | let len = br.read(self.bits)? as usize; | |
118 | if len == 0 { | |
119 | self.dec_pos = self.data.len(); | |
120 | self.read_pos = self.data.len() - 1; | |
121 | } | |
122 | Ok(len) | |
123 | } | |
124 | fn read_len_binkb(&mut self, br: &mut BitReader) -> DecoderResult<usize> { | |
125 | if self.read_pos < self.dec_pos { return Ok(0); } | |
126 | let len = br.read(13)? as usize; | |
127 | if len == 0 { | |
128 | self.dec_pos = self.data.len(); | |
129 | self.read_pos = self.data.len() - 1; | |
130 | } | |
b83a3961 KS |
131 | Ok(len) |
132 | } | |
133 | fn get_val(&mut self) -> DecoderResult<T> { | |
134 | validate!(self.read_pos < self.dec_pos); | |
135 | let val = self.data[self.read_pos]; | |
136 | self.read_pos += 1; | |
137 | Ok(val) | |
138 | } | |
139 | } | |
140 | ||
141 | const BLOCK_TYPE_RUNS: [usize; 4] = [ 4, 8, 12, 32 ]; | |
142 | impl Bundle<u8> { | |
143 | fn read_binkb(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
144 | let len = self.read_len_binkb(br)?; | |
145 | if len == 0 { return Ok(()); } | |
146 | let end = self.dec_pos + len; | |
147 | validate!(end <= self.data.len()); | |
148 | for i in 0..len { | |
149 | self.data[self.dec_pos + i] = br.read(self.bits)? as u8; | |
150 | } | |
151 | self.dec_pos += len; | |
152 | Ok(()) | |
153 | } | |
154 | fn read_runs(&mut self, br: &mut BitReader, trees: &BinkTrees) -> DecoderResult<()> { | |
155 | let len = self.read_len(br)?; | |
156 | if len == 0 { return Ok(()); } | |
157 | let end = self.dec_pos + len; | |
158 | validate!(end <= self.data.len()); | |
159 | if br.read_bool()? { | |
160 | let val = br.read(4)? as u8; | |
161 | for i in 0..len { self.data[self.dec_pos + i] = val; } | |
162 | self.dec_pos += len; | |
163 | } else { | |
164 | while self.dec_pos < end { | |
165 | self.data[self.dec_pos] = self.tree.read_sym(br, trees)?; | |
166 | self.dec_pos += 1; | |
167 | } | |
168 | } | |
169 | Ok(()) | |
170 | } | |
171 | fn read_block_types(&mut self, br: &mut BitReader, trees: &BinkTrees) -> DecoderResult<()> { | |
172 | let len = self.read_len(br)?; | |
173 | if len == 0 { return Ok(()); } | |
174 | let end = self.dec_pos + len; | |
175 | validate!(end <= self.data.len()); | |
176 | if br.read_bool()? { | |
177 | let val = br.read(4)? as u8; | |
178 | for i in 0..len { self.data[self.dec_pos + i] = val; } | |
179 | self.dec_pos += len; | |
180 | } else { | |
181 | let mut last = 0; | |
182 | while self.dec_pos < end { | |
183 | let val = self.tree.read_sym(br, trees)?; | |
184 | if val < 12 { | |
185 | self.data[self.dec_pos] = val; | |
186 | self.dec_pos += 1; | |
187 | last = val; | |
188 | } else { | |
189 | let run = BLOCK_TYPE_RUNS[(val - 12) as usize]; | |
190 | validate!(self.dec_pos + run <= end); | |
191 | for i in 0..run { | |
192 | self.data[self.dec_pos + i] = last; | |
193 | } | |
194 | self.dec_pos += run; | |
195 | } | |
196 | } | |
197 | } | |
198 | Ok(()) | |
199 | } | |
200 | fn read_patterns(&mut self, br: &mut BitReader, trees: &BinkTrees) -> DecoderResult<()> { | |
201 | let len = self.read_len(br)?; | |
202 | if len == 0 { return Ok(()); } | |
203 | let end = self.dec_pos + len; | |
204 | validate!(end <= self.data.len()); | |
205 | for i in 0..len { | |
206 | let pat_lo = self.tree.read_sym(br, trees)?; | |
207 | let pat_hi = self.tree.read_sym(br, trees)?; | |
208 | self.data[self.dec_pos + i] = pat_lo | (pat_hi << 4); | |
209 | } | |
210 | self.dec_pos += len; | |
211 | Ok(()) | |
212 | } | |
213 | fn cvt_color(lo: u8, hi: u8, new_bink: bool) -> u8 { | |
214 | let val = lo | (hi << 4); | |
215 | if !new_bink { | |
216 | let sign = ((val as i8) >> 7) as u8; | |
217 | ((val & 0x7F) ^ sign).wrapping_sub(sign) ^ 0x80 | |
218 | } else { | |
219 | val | |
220 | } | |
221 | } | |
222 | fn read_colors(&mut self, br: &mut BitReader, trees: &BinkTrees, col_hi: &[Tree; 16], col_last: &mut u8, new_bink: bool) -> DecoderResult<()> { | |
223 | let len = self.read_len(br)?; | |
224 | if len == 0 { return Ok(()); } | |
225 | let end = self.dec_pos + len; | |
226 | validate!(end <= self.data.len()); | |
227 | let mut last = *col_last; | |
228 | if br.read_bool()? { | |
229 | last = col_hi[last as usize].read_sym(br, trees)?; | |
230 | let lo = self.tree.read_sym(br, trees)?; | |
231 | let val = Self::cvt_color(lo, last, new_bink); | |
e6aaad5c | 232 | for i in 0..len { self.data[self.dec_pos + i] = val; } |
b83a3961 KS |
233 | self.dec_pos += len; |
234 | } else { | |
235 | while self.dec_pos < end { | |
236 | last = col_hi[last as usize].read_sym(br, trees)?; | |
237 | let lo = self.tree.read_sym(br, trees)?; | |
238 | let val = Self::cvt_color(lo, last, new_bink); | |
239 | self.data[self.dec_pos] = val; | |
240 | self.dec_pos += 1; | |
241 | } | |
242 | } | |
243 | *col_last = last; | |
244 | Ok(()) | |
245 | } | |
246 | } | |
247 | ||
248 | impl Bundle<i8> { | |
249 | fn read_binkb(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
250 | let len = self.read_len_binkb(br)?; | |
251 | if len == 0 { return Ok(()); } | |
252 | let end = self.dec_pos + len; | |
253 | validate!(end <= self.data.len()); | |
254 | let bias = 1 << (self.bits - 1); | |
255 | for i in 0..len { | |
256 | self.data[self.dec_pos + i] = (br.read(self.bits)? as i8) - bias; | |
257 | } | |
258 | self.dec_pos += len; | |
259 | Ok(()) | |
260 | } | |
261 | fn read_motion_values(&mut self, br: &mut BitReader, trees: &BinkTrees) -> DecoderResult<()> { | |
262 | let len = self.read_len(br)?; | |
263 | if len == 0 { return Ok(()); } | |
264 | let end = self.dec_pos + len; | |
265 | validate!(end <= self.data.len()); | |
266 | if br.read_bool()? { | |
267 | let mut val = br.read(4)? as i8; | |
268 | if val != 0 && br.read_bool()? { val = -val; } | |
269 | for i in 0..len { self.data[self.dec_pos + i] = val; } | |
270 | self.dec_pos += len; | |
271 | } else { | |
272 | while self.dec_pos < end { | |
273 | self.data[self.dec_pos] = self.tree.read_sym(br, trees)? as i8; | |
274 | if self.data[self.dec_pos] != 0 && br.read_bool()? { | |
275 | self.data[self.dec_pos] = -self.data[self.dec_pos]; | |
276 | } | |
277 | self.dec_pos += 1; | |
278 | } | |
279 | } | |
280 | Ok(()) | |
281 | } | |
282 | } | |
283 | ||
284 | const DC_START_BITS: u8 = 11; | |
285 | impl Bundle<u16> { | |
286 | fn read_binkb(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
287 | let len = self.read_len_binkb(br)?; | |
288 | if len == 0 { return Ok(()); } | |
289 | let end = self.dec_pos + len; | |
290 | validate!(end <= self.data.len()); | |
291 | for i in 0..len { | |
292 | self.data[self.dec_pos + i] = br.read(self.bits)? as u16; | |
293 | } | |
294 | self.dec_pos += len; | |
295 | Ok(()) | |
296 | } | |
297 | fn read_dcs(&mut self, br: &mut BitReader, start_bits: u8) -> DecoderResult<()> { | |
298 | let len = self.read_len(br)?; | |
299 | if len == 0 { return Ok(()); } | |
300 | let end = self.dec_pos + len; | |
301 | validate!(end <= self.data.len()); | |
302 | let mut val = br.read(start_bits)? as u16; | |
303 | self.data[self.dec_pos] = val; | |
304 | self.dec_pos += 1; | |
305 | for i in (1..len).step_by(8) { | |
306 | let seg_len = (len - i).min(8); | |
307 | let bits = br.read(4)? as u8; | |
308 | if bits != 0 { | |
309 | for _ in 0..seg_len { | |
310 | let diff = br.read(bits)? as u16; | |
311 | let res = if diff != 0 && br.read_bool()? { | |
312 | val.checked_sub(diff) | |
313 | } else { | |
314 | val.checked_add(diff) | |
315 | }; | |
316 | validate!(res.is_some()); | |
317 | val = res.unwrap(); | |
318 | self.data[self.dec_pos] = val; | |
319 | self.dec_pos += 1; | |
320 | } | |
321 | } else { | |
322 | for _ in 0..seg_len { | |
323 | self.data[self.dec_pos] = val; | |
324 | self.dec_pos += 1; | |
325 | } | |
326 | } | |
327 | } | |
328 | Ok(()) | |
329 | } | |
330 | } | |
331 | ||
332 | impl Bundle<i16> { | |
333 | fn read_binkb(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
334 | let len = self.read_len_binkb(br)?; | |
335 | if len == 0 { return Ok(()); } | |
336 | let end = self.dec_pos + len; | |
337 | validate!(end <= self.data.len()); | |
338 | let bias = 1 << (self.bits - 1); | |
339 | for i in 0..len { | |
340 | self.data[self.dec_pos + i] = (br.read(self.bits)? as i16) - bias; | |
341 | } | |
342 | self.dec_pos += len; | |
343 | Ok(()) | |
344 | } | |
345 | fn read_dcs(&mut self, br: &mut BitReader, start_bits: u8) -> DecoderResult<()> { | |
346 | let len = self.read_len(br)?; | |
347 | if len == 0 { return Ok(()); } | |
348 | let end = self.dec_pos + len; | |
349 | validate!(end <= self.data.len()); | |
350 | let mut val = br.read(start_bits - 1)? as i16; | |
351 | if val != 0 && br.read_bool()? { | |
352 | val = -val; | |
353 | } | |
354 | self.data[self.dec_pos] = val; | |
355 | self.dec_pos += 1; | |
356 | for i in (1..len).step_by(8) { | |
357 | let seg_len = (len - i).min(8); | |
358 | let bits = br.read(4)? as u8; | |
359 | if bits != 0 { | |
360 | for _ in 0..seg_len { | |
361 | let mut diff = br.read(bits)? as i16; | |
362 | if diff != 0 && br.read_bool()? { | |
363 | diff = -diff; | |
364 | } | |
365 | let res = val.checked_add(diff); | |
366 | validate!(res.is_some()); | |
367 | val = res.unwrap(); | |
368 | self.data[self.dec_pos] = val; | |
369 | self.dec_pos += 1; | |
370 | } | |
371 | } else { | |
372 | for _ in 0..seg_len { | |
373 | self.data[self.dec_pos] = val; | |
374 | self.dec_pos += 1; | |
375 | } | |
376 | } | |
377 | } | |
378 | Ok(()) | |
379 | } | |
380 | } | |
381 | ||
382 | struct BinkTrees { | |
383 | cb: [Codebook<u8>; 16], | |
384 | } | |
385 | ||
b83a3961 KS |
386 | impl Default for BinkTrees { |
387 | fn default() -> Self { | |
fd8666bc KS |
388 | let cb = unsafe { |
389 | let mut ucb: std::mem::MaybeUninit::<[Codebook<u8>; 16]> = std::mem::MaybeUninit::uninit(); | |
390 | for i in 0..16 { | |
635e4170 | 391 | let mut cr = TableCodebookDescReader::new(&BINK_TREE_CODES[i], &BINK_TREE_BITS[i], |idx| idx as u8); |
fd8666bc KS |
392 | std::ptr::write(&mut (*ucb.as_mut_ptr())[i], Codebook::new(&mut cr, CodebookMode::LSB).unwrap()); |
393 | } | |
394 | ucb.assume_init() | |
395 | }; | |
b83a3961 KS |
396 | Self { cb } |
397 | } | |
398 | } | |
399 | ||
400 | const A1: i32 = 2896; | |
401 | const A2: i32 = 2217; | |
402 | const A3: i32 = 3784; | |
403 | const A4: i32 = -5352; | |
404 | ||
405 | macro_rules! idct { | |
406 | ($src: expr, $sstep: expr, $dst: expr, $dstep: expr, $off: expr, $bias: expr, $shift: expr) => { | |
407 | let a0 = $src[$off + 0 * $sstep] + $src[$off + 4 * $sstep]; | |
408 | let a1 = $src[$off + 0 * $sstep] - $src[$off + 4 * $sstep]; | |
409 | let a2 = $src[$off + 2 * $sstep] + $src[$off + 6 * $sstep]; | |
410 | let a3 = A1.wrapping_mul($src[$off + 2 * $sstep] - $src[$off + 6 * $sstep]) >> 11; | |
411 | let a4 = $src[$off + 5 * $sstep] + $src[$off + 3 * $sstep]; | |
412 | let a5 = $src[$off + 5 * $sstep] - $src[$off + 3 * $sstep]; | |
413 | let a6 = $src[$off + 1 * $sstep] + $src[$off + 7 * $sstep]; | |
414 | let a7 = $src[$off + 1 * $sstep] - $src[$off + 7 * $sstep]; | |
415 | let b0 = a4 + a6; | |
416 | let b1 = A3.wrapping_mul(a5 + a7) >> 11; | |
417 | let b2 = (A4.wrapping_mul(a5) >> 11) - b0 + b1; | |
418 | let b3 = (A1.wrapping_mul(a6 - a4) >> 11) - b2; | |
419 | let b4 = (A2.wrapping_mul(a7) >> 11) + b3 - b1; | |
420 | let c0 = a0 + a2; | |
421 | let c1 = a0 - a2; | |
422 | let c2 = a1 + (a3 - a2); | |
423 | let c3 = a1 - (a3 - a2); | |
424 | ||
425 | $dst[$off + 0 * $dstep] = (c0 + b0 + $bias) >> $shift; | |
426 | $dst[$off + 1 * $dstep] = (c2 + b2 + $bias) >> $shift; | |
427 | $dst[$off + 2 * $dstep] = (c3 + b3 + $bias) >> $shift; | |
428 | $dst[$off + 3 * $dstep] = (c1 - b4 + $bias) >> $shift; | |
429 | $dst[$off + 4 * $dstep] = (c1 + b4 + $bias) >> $shift; | |
430 | $dst[$off + 5 * $dstep] = (c3 - b3 + $bias) >> $shift; | |
431 | $dst[$off + 6 * $dstep] = (c2 - b2 + $bias) >> $shift; | |
432 | $dst[$off + 7 * $dstep] = (c0 - b0 + $bias) >> $shift; | |
433 | }; | |
434 | } | |
435 | ||
b83a3961 KS |
436 | #[derive(Default)] |
437 | struct BinkDecoder { | |
2422d969 | 438 | info: NACodecInfoRef, |
b83a3961 | 439 | ips: IPShuffler, |
8d7a1c5c | 440 | hams: HAMShuffler<u8>, |
b83a3961 KS |
441 | |
442 | is_ver_b: bool, | |
443 | is_ver_i: bool, | |
444 | has_alpha: bool, | |
445 | is_gray: bool, | |
446 | swap_uv: bool, | |
447 | key_frame: bool, | |
448 | ||
449 | cur_w: usize, | |
450 | cur_h: usize, | |
451 | cur_plane: usize, | |
452 | ||
453 | colhi_tree: [Tree; 16], | |
454 | col_last: u8, | |
455 | ||
456 | btype: Bundle<u8>, | |
457 | sbtype: Bundle<u8>, | |
458 | colors: Bundle<u8>, | |
459 | pattern: Bundle<u8>, | |
460 | xoff: Bundle<i8>, | |
461 | yoff: Bundle<i8>, | |
462 | intradc: Bundle<u16>, | |
463 | interdc: Bundle<i16>, | |
464 | intraq: Bundle<u8>, | |
465 | interq: Bundle<u8>, | |
466 | nresidues: Bundle<u8>, | |
467 | run: Bundle<u8>, | |
468 | ||
469 | trees: BinkTrees, | |
470 | ||
471 | qmat_b: QuantMats, | |
472 | } | |
473 | ||
474 | fn calc_len(size: usize) -> u8 { | |
475 | (32 - ((size + 511) as u32).leading_zeros()) as u8 | |
476 | } | |
477 | ||
3687b8b3 | 478 | #[allow(clippy::too_many_arguments)] |
b83a3961 KS |
479 | impl BinkDecoder { |
480 | fn new() -> Self { | |
481 | Self::default() | |
482 | } | |
483 | fn init_bundle_bufs(&mut self, bw: usize, bh: usize) { | |
484 | let size = bw * bh * 64; | |
485 | self.btype.data.resize(size, 0); | |
486 | self.sbtype.data.resize(size, 0); | |
487 | self.colors.data.resize(size, 0); | |
488 | self.pattern.data.resize(size, 0); | |
489 | self.xoff.data.resize(size, 0); | |
490 | self.yoff.data.resize(size, 0); | |
491 | self.intradc.data.resize(size, 0); | |
492 | self.interdc.data.resize(size, 0); | |
493 | self.intraq.data.resize(size, 0); | |
494 | self.interq.data.resize(size, 0); | |
495 | self.nresidues.data.resize(size, 0); | |
496 | self.run.data.resize(size, 0); | |
497 | } | |
498 | fn init_bundle_lengths(&mut self, w: usize, bw: usize) { | |
4e376911 | 499 | let w = (w + 7) & !7; |
b83a3961 KS |
500 | self.btype.bits = calc_len(w >> 3); |
501 | self.sbtype.bits = calc_len(w >> 4); | |
502 | self.colors.bits = calc_len(bw * 64); | |
503 | self.pattern.bits = calc_len(bw * 8); | |
504 | self.xoff.bits = calc_len(w >> 3); | |
505 | self.yoff.bits = calc_len(w >> 3); | |
506 | self.intradc.bits = calc_len(w >> 3); | |
507 | self.interdc.bits = calc_len(w >> 3); | |
508 | self.run.bits = calc_len(bw * 48); | |
509 | } | |
510 | fn init_bundle_lengths_binkb(&mut self) { | |
511 | self.btype.binkb_reset(4); | |
512 | self.colors.binkb_reset(8); | |
513 | self.pattern.binkb_reset(8); | |
514 | self.xoff.binkb_reset(5); | |
515 | self.yoff.binkb_reset(5); | |
516 | self.intradc.binkb_reset(11); | |
517 | self.interdc.binkb_reset(11); | |
518 | self.intraq.binkb_reset(4); | |
519 | self.interq.binkb_reset(4); | |
520 | self.nresidues.binkb_reset(7); | |
521 | } | |
522 | fn read_bundles_desc(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
523 | self.btype.read_desc(br)?; | |
524 | self.sbtype.read_desc(br)?; | |
525 | for el in &mut self.colhi_tree { | |
526 | el.read_desc(br)?; | |
527 | } | |
528 | self.col_last = 0; | |
529 | self.colors.read_desc(br)?; | |
530 | self.pattern.read_desc(br)?; | |
531 | self.xoff.read_desc(br)?; | |
532 | self.yoff.read_desc(br)?; | |
533 | self.intradc.reset(); | |
534 | self.interdc.reset(); | |
535 | self.run.read_desc(br)?; | |
536 | Ok(()) | |
537 | } | |
538 | fn read_bundles_binkb(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
539 | self.btype.read_binkb(br)?; | |
b83a3961 | 540 | self.colors.read_binkb(br)?; |
b83a3961 | 541 | self.pattern.read_binkb(br)?; |
b83a3961 | 542 | self.xoff.read_binkb(br)?; |
b83a3961 | 543 | self.yoff.read_binkb(br)?; |
b83a3961 | 544 | self.intradc.read_binkb(br)?; |
b83a3961 | 545 | self.interdc.read_binkb(br)?; |
b83a3961 | 546 | self.intraq.read_binkb(br)?; |
b83a3961 | 547 | self.interq.read_binkb(br)?; |
b83a3961 | 548 | self.nresidues.read_binkb(br)?; |
b83a3961 KS |
549 | Ok(()) |
550 | } | |
551 | fn read_bundles(&mut self, br: &mut BitReader) -> DecoderResult<()> { | |
552 | self.btype.read_block_types(br, &self.trees)?; | |
553 | self.sbtype.read_block_types(br, &self.trees)?; | |
554 | self.colors.read_colors(br, &self.trees, &self.colhi_tree, &mut self.col_last, self.is_ver_i)?; | |
555 | self.pattern.read_patterns(br, &self.trees)?; | |
556 | self.xoff.read_motion_values(br, &self.trees)?; | |
557 | self.yoff.read_motion_values(br, &self.trees)?; | |
558 | self.intradc.read_dcs(br, DC_START_BITS)?; | |
559 | self.interdc.read_dcs(br, DC_START_BITS)?; | |
560 | self.run.read_runs(br, &self.trees)?; | |
561 | Ok(()) | |
562 | } | |
563 | ||
3687b8b3 | 564 | fn put_block(&self, block: &[u8; 64], dst: &mut [u8], off: usize, stride: usize, scaled: bool) { |
b83a3961 | 565 | if !scaled { |
3687b8b3 KS |
566 | for (src, dline) in block.chunks_exact(8).zip(dst[off..].chunks_mut(stride)) { |
567 | dline[..8].copy_from_slice(src); | |
b83a3961 KS |
568 | } |
569 | } else { | |
3687b8b3 KS |
570 | for (src, dlines) in block.chunks_exact(8).zip(dst[off..].chunks_mut(stride * 2)) { |
571 | let (dline0, dline1) = dlines.split_at_mut(stride); | |
572 | for (pair, &pix) in dline0.chunks_exact_mut(2).zip(src[..8].iter()) { | |
573 | pair[0] = pix; | |
574 | pair[1] = pix; | |
b83a3961 | 575 | } |
3687b8b3 KS |
576 | for (pair, &pix) in dline1.chunks_exact_mut(2).zip(src[..8].iter()) { |
577 | pair[0] = pix; | |
578 | pair[1] = pix; | |
b83a3961 | 579 | } |
b83a3961 KS |
580 | } |
581 | } | |
582 | } | |
583 | fn copy_block(&mut self, dst: &mut [u8], mut off: usize, stride: usize, bx: usize, by: usize, xoff: i8, yoff: i8) -> DecoderResult<()> { | |
584 | if let Some(prev_buf) = self.ips.get_ref() { | |
585 | let xoff = ((bx * 8) as isize) + (xoff as isize); | |
586 | let yoff = ((by * 8) as isize) + (yoff as isize); | |
587 | validate!((xoff >= 0) && (xoff + 8 <= (self.cur_w as isize))); | |
588 | validate!((yoff >= 0) && (yoff + 8 <= (self.cur_h as isize))); | |
589 | let pstride = prev_buf.get_stride(self.cur_plane); | |
590 | let mut poff = prev_buf.get_offset(self.cur_plane) + (xoff as usize) + (yoff as usize) * pstride; | |
591 | let pdata = prev_buf.get_data(); | |
592 | let ppix = pdata.as_slice(); | |
593 | for _ in 0..8 { | |
594 | let src = &ppix[poff..][..8]; | |
595 | let out = &mut dst[off..][..8]; | |
596 | out.copy_from_slice(src); | |
597 | off += stride; | |
598 | poff += pstride; | |
599 | } | |
600 | Ok(()) | |
601 | } else { | |
602 | Err(DecoderError::MissingReference) | |
603 | } | |
604 | } | |
605 | fn copy_overlapped(&mut self, dst: &mut [u8], mut off: usize, stride: usize, bx: usize, by: usize, xoff: i8, yoff1: i8) -> DecoderResult<()> { | |
606 | let ybias = if self.key_frame { -15 } else { 0 }; | |
607 | let yoff = yoff1 + ybias; | |
608 | ||
b83a3961 KS |
609 | let xpos = ((bx * 8) as isize) + (xoff as isize); |
610 | let ypos = ((by * 8) as isize) + (yoff as isize); | |
611 | validate!((xpos >= 0) && (xpos + 8 <= (self.cur_w as isize))); | |
612 | validate!((ypos >= 0) && (ypos + 8 <= (self.cur_h as isize))); | |
613 | ||
614 | let mut block: [u8; 64] = [0; 64]; | |
615 | let mut ref_off = ((off as isize) + (xoff as isize) + (yoff as isize) * (stride as isize)) as usize; | |
616 | for row in block.chunks_exact_mut(8) { | |
617 | row.copy_from_slice(&dst[ref_off..][..8]); | |
618 | ref_off += stride; | |
619 | } | |
620 | for row in block.chunks_exact(8) { | |
621 | let out = &mut dst[off..][..8]; | |
622 | out.copy_from_slice(row); | |
623 | off += stride; | |
624 | } | |
625 | ||
626 | Ok(()) | |
627 | } | |
628 | fn add_block(&self, coeffs: &[i32; 64], dst: &mut [u8], mut off: usize, stride: usize) { | |
629 | for src in coeffs.chunks_exact(8) { | |
630 | for i in 0..8 { | |
631 | let v = (dst[off + i] as i32) + src[i]; | |
632 | dst[off + i] = v as u8; | |
633 | } | |
634 | off += stride; | |
635 | } | |
636 | } | |
637 | fn idct_put(&self, coeffs: &[i32; 64], dst: &mut [u8], mut off: usize, stride: usize) { | |
638 | let mut tmp: [i32; 64] = [0; 64]; | |
639 | let mut row: [i32; 8] = [0; 8]; | |
640 | for i in 0..8 { | |
641 | idct!(coeffs, 8, tmp, 8, i, 0, 0); | |
642 | } | |
643 | for srow in tmp.chunks_exact(8) { | |
644 | idct!(srow, 1, row, 1, 0, 0x7F, 8); | |
645 | for i in 0..8 { | |
646 | dst[off + i] = row[i] as u8; | |
647 | } | |
648 | off += stride; | |
649 | } | |
650 | } | |
651 | fn idct_add(&self, coeffs: &[i32; 64], dst: &mut [u8], mut off: usize, stride: usize) { | |
652 | let mut tmp: [i32; 64] = [0; 64]; | |
653 | let mut row: [i32; 8] = [0; 8]; | |
654 | for i in 0..8 { | |
655 | idct!(coeffs, 8, tmp, 8, i, 0, 0); | |
656 | } | |
657 | for srow in tmp.chunks_exact(8) { | |
658 | idct!(srow, 1, row, 1, 0, 0x7F, 8); | |
659 | for i in 0..8 { | |
660 | let v = (dst[off + i] as i32) + row[i]; | |
661 | dst[off + i] = v as u8; | |
662 | } | |
663 | off += stride; | |
664 | } | |
665 | } | |
666 | ||
667 | fn decode_plane_binkb(&mut self, br: &mut BitReader, plane_no: usize, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<()> { | |
668 | let stride = buf.get_stride(plane_no); | |
669 | let mut off = buf.get_offset(plane_no); | |
670 | let (width, height) = buf.get_dimensions(plane_no); | |
1a967e6b | 671 | let data = buf.get_data_mut().unwrap(); |
b83a3961 KS |
672 | let dst = data.as_mut_slice(); |
673 | let bw = (width + 7) >> 3; | |
674 | let bh = (height + 7) >> 3; | |
675 | self.cur_w = (width + 7) & !7; | |
676 | self.cur_h = (height + 7) & !7; | |
677 | self.cur_plane = plane_no; | |
678 | self.init_bundle_lengths_binkb(); | |
b83a3961 KS |
679 | for by in 0..bh { |
680 | self.read_bundles_binkb(br)?; | |
b83a3961 KS |
681 | for bx in 0..bw { |
682 | let mut coeffs: [i32; 64] = [0; 64]; | |
683 | let btype = self.btype.get_val()?; | |
b83a3961 KS |
684 | match btype { |
685 | 0 => { // skip | |
686 | }, | |
687 | 1 => { // run | |
688 | let scan = BINK_PATTERNS[br.read(4)? as usize]; | |
689 | let mut idx = 0; | |
690 | while idx < 63 { | |
691 | let run = br.read_bool()?; | |
692 | let len = (br.read(BINKB_RUN_BITS[idx])? as usize) + 1; | |
693 | validate!(idx + len <= 64); | |
694 | if run { | |
695 | let val = self.colors.get_val()?; | |
696 | for j in 0..len { | |
697 | let pos = scan[idx + j] as usize; | |
698 | dst[off + (pos >> 3) * stride + (pos & 7)] = val; | |
699 | } | |
700 | idx += len; | |
701 | } else { | |
702 | for _ in 0..len { | |
703 | let pos = scan[idx] as usize; | |
704 | dst[off + (pos >> 3) * stride + (pos & 7)] = self.colors.get_val()?; | |
705 | idx += 1; | |
706 | } | |
707 | } | |
708 | } | |
709 | if idx == 63 { | |
710 | let pos = scan[idx] as usize; | |
711 | dst[off + (pos >> 3) * stride + (pos & 7)] = self.colors.get_val()?; | |
712 | } | |
713 | }, | |
714 | 2 => { // intra | |
715 | coeffs[0] = self.intradc.get_val()? as i32; | |
716 | let q = self.intraq.get_val()? as usize; | |
717 | read_dct_coefficients(br, &mut coeffs, &BINK_SCAN, &self.qmat_b.intra_qmat, Some(q))?; | |
718 | self.idct_put(&coeffs, dst, off, stride); | |
719 | }, | |
720 | 3 => { // residue | |
721 | let xoff = self.xoff.get_val()?; | |
722 | let yoff = self.yoff.get_val()?; | |
723 | self.copy_overlapped(dst, off, stride, bx, by, xoff, yoff)?; | |
724 | let nmasks = self.nresidues.get_val()? as usize; | |
725 | read_residue(br, &mut coeffs, nmasks)?; | |
726 | self.add_block(&coeffs, dst, off, stride); | |
727 | }, | |
728 | 4 => { // inter | |
729 | let xoff = self.xoff.get_val()?; | |
730 | let yoff = self.yoff.get_val()?; | |
731 | self.copy_overlapped(dst, off, stride, bx, by, xoff, yoff)?; | |
732 | coeffs[0] = self.interdc.get_val()? as i32; | |
733 | let q = self.interq.get_val()? as usize; | |
734 | read_dct_coefficients(br, &mut coeffs, &BINK_SCAN, &self.qmat_b.inter_qmat, Some(q))?; | |
735 | self.idct_add(&coeffs, dst, off, stride); | |
736 | }, | |
737 | 5 => { // fill | |
738 | let fill = self.colors.get_val()?; | |
739 | for i in 0..8 { | |
740 | for j in 0..8 { dst[off + i * stride + j] = fill; } | |
741 | } | |
742 | }, | |
743 | 6 => { // pattern | |
744 | let clr: [u8; 2] = [ self.colors.get_val()?, self.colors.get_val()? ]; | |
745 | for i in 0..8 { | |
746 | let pattern = self.pattern.get_val()? as usize; | |
747 | for j in 0..8 { | |
748 | dst[off + i * stride + j] = clr[(pattern >> j) & 1]; | |
749 | } | |
750 | } | |
751 | }, | |
752 | 7 => { // motion block | |
753 | let xoff = self.xoff.get_val()?; | |
754 | let yoff = self.yoff.get_val()?; | |
755 | self.copy_overlapped(dst, off, stride, bx, by, xoff, yoff)?; | |
756 | }, | |
757 | 8 => { // raw | |
758 | for i in 0..8 { | |
759 | for j in 0..8 { | |
760 | dst[off + i * stride + j] = self.colors.get_val()?; | |
761 | } | |
762 | } | |
763 | }, | |
764 | _ => { return Err(DecoderError::InvalidData); }, | |
765 | }; | |
766 | off += 8; | |
767 | } | |
768 | off += stride * 8 - bw * 8; | |
769 | } | |
770 | if (br.tell() & 0x1F) != 0 { | |
771 | let skip = (32 - (br.tell() & 0x1F)) as u32; | |
772 | br.skip(skip)?; | |
773 | } | |
774 | Ok(()) | |
775 | } | |
776 | fn handle_block(&mut self, br: &mut BitReader, bx: usize, by: usize, | |
777 | dst: &mut [u8], off: usize, stride: usize, btype: u8, scaled: bool) -> DecoderResult<()> { | |
778 | let mut oblock: [u8; 64] = [0; 64]; | |
779 | let mut coeffs: [i32; 64] = [0; 64]; | |
780 | match btype { | |
781 | SKIP_BLOCK => { | |
782 | validate!(!scaled); | |
783 | self.copy_block(dst, off, stride, bx, by, 0, 0)?; | |
784 | }, | |
785 | SCALED_BLOCK => { | |
786 | validate!(!scaled); | |
787 | let sbtype = self.sbtype.get_val()?; | |
788 | self.handle_block(br, bx, by, dst, off, stride, sbtype, true)?; | |
789 | }, | |
790 | MOTION_BLOCK => { | |
791 | validate!(!scaled); | |
792 | let xoff = self.xoff.get_val()?; | |
793 | let yoff = self.yoff.get_val()?; | |
794 | self.copy_block(dst, off, stride, bx, by, xoff, yoff)?; | |
795 | }, | |
796 | RUN_BLOCK => { | |
797 | let scan = BINK_PATTERNS[br.read(4)? as usize]; | |
798 | let mut idx = 0; | |
799 | while idx < 63 { | |
800 | let run = (self.run.get_val()? as usize) + 1; | |
801 | validate!(idx + run <= 64); | |
802 | if br.read_bool()? { | |
803 | let val = self.colors.get_val()?; | |
804 | for j in 0..run { | |
805 | oblock[scan[idx + j] as usize] = val; | |
806 | } | |
807 | idx += run; | |
808 | } else { | |
809 | for _ in 0..run { | |
810 | oblock[scan[idx] as usize] = self.colors.get_val()?; | |
811 | idx += 1; | |
812 | } | |
813 | } | |
814 | } | |
815 | if idx == 63 { oblock[scan[63] as usize] = self.colors.get_val()?; } | |
816 | self.put_block(&oblock, dst, off, stride, scaled); | |
817 | }, | |
818 | RESIDUE_BLOCK => { | |
819 | validate!(!scaled); | |
820 | let xoff = self.xoff.get_val()?; | |
821 | let yoff = self.yoff.get_val()?; | |
822 | self.copy_block(dst, off, stride, bx, by, xoff, yoff)?; | |
823 | let nmasks = br.read(7)? as usize; | |
824 | read_residue(br, &mut coeffs, nmasks)?; | |
825 | self.add_block(&coeffs, dst, off, stride); | |
826 | }, | |
827 | INTRA_BLOCK => { | |
828 | coeffs[0] = self.intradc.get_val()? as i32; | |
829 | read_dct_coefficients(br, &mut coeffs, &BINK_SCAN, BINK_INTRA_QUANT, None)?; | |
830 | if !scaled { | |
831 | self.idct_put(&coeffs, dst, off, stride); | |
832 | } else { | |
833 | self.idct_put(&coeffs, &mut oblock, 0, 8); | |
834 | self.put_block(&oblock, dst, off, stride, scaled); | |
835 | } | |
836 | }, | |
837 | FILL_BLOCK => { | |
838 | let fill = self.colors.get_val()?; | |
839 | oblock = [fill; 64]; | |
840 | self.put_block(&oblock, dst, off, stride, scaled); | |
841 | }, | |
842 | INTER_BLOCK => { | |
843 | validate!(!scaled); | |
844 | let xoff = self.xoff.get_val()?; | |
845 | let yoff = self.yoff.get_val()?; | |
846 | self.copy_block(dst, off, stride, bx, by, xoff, yoff)?; | |
847 | coeffs[0] = self.interdc.get_val()? as i32; | |
848 | read_dct_coefficients(br, &mut coeffs, &BINK_SCAN, BINK_INTER_QUANT, None)?; | |
849 | self.idct_add(&coeffs, dst, off, stride); | |
850 | }, | |
851 | PATTERN_BLOCK => { | |
852 | let clr: [u8; 2] = [ self.colors.get_val()?, self.colors.get_val()? ]; | |
853 | for i in 0..8 { | |
854 | let pattern = self.pattern.get_val()? as usize; | |
855 | for j in 0..8 { | |
856 | oblock[i * 8 + j] = clr[(pattern >> j) & 1]; | |
857 | } | |
858 | } | |
859 | self.put_block(&oblock, dst, off, stride, scaled); | |
860 | }, | |
861 | RAW_BLOCK => { | |
862 | for i in 0..8 { | |
863 | for j in 0..8 { | |
864 | oblock[i * 8 + j] = self.colors.get_val()?; | |
865 | } | |
866 | } | |
867 | self.put_block(&oblock, dst, off, stride, scaled); | |
868 | }, | |
869 | _ => { return Err(DecoderError::InvalidData); }, | |
870 | }; | |
871 | Ok(()) | |
872 | } | |
873 | fn decode_plane(&mut self, br: &mut BitReader, plane_no: usize, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<()> { | |
874 | let stride = buf.get_stride(plane_no); | |
875 | let mut off = buf.get_offset(plane_no); | |
876 | let (width, height) = buf.get_dimensions(plane_no); | |
1a967e6b | 877 | let data = buf.get_data_mut().unwrap(); |
b83a3961 KS |
878 | let dst = data.as_mut_slice(); |
879 | let bw = (width + 7) >> 3; | |
880 | let bh = (height + 7) >> 3; | |
881 | self.cur_w = (width + 7) & !7; | |
882 | self.cur_h = (height + 7) & !7; | |
883 | self.cur_plane = plane_no; | |
884 | self.init_bundle_lengths(width.max(8), bw); | |
885 | self.read_bundles_desc(br)?; | |
886 | for by in 0..bh { | |
887 | self.read_bundles(br)?; | |
888 | let mut bx = 0; | |
889 | while bx < bw { | |
890 | let btype = self.btype.get_val()?; | |
891 | if btype == SCALED_BLOCK && (by & 1) == 1 { // already decoded scaled block, skip | |
892 | bx += 2; | |
893 | continue; | |
894 | } | |
895 | self.handle_block(br, bx, by, dst, off + bx * 8, stride, btype, false)?; | |
896 | if btype == SCALED_BLOCK { | |
897 | bx += 1; | |
898 | } | |
899 | bx += 1; | |
900 | } | |
901 | off += stride * 8; | |
902 | } | |
903 | if (br.tell() & 0x1F) != 0 { | |
904 | let skip = (32 - (br.tell() & 0x1F)) as u32; | |
905 | br.skip(skip)?; | |
906 | } | |
907 | Ok(()) | |
908 | } | |
909 | } | |
910 | ||
911 | fn get_coef(br: &mut BitReader, bits1: u8) -> DecoderResult<i32> { | |
912 | let t; | |
913 | if bits1 == 1 { | |
914 | t = if br.read_bool()? { -1 } else { 1 }; | |
915 | } else { | |
916 | let bits = bits1 - 1; | |
917 | let val = (br.read(bits)? as i32) | (1 << bits); | |
918 | if br.read_bool()? { | |
919 | t = -val; | |
920 | } else { | |
921 | t = val; | |
922 | } | |
923 | } | |
924 | Ok(t) | |
925 | } | |
926 | ||
927 | fn read_dct_coefficients(br: &mut BitReader, block: &mut [i32; 64], scan: &[usize; 64], | |
928 | quant_matrices: &[[i32; 64]; 16], q: Option<usize>) -> DecoderResult<()> { | |
929 | let mut coef_list: [i32; 128] = [0; 128]; | |
930 | let mut mode_list: [u8; 128] = [0; 128]; | |
931 | let mut list_start = 64; | |
932 | let mut list_end = 64; | |
933 | let mut coef_idx: [usize; 64] = [0; 64]; | |
934 | let mut coef_count = 0; | |
935 | ||
936 | coef_list[list_end] = 4; mode_list[list_end] = 0; list_end += 1; | |
937 | coef_list[list_end] = 24; mode_list[list_end] = 0; list_end += 1; | |
938 | coef_list[list_end] = 44; mode_list[list_end] = 0; list_end += 1; | |
939 | coef_list[list_end] = 1; mode_list[list_end] = 3; list_end += 1; | |
940 | coef_list[list_end] = 2; mode_list[list_end] = 3; list_end += 1; | |
941 | coef_list[list_end] = 3; mode_list[list_end] = 3; list_end += 1; | |
942 | ||
943 | let mut bits1 = br.read(4)? as u8; | |
944 | while bits1 >= 1 { | |
945 | let mut list_pos = list_start; | |
946 | while list_pos < list_end { | |
947 | let ccoef = coef_list[list_pos]; | |
948 | let mode = mode_list[list_pos]; | |
949 | if (mode == 0 && ccoef == 0) || !br.read_bool()? { | |
950 | list_pos += 1; | |
951 | continue; | |
952 | } | |
953 | match mode { | |
954 | 0 | 2 => { | |
955 | if mode == 0 { | |
956 | coef_list[list_pos] = ccoef + 4; | |
957 | mode_list[list_pos] = 1; | |
958 | } else { | |
959 | coef_list[list_pos] = 0; | |
960 | mode_list[list_pos] = 0; | |
961 | list_pos += 1; | |
962 | } | |
963 | for i in 0..4 { | |
964 | if br.read_bool()? { | |
965 | list_start -= 1; | |
966 | coef_list[list_start] = ccoef + i; | |
967 | mode_list[list_start] = 3; | |
968 | } else { | |
969 | let idx = (ccoef + i) as usize; | |
970 | block[scan[idx]] = get_coef(br, bits1)?; | |
971 | coef_idx[coef_count] = idx; | |
972 | coef_count += 1; | |
973 | } | |
974 | } | |
975 | }, | |
976 | 1 => { | |
977 | mode_list[list_pos] = 2; | |
978 | for i in 0..3 { | |
979 | coef_list[list_end] = ccoef + i * 4 + 4; | |
980 | mode_list[list_end] = 2; | |
981 | list_end += 1; | |
982 | } | |
983 | }, | |
984 | 3 => { | |
985 | let idx = ccoef as usize; | |
986 | block[scan[idx]] = get_coef(br, bits1)?; | |
987 | coef_idx[coef_count] = idx; | |
988 | coef_count += 1; | |
989 | coef_list[list_pos] = 0; | |
990 | mode_list[list_pos] = 0; | |
991 | list_pos += 1; | |
992 | }, | |
993 | _ => unreachable!(), | |
994 | }; | |
995 | } | |
996 | bits1 -= 1; | |
997 | } | |
998 | ||
999 | let q_index = if let Some(qidx) = q { qidx } else { br.read(4)? as usize }; | |
1000 | let qmat = &quant_matrices[q_index]; | |
1001 | block[0] = block[0].wrapping_mul(qmat[0]) >> 11; | |
7e6086e5 | 1002 | for idx in coef_idx.iter().take(coef_count) { |
b83a3961 KS |
1003 | block[scan[*idx]] = block[scan[*idx]].wrapping_mul(qmat[*idx]) >> 11; |
1004 | } | |
1005 | ||
1006 | Ok(()) | |
1007 | } | |
1008 | ||
1009 | fn read_residue(br: &mut BitReader, block: &mut [i32; 64], mut masks_count: usize) -> DecoderResult<()> { | |
1010 | let mut coef_list: [i32; 128] = [0; 128]; | |
1011 | let mut mode_list: [u8; 128] = [0; 128]; | |
1012 | let mut list_start = 64; | |
1013 | let mut list_end = 64; | |
1014 | let mut nz_coef_idx: [usize; 64] = [0; 64]; | |
1015 | let mut nz_coef_count = 0; | |
1016 | ||
1017 | coef_list[list_end] = 4; mode_list[list_end] = 0; list_end += 1; | |
1018 | coef_list[list_end] = 24; mode_list[list_end] = 0; list_end += 1; | |
1019 | coef_list[list_end] = 44; mode_list[list_end] = 0; list_end += 1; | |
1020 | coef_list[list_end] = 0; mode_list[list_end] = 2; list_end += 1; | |
1021 | ||
1022 | let mut mask = 1 << br.read(3)?; | |
1023 | while mask > 0 { | |
3687b8b3 | 1024 | for &idx in nz_coef_idx[..nz_coef_count].iter() { |
b83a3961 | 1025 | if !br.read_bool()? { continue; } |
b83a3961 KS |
1026 | if block[idx] < 0 { |
1027 | block[idx] -= mask; | |
1028 | } else { | |
1029 | block[idx] += mask; | |
1030 | } | |
1031 | if masks_count == 0 { | |
1032 | return Ok(()); | |
1033 | } | |
1034 | masks_count -= 1; | |
1035 | } | |
1036 | let mut list_pos = list_start; | |
1037 | while list_pos < list_end { | |
1038 | let ccoef = coef_list[list_pos]; | |
1039 | let mode = mode_list[list_pos]; | |
1040 | if (mode == 0 && ccoef == 0) || !br.read_bool()? { | |
1041 | list_pos += 1; | |
1042 | continue; | |
1043 | } | |
1044 | match mode { | |
1045 | 0 | 2 => { | |
1046 | if mode == 0 { | |
1047 | coef_list[list_pos] = ccoef + 4; | |
1048 | mode_list[list_pos] = 1; | |
1049 | } else { | |
1050 | coef_list[list_pos] = 0; | |
1051 | mode_list[list_pos] = 0; | |
1052 | list_pos += 1; | |
1053 | } | |
1054 | for i in 0..4 { | |
1055 | if br.read_bool()? { | |
1056 | list_start -= 1; | |
1057 | coef_list[list_start] = ccoef + i; | |
1058 | mode_list[list_start] = 3; | |
1059 | } else { | |
1060 | let idx = (ccoef + i) as usize; | |
1061 | nz_coef_idx[nz_coef_count] = BINK_SCAN[idx]; | |
1062 | nz_coef_count += 1; | |
1063 | block[BINK_SCAN[idx]] = if br.read_bool()? { -mask } else { mask }; | |
1064 | if masks_count == 0 { | |
1065 | return Ok(()); | |
1066 | } | |
1067 | masks_count -= 1; | |
1068 | } | |
1069 | } | |
1070 | }, | |
1071 | 1 => { | |
1072 | mode_list[list_pos] = 2; | |
1073 | for i in 0..3 { | |
1074 | coef_list[list_end] = ccoef + i * 4 + 4; | |
1075 | mode_list[list_end] = 2; | |
1076 | list_end += 1; | |
1077 | } | |
1078 | }, | |
1079 | 3 => { | |
1080 | let idx = ccoef as usize; | |
1081 | nz_coef_idx[nz_coef_count] = BINK_SCAN[idx]; | |
1082 | nz_coef_count += 1; | |
1083 | block[BINK_SCAN[idx]] = if br.read_bool()? { -mask } else { mask }; | |
1084 | coef_list[list_pos] = 0; | |
1085 | mode_list[list_pos] = 0; | |
1086 | list_pos += 1; | |
1087 | if masks_count == 0 { | |
1088 | return Ok(()); | |
1089 | } | |
1090 | masks_count -= 1; | |
1091 | }, | |
1092 | _ => unreachable!(), | |
1093 | }; | |
1094 | } | |
1095 | mask >>= 1; | |
1096 | } | |
d24468d9 | 1097 | |
b83a3961 KS |
1098 | Ok(()) |
1099 | } | |
1100 | ||
1101 | const BINK_FLAG_ALPHA: u32 = 0x00100000; | |
1102 | const BINK_FLAG_GRAY: u32 = 0x00020000; | |
1103 | ||
1104 | impl NADecoder for BinkDecoder { | |
01613464 | 1105 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { |
b83a3961 KS |
1106 | if let NACodecTypeInfo::Video(vinfo) = info.get_properties() { |
1107 | let w = vinfo.get_width(); | |
1108 | let h = vinfo.get_height(); | |
1109 | ||
1110 | let edata = info.get_extradata().unwrap(); | |
1111 | validate!(edata.len() >= 8); | |
1112 | ||
1113 | let mut mr = MemoryReader::new_read(&edata); | |
1114 | let mut br = ByteReader::new(&mut mr); | |
1115 | let magic = br.read_u32be()?; | |
1116 | let flags = br.read_u32le()?; | |
1117 | ||
1118 | self.is_ver_b = (magic & 0xFF) == (b'b' as u32); | |
1119 | self.is_ver_i = (magic & 0xFF) >= (b'i' as u32); | |
1120 | self.has_alpha = (flags & BINK_FLAG_ALPHA) != 0; | |
1121 | self.is_gray = (flags & BINK_FLAG_GRAY) != 0; | |
1122 | self.swap_uv = (magic & 0xFF) >= (b'h' as u32); | |
1123 | if self.has_alpha && self.is_gray { return Err(DecoderError::NotImplemented); } | |
1124 | ||
1125 | let aplane = if self.has_alpha { Some(NAPixelChromaton::new(0, 0, false, 8, 0, 3, 1)) } else { None }; | |
3687b8b3 KS |
1126 | let fmt = if !self.is_gray { |
1127 | NAPixelFormaton::new(ColorModel::YUV(YUVSubmodel::YUVJ), | |
1128 | Some(NAPixelChromaton::new(0, 0, false, 8, 0, 0, 1)), | |
1129 | Some(NAPixelChromaton::new(1, 1, false, 8, 0, 1, 1)), | |
1130 | Some(NAPixelChromaton::new(1, 1, false, 8, 0, 2, 1)), | |
1131 | aplane, None, | |
1132 | 0, if self.has_alpha { 4 } else { 3 } ) | |
1133 | } else { | |
1134 | NAPixelFormaton::new(ColorModel::YUV(YUVSubmodel::YUVJ), | |
1135 | Some(NAPixelChromaton::new(0, 0, false, 8, 0, 0, 1)), | |
1136 | None, None, None, None, 0, 1) | |
1137 | }; | |
b83a3961 | 1138 | let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt)); |
2422d969 | 1139 | self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref(); |
b83a3961 KS |
1140 | |
1141 | //self.init_bundle_lengths(w.max(8), (w + 7) >> 3); | |
1142 | self.init_bundle_bufs((w + 7) >> 3, (h + 7) >> 3); | |
1143 | ||
1144 | if self.is_ver_b { | |
1145 | self.qmat_b.calc_binkb_quants(); | |
1146 | } | |
1147 | ||
1148 | Ok(()) | |
1149 | } else { | |
1150 | Err(DecoderError::InvalidData) | |
1151 | } | |
1152 | } | |
01613464 | 1153 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { |
b83a3961 KS |
1154 | let src = pkt.get_buffer(); |
1155 | ||
fa90ccfb | 1156 | let mut br = BitReader::new(&src, BitReaderMode::LE); |
b83a3961 KS |
1157 | |
1158 | let mut buf; | |
1159 | self.key_frame = pkt.is_keyframe(); | |
1160 | if self.is_ver_b { | |
1161 | let bufret = self.hams.clone_ref(); | |
1162 | if let Some(bbuf) = bufret { | |
1163 | buf = bbuf; | |
1164 | } else { | |
7e6086e5 | 1165 | let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?; |
b83a3961 KS |
1166 | buf = bufinfo.get_vbuf().unwrap(); |
1167 | self.key_frame = true; | |
1168 | self.hams.add_frame(buf); | |
1169 | buf = self.hams.get_output_frame().unwrap(); | |
1170 | } | |
1171 | } else { | |
7e6086e5 | 1172 | let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?; |
b83a3961 KS |
1173 | buf = bufinfo.get_vbuf().unwrap(); |
1174 | } | |
1175 | ||
b83a3961 KS |
1176 | let nplanes = if self.is_gray { 1 } else { 3 }; |
1177 | if self.has_alpha { | |
1178 | validate!(!self.is_ver_b); | |
1179 | if self.is_ver_i { | |
1180 | br.skip(32)?; | |
1181 | } | |
1182 | self.decode_plane(&mut br, nplanes, &mut buf)?; | |
1183 | } | |
1184 | if self.is_ver_i { | |
1185 | br.skip(32)?; | |
1186 | } | |
1187 | for plane in 0..nplanes { | |
1188 | if self.is_ver_b { | |
1189 | self.decode_plane_binkb(&mut br, plane, &mut buf)?; | |
1190 | } else { | |
1191 | let plane_idx = if plane > 0 && self.swap_uv { plane ^ 3 } else { plane }; | |
1192 | self.decode_plane(&mut br, plane_idx, &mut buf)?; | |
1193 | } | |
1194 | } | |
b70cc006 | 1195 | let bufinfo = NABufferType::Video(buf); |
b83a3961 KS |
1196 | if !self.is_ver_b { |
1197 | self.ips.add_frame(bufinfo.get_vbuf().unwrap()); | |
1198 | } | |
1199 | ||
1200 | let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo); | |
1201 | frm.set_frame_type(FrameType::P); | |
171860fc | 1202 | Ok(frm.into_ref()) |
b83a3961 | 1203 | } |
f9be4e75 KS |
1204 | fn flush(&mut self) { |
1205 | self.ips.clear(); | |
1206 | } | |
b83a3961 | 1207 | } |
606c448e | 1208 | |
7d57ae2f KS |
1209 | impl NAOptionHandler for BinkDecoder { |
1210 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
1211 | fn set_options(&mut self, _options: &[NAOption]) { } | |
1212 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
1213 | } | |
1214 | ||
08a1fab7 | 1215 | pub fn get_decoder() -> Box<dyn NADecoder + Send> { |
b83a3961 KS |
1216 | Box::new(BinkDecoder::new()) |
1217 | } | |
1218 | ||
1219 | #[cfg(test)] | |
1220 | mod test { | |
1221 | use nihav_core::codecs::RegisteredDecoders; | |
1222 | use nihav_core::demuxers::RegisteredDemuxers; | |
ce742854 | 1223 | use nihav_codec_support::test::dec_video::*; |
78fb6560 | 1224 | use crate::rad_register_all_decoders; |
e64739f8 | 1225 | use crate::rad_register_all_demuxers; |
b83a3961 | 1226 | #[test] |
e3dbe0a0 | 1227 | fn test_binkvid_b() { |
b83a3961 KS |
1228 | let mut dmx_reg = RegisteredDemuxers::new(); |
1229 | rad_register_all_demuxers(&mut dmx_reg); | |
1230 | let mut dec_reg = RegisteredDecoders::new(); | |
78fb6560 | 1231 | rad_register_all_decoders(&mut dec_reg); |
b83a3961 | 1232 | |
886cde48 | 1233 | // sample: https://samples.mplayerhq.hu/game-formats/bink/bikb/NEW.BIK |
e3dbe0a0 KS |
1234 | test_decoding("bink", "bink-video", "assets/RAD/NEW.BIK", Some(16), &dmx_reg, &dec_reg, |
1235 | ExpectedTestResult::MD5Frames(vec![ | |
1236 | [0x00edef7e, 0x7efad3b1, 0x7e8bdd74, 0x3f6b00ba], | |
1237 | [0xbc40683f, 0xbeb1c5e4, 0x934777b5, 0x8a8a350d], | |
1238 | [0x68b78627, 0x28ceb63d, 0xfdb1171a, 0x23e69d90], | |
1239 | [0xc8d907a0, 0xb8d44079, 0x0286336b, 0x996479f3], | |
1240 | [0x57bbe4ec, 0xdb8bb9c2, 0x0e6f1fd6, 0xe180125e], | |
1241 | [0xd43c2ae0, 0x4010007f, 0x2a6360a1, 0xb5203a05], | |
1242 | [0xa883acf6, 0x25843f92, 0x4ced9a46, 0x6d513ad9], | |
1243 | [0x959e843f, 0x8d8182b9, 0x3f12d29b, 0x2af8d39f], | |
1244 | [0x93840946, 0x1188c6d1, 0xd5499833, 0x62aac0c6], | |
1245 | [0x4e5a56a6, 0x21517d9a, 0xbe1f270d, 0xe5621945], | |
1246 | [0x1b133742, 0x1eb1bf0a, 0x68cab2e3, 0x92176b5d], | |
1247 | [0x0cf78c43, 0x4bc15549, 0x3dd94323, 0x737eaaae], | |
1248 | [0xdd731c4a, 0x801453b3, 0xa38bef3e, 0x285cfdfe], | |
1249 | [0xe1fec4ee, 0x46737abc, 0x8c452209, 0xc8c6addd], | |
1250 | [0x2978aa50, 0x5f1e6d5a, 0x1f5b0fba, 0xb8e32196], | |
1251 | [0x2e1e95ab, 0x8e31a0b0, 0xfe998512, 0xea9397b6], | |
1252 | [0xf7f6c0d8, 0x893e77a7, 0xdfe0309f, 0xf5e644e2]])); | |
1253 | } | |
1254 | #[test] | |
1255 | fn test_binkvid() { | |
1256 | let mut dmx_reg = RegisteredDemuxers::new(); | |
1257 | rad_register_all_demuxers(&mut dmx_reg); | |
1258 | let mut dec_reg = RegisteredDecoders::new(); | |
78fb6560 | 1259 | rad_register_all_decoders(&mut dec_reg); |
b83a3961 | 1260 | |
886cde48 | 1261 | // sample: https://samples.mplayerhq.hu/game-formats/bink/ActivisionLogo.bik |
e3dbe0a0 KS |
1262 | test_decoding("bink", "bink-video", "assets/RAD/ActivisionLogo.bik", Some(42), |
1263 | &dmx_reg, &dec_reg, | |
1264 | ExpectedTestResult::MD5([0x41128884, 0x73a8c710, 0x5072ea4a, 0x8caca428])); | |
b83a3961 | 1265 | } |
606c448e | 1266 | } |