rename register_all_codecs to register_all_decoders
[nihav.git] / nihav-duck / src / codecs / vp7.rs
CommitLineData
587a6d78
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
b4d5b851
KS
3use nihav_codec_support::codecs::{MV, ZERO_MV};
4use nihav_codec_support::data::GenericCache;
587a6d78
KS
5use super::vpcommon::*;
6use super::vp7data::*;
7use super::vp7dsp::*;
8
9enum VPTreeDef<T: Copy> {
10 Index(u8),
11 Value(T),
12}
13
14trait VPTreeReader {
15 fn read_tree<T:Copy>(&mut self, tree_def: &[VPTreeDef<T>], tree_prob: &[u8]) -> T;
16}
17
18impl<'a> VPTreeReader for BoolCoder<'a> {
19 fn read_tree<T:Copy>(&mut self, tree_def: &[VPTreeDef<T>], tree_prob: &[u8]) -> T {
20 let mut idx = 0;
21
22 loop {
23 let bit = self.read_prob(tree_prob[idx >> 1]);
24 match tree_def[idx + (bit as usize)] {
25 VPTreeDef::Value(v) => return v,
26 VPTreeDef::Index(ix) => { idx = ix as usize; },
27 };
28 }
29 }
30}
31
32#[repr(u8)]
33#[derive(Clone,Copy,PartialEq,Debug)]
34enum PredMode {
35 DCPred,
36 HPred,
37 VPred,
38 TMPred,
39 BPred,
40
41 //sub-block prediction modes
42 LDPred,
43 RDPred,
44 VRPred,
45 VLPred,
46 HDPred,
47 HUPred,
48
49 Inter,
50}
51
52impl Default for PredMode {
53 fn default() -> Self { PredMode::DCPred }
54}
55
56impl PredMode {
57 fn to_b_mode(self) -> Self {
58 if self == PredMode::DCPred {
59 self
60 } else {
61 PredMode::TMPred
62 }
63 }
64 fn to_b_index(self) -> usize {
65 match self {
66 PredMode::DCPred => 0,
67 PredMode::TMPred => 1,
68 PredMode::VPred => 2,
69 PredMode::HPred => 3,
70 PredMode::LDPred => 4,
71 PredMode::RDPred => 5,
72 PredMode::VRPred => 6,
73 PredMode::VLPred => 7,
74 PredMode::HDPred => 8,
75 PredMode::HUPred => 9,
76 _ => unreachable!(),
77 }
78 }
79}
80
81const PITCH_MODE_NORMAL: u8 = 0;
82const PITCH_MODE_FOUR: u8 = 1;
83const PITCH_MODE_X2: u8 = 2;
84const PITCH_MODE_X4: u8 = 3;
85
86#[derive(Clone,Copy,Default)]
87struct MBFeature {
88 present_prob: u8,
89 tree_probs: [u8; 3],
90 def_val: [u8; 4],
91}
92
93#[derive(Clone,Copy,PartialEq)]
94enum DCTToken {
95 Zero,
96 One,
97 Two,
98 Three,
99 Four,
100 Cat1,
101 Cat2,
102 Cat3,
103 Cat4,
104 Cat5,
105 Cat6,
106 EOB,
107}
108
109fn expand_token(bc: &mut BoolCoder, token: DCTToken) -> i16 {
110 let cat;
111 match token {
112 DCTToken::Zero => return 0,
113 DCTToken::One => return if bc.read_bool() { -1 } else { 1 },
114 DCTToken::Two => return if bc.read_bool() { -2 } else { 2 },
115 DCTToken::Three => return if bc.read_bool() { -3 } else { 3 },
116 DCTToken::Four => return if bc.read_bool() { -4 } else { 4 },
117 DCTToken::Cat1 => cat = 0,
118 DCTToken::Cat2 => cat = 1,
119 DCTToken::Cat3 => cat = 2,
120 DCTToken::Cat4 => cat = 3,
121 DCTToken::Cat5 => cat = 4,
122 DCTToken::Cat6 => cat = 5,
123 _ => unreachable!(),
124 };
125 let mut add = 0i16;
126 let add_probs = &VP56_COEF_ADD_PROBS[cat];
127 for prob in add_probs.iter() {
128 if *prob == 128 { break; }
129 add = (add << 1) | (bc.read_prob(*prob) as i16);
130 }
131 let sign = bc.read_bool();
132 let level = VP56_COEF_BASE[cat] + add;
133 if !sign {
134 level
135 } else {
136 -level
137 }
138}
139
140struct SBParams<'a> {
141 coef_probs: &'a [[[[u8; 11]; 3]; 8]; 4],
142 scan: &'a [usize; 16],
143 qmat: &'a [i16; 16],
144}
145
47933c6d 146fn decode_subblock(bc: &mut BoolCoder, coeffs: &mut [i16; 16], ctype: usize, pctx: u8, sbparams: &SBParams) -> u8 {
587a6d78
KS
147 const COEF_BANDS: [usize; 16] = [ 0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7 ];
148
149 let mut has_nz = 0;
150 let start = if ctype != 0 { 0 } else { 1 };
151 *coeffs = [0; 16];
152 let mut cval = pctx as usize;
153 for idx in start..16 {
154 let probs = &sbparams.coef_probs[ctype][COEF_BANDS[idx]][cval];
155 let tok = bc.read_tree(COEF_TREE, probs);
156 if tok == DCTToken::EOB { break; }
157 let level = expand_token(bc, tok);
158 coeffs[sbparams.scan[idx]] = level.wrapping_mul(sbparams.qmat[idx]);
159 cval = level.abs().min(2) as usize;
160 has_nz |= cval;
161 }
162 if has_nz > 0 { 1 } else { 0 }
163}
164
165#[derive(Clone,Copy,Default)]
166struct MBInfo {
167 mb_type: VPMBType,
168 ymode: PredMode,
169 uvmode: PredMode,
170 loop_str: u8,
171 upd_gf: bool,
172}
173
174#[derive(Default)]
175struct DecoderState {
176 features: [Option<MBFeature>; 4],
177
178 fading: bool,
179 fade_alpha: u16,
180 fade_beta: u16,
181
182 lf_simple: bool,
183 loop_filter_level: u8,
184 loop_sharpness: u8,
185
186 is_intra: bool,
187 version: u8,
188
189 kf_ymode_prob: [u8; 4],
190 kf_uvmode_prob: [u8; 3],
191
192 prob_intra_pred: u8,
193 prob_last_pred: u8,
194
195 coef_probs: [[[[u8; 11]; 3]; 8]; 4],
196 mv_probs: [[u8; 17]; 2],
197
198 force_quant: Option<u8>,
199 force_loop_str: Option<u8>,
200 force_gf_update: bool,
201 force_pitch: Option<u8>,
202
203 has_y2: bool,
99cc55ef
KS
204 pdc_pred_val: [i16; 2],
205 pdc_pred_count: [usize; 2],
587a6d78
KS
206
207 ipred_ctx_y: IPredContext,
208 ipred_ctx_u: IPredContext,
209 ipred_ctx_v: IPredContext,
210}
211
212impl DecoderState {
213 fn reset(&mut self) {
214 self.kf_ymode_prob.copy_from_slice(Y_MODE_TREE_PROBS);
215 self.kf_uvmode_prob.copy_from_slice(UV_MODE_TREE_PROBS);
216 self.coef_probs.copy_from_slice(&DEFAULT_DCT_PROBS);
217 self.mv_probs.copy_from_slice(&DEFAULT_MV_PROBS);
218 }
219}
220
221#[derive(Clone,Copy,Debug,PartialEq)]
222enum MVSplitMode {
223 TopBottom,
224 LeftRight,
225 Quarters,
226 Sixteenths,
227}
228
229#[derive(Clone,Copy,Debug,PartialEq)]
230enum SubMVRef {
231 Left,
232 Above,
233 New,
234 Zero,
235}
236
237fn decode_mv_component(bc: &mut BoolCoder, probs: &[u8; 17]) -> i16 {
238 const LONG_VECTOR_ORDER: [usize; 7] = [ 0, 1, 2, 7, 6, 5, 4 ];
239
240 let val = if !bc.read_prob(probs[0]) {
241 bc.read_tree(SMALL_MV_TREE, &probs[2..9])
242 } else {
243 let raw_probs = &probs[9..];
244 let mut raw = 0;
245 for ord in LONG_VECTOR_ORDER.iter() {
246 raw |= (bc.read_prob(raw_probs[*ord]) as i16) << *ord;
247 }
248 if (raw & 0xF0) != 0 {
249 raw |= (bc.read_prob(raw_probs[3]) as i16) << 3;
250 } else {
251 raw |= 1 << 3;
252 }
253 raw
254 };
255 if (val == 0) || !bc.read_prob(probs[1]) {
256 val
257 } else {
258 -val
259 }
260}
261
262struct PredCache {
263 y_pred: GenericCache<u8>,
264 u_pred: GenericCache<u8>,
265 v_pred: GenericCache<u8>,
266 y2_pred: GenericCache<u8>,
267 y_pred_left: [u8; 4],
268 u_pred_left: [u8; 2],
269 v_pred_left: [u8; 2],
270 y2_pred_left: u8,
271}
272
273impl PredCache {
274 fn new() -> Self {
275 Self {
276 y_pred: GenericCache::new(1, 1, 0),
277 u_pred: GenericCache::new(1, 1, 0),
278 v_pred: GenericCache::new(1, 1, 0),
279 y2_pred: GenericCache::new(1, 1, 0),
280 y_pred_left: [0; 4],
281 u_pred_left: [0; 2],
282 v_pred_left: [0; 2],
283 y2_pred_left: 0,
284 }
285 }
286 fn resize(&mut self, mb_w: usize) {
287 self.y_pred = GenericCache::new(4, mb_w * 4 + 1, 0);
288 self.u_pred = GenericCache::new(2, mb_w * 2 + 1, 0);
289 self.v_pred = GenericCache::new(2, mb_w * 2 + 1, 0);
290 self.y2_pred = GenericCache::new(1, mb_w + 1, 0);
291 }
292 fn reset(&mut self) {
293 self.y_pred.reset();
294 self.u_pred.reset();
295 self.v_pred.reset();
296 self.y2_pred.reset();
297 self.y_pred_left = [0; 4];
298 self.u_pred_left = [0; 2];
299 self.v_pred_left = [0; 2];
300 self.y2_pred_left = 0;
301 }
302 fn update_row(&mut self) {
303 self.y_pred.update_row();
304 self.u_pred.update_row();
305 self.v_pred.update_row();
306 self.y2_pred.update_row();
307 }
308}
309
310struct VP7Decoder {
311 info: NACodecInfoRef,
312
313 shuf: VPShuffler,
314 width: usize,
315 height: usize,
316 mb_w: usize,
317 mb_h: usize,
318 mb_info: Vec<MBInfo>,
319 mvs: Vec<MV>,
320 mv_stride: usize,
321
322 ymodes: Vec<PredMode>,
323 ymode_stride: usize,
324 uvmodes: Vec<PredMode>,
325 uvmode_stride: usize,
326
327 dstate: DecoderState,
328 pcache: PredCache,
329
330 coeffs: [[i16; 16]; 25],
331 scan: [usize; 16],
332 qmat: [[[i16; 16]; 3]; 5],
333
334 mc_buf: NAVideoBufferRef<u8>,
335
336 tmp_scan: [usize; 16],
337}
338
339impl VP7Decoder {
340 fn new() -> Self {
341 let vt = alloc_video_buffer(NAVideoInfo::new(128, 128, false, YUV420_FORMAT), 4).unwrap();
342 let mut scan = [0; 16];
343 scan.copy_from_slice(&DEFAULT_SCAN_ORDER);
344 let mc_buf = vt.get_vbuf().unwrap();
345 Self {
346 info: NACodecInfoRef::default(),
347
348 shuf: VPShuffler::new(),
349 width: 0,
350 height: 0,
351 mb_w: 0,
352 mb_h: 0,
353 mb_info: Vec::new(),
354 mvs: Vec::new(),
355 mv_stride: 0,
356
357 ymodes: Vec::new(),
358 ymode_stride: 0,
359 uvmodes: Vec::new(),
360 uvmode_stride: 0,
361
362 dstate: DecoderState::default(),
363 pcache: PredCache::new(),
364
365 coeffs: [[0; 16]; 25],
366 scan,
367 tmp_scan: [0; 16],
368 qmat: [[[0; 16]; 3]; 5],
369
370 mc_buf,
371 }
372 }
373 fn set_dimensions(&mut self, width: usize, height: usize) {
374 if (width == self.width) && (height == self.height) {
375 return;
376 }
377 self.width = width;
378 self.height = height;
379 self.mb_w = (self.width + 15) >> 4;
380 self.mb_h = (self.height + 15) >> 4;
381 self.mb_info.resize(self.mb_w * self.mb_h, MBInfo::default());
382 self.mv_stride = self.mb_w * 4;
383 self.mvs.resize(self.mv_stride * self.mb_h * 4, ZERO_MV);
384
385 self.ymode_stride = self.mb_w * 4;
386 self.uvmode_stride = self.mb_w;
387 self.ymodes.resize(self.ymode_stride * self.mb_h * 4, PredMode::default());
388 self.uvmodes.resize(self.uvmode_stride * self.mb_h, PredMode::default());
389
390 self.pcache.resize(self.mb_w);
391 }
392 fn read_features(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
393 for (i, feat) in self.dstate.features.iter_mut().enumerate() {
394 if bc.read_bool() {
395 let mut feature = MBFeature::default();
396 feature.present_prob = bc.read_byte();
397 for tp in feature.tree_probs.iter_mut() {
398 if bc.read_bool() {
399 *tp = bc.read_byte();
400 } else {
401 *tp = 255;
402 }
403 }
404 if i != 2 {
405 let fbits = match i {
406 0 => 7,
407 1 => 6,
408 _ => if self.dstate.version == 0 { 8 } else { 5 },
409 };
410 for dval in feature.def_val.iter_mut() {
411 if bc.read_bool() {
412 *dval = bc.read_bits(fbits) as u8;
413 } else {
414 *dval = 0;
415 }
416 }
417 }
418 *feat = Some(feature);
419 } else {
420 *feat = None;
421 }
422 }
423 Ok(())
424 }
425 fn read_dct_coef_prob_upd(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
426 for i in 0..4 {
427 for j in 0..8 {
428 for k in 0..3 {
429 for l in 0..11 {
430 if bc.read_prob(DCT_UPDATE_PROBS[i][j][k][l]) {
431 self.dstate.coef_probs[i][j][k][l] = bc.read_byte();
432 }
433 }
434 }
435 }
436 }
437 Ok(())
438 }
439 fn read_mv_prob_upd(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
440 for comp in 0..2 {
441 for i in 0..17 {
442 if bc.read_prob(MV_UPDATE_PROBS[comp][i]) {
443 self.dstate.mv_probs[comp][i] = bc.read_probability();
444 }
445 }
446 }
447 Ok(())
448 }
449 fn decode_mb_features(&mut self, bc: &mut BoolCoder, _mb_x: usize, _mb_y: usize) -> DecoderResult<()> {
450 self.dstate.force_quant = None;
451 self.dstate.force_loop_str = None;
452 self.dstate.force_gf_update = false;
453 self.dstate.force_pitch = None;
454 for (i, feat) in self.dstate.features.iter().enumerate() {
455 if let Some(feat) = feat {
456 let present = bc.read_prob(feat.present_prob);
457 if present {
458 let ftype_idx = bc.read_tree(FEATURE_TREE, &feat.tree_probs);
459 let val = feat.def_val[ftype_idx];
460 match i {
461 0 => self.dstate.force_quant = Some(ftype_idx as u8),
462 1 => self.dstate.force_loop_str = Some(val),
463 2 => self.dstate.force_gf_update = true,
464 _ => self.dstate.force_pitch = Some(val),
465 };
466 }
467 }
468 }
469 Ok(())
470 }
99cc55ef 471 fn decode_residue(&mut self, bc: &mut BoolCoder, mb_x: usize, mb_idx: usize, use_last: bool) {
587a6d78
KS
472 let qmat_idx = if let Some(idx) = self.dstate.force_quant { (idx as usize) + 1 } else { 0 };
473 let mut sbparams = SBParams {
474 scan: &DEFAULT_SCAN_ORDER,
475 qmat: &self.qmat[qmat_idx][2],
476 coef_probs: &self.dstate.coef_probs,
477 };
478 let mut has_ac = [false; 25];
479 let ytype;
480 if self.dstate.has_y2 {
481 let pred = &self.pcache.y2_pred;
482 let pidx = pred.xpos + mb_x;
483 let pctx = self.pcache.y2_pred_left + pred.data[pidx - pred.stride];
484
485 let has_nz = decode_subblock(bc, &mut self.coeffs[24], 1, pctx, &sbparams);
486 self.pcache.y2_pred.data[pidx] = has_nz;
487 self.pcache.y2_pred_left = has_nz;
488 has_ac[24] = has_nz > 0;
489
490 ytype = 0;
491 } else {
492 let pred = &mut self.pcache.y2_pred;
493 let pidx = pred.xpos + mb_x;
494 pred.data[pidx] = pred.data[pidx - pred.stride];
495
496 ytype = 3;
497 }
498 sbparams.scan = &self.scan;
499 sbparams.qmat = &self.qmat[qmat_idx][0];
500 for i in 0..16 {
501 let bx = i & 3;
502 let by = i >> 2;
503 let pred = &self.pcache.y_pred;
504 let pidx = pred.xpos + mb_x * 4 + bx + by * pred.stride;
505 let pctx = self.pcache.y_pred_left[by] + pred.data[pidx - pred.stride];
506
507 let has_nz = decode_subblock(bc, &mut self.coeffs[i], ytype, pctx, &sbparams);
508 self.pcache.y_pred.data[pidx] = has_nz;
509 self.pcache.y_pred_left[by] = has_nz;
510 has_ac[i] = has_nz > 0;
511 }
512 sbparams.qmat = &self.qmat[qmat_idx][1];
513 for i in 16..20 {
514 let bx = i & 1;
515 let by = (i >> 1) & 1;
516 let pred = &self.pcache.u_pred;
517 let pidx = pred.xpos + mb_x * 2 + bx + by * pred.stride;
518 let pctx = self.pcache.u_pred_left[by] + pred.data[pidx - pred.stride];
519
520 let has_nz = decode_subblock(bc, &mut self.coeffs[i], 2, pctx, &sbparams);
521 self.pcache.u_pred.data[pidx] = has_nz;
522 self.pcache.u_pred_left[by] = has_nz;
523 has_ac[i] = has_nz > 0;
524 }
525 for i in 20..24 {
526 let bx = i & 1;
527 let by = (i >> 1) & 1;
528 let pred = &self.pcache.v_pred;
529 let pidx = pred.xpos + mb_x * 2 + bx + by * pred.stride;
530 let pctx = self.pcache.v_pred_left[by] + pred.data[pidx - pred.stride];
531
532 let has_nz = decode_subblock(bc, &mut self.coeffs[i], 2, pctx, &sbparams);
533 self.pcache.v_pred.data[pidx] = has_nz;
534 self.pcache.v_pred_left[by] = has_nz;
535 has_ac[i] = has_nz > 0;
536 }
537
538 if self.dstate.has_y2 {
539 let y2block = &mut self.coeffs[24];
540 if self.mb_info[mb_idx].mb_type != VPMBType::Intra {
541 let mut dc = y2block[0];
99cc55ef
KS
542 let pdc_idx = if use_last { 0 } else { 1 };
543 let pval = self.dstate.pdc_pred_val[pdc_idx];
544
545 if self.dstate.pdc_pred_count[pdc_idx] > 3 {
587a6d78
KS
546 dc += pval;
547 y2block[0] = dc;
548 }
549 if (pval == 0) || (dc == 0) || ((pval ^ dc) < 0) {
99cc55ef 550 self.dstate.pdc_pred_count[pdc_idx] = 0;
587a6d78 551 } else if dc == pval {
99cc55ef 552 self.dstate.pdc_pred_count[pdc_idx] += 1;
587a6d78 553 }
99cc55ef 554 self.dstate.pdc_pred_val[pdc_idx] = dc;
587a6d78
KS
555 }
556 if has_ac[24] {
557 idct4x4(y2block);
4726ca2c 558 } else if y2block[0] != 0 {
587a6d78
KS
559 idct4x4_dc(y2block);
560 }
561 for i in 0..16 {
562 self.coeffs[i][0] = self.coeffs[24][i];
563 }
564 }
565 for i in 0..24 {
566 if has_ac[i] {
567 idct4x4(&mut self.coeffs[i]);
4726ca2c 568 } else if self.coeffs[i][0] != 0 {
587a6d78
KS
569 idct4x4_dc(&mut self.coeffs[i]);
570 }
571 }
572 }
573
574 fn set_qmat(&mut self, y_dc_q: usize, y_ac_q: usize, y2_dc_q: usize, y2_ac_q: usize, uv_dc_q: usize, uv_ac_q: usize) {
575 self.qmat[0][0][0] = Y_DC_QUANTS[y_dc_q];
576 for i in 1..16 {
577 self.qmat[0][0][i] = Y_AC_QUANTS[y_ac_q];
578 }
579 self.qmat[0][1][0] = UV_DC_QUANTS[uv_dc_q];
580 for i in 1..16 {
581 self.qmat[0][1][i] = UV_AC_QUANTS[uv_ac_q];
582 }
583 self.qmat[0][2][0] = Y2_DC_QUANTS[y2_dc_q];
584 for i in 1..16 {
585 self.qmat[0][2][i] = Y2_AC_QUANTS[y2_ac_q];
586 }
587 if let Some(ref feat) = self.dstate.features[0] {
588 for j in 0..4 {
589 let q = feat.def_val[j] as usize;
590 self.qmat[j + 1][0][0] = Y_DC_QUANTS[q];
591 for i in 1..16 {
592 self.qmat[j + 1][0][i] = Y_AC_QUANTS[q];
593 }
594 self.qmat[j + 1][1][0] = UV_DC_QUANTS[q];
595 for i in 1..16 {
596 self.qmat[j + 1][1][i] = UV_AC_QUANTS[q];
597 }
598 self.qmat[j + 1][2][0] = Y2_DC_QUANTS[q];
599 for i in 1..16 {
600 self.qmat[j + 1][2][i] = Y2_AC_QUANTS[q];
601 }
602 }
603 }
604 }
605 fn fill_ymode(&mut self, mb_x: usize, mb_y: usize, ymode: PredMode) {
606 let mut iidx = mb_x * 4 + mb_y * 4 * self.ymode_stride;
607 for _ in 0..4 {
608 for x in 0..4 {
609 self.ymodes[iidx + x] = ymode;
610 }
611 iidx += self.ymode_stride;
612 }
613 }
614 fn fill_mv(&mut self, mb_x: usize, mb_y: usize, mv: MV) {
615 let mut iidx = mb_x * 4 + mb_y * 4 * self.mv_stride;
616 for _ in 0..4 {
617 for x in 0..4 {
618 self.mvs[iidx + x] = mv;
619 }
620 iidx += self.mb_w * 4;
621 }
622 }
623 fn find_mv_pred(&self, mb_x: usize, mb_y: usize) -> ([u8; 4], MV, MV, MV) {
624 const CAND_POS: [(i8, i8, u8, u8); 12] = [
625 (-1, 0, 8, 12), ( 0, -1, 8, 3),
626 (-1, -1, 2, 15), (-1, 1, 2, 12),
627 (-2, 0, 2, 12), ( 0, -2, 2, 3),
628 (-1, -2, 1, 15), (-2, -1, 1, 15),
629 (-2, 1, 1, 12), (-1, 2, 1, 12),
630 (-2, -2, 1, 15), (-2, 2, 1, 12)
631 ];
632
633 let mut nearest_mv = ZERO_MV;
634 let mut near_mv = ZERO_MV;
635
636 let mut ct: [u8; 4] = [0; 4];
637
638 let start = if self.dstate.version == 0 { 1 } else { 0 };
639 let mvwrap = (self.mb_w as isize) + 1;
640 for (yoff, xoff, weight, blk_no) in CAND_POS.iter() {
641 let cx = (mb_x as isize) + (*xoff as isize);
642 let cy = (mb_y as isize) + (*yoff as isize);
643 let mvpos = cx + cy * mvwrap;
644 if (mvpos < start) || ((mvpos % mvwrap) == (mvwrap - 1)) {
645 ct[0] += weight;
646 continue;
647 }
648 let cx = (mvpos % mvwrap) as usize;
649 let cy = (mvpos / mvwrap) as usize;
650 let bx = (*blk_no as usize) & 3;
651 let by = (*blk_no as usize) >> 2;
652 let blk_pos = cx * 4 + bx + (cy * 4 + by) * self.mv_stride;
653 let mv = self.mvs[blk_pos];
654 if mv == ZERO_MV {
655 ct[0] += weight;
656 continue;
657 }
658 let idx;
659 if (nearest_mv == ZERO_MV) || (nearest_mv == mv) {
660 nearest_mv = mv;
661 idx = 1;
662 } else if near_mv == ZERO_MV {
663 near_mv = mv;
664 idx = 2;
665 } else {
666 idx = if mv == near_mv { 2 } else { 3 };
667 }
668 ct[idx] += weight;
669 }
670 let pred_mv = if ct[1] > ct[2] {
671 if ct[1] >= ct[0] { nearest_mv } else { ZERO_MV }
672 } else {
673 if ct[2] >= ct[0] { near_mv } else { ZERO_MV }
674 };
675
676 let mvprobs = [INTER_MODE_PROBS[ct[0] as usize][0],
677 INTER_MODE_PROBS[ct[1] as usize][1],
678 INTER_MODE_PROBS[ct[2] as usize][2],
679 INTER_MODE_PROBS[ct[2] as usize][3]];
680
681 (mvprobs, nearest_mv, near_mv, pred_mv)
682 }
683 fn get_split_mv(&self, bc: &mut BoolCoder, mb_x: usize, mb_y: usize, bx: usize, by: usize, pred_mv: MV) -> MV {
684 let mode = bc.read_tree(SUB_MV_REF_TREE, &SUB_MV_REF_PROBS);
685 let mvidx = mb_x * 4 + bx + (mb_y * 4 + by) * self.mv_stride;
686 match mode {
687 SubMVRef::Left => {
688 if (mb_x > 0) || (bx > 0) {
689 self.mvs[mvidx - 1]
690 } else {
691 ZERO_MV
692 }
693 },
694 SubMVRef::Above => {
695 if (mb_y > 0) || (by > 0) {
696 self.mvs[mvidx - self.mv_stride]
697 } else {
698 ZERO_MV
699 }
700 },
701 SubMVRef::Zero => ZERO_MV,
702 SubMVRef::New => {
703 let dmy = decode_mv_component(bc, &self.dstate.mv_probs[0]);
704 let dmx = decode_mv_component(bc, &self.dstate.mv_probs[1]);
705 pred_mv + MV{ x: dmx, y: dmy }
706 },
707 }
708 }
709 fn do_split_mv(&mut self, bc: &mut BoolCoder, mb_x: usize, mb_y: usize, pred_mv: MV) -> DecoderResult<()> {
710 let split_mode = bc.read_tree(MV_SPLIT_MODE_TREE, &MV_SPLIT_MODE_PROBS);
711 let mut mvidx = mb_x * 4 + mb_y * 4 * self.mv_stride;
712 match split_mode {
713 MVSplitMode::TopBottom => {
714 let top_mv = self.get_split_mv(bc, mb_x, mb_y, 0, 0, pred_mv);
715 for _ in 0..2 {
716 for x in 0..4 { self.mvs[mvidx + x] = top_mv; }
717 mvidx += self.mv_stride;
718 }
719 let bot_mv = self.get_split_mv(bc, mb_x, mb_y, 0, 2, pred_mv);
720 for _ in 2..4 {
721 for x in 0..4 { self.mvs[mvidx + x] = bot_mv; }
722 mvidx += self.mv_stride;
723 }
724 },
725 MVSplitMode::LeftRight => {
726 let left_mv = self.get_split_mv(bc, mb_x, mb_y, 0, 0, pred_mv);
727 self.mvs[mvidx + 1] = left_mv;
728 let right_mv = self.get_split_mv(bc, mb_x, mb_y, 2, 0, pred_mv);
729 for _ in 0..4 {
730 self.mvs[mvidx + 0] = left_mv;
731 self.mvs[mvidx + 1] = left_mv;
732 self.mvs[mvidx + 2] = right_mv;
733 self.mvs[mvidx + 3] = right_mv;
734 mvidx += self.mv_stride;
735 }
736 },
737 MVSplitMode::Quarters => {
738 for y in (0..4).step_by(2) {
739 for x in (0..4).step_by(2) {
740 self.mvs[mvidx + x] = self.get_split_mv(bc, mb_x, mb_y, x, y, pred_mv);
741 self.mvs[mvidx + x + 1] = self.mvs[mvidx + x];
742 }
743 for x in 0..4 {
744 self.mvs[mvidx + x + self.mv_stride] = self.mvs[mvidx + x];
745 }
746 mvidx += self.mv_stride * 2;
747 }
748 },
749 MVSplitMode::Sixteenths => {
750 for y in 0..4 {
751 for x in 0..4 {
752 self.mvs[mvidx + x] = self.get_split_mv(bc, mb_x, mb_y, x, y, pred_mv);
753 }
754 mvidx += self.mv_stride;
755 }
756 },
757 };
758 Ok(())
759 }
760
761 fn add_residue(&self, dframe: &mut NASimpleVideoFrame<u8>, mb_x: usize, mb_y: usize, do_luma: bool, pitch_mode: u8) {
762 if do_luma {
763 let ydst = &mut dframe.data[dframe.offset[0]..];
764 let ystride = dframe.stride[0];
765 let mut yoff = mb_x * 16 + mb_y * 16 * ystride;
766 match pitch_mode {
767 PITCH_MODE_NORMAL => {
768 for y in 0..4 {
769 for x in 0..4 {
770 add_coeffs4x4(ydst, yoff + x * 4, ystride, &self.coeffs[x + y * 4]);
771 }
772 yoff += 4 * ystride;
773 }
774 },
775 PITCH_MODE_FOUR => {
776 for y in 0..16 {
777 add_coeffs16x1(ydst, yoff, &self.coeffs[y]);
778 yoff += ystride;
779 }
780 },
781 PITCH_MODE_X2 => {
782 for y in 0..2 {
783 for x in 0..4 {
784 add_coeffs4x4(ydst, yoff + x * 4, ystride * 2, &self.coeffs[x + y * 4]);
785 }
786 yoff += 8 * ystride;
787 }
788 yoff -= 15 * ystride;
789 for y in 2..4 {
790 for x in 0..4 {
791 add_coeffs4x4(ydst, yoff + x * 4, ystride * 2, &self.coeffs[x + y * 4]);
792 }
793 yoff += 8 * ystride;
794 }
795 },
796 PITCH_MODE_X4 => {
797 for y in 0..4 {
798 for x in 0..4 {
799 add_coeffs4x4(ydst, yoff + x * 4, ystride * 4, &self.coeffs[x + y * 4]);
800 }
801 yoff += ystride;
802 }
803 },
804 _ => unreachable!(),
805 };
806 }
807 let dst = &mut dframe.data[0..];
808 let mut uoff = dframe.offset[1] + mb_x * 8 + mb_y * 8 * dframe.stride[1];
809 let ustride = dframe.stride[1];
810 let mut voff = dframe.offset[2] + mb_x * 8 + mb_y * 8 * dframe.stride[2];
811 let vstride = dframe.stride[2];
812 if (pitch_mode == PITCH_MODE_NORMAL) || (pitch_mode == PITCH_MODE_FOUR) {
813 for y in 0..2 {
814 for x in 0..2 {
815 add_coeffs4x4(dst, uoff + x * 4, ustride, &self.coeffs[16 + x + y * 2]);
816 add_coeffs4x4(dst, voff + x * 4, vstride, &self.coeffs[20 + x + y * 2]);
817 }
818 uoff += ustride * 4;
819 voff += vstride * 4;
820 }
821 } else {
822 for y in 0..2 {
823 for x in 0..2 {
824 add_coeffs4x4(dst, uoff + x * 4, ustride * 2, &self.coeffs[16 + x + y * 2]);
825 add_coeffs4x4(dst, voff + x * 4, vstride * 2, &self.coeffs[20 + x + y * 2]);
826 }
827 uoff += ustride;
828 voff += vstride;
829 }
830 }
831 }
832 fn recon_intra_mb(&mut self, dframe: &mut NASimpleVideoFrame<u8>, mb_x: usize, mb_y: usize) -> DecoderResult<()> {
833 let pitch = self.dstate.force_pitch.unwrap_or(0);
834 let pitch_mode = (pitch >> 3) & 3;
835
836 let mb_idx = mb_x + mb_y * self.mb_w;
837 let has_top = mb_y > 0;
838 let has_left = mb_x > 0;
839 let ydst = &mut dframe.data[dframe.offset[0]..];
840 let ystride = dframe.stride[0];
841 let mut yoff = mb_x * 16 + mb_y * 16 * ystride;
842 let ipred_ctx_y = &mut self.dstate.ipred_ctx_y;
843 ipred_ctx_y.has_top = has_top;
844 ipred_ctx_y.has_left = has_left;
845 let is_normal = self.mb_info[mb_idx].ymode != PredMode::BPred;
846 if is_normal {
847 ipred_ctx_y.fill(ydst, yoff, ystride, 16, 16);
848 match self.mb_info[mb_idx].ymode {
849 PredMode::DCPred => IPred16x16::ipred_dc(ydst, yoff, ystride, ipred_ctx_y),
850 PredMode::HPred => IPred16x16::ipred_h (ydst, yoff, ystride, ipred_ctx_y),
851 PredMode::VPred => IPred16x16::ipred_v (ydst, yoff, ystride, ipred_ctx_y),
852 PredMode::TMPred => IPred16x16::ipred_tm(ydst, yoff, ystride, ipred_ctx_y),
853 _ => unreachable!(),
854 };
855 } else {
856 validate!((pitch_mode == PITCH_MODE_NORMAL) || (pitch_mode == PITCH_MODE_X2));
857 let mut iidx = mb_x * 4 + mb_y * 4 * self.ymode_stride;
858 let mut tr_save = [0x80u8; 16];
859 if pitch_mode == PITCH_MODE_X2 {
860 // reorganise coefficient data for interlaced case
861 for y in (0..4).step_by(2) {
862 for x in 0..4 {
863 let mut tmpblock = [0i16; 16 * 2];
864 let eidx = x + y * 4;
865 let oidx = x + y * 4 + 4;
866 for i in 0..4 {
867 for j in 0..4 {
868 tmpblock[i * 8 + 0 + j] = self.coeffs[eidx][i * 4 + j];
869 tmpblock[i * 8 + 4 + j] = self.coeffs[oidx][i * 4 + j];
870 }
871 }
872 self.coeffs[eidx].copy_from_slice(&tmpblock[0..16]);
873 self.coeffs[oidx].copy_from_slice(&tmpblock[16..32]);
874 }
875 }
876 }
44901bc9 877 let tr_edge = if has_top { ydst[yoff - ystride + 15] } else { 0x80 };
587a6d78
KS
878 for y in 0..4 {
879 for x in 0..4 {
880 ipred_ctx_y.has_left = has_left || x > 0;
881 let bmode = self.ymodes[iidx + x];
882 let cur_yoff = yoff + x * 4;
44901bc9
KS
883 let has_tr = ipred_ctx_y.has_top && ((x < 3) || ((y == 0) && (mb_y < self.mb_w - 1)));
884 let has_dl = ipred_ctx_y.has_left && (x == 0) && (y < 3);
587a6d78
KS
885 ipred_ctx_y.fill(ydst, cur_yoff, ystride,
886 if has_tr { 8 } else { 4 },
887 if has_dl { 8 } else { 4 });
888 if !has_tr {
889 for i in 0..4 {
890 ipred_ctx_y.top[i + 4] = tr_save[x * 4 + i];
891 }
892 } else {
893 for i in 0..4 {
894 tr_save[x * 4 + i] = ipred_ctx_y.top[i + 4];
895 }
896 }
44901bc9
KS
897 if (mb_x == self.mb_w - 1) && has_top && (x == 3) {
898 for i in 0..4 {
899 ipred_ctx_y.top[i + 4] = tr_edge;
900 }
901 }
587a6d78
KS
902 match bmode {
903 PredMode::DCPred => IPred4x4::ipred_dc(ydst, cur_yoff, ystride, ipred_ctx_y),
904 PredMode::TMPred => IPred4x4::ipred_tm(ydst, cur_yoff, ystride, ipred_ctx_y),
905 PredMode::HPred => IPred4x4::ipred_he(ydst, cur_yoff, ystride, ipred_ctx_y),
906 PredMode::VPred => IPred4x4::ipred_ve(ydst, cur_yoff, ystride, ipred_ctx_y),
907 PredMode::LDPred => IPred4x4::ipred_ld(ydst, cur_yoff, ystride, ipred_ctx_y),
908 PredMode::RDPred => IPred4x4::ipred_rd(ydst, cur_yoff, ystride, ipred_ctx_y),
909 PredMode::VRPred => IPred4x4::ipred_vr(ydst, cur_yoff, ystride, ipred_ctx_y),
910 PredMode::VLPred => IPred4x4::ipred_vl(ydst, cur_yoff, ystride, ipred_ctx_y),
911 PredMode::HDPred => IPred4x4::ipred_hd(ydst, cur_yoff, ystride, ipred_ctx_y),
912 PredMode::HUPred => IPred4x4::ipred_hu(ydst, cur_yoff, ystride, ipred_ctx_y),
913 _ => unreachable!(),
914 };
915 add_coeffs4x4(ydst, cur_yoff, ystride, &self.coeffs[x + y * 4]);
916 }
917 ipred_ctx_y.has_top = true;
918 yoff += 4 * ystride;
919 iidx += self.ymode_stride;
920 }
921 }
922 let dst = &mut dframe.data[0..];
923 let uoff = dframe.offset[1] + mb_x * 8 + mb_y * 8 * dframe.stride[1];
924 let ustride = dframe.stride[1];
925 let voff = dframe.offset[2] + mb_x * 8 + mb_y * 8 * dframe.stride[2];
926 let vstride = dframe.stride[2];
927 let ipred_ctx_u = &mut self.dstate.ipred_ctx_u;
928 let ipred_ctx_v = &mut self.dstate.ipred_ctx_v;
929 ipred_ctx_u.has_top = has_top;
930 ipred_ctx_v.has_top = has_top;
931 ipred_ctx_u.has_left = has_left;
932 ipred_ctx_v.has_left = has_left;
933 ipred_ctx_u.fill(dst, uoff, ustride, 8, 8);
934 ipred_ctx_v.fill(dst, voff, vstride, 8, 8);
935 match self.mb_info[mb_idx].uvmode {
936 PredMode::DCPred => {
937 IPred8x8::ipred_dc(dst, uoff, ustride, ipred_ctx_u);
938 IPred8x8::ipred_dc(dst, voff, vstride, ipred_ctx_v);
939 },
940 PredMode::HPred => {
941 IPred8x8::ipred_h(dst, uoff, ustride, ipred_ctx_u);
942 IPred8x8::ipred_h(dst, voff, vstride, ipred_ctx_v);
943 },
944 PredMode::VPred => {
945 IPred8x8::ipred_v(dst, uoff, ustride, ipred_ctx_u);
946 IPred8x8::ipred_v(dst, voff, vstride, ipred_ctx_v);
947 },
948 PredMode::TMPred => {
949 IPred8x8::ipred_tm(dst, uoff, ustride, ipred_ctx_u);
950 IPred8x8::ipred_tm(dst, voff, vstride, ipred_ctx_v);
951 },
952 _ => unreachable!(),
953 };
954 self.add_residue(dframe, mb_x, mb_y, is_normal, pitch_mode);
955 Ok(())
956 }
957 fn recon_inter_mb(&mut self, dframe: &mut NASimpleVideoFrame<u8>, mb_x: usize, mb_y: usize, use_last: bool) {
958 let pitch = self.dstate.force_pitch.unwrap_or(0);
959 let pitch_dmode = (pitch >> 3) & 3;
960 let pitch_smode = pitch & 7;
961
962 let refframe = (if use_last { self.shuf.get_last() } else { self.shuf.get_golden() }).unwrap();
963 let single_mv = self.mb_info[mb_x + mb_y * self.mb_w].mb_type != VPMBType::InterFourMV;
964 let mut iidx = mb_x * 4 + mb_y * 4 * self.mv_stride;
965 let mut mc_buf = self.mc_buf.get_data_mut().unwrap();
966
967 let dst = &mut dframe.data[0..];
968 let ystride = dframe.stride[0];
969 let mut yoff = dframe.offset[0] + mb_x * 16 + mb_y * 16 * ystride;
970 if pitch_smode == 0 {
971 if single_mv {
972 mc_block16x16(dst, yoff, ystride, mb_x * 16, mb_y * 16,
973 self.mvs[iidx].x * 2, self.mvs[iidx].y * 2, refframe.clone(), 0, &mut mc_buf);
974 } else {
975 for y in 0..4 {
976 for x in 0..4 {
977 mc_block4x4(dst, yoff + x * 4, ystride, mb_x * 16 + x * 4, mb_y * 16 + y * 4,
978 self.mvs[iidx + x].x * 2, self.mvs[iidx + x].y * 2, refframe.clone(), 0, &mut mc_buf);
979 }
980 yoff += 4 * ystride;
981 iidx += self.mv_stride;
982 }
983 }
984 } else {
985 if single_mv {
986 mc_block_special(dst, yoff, ystride, mb_x * 16, mb_y * 16,
987 self.mvs[iidx].x * 2, self.mvs[iidx].y * 2,
988 refframe.clone(), 0, &mut mc_buf, 16, pitch_smode);
989 } else {
990 for y in 0..4 {
991 for x in 0..4 {
992 mc_block_special(dst, yoff + x * 4, ystride,
993 mb_x * 16 + x * 4, mb_y * 16 + y * 4,
994 self.mvs[iidx + x].x * 2, self.mvs[iidx + x].y * 2,
995 refframe.clone(), 0, &mut mc_buf, 4, pitch_smode);
996 }
997 yoff += 4 * ystride;
998 iidx += self.mv_stride;
999 }
1000 }
1001 }
1002
1003 let mut iidx = mb_x * 4 + mb_y * 4 * self.mv_stride;
1004 let mut uoff = dframe.offset[1] + mb_x * 8 + mb_y * 8 * dframe.stride[1];
1005 let ustride = dframe.stride[1];
1006 let mut voff = dframe.offset[2] + mb_x * 8 + mb_y * 8 * dframe.stride[2];
1007 let vstride = dframe.stride[2];
1008 if single_mv {
1009 let chroma_mv = self.mvs[iidx];
1010
1011 if pitch_smode == 0 {
1012 mc_block8x8(dst, uoff, ustride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf);
1013 mc_block8x8(dst, voff, vstride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe.clone(), 2, &mut mc_buf);
1014 } else {
1015 mc_block_special(dst, uoff, ustride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y,
1016 refframe.clone(), 1, &mut mc_buf, 8, pitch_smode);
1017 mc_block_special(dst, voff, vstride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y,
1018 refframe.clone(), 2, &mut mc_buf, 8, pitch_smode);
1019 }
1020 } else {
1021 for y in 0..2 {
1022 for x in 0..2 {
7589c13a
KS
1023 let mut chroma_mv = self.mvs[iidx + x * 2] + self.mvs[iidx + x * 2 + 1]
1024 + self.mvs[iidx + x * 2 + self.mv_stride]
1025 + self.mvs[iidx + x * 2 + self.mv_stride + 1];
1026 if chroma_mv.x < 0 {
1027 chroma_mv.x += 1;
1028 } else {
1029 chroma_mv.x += 2;
1030 }
1031 if chroma_mv.y < 0 {
1032 chroma_mv.y += 1;
1033 } else {
1034 chroma_mv.y += 2;
1035 }
1036 chroma_mv.x >>= 2;
1037 chroma_mv.y >>= 2;
587a6d78
KS
1038
1039 if pitch_smode == 0 {
7589c13a 1040 mc_block4x4(dst, uoff + x * 4, ustride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
587a6d78 1041 chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf);
7589c13a 1042 mc_block4x4(dst, voff + x * 4, vstride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
587a6d78
KS
1043 chroma_mv.x, chroma_mv.y, refframe.clone(), 2, &mut mc_buf);
1044 } else {
7589c13a 1045 mc_block_special(dst, uoff + x * 4, ustride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
587a6d78
KS
1046 chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf,
1047 4, pitch_smode);
7589c13a 1048 mc_block_special(dst, voff + x * 4, vstride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
587a6d78
KS
1049 chroma_mv.x, chroma_mv.y, refframe.clone(), 2, &mut mc_buf,
1050 4, pitch_smode);
1051 }
1052 }
1053 uoff += ustride * 4;
1054 voff += vstride * 4;
1055 iidx += 2 * self.mv_stride;
1056 }
1057 }
1058 self.add_residue(dframe, mb_x, mb_y, true, pitch_dmode);
1059 }
1060 fn loop_filter_mb(&mut self, dframe: &mut NASimpleVideoFrame<u8>, mb_x: usize, mb_y: usize, loop_str: u8) {
1061 const HIGH_EDGE_VAR_THR: [[u8; 64]; 2] = [
1062 [
1063 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1064 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1065 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
1066 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
1067 ], [
1068 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1069 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1070 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
1071 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
1072 ]];
1073
47933c6d
KS
1074 let edge_thr = i16::from(loop_str) + 2;
1075 let luma_thr = i16::from(loop_str);
1076 let chroma_thr = i16::from(loop_str) * 2;
587a6d78 1077 let inner_thr = if self.dstate.loop_sharpness == 0 {
47933c6d 1078 i16::from(loop_str)
587a6d78 1079 } else {
47933c6d 1080 let bound1 = i16::from(9 - self.dstate.loop_sharpness);
587a6d78 1081 let shift = (self.dstate.loop_sharpness + 3) >> 2;
47933c6d 1082 (i16::from(loop_str) >> shift).min(bound1)
587a6d78 1083 };
47933c6d 1084 let hev_thr = i16::from(HIGH_EDGE_VAR_THR[if self.dstate.is_intra { 1 } else { 0 }][loop_str as usize]);
587a6d78
KS
1085
1086 let ystride = dframe.stride[0];
1087 let ustride = dframe.stride[1];
1088 let vstride = dframe.stride[2];
1089 let ypos = dframe.offset[0] + mb_x * 16 + mb_y * 16 * ystride;
1090 let upos = dframe.offset[1] + mb_x * 8 + mb_y * 8 * ustride;
1091 let vpos = dframe.offset[2] + mb_x * 8 + mb_y * 8 * vstride;
1092
1093 let (loop_edge, loop_inner) = if self.dstate.lf_simple {
1094 (simple_loop_filter as LoopFilterFunc, simple_loop_filter as LoopFilterFunc)
1095 } else {
1096 (normal_loop_filter_edge as LoopFilterFunc, normal_loop_filter_inner as LoopFilterFunc)
1097 };
1098
1099 if mb_x > 0 {
1100 loop_edge(dframe.data, ypos, 1, ystride, 16, edge_thr, inner_thr, hev_thr);
1101 loop_edge(dframe.data, upos, 1, ustride, 8, edge_thr, inner_thr, hev_thr);
1102 loop_edge(dframe.data, vpos, 1, vstride, 8, edge_thr, inner_thr, hev_thr);
1103 }
1104 if mb_y > 0 {
1105 loop_edge(dframe.data, ypos, ystride, 1, 16, edge_thr, inner_thr, hev_thr);
1106 loop_edge(dframe.data, upos, ustride, 1, 8, edge_thr, inner_thr, hev_thr);
1107 loop_edge(dframe.data, vpos, vstride, 1, 8, edge_thr, inner_thr, hev_thr);
1108 }
1109
1110 for y in 1..4 {
1111 loop_inner(dframe.data, ypos + y * 4 * ystride, ystride, 1, 16, luma_thr, inner_thr, hev_thr);
1112 }
1113 loop_inner(dframe.data, upos + 4 * ustride, ustride, 1, 8, chroma_thr, inner_thr, hev_thr);
1114 loop_inner(dframe.data, vpos + 4 * vstride, vstride, 1, 8, chroma_thr, inner_thr, hev_thr);
1115
1116 for x in 1..4 {
1117 loop_inner(dframe.data, ypos + x * 4, 1, ystride, 16, luma_thr, inner_thr, hev_thr);
1118 }
1119 loop_inner(dframe.data, upos + 4, 1, ustride, 8, chroma_thr, inner_thr, hev_thr);
1120 loop_inner(dframe.data, vpos + 4, 1, vstride, 8, chroma_thr, inner_thr, hev_thr);
1121 }
1122}
1123
1124impl NADecoder for VP7Decoder {
1125 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1126 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1127 let fmt = YUV420_FORMAT;
1128 let myvinfo = NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt);
47933c6d 1129 let myinfo = NACodecTypeInfo::Video(myvinfo);
587a6d78
KS
1130 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1131
1132 supp.pool_u8.set_dec_bufs(4);
1133 supp.pool_u8.prealloc_video(NAVideoInfo::new(myvinfo.get_width(), myvinfo.get_height(), false, vinfo.get_format()), 4)?;
1134 self.set_dimensions(myvinfo.get_width(), myvinfo.get_height());
1135 Ok(())
1136 } else {
1137 Err(DecoderError::InvalidData)
1138 }
1139 }
47933c6d 1140 #[allow(clippy::cyclomatic_complexity)]
587a6d78
KS
1141 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1142 let src = pkt.get_buffer();
1143
1144 validate!(src.len() > 4);
1145
1146 let frame_tag = read_u24le(src.as_slice())?;
1147 self.dstate.is_intra = (frame_tag & 1) == 0;
1148 self.dstate.version = ((frame_tag >> 1) & 7) as u8;
1149 let part2_off = (frame_tag >> 4) as usize;
1150 let part1_off = if self.dstate.version == 0 { 4 } else { 3 };
1151
1152 validate!(src.len() > part1_off + part2_off);
1153 let mut bc = BoolCoder::new(&src[part1_off..][..part2_off])?;
1154 let mut bc_main = BoolCoder::new(&src[part1_off + part2_off..])?;
1155 if self.dstate.is_intra {
1156 let width = bc.read_bits(12) as usize;
1157 let height = bc.read_bits(12) as usize;
1158 let _scalev = bc.read_bits(2);
1159 let _scaleh = bc.read_bits(2);
1160 validate!((width > 0) && (height > 0));
1161 self.set_dimensions(width, height);
1162
1163 self.dstate.reset();
9ceb80a2 1164 self.scan.copy_from_slice(&DEFAULT_SCAN_ORDER);
6e24ec0b
KS
1165 } else {
1166 if !self.shuf.has_refs() {
1167 return Err(DecoderError::MissingReference);
1168 }
587a6d78
KS
1169 }
1170
1171 self.read_features(&mut bc)?;
1172
1173 let y_ac_q = bc.read_bits(7) as usize;
1174 let y_dc_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1175 let y2_dc_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1176 let y2_ac_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1177 let uv_dc_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1178 let uv_ac_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1179 self.set_qmat(y_dc_q, y_ac_q, y2_dc_q, y2_ac_q, uv_dc_q, uv_ac_q);
1180
1181 let update_gf = if self.dstate.is_intra { true } else { bc.read_bool() };
1182
1183 let mut has_fading_feature = true;
1184 let mut keep_probs = true;
1185 if self.dstate.version != 0 {
1186 keep_probs = bc.read_bool();
1187 if self.dstate.is_intra {
1188 has_fading_feature = true;
1189 } else {
1190 has_fading_feature = bc.read_bool();
1191 }
1192 }
1193
1194 if has_fading_feature {
1195 self.dstate.fading = bc.read_bool();
1196 if self.dstate.fading {
1197 self.dstate.fade_alpha = bc.read_sbits(8) as u16;
1198 self.dstate.fade_beta = bc.read_sbits(8) as u16;
1199 if let Some(pframe) = self.shuf.get_last() {
1200 let mut fframe = supp.pool_u8.get_free().unwrap();
1201 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut fframe).unwrap();
1202 fade_frame(pframe, &mut dframe, self.dstate.fade_alpha, self.dstate.fade_beta);
1203 self.shuf.add_frame(fframe);
1204 }
1205 }
1206 } else {
1207 self.dstate.fading = false;
1208 }
1209
1210 if self.dstate.version == 0 {
1211 self.dstate.lf_simple = bc.read_bool();
1212 }
1213
1214 if bc.read_bool() {
1215 for i in 1..16 {
1216 self.scan[i] = DEFAULT_SCAN_ORDER[bc.read_bits(4) as usize];
1217 }
1218 }
1219
1220 if self.dstate.version != 0 {
1221 self.dstate.lf_simple = bc.read_bool();
1222 } else {
1223 self.dstate.lf_simple = false;
1224 }
1225
1226 self.dstate.loop_filter_level = bc.read_bits(6) as u8;
1227 self.dstate.loop_sharpness = bc.read_bits(3) as u8;
1228
1229 self.read_dct_coef_prob_upd(&mut bc)?;
1230
1231 if !self.dstate.is_intra {
1232 self.dstate.prob_intra_pred = bc.read_byte();
1233 self.dstate.prob_last_pred = bc.read_byte();
1234 if bc.read_bool() {
1235 for i in 0..4 {
1236 self.dstate.kf_ymode_prob[i] = bc.read_byte();
1237 }
1238 }
1239 if bc.read_bool() {
1240 for i in 0..3 {
1241 self.dstate.kf_uvmode_prob[i] = bc.read_byte();
1242 }
1243 }
1244 self.read_mv_prob_upd(&mut bc)?;
1245 }
1246 if !keep_probs {
1247 self.tmp_scan.copy_from_slice(&self.scan);
1248 }
1249
1250 let vinfo = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
1251 let ret = supp.pool_u8.get_free();
1252 if ret.is_none() {
1253 return Err(DecoderError::AllocError);
1254 }
1255 let mut buf = ret.unwrap();
1256 if buf.get_info() != vinfo {
1257 self.shuf.clear();
1258 supp.pool_u8.reset();
1259 supp.pool_u8.prealloc_video(vinfo, 4)?;
1260 let ret = supp.pool_u8.get_free();
1261 if ret.is_none() {
1262 return Err(DecoderError::AllocError);
1263 }
1264 buf = ret.unwrap();
1265 }
1266 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1267
1268 let mut mb_idx = 0;
1269 self.pcache.reset();
f7125215 1270 if self.dstate.is_intra || (self.dstate.version > 0) {
99cc55ef
KS
1271 self.dstate.pdc_pred_val = [0; 2];
1272 self.dstate.pdc_pred_count = [0; 2];
f7125215 1273 }
587a6d78
KS
1274 let mut use_last = true;
1275 for mb_y in 0..self.mb_h {
1276 for mb_x in 0..self.mb_w {
1277 self.decode_mb_features(&mut bc, mb_x, mb_y)?;
1278 self.dstate.has_y2 = true;
1279 if self.dstate.is_intra {
1280 let ymode = bc.read_tree(KF_Y_MODE_TREE, KF_Y_MODE_TREE_PROBS);
1281 if ymode == PredMode::BPred {
1282 self.dstate.has_y2 = false;
1283 let mut iidx = mb_x * 4 + mb_y * 4 * self.ymode_stride;
1284 for y in 0..4 {
1285 for x in 0..4 {
1286 let top_mode = if (y > 0) || (mb_y > 0) {
1287 self.ymodes[iidx + x - self.ymode_stride]
1288 } else {
1289 PredMode::DCPred
1290 };
1291 let left_mode = if (x > 0) || (mb_x > 0) {
1292 self.ymodes[iidx + x - 1]
1293 } else {
1294 PredMode::DCPred
1295 };
1296 let top_idx = top_mode.to_b_index();
1297 let left_idx = left_mode.to_b_index();
1298 let bmode = bc.read_tree(B_MODE_TREE, &KF_B_MODE_TREE_PROBS[top_idx][left_idx]);
1299 self.ymodes[iidx + x] = bmode;
1300 }
1301 iidx += self.ymode_stride;
1302 }
1303 } else {
1304 self.fill_ymode(mb_x, mb_y, ymode.to_b_mode());
1305 }
1306 let uvmode = bc.read_tree(UV_MODE_TREE, KF_UV_MODE_TREE_PROBS);
1307 self.mb_info[mb_idx].mb_type = VPMBType::Intra;
1308 self.mb_info[mb_idx].ymode = ymode;
1309 self.mb_info[mb_idx].uvmode = uvmode;
1310 } else if !bc.read_prob(self.dstate.prob_intra_pred) {
1311 let ymode = bc.read_tree(Y_MODE_TREE, &self.dstate.kf_ymode_prob);
1312 if ymode == PredMode::BPred {
1313 self.dstate.has_y2 = false;
1314 let mut iidx = mb_x * 4 + mb_y * 4 * self.ymode_stride;
1315 for _y in 0..4 {
1316 for x in 0..4 {
1317 let bmode = bc.read_tree(B_MODE_TREE, B_MODE_TREE_PROBS);
1318 self.ymodes[iidx + x] = bmode;
1319 }
1320 iidx += self.ymode_stride;
1321 }
1322 } else {
1323 self.fill_ymode(mb_x, mb_y, PredMode::Inter);
1324 }
1325 let uvmode = bc.read_tree(UV_MODE_TREE, &self.dstate.kf_uvmode_prob);
1326 self.mb_info[mb_idx].mb_type = VPMBType::Intra;
1327 self.mb_info[mb_idx].ymode = ymode;
1328 self.mb_info[mb_idx].uvmode = uvmode;
1329 self.fill_mv(mb_x, mb_y, ZERO_MV);
1330 } else {
1331 use_last = !bc.read_prob(self.dstate.prob_last_pred);
1332
1333 let (mvprobs, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(mb_x, mb_y);
1334 let mbtype = bc.read_tree(MV_REF_TREE, &mvprobs);
1335
1336 match mbtype {
1337 VPMBType::InterNearest => {
1338 self.fill_mv(mb_x, mb_y, nearest_mv);
1339 },
1340 VPMBType::InterNear => {
1341 self.fill_mv(mb_x, mb_y, near_mv);
1342 },
1343 VPMBType::InterNoMV => {
1344 self.fill_mv(mb_x, mb_y, ZERO_MV);
1345 },
1346 VPMBType::InterMV => {
1347 let dmy = decode_mv_component(&mut bc, &self.dstate.mv_probs[0]);
1348 let dmx = decode_mv_component(&mut bc, &self.dstate.mv_probs[1]);
1349 let new_mv = pred_mv + MV{ x: dmx, y: dmy };
1350 self.fill_mv(mb_x, mb_y, new_mv);
1351 },
1352 VPMBType::InterFourMV => {
1353 self.do_split_mv(&mut bc, mb_x, mb_y, pred_mv)?;
1354 },
1355 _ => unreachable!(),
1356 };
1357
1358 self.fill_ymode(mb_x, mb_y, PredMode::Inter);
1359 self.mb_info[mb_idx].mb_type = mbtype;
1360 self.mb_info[mb_idx].ymode = PredMode::Inter;
1361 self.mb_info[mb_idx].uvmode = PredMode::Inter;
1362 }
99cc55ef 1363 self.decode_residue(&mut bc_main, mb_x, mb_idx, use_last);
587a6d78
KS
1364 match self.mb_info[mb_idx].mb_type {
1365 VPMBType::Intra => {
1366 self.recon_intra_mb(&mut dframe, mb_x, mb_y)?;
1367 },
1368 _ => {
1369 self.recon_inter_mb(&mut dframe, mb_x, mb_y, use_last);
1370 },
1371 }
1372 if let Some(loop_str) = self.dstate.force_loop_str {
1373 self.mb_info[mb_idx].loop_str = loop_str;
1374 } else {
1375 self.mb_info[mb_idx].loop_str = self.dstate.loop_filter_level;
1376 }
1377 self.mb_info[mb_idx].upd_gf = self.dstate.force_gf_update;
1378 mb_idx += 1;
1379 }
1380 self.pcache.update_row();
1381 }
1382 let mut mb_idx = 0;
1383 for mb_y in 0..self.mb_h {
1384 for mb_x in 0..self.mb_w {
1385 let loop_str = self.mb_info[mb_idx].loop_str;
1386 self.loop_filter_mb(&mut dframe, mb_x, mb_y, loop_str);
1387 mb_idx += 1;
1388 }
1389 }
1390 if !update_gf && self.dstate.features[2].is_some() {
1391 let gf = self.shuf.get_golden().unwrap();
1392 let mut new_gf = supp.pool_u8.get_copy(&gf).unwrap();
1393 let dframe = NASimpleVideoFrame::from_video_buf(&mut new_gf).unwrap();
1394 let mut mb_idx = 0;
1395 let mut mc_buf = self.mc_buf.get_data_mut().unwrap();
1396 for mb_y in 0..self.mb_h {
1397 for mb_x in 0..self.mb_w {
1398 if self.mb_info[mb_idx].upd_gf {
1399 mc_block16x16(dframe.data, dframe.offset[0] + mb_x * 16 + mb_y * 16 * dframe.stride[0], dframe.stride[0], mb_x * 16, mb_y * 16, 0, 0, buf.clone(), 0, &mut mc_buf);
1400 mc_block8x8(dframe.data, dframe.offset[1] + mb_x * 8 + mb_y * 8 * dframe.stride[1], dframe.stride[1], mb_x * 8, mb_y * 8, 0, 0, buf.clone(), 1, &mut mc_buf);
1401 mc_block8x8(dframe.data, dframe.offset[2] + mb_x * 8 + mb_y * 8 * dframe.stride[2], dframe.stride[2], mb_x * 8, mb_y * 8, 0, 0, buf.clone(), 2, &mut mc_buf);
1402 }
1403 mb_idx += 1;
1404 }
1405 }
1406 self.shuf.add_golden_frame(new_gf);
1407 }
1408
1409 if !keep_probs {
1410 self.scan.copy_from_slice(&self.tmp_scan);
1411 }
1412 if update_gf {
1413 self.shuf.add_golden_frame(buf.clone());
1414 }
1415 self.shuf.add_frame(buf.clone());
1416
1417 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1418 frm.set_keyframe(self.dstate.is_intra);
1419 frm.set_frame_type(if self.dstate.is_intra { FrameType::I } else { FrameType::P });
1420 Ok(frm.into_ref())
1421 }
f9be4e75
KS
1422 fn flush(&mut self) {
1423 self.shuf.clear();
1424 }
587a6d78
KS
1425}
1426
7d57ae2f
KS
1427impl NAOptionHandler for VP7Decoder {
1428 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
1429 fn set_options(&mut self, _options: &[NAOption]) { }
1430 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
1431}
1432
08a1fab7 1433pub fn get_decoder() -> Box<NADecoder + Send> {
587a6d78
KS
1434 Box::new(VP7Decoder::new())
1435}
1436
1437#[cfg(test)]
1438mod test {
1439 use nihav_core::codecs::RegisteredDecoders;
1440 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 1441 use nihav_codec_support::test::dec_video::*;
78fb6560 1442 use crate::duck_register_all_decoders;
e64739f8 1443 use nihav_commonfmt::generic_register_all_demuxers;
587a6d78
KS
1444
1445 #[test]
1446 fn test_vp7() {
1447 let mut dmx_reg = RegisteredDemuxers::new();
1448 generic_register_all_demuxers(&mut dmx_reg);
1449 let mut dec_reg = RegisteredDecoders::new();
78fb6560 1450 duck_register_all_decoders(&mut dec_reg);
587a6d78 1451
d24468d9 1452 test_decoding("avi", "vp7", "assets/Duck/interlaced_blit_pitch.avi", Some(12), &dmx_reg,
d9dcff04
KS
1453 &dec_reg, ExpectedTestResult::MD5Frames(vec![
1454 [0xb79fb6f8, 0xed51ac9e, 0x9e423456, 0xc0918e7f],
1455 [0xbf8d1274, 0x83515e15, 0x8c0887de, 0xfbfd05d3],
1456 [0x8ad00466, 0x80b6cbfb, 0x54de408e, 0x9efbc05e],
1457 [0x144122c5, 0x6897b553, 0x93474d29, 0x1a1274ec],
1458 [0x06ff5d07, 0x55825d38, 0x072b0a78, 0xfcb5020f],
1459 [0xfd01591b, 0xc42113e7, 0xc5a5550f, 0xb30f3b02],
1460 [0x155e0d6e, 0x96d75e06, 0x9bd7ce87, 0xacf868e1],
1461 [0xfd79103a, 0x695d21d3, 0xfeacb5b4, 0x1d869d08],
1462 [0xf4bcfeac, 0x0d2c305c, 0x11416c96, 0x626a5ef6],
1463 [0x3579b66c, 0x0a7d7dc0, 0xe80b0395, 0xf6a70661],
1464 [0x5773768c, 0x813442e9, 0x4dd6f793, 0xb10fe55f],
1465 [0xcaaf0ddb, 0x65c2410e, 0x95da5bba, 0x3b90128e],
1466 [0x74773773, 0xe1dbadeb, 0x57aaf64b, 0x9c21e3c7]]));
587a6d78
KS
1467 }
1468}
1469
1470/*const DEFAULT_ZIGZAG: [usize; 16] = [
1471 0, 1, 5, 6,
1472 2, 4, 7, 12,
1473 3, 8, 11, 13,
1474 9, 10, 14, 15
1475];*/
1476const DEFAULT_SCAN_ORDER: [usize; 16] = [
1477 0, 1, 4, 8,
1478 5, 2, 3, 6,
1479 9, 12, 13, 10,
1480 7, 11, 14, 15
1481];
1482
1483const Y_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1484 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Index(2),
1485 VPTreeDef::Index(4), VPTreeDef::Index(6),
1486 VPTreeDef::Value(PredMode::VPred), VPTreeDef::Value(PredMode::HPred),
1487 VPTreeDef::Value(PredMode::TMPred), VPTreeDef::Value(PredMode::BPred),
1488];
1489const KF_Y_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1490 VPTreeDef::Value(PredMode::BPred), VPTreeDef::Index(2),
1491 VPTreeDef::Index(4), VPTreeDef::Index(6),
1492 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Value(PredMode::VPred),
1493 VPTreeDef::Value(PredMode::HPred), VPTreeDef::Value(PredMode::TMPred),
1494];
1495const UV_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1496 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Index(2),
1497 VPTreeDef::Value(PredMode::VPred), VPTreeDef::Index(4),
1498 VPTreeDef::Value(PredMode::HPred), VPTreeDef::Value(PredMode::TMPred)
1499];
1500const B_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1501 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Index(2),
1502 VPTreeDef::Value(PredMode::TMPred), VPTreeDef::Index(4),
1503 VPTreeDef::Value(PredMode::VPred), VPTreeDef::Index(6),
1504 VPTreeDef::Index(8), VPTreeDef::Index(12),
1505 VPTreeDef::Value(PredMode::HPred), VPTreeDef::Index(10),
1506 VPTreeDef::Value(PredMode::RDPred), VPTreeDef::Value(PredMode::VRPred),
1507 VPTreeDef::Value(PredMode::LDPred), VPTreeDef::Index(14),
1508 VPTreeDef::Value(PredMode::VLPred), VPTreeDef::Index(16),
1509 VPTreeDef::Value(PredMode::HDPred), VPTreeDef::Value(PredMode::HUPred)
1510];
1511
1512const FEATURE_TREE: &[VPTreeDef<usize>] = &[
1513 VPTreeDef::Index(2), VPTreeDef::Index(4),
1514 VPTreeDef::Value(0), VPTreeDef::Value(1),
1515 VPTreeDef::Value(2), VPTreeDef::Value(3)
1516];
1517
1518const COEF_TREE: &[VPTreeDef<DCTToken>] = &[
1519 VPTreeDef::Value(DCTToken::EOB), VPTreeDef::Index(2),
1520 VPTreeDef::Value(DCTToken::Zero), VPTreeDef::Index(4),
1521 VPTreeDef::Value(DCTToken::One), VPTreeDef::Index(6),
1522 VPTreeDef::Index(8), VPTreeDef::Index(12),
1523 VPTreeDef::Value(DCTToken::Two), VPTreeDef::Index(10),
1524 VPTreeDef::Value(DCTToken::Three), VPTreeDef::Value(DCTToken::Four),
1525 VPTreeDef::Index(14), VPTreeDef::Index(16),
1526 VPTreeDef::Value(DCTToken::Cat1), VPTreeDef::Value(DCTToken::Cat2),
1527 VPTreeDef::Index(18), VPTreeDef::Index(20),
1528 VPTreeDef::Value(DCTToken::Cat3), VPTreeDef::Value(DCTToken::Cat4),
1529 VPTreeDef::Value(DCTToken::Cat5), VPTreeDef::Value(DCTToken::Cat6)
1530];
1531
1532const MV_REF_TREE: &[VPTreeDef<VPMBType>] = &[
1533 VPTreeDef::Value(VPMBType::InterNoMV), VPTreeDef::Index(2),
1534 VPTreeDef::Value(VPMBType::InterNearest), VPTreeDef::Index(4),
1535 VPTreeDef::Value(VPMBType::InterNear), VPTreeDef::Index(6),
1536 VPTreeDef::Value(VPMBType::InterMV), VPTreeDef::Value(VPMBType::InterFourMV)
1537];
1538const SMALL_MV_TREE: &[VPTreeDef<i16>] = &[
1539 VPTreeDef::Index(2), VPTreeDef::Index(8),
1540 VPTreeDef::Index(4), VPTreeDef::Index(6),
1541 VPTreeDef::Value(0), VPTreeDef::Value(1),
1542 VPTreeDef::Value(2), VPTreeDef::Value(3),
1543 VPTreeDef::Index(10), VPTreeDef::Index(12),
1544 VPTreeDef::Value(4), VPTreeDef::Value(5),
1545 VPTreeDef::Value(6), VPTreeDef::Value(7)
1546];
1547const MV_SPLIT_MODE_TREE: &[VPTreeDef<MVSplitMode>] = &[
1548 VPTreeDef::Value(MVSplitMode::Sixteenths), VPTreeDef::Index(2),
1549 VPTreeDef::Value(MVSplitMode::Quarters), VPTreeDef::Index(4),
1550 VPTreeDef::Value(MVSplitMode::TopBottom), VPTreeDef::Value(MVSplitMode::LeftRight)
1551];
1552const SUB_MV_REF_TREE: &[VPTreeDef<SubMVRef>] = &[
1553 VPTreeDef::Value(SubMVRef::Left), VPTreeDef::Index(2),
1554 VPTreeDef::Value(SubMVRef::Above), VPTreeDef::Index(4),
1555 VPTreeDef::Value(SubMVRef::Zero), VPTreeDef::Value(SubMVRef::New)
1556];