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