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