introduce option handling for decoders
[nihav.git] / nihav-duck / src / codecs / vp6.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::bitreader::*;
3 use nihav_codec_support::codecs::{MV, ZIGZAG};
4 use nihav_codec_support::codecs::blockdsp::edge_emu;
5 use super::vpcommon::*;
6 use super::vp56::*;
7
8 const VERSION_VP60: u8 = 6;
9 //const VERSION_VP61: u8 = 7;
10 const VERSION_VP62: u8 = 8;
11
12 const VP6_SIMPLE_PROFILE: u8 = 0;
13 const VP6_ADVANCED_PROFILE: u8 = 3;
14
15 #[derive(Default)]
16 struct VP6BR {
17 vpversion: u8,
18 profile: u8,
19 interlaced: bool,
20 do_pm: bool,
21 loop_mode: u8,
22 autosel_pm: bool,
23 var_thresh: u16,
24 mv_thresh: u8,
25 bicubic: bool,
26 filter_alpha: usize,
27 }
28
29 impl VP6BR {
30 fn new() -> Self {
31 Self::default()
32 }
33 }
34
35 impl VP56Parser for VP6BR {
36 fn parse_header(&mut self, bc: &mut BoolCoder) -> DecoderResult<VP56Header> {
37 let mut hdr = VP56Header::default();
38 // horrible hack to match VP6 header parsing
39 let src = bc.src;
40 let mut br = BitReader::new(src, BitReaderMode::BE);
41
42 hdr.is_intra = !br.read_bool()?;
43 hdr.is_golden = hdr.is_intra;
44 hdr.quant = br.read(6)? as u8;
45 hdr.multistream = br.read_bool()?;
46 if hdr.is_intra {
47 hdr.version = br.read(5)? as u8;
48 validate!((hdr.version >= VERSION_VP60) && (hdr.version <= VERSION_VP62));
49 hdr.profile = br.read(2)? as u8;
50 validate!((hdr.profile == VP6_SIMPLE_PROFILE) || (hdr.profile == VP6_ADVANCED_PROFILE));
51 hdr.interlaced = br.read_bool()?;
52 } else {
53 hdr.version = self.vpversion;
54 hdr.profile = self.profile;
55 hdr.interlaced = self.interlaced;
56 }
57 if hdr.multistream || (hdr.profile == VP6_SIMPLE_PROFILE) {
58 hdr.offset = br.read(16)? as u16;
59 validate!(hdr.offset > if hdr.is_intra { 6 } else { 2 });
60 }
61 let bytes = br.tell() >> 3;
62 std::mem::drop(br);
63 bc.skip_bytes(bytes);
64 self.loop_mode = 0;
65 if hdr.is_intra {
66 hdr.mb_h = bc.read_bits(8) as u8;
67 hdr.mb_w = bc.read_bits(8) as u8;
68 hdr.disp_h = bc.read_bits(8) as u8;
69 hdr.disp_w = bc.read_bits(8) as u8;
70 validate!((hdr.mb_h > 0) && (hdr.mb_w > 0) && (hdr.disp_w > 0) && (hdr.disp_h > 0));
71 validate!((hdr.disp_w <= hdr.mb_w) && (hdr.disp_h <= hdr.mb_h));
72 hdr.scale = bc.read_bits(2) as u8;
73 } else {
74 hdr.is_golden = bc.read_bool();
75 if hdr.profile == VP6_ADVANCED_PROFILE {
76 self.loop_mode = bc.read_bool() as u8;
77 if self.loop_mode != 0 {
78 self.loop_mode += bc.read_bool() as u8;
79 validate!(self.loop_mode <= 1);
80 }
81 if hdr.version == VERSION_VP62 {
82 self.do_pm = bc.read_bool();
83 }
84 }
85 }
86
87 if (hdr.profile == VP6_ADVANCED_PROFILE) && (hdr.is_intra || self.do_pm) {
88 self.autosel_pm = bc.read_bool();
89 if self.autosel_pm {
90 self.var_thresh = bc.read_bits(5) as u16;
91 if hdr.version != VERSION_VP62 {
92 self.var_thresh <<= 5;
93 }
94 self.mv_thresh = bc.read_bits(3) as u8;
95 } else {
96 self.bicubic = bc.read_bool();
97 }
98 if hdr.version == VERSION_VP62 {
99 self.filter_alpha = bc.read_bits(4) as usize;
100 } else {
101 self.filter_alpha = 16;
102 }
103 }
104
105 hdr.use_huffman = bc.read_bool();
106
107 self.vpversion = hdr.version;
108 self.profile = hdr.profile;
109 self.interlaced = hdr.interlaced;
110 Ok(hdr)
111 }
112 fn decode_mv(&self, bc: &mut BoolCoder, model: &VP56MVModel) -> i16 {
113 const LONG_VECTOR_ORDER: [usize; 7] = [ 0, 1, 2, 7, 6, 5, 4 ];
114
115 let val = if !bc.read_prob(model.nz_prob) { // short vector
116 vp_tree!(bc, model.tree_probs[0],
117 vp_tree!(bc, model.tree_probs[1],
118 vp_tree!(bc, model.tree_probs[2], 0, 1),
119 vp_tree!(bc, model.tree_probs[3], 2, 3)),
120 vp_tree!(bc, model.tree_probs[4],
121 vp_tree!(bc, model.tree_probs[5], 4, 5),
122 vp_tree!(bc, model.tree_probs[6], 6, 7)))
123 } else {
124 let mut raw = 0;
125 for ord in LONG_VECTOR_ORDER.iter() {
126 raw |= (bc.read_prob(model.raw_probs[*ord]) as i16) << *ord;
127 }
128 if (raw & 0xF0) != 0 {
129 raw |= (bc.read_prob(model.raw_probs[3]) as i16) << 3;
130 } else {
131 raw |= 1 << 3;
132 }
133 raw
134 };
135 if (val != 0) && bc.read_prob(model.sign_prob) {
136 -val
137 } else {
138 val
139 }
140 }
141 fn reset_models(&self, models: &mut VP56Models) {
142 const NZ_PROBS: [u8; 2] = [ 162, 164 ];
143 const RAW_PROBS: [[u8; 8]; 2] = [
144 [ 247, 210, 135, 68, 138, 220, 239, 246 ],
145 [ 244, 184, 201, 44, 173, 221, 239, 253 ]
146 ];
147 const TREE_PROBS: [[u8; 7]; 2] = [
148 [ 225, 146, 172, 147, 214, 39, 156 ],
149 [ 204, 170, 119, 235, 140, 230, 228 ]
150 ];
151 const ZERO_RUN_PROBS: [[u8; 14]; 2] = [
152 [ 198, 197, 196, 146, 198, 204, 169, 142, 130, 136, 149, 149, 191, 249 ],
153 [ 135, 201, 181, 154, 98, 117, 132, 126, 146, 169, 184, 240, 246, 254 ]
154 ];
155
156 for (i, mdl) in models.mv_models.iter_mut().enumerate() {
157 mdl.nz_prob = NZ_PROBS[i];
158 mdl.sign_prob = 128;
159 mdl.raw_probs.copy_from_slice(&RAW_PROBS[i]);
160 mdl.tree_probs.copy_from_slice(&TREE_PROBS[i]);
161 }
162 models.vp6models.zero_run_probs.copy_from_slice(&ZERO_RUN_PROBS);
163 reset_scan(&mut models.vp6models, self.interlaced);
164 }
165 fn decode_mv_models(&self, bc: &mut BoolCoder, models: &mut [VP56MVModel; 2]) -> DecoderResult<()> {
166 const HAS_NZ_PROB: [u8; 2] = [ 237, 231 ];
167 const HAS_SIGN_PROB: [u8; 2] = [ 246, 243 ];
168 const HAS_TREE_PROB: [[u8; 7]; 2] = [
169 [ 253, 253, 254, 254, 254, 254, 254 ],
170 [ 245, 253, 254, 254, 254, 254, 254 ]
171 ];
172 const HAS_RAW_PROB: [[u8; 8]; 2] = [
173 [ 254, 254, 254, 254, 254, 250, 250, 252 ],
174 [ 254, 254, 254, 254, 254, 251, 251, 254 ]
175 ];
176
177 for comp in 0..2 {
178 if bc.read_prob(HAS_NZ_PROB[comp]) {
179 models[comp].nz_prob = bc.read_probability();
180 }
181 if bc.read_prob(HAS_SIGN_PROB[comp]) {
182 models[comp].sign_prob = bc.read_probability();
183 }
184 }
185 for comp in 0..2 {
186 for (i, prob) in HAS_TREE_PROB[comp].iter().enumerate() {
187 if bc.read_prob(*prob) {
188 models[comp].tree_probs[i] = bc.read_probability();
189 }
190 }
191 }
192 for comp in 0..2 {
193 for (i, prob) in HAS_RAW_PROB[comp].iter().enumerate() {
194 if bc.read_prob(*prob) {
195 models[comp].raw_probs[i] = bc.read_probability();
196 }
197 }
198 }
199 Ok(())
200 }
201 fn decode_coeff_models(&self, bc: &mut BoolCoder, models: &mut VP56Models, is_intra: bool) -> DecoderResult<()> {
202 const COEF_PROBS: [[u8; 11]; 2] = [
203 [ 146, 255, 181, 207, 232, 243, 238, 251, 244, 250, 249 ],
204 [ 179, 255, 214, 240, 250, 255, 244, 255, 255, 255, 255 ]
205 ];
206 const SCAN_UPD_PROBS: [u8; 64] = [
207 0, 132, 132, 159, 153, 151, 161, 170,
208 164, 162, 136, 110, 103, 114, 129, 118,
209 124, 125, 132, 136, 114, 110, 142, 135,
210 134, 123, 143, 126, 153, 183, 166, 161,
211 171, 180, 179, 164, 203, 218, 225, 217,
212 215, 206, 203, 217, 229, 241, 248, 243,
213 253, 255, 253, 255, 255, 255, 255, 255,
214 255, 255, 255, 255, 255, 255, 255, 255
215 ];
216 const ZERO_RUN_PROBS: [[u8; 14]; 2] = [
217 [ 219, 246, 238, 249, 232, 239, 249, 255, 248, 253, 239, 244, 241, 248 ],
218 [ 198, 232, 251, 253, 219, 241, 253, 255, 248, 249, 244, 238, 251, 255 ]
219 ];
220
221 let mut def_prob = [128u8; 11];
222 for plane in 0..2 {
223 for i in 0..11 {
224 if bc.read_prob(COEF_PROBS[plane][i]) {
225 def_prob[i] = bc.read_probability();
226 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
227 } else if is_intra {
228 models.coeff_models[plane].dc_value_probs[i] = def_prob[i];
229 }
230 }
231 }
232
233 if bc.read_bool() {
234 for i in 1..64 {
235 if bc.read_prob(SCAN_UPD_PROBS[i]) {
236 models.vp6models.scan_order[i] = bc.read_bits(4) as usize;
237 }
238 }
239 update_scan(&mut models.vp6models);
240 } else {
241 reset_scan(&mut models.vp6models, self.interlaced);
242 }
243
244 for comp in 0..2 {
245 for i in 0..14 {
246 if bc.read_prob(ZERO_RUN_PROBS[comp][i]) {
247 models.vp6models.zero_run_probs[comp][i] = bc.read_probability();
248 }
249 }
250 }
251
252 for ctype in 0..3 {
253 for plane in 0..2 {
254 for group in 0..6 {
255 for i in 0..11 {
256 if bc.read_prob(VP6_AC_PROBS[ctype][plane][group][i]) {
257 def_prob[i] = bc.read_probability();
258 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
259 } else if is_intra {
260 models.coeff_models[plane].ac_val_probs[ctype][group][i] = def_prob[i];
261 }
262 }
263 }
264 }
265 }
266 for plane in 0..2 {
267 let mdl = &mut models.coeff_models[plane];
268 for i in 0..3 {
269 for k in 0..5 {
270 mdl.dc_token_probs[0][i][k] = rescale_prob(mdl.dc_value_probs[k], &VP6_DC_WEIGHTS[k][i], 255);
271 }
272 }
273 }
274 Ok(())
275 }
276 fn decode_block(&self, bc: &mut BoolCoder, coeffs: &mut [i16; 64], model: &VP56CoeffModel, vp6model: &VP6Models, fstate: &mut FrameState) -> DecoderResult<()> {
277 let left_ctx = fstate.coeff_cat[fstate.ctx_idx][0] as usize;
278 let top_ctx = fstate.top_ctx as usize;
279 let dc_mode = top_ctx + left_ctx;
280 let token = decode_token_bc(bc, &model.dc_token_probs[0][dc_mode], model.dc_value_probs[5], true, true);
281 let val = expand_token_bc(bc, &model.dc_value_probs, token, 6);
282 coeffs[0] = val;
283 fstate.last_idx[fstate.ctx_idx] = 0;
284
285 let mut idx = 1;
286 let mut last_val = val;
287 while idx < 64 {
288 let ac_band = VP6_IDX_TO_AC_BAND[idx];
289 let ac_mode = last_val.abs().min(2) as usize;
290 let has_nnz = (idx == 1) || (last_val != 0);
291 let token = decode_token_bc(bc, &model.ac_val_probs[ac_mode][ac_band], model.ac_val_probs[ac_mode][ac_band][5], false, has_nnz);
292 if token == 42 { break; }
293 let val = expand_token_bc(bc, &model.ac_val_probs[ac_mode][ac_band], token, 6);
294 coeffs[vp6model.zigzag[idx]] = val.wrapping_mul(fstate.ac_quant);
295 idx += 1;
296 last_val = val;
297 if val == 0 {
298 idx += decode_zero_run_bc(bc, &vp6model.zero_run_probs[if idx >= 7 { 1 } else { 0 }]);
299 validate!(idx <= 64);
300 }
301 }
302 fstate.coeff_cat[fstate.ctx_idx][0] = if coeffs[0] != 0 { 1 } else { 0 };
303 fstate.top_ctx = fstate.coeff_cat[fstate.ctx_idx][0];
304 fstate.last_idx[fstate.ctx_idx] = idx;
305 Ok(())
306 }
307 fn decode_block_huff(&self, br: &mut BitReader, coeffs: &mut [i16; 64], vp6model: &VP6Models, model: &VP6HuffModels, fstate: &mut FrameState) -> DecoderResult<()> {
308 let plane = if (fstate.plane == 0) || (fstate.plane == 3) { 0 } else { 1 };
309 let mut last_val;
310
311 if fstate.dc_zero_run[plane] == 0 {
312 let (val, eob) = decode_token_huff(br, &model.dc_token_tree[plane])?;
313 if eob {
314 return Ok(());
315 }
316 last_val = val;
317 coeffs[0] = val;
318 if val == 0 {
319 fstate.dc_zero_run[plane] = decode_eob_run_huff(br)?;
320 }
321 } else {
322 last_val = 0;
323 fstate.dc_zero_run[plane] -= 1;
324 }
325
326 if fstate.ac_zero_run[plane] > 0 {
327 fstate.ac_zero_run[plane] -= 1;
328 fstate.last_idx[fstate.ctx_idx] = 0;
329 return Ok(());
330 }
331
332 let mut idx = 1;
333 while idx < 64 {
334 let ac_band = VP6_IDX_TO_AC_BAND[idx].min(3);
335 let ac_mode = last_val.abs().min(2) as usize;
336 let (val, eob) = decode_token_huff(br, &model.ac_token_tree[plane][ac_mode][ac_band])?;
337 if eob {
338 if idx == 1 {
339 fstate.ac_zero_run[plane] = decode_eob_run_huff(br)?;
340 }
341 break;
342 }
343 coeffs[vp6model.zigzag[idx]] = val.wrapping_mul(fstate.ac_quant);
344 idx += 1;
345 last_val = val;
346 if val == 0 {
347 idx += decode_zero_run_huff(br, &model.zero_run_tree[if idx >= 7 { 1 } else { 0 }])?;
348 validate!(idx <= 64);
349 }
350 }
351
352 fstate.last_idx[fstate.ctx_idx] = idx;
353
354 Ok(())
355 }
356 fn mc_block(&self, dst: &mut NASimpleVideoFrame<u8>, mut mc_buf: NAVideoBufferRef<u8>, src: NAVideoBufferRef<u8>, plane: usize, x: usize, y: usize, mv: MV, loop_str: i16) {
357 let is_luma = (plane != 1) && (plane != 2);
358 let (sx, sy, mx, my, msx, msy) = if is_luma {
359 (mv.x >> 2, mv.y >> 2, (mv.x & 3) << 1, (mv.y & 3) << 1, mv.x / 4, mv.y / 4)
360 } else {
361 (mv.x >> 3, mv.y >> 3, mv.x & 7, mv.y & 7, mv.x / 8, mv.y / 8)
362 };
363 let tmp_blk = mc_buf.get_data_mut().unwrap();
364 get_block(tmp_blk, 16, src.clone(), plane, x, y, sx, sy);
365 if (msx & 7) != 0 {
366 let foff = (8 - (sx & 7)) as usize;
367 let off = 2 + foff;
368 vp31_loop_filter(tmp_blk, off, 1, 16, 12, loop_str);
369 }
370 if (msy & 7) != 0 {
371 let foff = (8 - (sy & 7)) as usize;
372 let off = (2 + foff) * 16;
373 vp31_loop_filter(tmp_blk, off, 16, 1, 12, loop_str);
374 }
375 let copy_mode = (mx == 0) && (my == 0);
376 let mut bicubic = !copy_mode && is_luma && self.bicubic;
377 if is_luma && !copy_mode && (self.profile == VP6_ADVANCED_PROFILE) {
378 if !self.autosel_pm {
379 bicubic = true;
380 } else {
381 let mv_limit = 1 << (self.mv_thresh + 1);
382 if (mv.x.abs() <= mv_limit) && (mv.y.abs() <= mv_limit) {
383 let mut var_off = 16 * 2 + 2;
384 if mv.x < 0 { var_off += 1; }
385 if mv.y < 0 { var_off += 16; }
386 let var = calc_variance(&tmp_blk[var_off..], 16);
387 if var >= self.var_thresh {
388 bicubic = true;
389 }
390 }
391 }
392 }
393 let dstride = dst.stride[plane];
394 let dbuf = &mut dst.data[dst.offset[plane] + x + y * dstride..];
395 if copy_mode {
396 let src = &tmp_blk[2 * 16 + 2..];
397 for (dline, sline) in dbuf.chunks_mut(dst.stride[plane]).zip(src.chunks(16)).take(8) {
398 for i in 0..8 { dline[i] = sline[i]; }
399 }
400 } else if bicubic {
401 let coeff_h = &VP6_BICUBIC_COEFFS[self.filter_alpha][mx as usize];
402 let coeff_v = &VP6_BICUBIC_COEFFS[self.filter_alpha][my as usize];
403 mc_bicubic(dbuf, dstride, tmp_blk, 16 * 2 + 2, 16, coeff_h, coeff_v);
404 } else {
405 mc_bilinear(dbuf, dstride, tmp_blk, 16 * 2 + 2, 16, mx as u16, my as u16);
406 }
407 }
408 }
409
410 fn update_scan(model: &mut VP6Models) {
411 let mut idx = 1;
412 for band in 0..16 {
413 for i in 1..64 {
414 if model.scan_order[i] == band {
415 model.scan[idx] = i;
416 idx += 1;
417 }
418 }
419 }
420 for i in 1..64 {
421 model.zigzag[i] = ZIGZAG[model.scan[i]];
422 }
423 }
424
425 fn reset_scan(model: &mut VP6Models, interlaced: bool) {
426 const VP6_DEFAULT_SCAN_ORDER: [usize; 64] = [
427 0, 0, 1, 1, 1, 2, 2, 2,
428 2, 2, 2, 3, 3, 4, 4, 4,
429 5, 5, 5, 5, 6, 6, 7, 7,
430 7, 7, 7, 8, 8, 9, 9, 9,
431 9, 9, 9, 10, 10, 11, 11, 11,
432 11, 11, 11, 12, 12, 12, 12, 12,
433 12, 13, 13, 13, 13, 13, 14, 14,
434 14, 14, 15, 15, 15, 15, 15, 15
435 ];
436 const VP6_INTERLACED_SCAN_ORDER: [usize; 64] = [
437 0, 1, 0, 1, 1, 2, 5, 3,
438 2, 2, 2, 2, 4, 7, 8, 10,
439 9, 7, 5, 4, 2, 3, 5, 6,
440 8, 9, 11, 12, 13, 12, 11, 10,
441 9, 7, 5, 4, 6, 7, 9, 11,
442 12, 12, 13, 13, 14, 12, 11, 9,
443 7, 9, 11, 12, 14, 14, 14, 15,
444 13, 11, 13, 15, 15, 15, 15, 15
445 ];
446
447 if !interlaced {
448 model.scan_order.copy_from_slice(&VP6_DEFAULT_SCAN_ORDER);
449 } else {
450 model.scan_order.copy_from_slice(&VP6_INTERLACED_SCAN_ORDER);
451 }
452 for i in 0..64 { model.scan[i] = i; }
453 model.zigzag.copy_from_slice(&ZIGZAG);
454 }
455
456 fn decode_token_bc(bc: &mut BoolCoder, probs: &[u8], prob34: u8, is_dc: bool, has_nnz: bool) -> u8 {
457 if has_nnz && !bc.read_prob(probs[0]) {
458 if is_dc || bc.read_prob(probs[1]) {
459 0
460 } else {
461 TOKEN_EOB
462 }
463 } else {
464 vp_tree!(bc, probs[2],
465 1,
466 vp_tree!(bc, probs[3],
467 vp_tree!(bc, probs[4],
468 2,
469 vp_tree!(bc, prob34, 3, 4)),
470 TOKEN_LARGE))
471 }
472 }
473
474 fn decode_zero_run_bc(bc: &mut BoolCoder, probs: &[u8; 14]) -> usize {
475 let val = vp_tree!(bc, probs[0],
476 vp_tree!(bc, probs[1],
477 vp_tree!(bc, probs[2], 0, 1),
478 vp_tree!(bc, probs[3], 2, 3)),
479 vp_tree!(bc, probs[4],
480 vp_tree!(bc, probs[5],
481 vp_tree!(bc, probs[6], 4, 5),
482 vp_tree!(bc, probs[7], 6, 7)),
483 42));
484 if val != 42 {
485 val
486 } else {
487 let mut nval = 8;
488 for i in 0..6 {
489 nval += (bc.read_prob(probs[i + 8]) as usize) << i;
490 }
491 nval
492 }
493 }
494
495 fn decode_token_huff(br: &mut BitReader, huff: &VP6Huff) -> DecoderResult<(i16, bool)> {
496 const COEF_ADD_BITS: [u8; 6] = [ 1, 2, 3, 4, 5, 11 ];
497 let tok = br.read_huff(huff)?;
498 match tok {
499 0 => Ok((0, false)),
500 1 | 2 | 3 | 4 => {
501 if !br.read_bool()? {
502 Ok((tok as i16, false))
503 } else {
504 Ok((-(tok as i16), false))
505 }
506 },
507 5 | 6 | 7 | 8 | 9 | 10 => {
508 let base = (tok - 5) as usize;
509 let add_bits = br.read(COEF_ADD_BITS[base])? as i16;
510 let val = VP56_COEF_BASE[base] + add_bits;
511 if !br.read_bool()? {
512 Ok((val, false))
513 } else {
514 Ok((-val, false))
515 }
516 },
517 _ => Ok((0, true)),
518 }
519 }
520
521 fn decode_eob_run_huff(br: &mut BitReader) -> DecoderResult<usize> {
522 let val = br.read(2)?;
523 match val {
524 0 => Ok(0),
525 1 => Ok(1),
526 2 => {
527 let val = br.read(2)?;
528 Ok((val as usize) + 2)
529 },
530 _ => {
531 if br.read_bool()? {
532 Ok((br.read(6)? as usize) + 10)
533 } else {
534 Ok((br.read(2)? as usize) + 6)
535 }
536 },
537 }
538 }
539
540 fn decode_zero_run_huff(br: &mut BitReader, huff: &VP6Huff) -> DecoderResult<usize> {
541 let val = br.read_huff(huff)?;
542 if val < 8 {
543 Ok(val as usize)
544 } else {
545 Ok((br.read(6)? as usize) + 8)
546 }
547 }
548
549
550 fn get_block(dst: &mut [u8], dstride: usize, src: NAVideoBufferRef<u8>, comp: usize,
551 dx: usize, dy: usize, mv_x: i16, mv_y: i16)
552 {
553 let (w, h) = src.get_dimensions(comp);
554 let sx = (dx as isize) + (mv_x as isize);
555 let sy = (dy as isize) + (mv_y as isize);
556
557 if (sx - 2 < 0) || (sx + 8 + 2 > (w as isize)) ||
558 (sy - 2 < 0) || (sy + 8 + 2 > (h as isize)) {
559 edge_emu(&src, sx - 2, sy - 2, 8 + 2 + 2, 8 + 2 + 2,
560 dst, dstride, comp, 0);
561 } else {
562 let sstride = src.get_stride(comp);
563 let soff = src.get_offset(comp);
564 let sdta = src.get_data();
565 let sbuf: &[u8] = sdta.as_slice();
566 let saddr = soff + ((sx - 2) as usize) + ((sy - 2) as usize) * sstride;
567 let src = &sbuf[saddr..];
568 for (dline, sline) in dst.chunks_mut(dstride).zip(src.chunks(sstride)).take(12) {
569 for i in 0..12 {
570 dline[i] = sline[i];
571 }
572 }
573 }
574 }
575
576 fn calc_variance(src: &[u8], stride: usize) -> u16 {
577 let mut sum = 0;
578 let mut ssum = 0;
579 for line in src.chunks(stride * 2).take(4) {
580 for el in line.iter().take(8).step_by(2) {
581 let pix = *el as u32;
582 sum += pix;
583 ssum += pix * pix;
584 }
585 }
586 ((ssum * 16 - sum * sum) >> 8) as u16
587 }
588
589 macro_rules! mc_filter {
590 (bilinear; $a: expr, $b: expr, $c: expr) => {
591 ((($a as u16) * (8 - $c) + ($b as u16) * $c + 4) >> 3) as u8
592 };
593 (bicubic; $src: expr, $off: expr, $step: expr, $coeffs: expr) => {
594 ((($src[$off - $step] as i32) * ($coeffs[0] as i32) +
595 ($src[$off] as i32) * ($coeffs[1] as i32) +
596 ($src[$off + $step] as i32) * ($coeffs[2] as i32) +
597 ($src[$off + $step * 2] as i32) * ($coeffs[3] as i32) + 64) >> 7).min(255).max(0) as u8
598 }
599 }
600
601 //#[allow(snake_case)]
602 fn mc_bilinear(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, mx: u16, my: u16) {
603 if my == 0 {
604 for dline in dst.chunks_mut(dstride).take(8) {
605 for i in 0..8 {
606 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
607 }
608 soff += sstride;
609 }
610 } else if mx == 0 {
611 for dline in dst.chunks_mut(dstride).take(8) {
612 for i in 0..8 {
613 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + sstride], my);
614 }
615 soff += sstride;
616 }
617 } else {
618 let mut tmp = [0u8; 8];
619 for i in 0..8 {
620 tmp[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
621 }
622 soff += sstride;
623 for dline in dst.chunks_mut(dstride).take(8) {
624 for i in 0..8 {
625 let cur = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
626 dline[i] = mc_filter!(bilinear; tmp[i], cur, my);
627 tmp[i] = cur;
628 }
629 soff += sstride;
630 }
631 }
632 }
633
634 fn mc_bicubic(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, coeffs_w: &[i16; 4], coeffs_h: &[i16; 4]) {
635 if coeffs_h[1] == 128 {
636 for dline in dst.chunks_mut(dstride).take(8) {
637 for i in 0..8 {
638 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
639 }
640 soff += sstride;
641 }
642 } else if coeffs_w[1] == 128 { // horizontal-only interpolation
643 for dline in dst.chunks_mut(dstride).take(8) {
644 for i in 0..8 {
645 dline[i] = mc_filter!(bicubic; src, soff + i, sstride, coeffs_h);
646 }
647 soff += sstride;
648 }
649 } else {
650 let mut buf = [0u8; 16 * 11];
651 soff -= sstride;
652 for dline in buf.chunks_mut(16) {
653 for i in 0..8 {
654 dline[i] = mc_filter!(bicubic; src, soff + i, 1, coeffs_w);
655 }
656 soff += sstride;
657 }
658 let mut soff = 16;
659 for dline in dst.chunks_mut(dstride).take(8) {
660 for i in 0..8 {
661 dline[i] = mc_filter!(bicubic; buf, soff + i, 16, coeffs_h);
662 }
663 soff += 16;
664 }
665 }
666 }
667
668 struct VP6Decoder {
669 dec: VP56Decoder,
670 info: NACodecInfoRef,
671 br: VP6BR,
672 has_alpha: bool,
673 }
674
675 impl VP6Decoder {
676 fn new(has_alpha: bool) -> Self {
677 Self {
678 dec: VP56Decoder::new(6, has_alpha, true),
679 info: NACodecInfoRef::default(),
680 br: VP6BR::new(),
681 has_alpha,
682 }
683 }
684 }
685
686 impl NADecoder for VP6Decoder {
687 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
688 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
689 let fmt = if !self.has_alpha {
690 YUV420_FORMAT
691 } else {
692 VP_YUVA420_FORMAT
693 };
694 let myvinfo = NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt);
695 let myinfo = NACodecTypeInfo::Video(myvinfo.clone());
696 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
697 self.dec.init(supp, myvinfo)?;
698 Ok(())
699 } else {
700 Err(DecoderError::InvalidData)
701 }
702 }
703 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
704 let src = pkt.get_buffer();
705
706 let (bufinfo, ftype) = self.dec.decode_frame(supp, src.as_slice(), &mut self.br)?;
707
708 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
709 frm.set_keyframe(ftype == FrameType::I);
710 frm.set_frame_type(ftype);
711 Ok(frm.into_ref())
712 }
713 fn flush(&mut self) {
714 self.dec.flush();
715 }
716 }
717
718 impl NAOptionHandler for VP6Decoder {
719 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
720 fn set_options(&mut self, _options: &[NAOption]) { }
721 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
722 }
723
724 pub fn get_decoder_vp6() -> Box<NADecoder + Send> {
725 Box::new(VP6Decoder::new(false))
726 }
727
728 pub fn get_decoder_vp6_alpha() -> Box<NADecoder + Send> {
729 Box::new(VP6Decoder::new(true))
730 }
731
732 #[cfg(test)]
733 mod test {
734 use nihav_core::codecs::RegisteredDecoders;
735 use nihav_core::demuxers::RegisteredDemuxers;
736 use nihav_codec_support::test::dec_video::*;
737 use crate::duck_register_all_codecs;
738 use nihav_commonfmt::generic_register_all_demuxers;
739
740 #[test]
741 fn test_vp6() {
742 let mut dmx_reg = RegisteredDemuxers::new();
743 generic_register_all_demuxers(&mut dmx_reg);
744 let mut dec_reg = RegisteredDecoders::new();
745 duck_register_all_codecs(&mut dec_reg);
746
747 test_decoding("avi", "vp6", "assets/Duck/selection_720x576_300kBit_vp60i.avi", Some(16),
748 &dmx_reg, &dec_reg,
749 ExpectedTestResult::MD5([0x042c3e96, 0x8a9b26a2, 0x4dcbaf66, 0x1b788d03]));
750 }
751 #[test]
752 fn test_vp6_huff() {
753 let mut dmx_reg = RegisteredDemuxers::new();
754 generic_register_all_demuxers(&mut dmx_reg);
755 let mut dec_reg = RegisteredDecoders::new();
756 duck_register_all_codecs(&mut dec_reg);
757
758 test_decoding("avi", "vp6", "assets/Duck/vp6_crash.avi", Some(4),
759 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
760 [0xdcd70fa0, 0x0d075ce2, 0xc9e65077, 0xb003a92e],
761 [0x334abf96, 0x3a004c7a, 0x5781cd5c, 0x25c3ae5c],
762 [0x6164b851, 0x528cd8de, 0xecab7328, 0x4b49708a],
763 [0x11b048ac, 0xedb3e471, 0xd04e9399, 0x64e623e3],
764 [0x182871b1, 0x2146893a, 0x2912210e, 0x6dd592e8]]));
765 }
766 // todo find good sample for vp6a test
767 }
768
769 const VP6_AC_PROBS: [[[[u8; 11]; 6]; 2]; 3] = [
770 [
771 [
772 [ 227, 246, 230, 247, 244, 255, 255, 255, 255, 255, 255 ],
773 [ 255, 255, 209, 231, 231, 249, 249, 253, 255, 255, 255 ],
774 [ 255, 255, 225, 242, 241, 251, 253, 255, 255, 255, 255 ],
775 [ 255, 255, 241, 253, 252, 255, 255, 255, 255, 255, 255 ],
776 [ 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
777 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
778 ], [
779 [ 240, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
780 [ 255, 255, 240, 253, 255, 255, 255, 255, 255, 255, 255 ],
781 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
782 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
783 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
784 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
785 ]
786 ], [
787 [
788 [ 206, 203, 227, 239, 247, 255, 253, 255, 255, 255, 255 ],
789 [ 207, 199, 220, 236, 243, 252, 252, 255, 255, 255, 255 ],
790 [ 212, 219, 230, 243, 244, 253, 252, 255, 255, 255, 255 ],
791 [ 236, 237, 247, 252, 253, 255, 255, 255, 255, 255, 255 ],
792 [ 240, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
793 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
794 ], [
795 [ 230, 233, 249, 255, 255, 255, 255, 255, 255, 255, 255 ],
796 [ 238, 238, 250, 255, 255, 255, 255, 255, 255, 255, 255 ],
797 [ 248, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
798 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
799 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
800 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
801 ]
802 ], [
803 [
804 [ 225, 239, 227, 231, 244, 253, 243, 255, 255, 253, 255 ],
805 [ 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 255 ],
806 [ 235, 249, 238, 240, 251, 255, 249, 255, 253, 253, 255 ],
807 [ 249, 253, 251, 250, 255, 255, 255, 255, 255, 255, 255 ],
808 [ 251, 250, 249, 255, 255, 255, 255, 255, 255, 255, 255 ],
809 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
810 ], [
811 [ 243, 244, 250, 250, 255, 255, 255, 255, 255, 255, 255 ],
812 [ 249, 248, 250, 253, 255, 255, 255, 255, 255, 255, 255 ],
813 [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
814 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
815 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
816 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
817 ]
818 ]
819 ];
820
821 const VP6_DC_WEIGHTS: [[[i16; 2]; 3]; 5] = [
822 [ [ 122, 133 ], [ 133, 51 ], [ 142, -16 ] ],
823 [ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
824 [ [ 78, 171 ], [ 169, 71 ], [ 221, -30 ] ],
825 [ [ 139, 117 ], [ 214, 44 ], [ 246, -3 ] ],
826 [ [ 168, 79 ], [ 210, 38 ], [ 203, 17 ] ]
827 ];
828
829 const VP6_IDX_TO_AC_BAND: [usize; 64] = [
830 0, 0, 1, 1, 1, 2, 2, 2,
831 2, 2, 2, 3, 3, 3, 3, 3,
832 3, 3, 3, 3, 3, 3, 4, 4,
833 4, 4, 4, 4, 4, 4, 4, 4,
834 4, 4, 4, 4, 4, 5, 5, 5,
835 5, 5, 5, 5, 5, 5, 5, 5,
836 5, 5, 5, 5, 5, 5, 5, 5,
837 5, 5, 5, 5, 5, 5, 5, 5
838 ];
839
840 const VP6_BICUBIC_COEFFS: [[[i16; 4]; 8]; 17] = [
841 [
842 [ 0, 128, 0, 0 ],
843 [ -3, 122, 9, 0 ],
844 [ -4, 109, 24, -1 ],
845 [ -5, 91, 45, -3 ],
846 [ -4, 68, 68, -4 ],
847 [ -3, 45, 91, -5 ],
848 [ -1, 24, 109, -4 ],
849 [ 0, 9, 122, -3 ]
850 ], [
851 [ 0, 128, 0, 0 ],
852 [ -4, 124, 9, -1 ],
853 [ -5, 110, 25, -2 ],
854 [ -6, 91, 46, -3 ],
855 [ -5, 69, 69, -5 ],
856 [ -3, 46, 91, -6 ],
857 [ -2, 25, 110, -5 ],
858 [ -1, 9, 124, -4 ]
859 ], [
860 [ 0, 128, 0, 0 ],
861 [ -4, 123, 10, -1 ],
862 [ -6, 110, 26, -2 ],
863 [ -7, 92, 47, -4 ],
864 [ -6, 70, 70, -6 ],
865 [ -4, 47, 92, -7 ],
866 [ -2, 26, 110, -6 ],
867 [ -1, 10, 123, -4 ]
868 ], [
869 [ 0, 128, 0, 0 ],
870 [ -5, 124, 10, -1 ],
871 [ -7, 110, 27, -2 ],
872 [ -7, 91, 48, -4 ],
873 [ -6, 70, 70, -6 ],
874 [ -4, 48, 92, -8 ],
875 [ -2, 27, 110, -7 ],
876 [ -1, 10, 124, -5 ]
877 ], [
878 [ 0, 128, 0, 0 ],
879 [ -6, 124, 11, -1 ],
880 [ -8, 111, 28, -3 ],
881 [ -8, 92, 49, -5 ],
882 [ -7, 71, 71, -7 ],
883 [ -5, 49, 92, -8 ],
884 [ -3, 28, 111, -8 ],
885 [ -1, 11, 124, -6 ]
886 ], [
887 [ 0, 128, 0, 0 ],
888 [ -6, 123, 12, -1 ],
889 [ -9, 111, 29, -3 ],
890 [ -9, 93, 50, -6 ],
891 [ -8, 72, 72, -8 ],
892 [ -6, 50, 93, -9 ],
893 [ -3, 29, 111, -9 ],
894 [ -1, 12, 123, -6 ]
895 ], [
896 [ 0, 128, 0, 0 ],
897 [ -7, 124, 12, -1 ],
898 [ -10, 111, 30, -3 ],
899 [ -10, 93, 51, -6 ],
900 [ -9, 73, 73, -9 ],
901 [ -6, 51, 93, -10 ],
902 [ -3, 30, 111, -10 ],
903 [ -1, 12, 124, -7 ]
904 ], [
905 [ 0, 128, 0, 0 ],
906 [ -7, 123, 13, -1 ],
907 [ -11, 112, 31, -4 ],
908 [ -11, 94, 52, -7 ],
909 [ -10, 74, 74, -10 ],
910 [ -7, 52, 94, -11 ],
911 [ -4, 31, 112, -11 ],
912 [ -1, 13, 123, -7 ]
913 ], [
914 [ 0, 128, 0, 0 ],
915 [ -8, 124, 13, -1 ],
916 [ -12, 112, 32, -4 ],
917 [ -12, 94, 53, -7 ],
918 [ -10, 74, 74, -10 ],
919 [ -7, 53, 94, -12 ],
920 [ -4, 32, 112, -12 ],
921 [ -1, 13, 124, -8 ]
922 ], [
923 [ 0, 128, 0, 0 ],
924 [ -9, 124, 14, -1 ],
925 [ -13, 112, 33, -4 ],
926 [ -13, 95, 54, -8 ],
927 [ -11, 75, 75, -11 ],
928 [ -8, 54, 95, -13 ],
929 [ -4, 33, 112, -13 ],
930 [ -1, 14, 124, -9 ]
931 ], [
932 [ 0, 128, 0, 0 ],
933 [ -9, 123, 15, -1 ],
934 [ -14, 113, 34, -5 ],
935 [ -14, 95, 55, -8 ],
936 [ -12, 76, 76, -12 ],
937 [ -8, 55, 95, -14 ],
938 [ -5, 34, 112, -13 ],
939 [ -1, 15, 123, -9 ]
940 ], [
941 [ 0, 128, 0, 0 ],
942 [ -10, 124, 15, -1 ],
943 [ -14, 113, 34, -5 ],
944 [ -15, 96, 56, -9 ],
945 [ -13, 77, 77, -13 ],
946 [ -9, 56, 96, -15 ],
947 [ -5, 34, 113, -14 ],
948 [ -1, 15, 124, -10 ]
949 ], [
950 [ 0, 128, 0, 0 ],
951 [ -10, 123, 16, -1 ],
952 [ -15, 113, 35, -5 ],
953 [ -16, 98, 56, -10 ],
954 [ -14, 78, 78, -14 ],
955 [ -10, 56, 98, -16 ],
956 [ -5, 35, 113, -15 ],
957 [ -1, 16, 123, -10 ]
958 ], [
959 [ 0, 128, 0, 0 ],
960 [ -11, 124, 17, -2 ],
961 [ -16, 113, 36, -5 ],
962 [ -17, 98, 57, -10 ],
963 [ -14, 78, 78, -14 ],
964 [ -10, 57, 98, -17 ],
965 [ -5, 36, 113, -16 ],
966 [ -2, 17, 124, -11 ]
967 ], [
968 [ 0, 128, 0, 0 ],
969 [ -12, 125, 17, -2 ],
970 [ -17, 114, 37, -6 ],
971 [ -18, 99, 58, -11 ],
972 [ -15, 79, 79, -15 ],
973 [ -11, 58, 99, -18 ],
974 [ -6, 37, 114, -17 ],
975 [ -2, 17, 125, -12 ]
976 ], [
977 [ 0, 128, 0, 0 ],
978 [ -12, 124, 18, -2 ],
979 [ -18, 114, 38, -6 ],
980 [ -19, 99, 59, -11 ],
981 [ -16, 80, 80, -16 ],
982 [ -11, 59, 99, -19 ],
983 [ -6, 38, 114, -18 ],
984 [ -2, 18, 124, -12 ]
985 ], [
986 [ 0, 128, 0, 0 ],
987 [ -4, 118, 16, -2 ],
988 [ -7, 106, 34, -5 ],
989 [ -8, 90, 53, -7 ],
990 [ -8, 72, 72, -8 ],
991 [ -7, 53, 90, -8 ],
992 [ -5, 34, 106, -7 ],
993 [ -2, 16, 118, -4 ]
994 ]
995 ];