rename register_all_codecs to register_all_decoders
[nihav.git] / nihav-duck / src / codecs / vp6.rs
CommitLineData
3584b223
KS
1use nihav_core::codecs::*;
2use nihav_core::io::bitreader::*;
b4d5b851
KS
3use nihav_codec_support::codecs::{MV, ZIGZAG};
4use nihav_codec_support::codecs::blockdsp::edge_emu;
3584b223
KS
5use super::vpcommon::*;
6use super::vp56::*;
7
8const VERSION_VP60: u8 = 6;
9//const VERSION_VP61: u8 = 7;
10const VERSION_VP62: u8 = 8;
11
12const VP6_SIMPLE_PROFILE: u8 = 0;
13const VP6_ADVANCED_PROFILE: u8 = 3;
14
15#[derive(Default)]
16struct 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
29impl VP6BR {
30 fn new() -> Self {
31 Self::default()
32 }
33}
34
35impl 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;
fa90ccfb 40 let mut br = BitReader::new(src, BitReaderMode::BE);
3584b223
KS
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;
adb9c3d4 55 hdr.interlaced = self.interlaced;
3584b223
KS
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 }
85d7efe3 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) {
3584b223 357 let is_luma = (plane != 1) && (plane != 2);
85d7efe3
KS
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)
3584b223 360 } else {
85d7efe3 361 (mv.x >> 3, mv.y >> 3, mv.x & 7, mv.y & 7, mv.x / 8, mv.y / 8)
3584b223
KS
362 };
363 let tmp_blk = mc_buf.get_data_mut().unwrap();
364 get_block(tmp_blk, 16, src.clone(), plane, x, y, sx, sy);
85d7efe3
KS
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) {
3584b223
KS
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) {
85d7efe3
KS
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;
3584b223
KS
389 }
390 }
391 }
392 }
393 let dstride = dst.stride[plane];
394 let dbuf = &mut dst.data[dst.offset[plane] + x + y * dstride..];
85d7efe3 395 if copy_mode {
3584b223
KS
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) {
47933c6d 398 dline[..8].copy_from_slice(&sline[..8]);
3584b223 399 }
85d7efe3 400 } else if bicubic {
3584b223
KS
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
410fn 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
425fn 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
456fn 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
474fn 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
495fn 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()? {
47933c6d 502 Ok((i16::from(tok), false))
3584b223 503 } else {
47933c6d 504 Ok((-i16::from(tok), false))
3584b223
KS
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
521fn 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
540fn 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
47933c6d 549#[allow(clippy::too_many_arguments)]
3584b223
KS
550fn 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,
86081fed 560 dst, dstride, comp, 0);
3584b223
KS
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) {
47933c6d 569 dline[..12].copy_from_slice(&sline[..12]);
3584b223
KS
570 }
571 }
572}
573
574fn calc_variance(src: &[u8], stride: usize) -> u16 {
575 let mut sum = 0;
576 let mut ssum = 0;
85d7efe3 577 for line in src.chunks(stride * 2).take(4) {
3584b223 578 for el in line.iter().take(8).step_by(2) {
47933c6d 579 let pix = u32::from(*el);
3584b223
KS
580 sum += pix;
581 ssum += pix * pix;
582 }
583 }
584 ((ssum * 16 - sum * sum) >> 8) as u16
585}
586
587macro_rules! mc_filter {
588 (bilinear; $a: expr, $b: expr, $c: expr) => {
47933c6d 589 ((u16::from($a) * (8 - $c) + u16::from($b) * $c + 4) >> 3) as u8
3584b223
KS
590 };
591 (bicubic; $src: expr, $off: expr, $step: expr, $coeffs: expr) => {
47933c6d
KS
592 ((i32::from($src[$off - $step] ) * i32::from($coeffs[0]) +
593 i32::from($src[$off] ) * i32::from($coeffs[1]) +
594 i32::from($src[$off + $step] ) * i32::from($coeffs[2]) +
595 i32::from($src[$off + $step * 2]) * i32::from($coeffs[3]) + 64) >> 7).min(255).max(0) as u8
3584b223
KS
596 }
597}
598
599//#[allow(snake_case)]
600fn mc_bilinear(dst: &mut [u8], dstride: usize, src: &[u8], mut soff: usize, sstride: usize, mx: u16, my: u16) {
601 if my == 0 {
602 for dline in dst.chunks_mut(dstride).take(8) {
603 for i in 0..8 {
604 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
605 }
606 soff += sstride;
607 }
608 } else if mx == 0 {
609 for dline in dst.chunks_mut(dstride).take(8) {
610 for i in 0..8 {
611 dline[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + sstride], my);
612 }
613 soff += sstride;
614 }
615 } else {
616 let mut tmp = [0u8; 8];
617 for i in 0..8 {
618 tmp[i] = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
619 }
620 soff += sstride;
621 for dline in dst.chunks_mut(dstride).take(8) {
622 for i in 0..8 {
623 let cur = mc_filter!(bilinear; src[soff + i], src[soff + i + 1], mx);
624 dline[i] = mc_filter!(bilinear; tmp[i], cur, my);
625 tmp[i] = cur;
626 }
627 soff += sstride;
628 }
629 }
630}
631
47933c6d 632#[allow(clippy::trivially_copy_pass_by_ref)]
3584b223
KS
633fn 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
667struct VP6Decoder {
668 dec: VP56Decoder,
669 info: NACodecInfoRef,
670 br: VP6BR,
671 has_alpha: bool,
672}
673
674impl 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
685impl 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 {
93bbc2b0 691 VP_YUVA420_FORMAT
3584b223
KS
692 };
693 let myvinfo = NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt);
47933c6d 694 let myinfo = NACodecTypeInfo::Video(myvinfo);
3584b223
KS
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 }
f9be4e75
KS
712 fn flush(&mut self) {
713 self.dec.flush();
714 }
3584b223
KS
715}
716
7d57ae2f
KS
717impl NAOptionHandler for VP6Decoder {
718 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
719 fn set_options(&mut self, _options: &[NAOption]) { }
720 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
721}
722
08a1fab7 723pub fn get_decoder_vp6() -> Box<NADecoder + Send> {
3584b223
KS
724 Box::new(VP6Decoder::new(false))
725}
726
08a1fab7 727pub fn get_decoder_vp6_alpha() -> Box<NADecoder + Send> {
3584b223
KS
728 Box::new(VP6Decoder::new(true))
729}
730
731#[cfg(test)]
732mod test {
733 use nihav_core::codecs::RegisteredDecoders;
734 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 735 use nihav_codec_support::test::dec_video::*;
78fb6560 736 use crate::duck_register_all_decoders;
e64739f8 737 use nihav_commonfmt::generic_register_all_demuxers;
3584b223
KS
738
739 #[test]
740 fn test_vp6() {
741 let mut dmx_reg = RegisteredDemuxers::new();
742 generic_register_all_demuxers(&mut dmx_reg);
743 let mut dec_reg = RegisteredDecoders::new();
78fb6560 744 duck_register_all_decoders(&mut dec_reg);
3584b223 745
7be4326b
KS
746 test_decoding("avi", "vp6", "assets/Duck/selection_720x576_300kBit_vp60i.avi", Some(16),
747 &dmx_reg, &dec_reg,
748 ExpectedTestResult::MD5([0x042c3e96, 0x8a9b26a2, 0x4dcbaf66, 0x1b788d03]));
3584b223 749 }
7be4326b
KS
750 #[test]
751 fn test_vp6_huff() {
752 let mut dmx_reg = RegisteredDemuxers::new();
753 generic_register_all_demuxers(&mut dmx_reg);
754 let mut dec_reg = RegisteredDecoders::new();
78fb6560 755 duck_register_all_decoders(&mut dec_reg);
7be4326b
KS
756
757 test_decoding("avi", "vp6", "assets/Duck/vp6_crash.avi", Some(4),
758 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
759 [0xdcd70fa0, 0x0d075ce2, 0xc9e65077, 0xb003a92e],
760 [0x334abf96, 0x3a004c7a, 0x5781cd5c, 0x25c3ae5c],
761 [0x6164b851, 0x528cd8de, 0xecab7328, 0x4b49708a],
762 [0x11b048ac, 0xedb3e471, 0xd04e9399, 0x64e623e3],
763 [0x182871b1, 0x2146893a, 0x2912210e, 0x6dd592e8]]));
764 }
765 // todo find good sample for vp6a test
3584b223
KS
766}
767
768const VP6_AC_PROBS: [[[[u8; 11]; 6]; 2]; 3] = [
769 [
770 [
771 [ 227, 246, 230, 247, 244, 255, 255, 255, 255, 255, 255 ],
772 [ 255, 255, 209, 231, 231, 249, 249, 253, 255, 255, 255 ],
773 [ 255, 255, 225, 242, 241, 251, 253, 255, 255, 255, 255 ],
774 [ 255, 255, 241, 253, 252, 255, 255, 255, 255, 255, 255 ],
775 [ 255, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
776 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
777 ], [
778 [ 240, 255, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
779 [ 255, 255, 240, 253, 255, 255, 255, 255, 255, 255, 255 ],
780 [ 255, 255, 255, 255, 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 ]
785 ], [
786 [
787 [ 206, 203, 227, 239, 247, 255, 253, 255, 255, 255, 255 ],
788 [ 207, 199, 220, 236, 243, 252, 252, 255, 255, 255, 255 ],
789 [ 212, 219, 230, 243, 244, 253, 252, 255, 255, 255, 255 ],
790 [ 236, 237, 247, 252, 253, 255, 255, 255, 255, 255, 255 ],
791 [ 240, 240, 248, 255, 255, 255, 255, 255, 255, 255, 255 ],
792 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
793 ], [
794 [ 230, 233, 249, 255, 255, 255, 255, 255, 255, 255, 255 ],
795 [ 238, 238, 250, 255, 255, 255, 255, 255, 255, 255, 255 ],
796 [ 248, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
797 [ 255, 255, 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 ]
801 ], [
802 [
803 [ 225, 239, 227, 231, 244, 253, 243, 255, 255, 253, 255 ],
804 [ 232, 234, 224, 228, 242, 249, 242, 252, 251, 251, 255 ],
805 [ 235, 249, 238, 240, 251, 255, 249, 255, 253, 253, 255 ],
806 [ 249, 253, 251, 250, 255, 255, 255, 255, 255, 255, 255 ],
807 [ 251, 250, 249, 255, 255, 255, 255, 255, 255, 255, 255 ],
808 [ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ]
809 ], [
810 [ 243, 244, 250, 250, 255, 255, 255, 255, 255, 255, 255 ],
811 [ 249, 248, 250, 253, 255, 255, 255, 255, 255, 255, 255 ],
812 [ 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 ],
813 [ 255, 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 ]
817 ]
818];
819
820const VP6_DC_WEIGHTS: [[[i16; 2]; 3]; 5] = [
821 [ [ 122, 133 ], [ 133, 51 ], [ 142, -16 ] ],
822 [ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
823 [ [ 78, 171 ], [ 169, 71 ], [ 221, -30 ] ],
824 [ [ 139, 117 ], [ 214, 44 ], [ 246, -3 ] ],
825 [ [ 168, 79 ], [ 210, 38 ], [ 203, 17 ] ]
826];
827
828const VP6_IDX_TO_AC_BAND: [usize; 64] = [
829 0, 0, 1, 1, 1, 2, 2, 2,
830 2, 2, 2, 3, 3, 3, 3, 3,
831 3, 3, 3, 3, 3, 3, 4, 4,
832 4, 4, 4, 4, 4, 4, 4, 4,
833 4, 4, 4, 4, 4, 5, 5, 5,
834 5, 5, 5, 5, 5, 5, 5, 5,
835 5, 5, 5, 5, 5, 5, 5, 5,
836 5, 5, 5, 5, 5, 5, 5, 5
837];
838
839const VP6_BICUBIC_COEFFS: [[[i16; 4]; 8]; 17] = [
840 [
841 [ 0, 128, 0, 0 ],
842 [ -3, 122, 9, 0 ],
843 [ -4, 109, 24, -1 ],
844 [ -5, 91, 45, -3 ],
845 [ -4, 68, 68, -4 ],
846 [ -3, 45, 91, -5 ],
847 [ -1, 24, 109, -4 ],
848 [ 0, 9, 122, -3 ]
849 ], [
850 [ 0, 128, 0, 0 ],
851 [ -4, 124, 9, -1 ],
852 [ -5, 110, 25, -2 ],
853 [ -6, 91, 46, -3 ],
854 [ -5, 69, 69, -5 ],
855 [ -3, 46, 91, -6 ],
856 [ -2, 25, 110, -5 ],
857 [ -1, 9, 124, -4 ]
858 ], [
859 [ 0, 128, 0, 0 ],
860 [ -4, 123, 10, -1 ],
861 [ -6, 110, 26, -2 ],
862 [ -7, 92, 47, -4 ],
863 [ -6, 70, 70, -6 ],
864 [ -4, 47, 92, -7 ],
865 [ -2, 26, 110, -6 ],
866 [ -1, 10, 123, -4 ]
867 ], [
868 [ 0, 128, 0, 0 ],
869 [ -5, 124, 10, -1 ],
870 [ -7, 110, 27, -2 ],
871 [ -7, 91, 48, -4 ],
872 [ -6, 70, 70, -6 ],
873 [ -4, 48, 92, -8 ],
874 [ -2, 27, 110, -7 ],
875 [ -1, 10, 124, -5 ]
876 ], [
877 [ 0, 128, 0, 0 ],
878 [ -6, 124, 11, -1 ],
879 [ -8, 111, 28, -3 ],
880 [ -8, 92, 49, -5 ],
881 [ -7, 71, 71, -7 ],
882 [ -5, 49, 92, -8 ],
883 [ -3, 28, 111, -8 ],
884 [ -1, 11, 124, -6 ]
885 ], [
886 [ 0, 128, 0, 0 ],
887 [ -6, 123, 12, -1 ],
888 [ -9, 111, 29, -3 ],
889 [ -9, 93, 50, -6 ],
890 [ -8, 72, 72, -8 ],
891 [ -6, 50, 93, -9 ],
892 [ -3, 29, 111, -9 ],
893 [ -1, 12, 123, -6 ]
894 ], [
895 [ 0, 128, 0, 0 ],
896 [ -7, 124, 12, -1 ],
897 [ -10, 111, 30, -3 ],
898 [ -10, 93, 51, -6 ],
899 [ -9, 73, 73, -9 ],
900 [ -6, 51, 93, -10 ],
901 [ -3, 30, 111, -10 ],
902 [ -1, 12, 124, -7 ]
903 ], [
904 [ 0, 128, 0, 0 ],
905 [ -7, 123, 13, -1 ],
906 [ -11, 112, 31, -4 ],
907 [ -11, 94, 52, -7 ],
908 [ -10, 74, 74, -10 ],
909 [ -7, 52, 94, -11 ],
910 [ -4, 31, 112, -11 ],
911 [ -1, 13, 123, -7 ]
912 ], [
913 [ 0, 128, 0, 0 ],
914 [ -8, 124, 13, -1 ],
915 [ -12, 112, 32, -4 ],
916 [ -12, 94, 53, -7 ],
917 [ -10, 74, 74, -10 ],
918 [ -7, 53, 94, -12 ],
919 [ -4, 32, 112, -12 ],
920 [ -1, 13, 124, -8 ]
921 ], [
922 [ 0, 128, 0, 0 ],
923 [ -9, 124, 14, -1 ],
924 [ -13, 112, 33, -4 ],
925 [ -13, 95, 54, -8 ],
926 [ -11, 75, 75, -11 ],
927 [ -8, 54, 95, -13 ],
928 [ -4, 33, 112, -13 ],
929 [ -1, 14, 124, -9 ]
930 ], [
931 [ 0, 128, 0, 0 ],
932 [ -9, 123, 15, -1 ],
933 [ -14, 113, 34, -5 ],
934 [ -14, 95, 55, -8 ],
935 [ -12, 76, 76, -12 ],
936 [ -8, 55, 95, -14 ],
937 [ -5, 34, 112, -13 ],
938 [ -1, 15, 123, -9 ]
939 ], [
940 [ 0, 128, 0, 0 ],
941 [ -10, 124, 15, -1 ],
942 [ -14, 113, 34, -5 ],
943 [ -15, 96, 56, -9 ],
944 [ -13, 77, 77, -13 ],
945 [ -9, 56, 96, -15 ],
946 [ -5, 34, 113, -14 ],
947 [ -1, 15, 124, -10 ]
948 ], [
949 [ 0, 128, 0, 0 ],
950 [ -10, 123, 16, -1 ],
951 [ -15, 113, 35, -5 ],
952 [ -16, 98, 56, -10 ],
953 [ -14, 78, 78, -14 ],
954 [ -10, 56, 98, -16 ],
955 [ -5, 35, 113, -15 ],
956 [ -1, 16, 123, -10 ]
957 ], [
958 [ 0, 128, 0, 0 ],
959 [ -11, 124, 17, -2 ],
960 [ -16, 113, 36, -5 ],
961 [ -17, 98, 57, -10 ],
962 [ -14, 78, 78, -14 ],
963 [ -10, 57, 98, -17 ],
964 [ -5, 36, 113, -16 ],
965 [ -2, 17, 124, -11 ]
966 ], [
967 [ 0, 128, 0, 0 ],
968 [ -12, 125, 17, -2 ],
969 [ -17, 114, 37, -6 ],
970 [ -18, 99, 58, -11 ],
971 [ -15, 79, 79, -15 ],
972 [ -11, 58, 99, -18 ],
973 [ -6, 37, 114, -17 ],
974 [ -2, 17, 125, -12 ]
975 ], [
976 [ 0, 128, 0, 0 ],
977 [ -12, 124, 18, -2 ],
978 [ -18, 114, 38, -6 ],
979 [ -19, 99, 59, -11 ],
980 [ -16, 80, 80, -16 ],
981 [ -11, 59, 99, -19 ],
982 [ -6, 38, 114, -18 ],
983 [ -2, 18, 124, -12 ]
984 ], [
985 [ 0, 128, 0, 0 ],
986 [ -4, 118, 16, -2 ],
987 [ -7, 106, 34, -5 ],
988 [ -8, 90, 53, -7 ],
989 [ -8, 72, 72, -8 ],
990 [ -7, 53, 90, -8 ],
991 [ -5, 34, 106, -7 ],
992 [ -2, 16, 118, -4 ]
993 ]
994];