introduce option handling for encoders
[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
146fn decode_subblock<'a>(bc: &mut BoolCoder, coeffs: &mut [i16; 16], ctype: usize, pctx: u8, sbparams: &SBParams) -> u8 {
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
1074 let edge_thr = (loop_str as i16) + 2;
1075 let luma_thr = loop_str as i16;
1076 let chroma_thr = (loop_str as i16) * 2;
1077 let inner_thr = if self.dstate.loop_sharpness == 0 {
1078 loop_str as i16
1079 } else {
1080 let bound1 = (9 - self.dstate.loop_sharpness) as i16;
1081 let shift = (self.dstate.loop_sharpness + 3) >> 2;
1082 ((loop_str as i16) >> shift).min(bound1)
1083 };
1084 let hev_thr = HIGH_EDGE_VAR_THR[if self.dstate.is_intra { 1 } else { 0 }][loop_str as usize] as i16;
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);
1129 let myinfo = NACodecTypeInfo::Video(myvinfo.clone());
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 }
1140 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1141 let src = pkt.get_buffer();
1142
1143 validate!(src.len() > 4);
1144
1145 let frame_tag = read_u24le(src.as_slice())?;
1146 self.dstate.is_intra = (frame_tag & 1) == 0;
1147 self.dstate.version = ((frame_tag >> 1) & 7) as u8;
1148 let part2_off = (frame_tag >> 4) as usize;
1149 let part1_off = if self.dstate.version == 0 { 4 } else { 3 };
1150
1151 validate!(src.len() > part1_off + part2_off);
1152 let mut bc = BoolCoder::new(&src[part1_off..][..part2_off])?;
1153 let mut bc_main = BoolCoder::new(&src[part1_off + part2_off..])?;
1154 if self.dstate.is_intra {
1155 let width = bc.read_bits(12) as usize;
1156 let height = bc.read_bits(12) as usize;
1157 let _scalev = bc.read_bits(2);
1158 let _scaleh = bc.read_bits(2);
1159 validate!((width > 0) && (height > 0));
1160 self.set_dimensions(width, height);
1161
1162 self.dstate.reset();
9ceb80a2 1163 self.scan.copy_from_slice(&DEFAULT_SCAN_ORDER);
6e24ec0b
KS
1164 } else {
1165 if !self.shuf.has_refs() {
1166 return Err(DecoderError::MissingReference);
1167 }
587a6d78
KS
1168 }
1169
1170 self.read_features(&mut bc)?;
1171
1172 let y_ac_q = bc.read_bits(7) as usize;
1173 let y_dc_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1174 let y2_dc_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1175 let y2_ac_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1176 let uv_dc_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1177 let uv_ac_q = if bc.read_bool() { bc.read_bits(7) as usize } else { y_ac_q };
1178 self.set_qmat(y_dc_q, y_ac_q, y2_dc_q, y2_ac_q, uv_dc_q, uv_ac_q);
1179
1180 let update_gf = if self.dstate.is_intra { true } else { bc.read_bool() };
1181
1182 let mut has_fading_feature = true;
1183 let mut keep_probs = true;
1184 if self.dstate.version != 0 {
1185 keep_probs = bc.read_bool();
1186 if self.dstate.is_intra {
1187 has_fading_feature = true;
1188 } else {
1189 has_fading_feature = bc.read_bool();
1190 }
1191 }
1192
1193 if has_fading_feature {
1194 self.dstate.fading = bc.read_bool();
1195 if self.dstate.fading {
1196 self.dstate.fade_alpha = bc.read_sbits(8) as u16;
1197 self.dstate.fade_beta = bc.read_sbits(8) as u16;
1198 if let Some(pframe) = self.shuf.get_last() {
1199 let mut fframe = supp.pool_u8.get_free().unwrap();
1200 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut fframe).unwrap();
1201 fade_frame(pframe, &mut dframe, self.dstate.fade_alpha, self.dstate.fade_beta);
1202 self.shuf.add_frame(fframe);
1203 }
1204 }
1205 } else {
1206 self.dstate.fading = false;
1207 }
1208
1209 if self.dstate.version == 0 {
1210 self.dstate.lf_simple = bc.read_bool();
1211 }
1212
1213 if bc.read_bool() {
1214 for i in 1..16 {
1215 self.scan[i] = DEFAULT_SCAN_ORDER[bc.read_bits(4) as usize];
1216 }
1217 }
1218
1219 if self.dstate.version != 0 {
1220 self.dstate.lf_simple = bc.read_bool();
1221 } else {
1222 self.dstate.lf_simple = false;
1223 }
1224
1225 self.dstate.loop_filter_level = bc.read_bits(6) as u8;
1226 self.dstate.loop_sharpness = bc.read_bits(3) as u8;
1227
1228 self.read_dct_coef_prob_upd(&mut bc)?;
1229
1230 if !self.dstate.is_intra {
1231 self.dstate.prob_intra_pred = bc.read_byte();
1232 self.dstate.prob_last_pred = bc.read_byte();
1233 if bc.read_bool() {
1234 for i in 0..4 {
1235 self.dstate.kf_ymode_prob[i] = bc.read_byte();
1236 }
1237 }
1238 if bc.read_bool() {
1239 for i in 0..3 {
1240 self.dstate.kf_uvmode_prob[i] = bc.read_byte();
1241 }
1242 }
1243 self.read_mv_prob_upd(&mut bc)?;
1244 }
1245 if !keep_probs {
1246 self.tmp_scan.copy_from_slice(&self.scan);
1247 }
1248
1249 let vinfo = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
1250 let ret = supp.pool_u8.get_free();
1251 if ret.is_none() {
1252 return Err(DecoderError::AllocError);
1253 }
1254 let mut buf = ret.unwrap();
1255 if buf.get_info() != vinfo {
1256 self.shuf.clear();
1257 supp.pool_u8.reset();
1258 supp.pool_u8.prealloc_video(vinfo, 4)?;
1259 let ret = supp.pool_u8.get_free();
1260 if ret.is_none() {
1261 return Err(DecoderError::AllocError);
1262 }
1263 buf = ret.unwrap();
1264 }
1265 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1266
1267 let mut mb_idx = 0;
1268 self.pcache.reset();
f7125215 1269 if self.dstate.is_intra || (self.dstate.version > 0) {
99cc55ef
KS
1270 self.dstate.pdc_pred_val = [0; 2];
1271 self.dstate.pdc_pred_count = [0; 2];
f7125215 1272 }
587a6d78
KS
1273 let mut use_last = true;
1274 for mb_y in 0..self.mb_h {
1275 for mb_x in 0..self.mb_w {
1276 self.decode_mb_features(&mut bc, mb_x, mb_y)?;
1277 self.dstate.has_y2 = true;
1278 if self.dstate.is_intra {
1279 let ymode = bc.read_tree(KF_Y_MODE_TREE, KF_Y_MODE_TREE_PROBS);
1280 if ymode == PredMode::BPred {
1281 self.dstate.has_y2 = false;
1282 let mut iidx = mb_x * 4 + mb_y * 4 * self.ymode_stride;
1283 for y in 0..4 {
1284 for x in 0..4 {
1285 let top_mode = if (y > 0) || (mb_y > 0) {
1286 self.ymodes[iidx + x - self.ymode_stride]
1287 } else {
1288 PredMode::DCPred
1289 };
1290 let left_mode = if (x > 0) || (mb_x > 0) {
1291 self.ymodes[iidx + x - 1]
1292 } else {
1293 PredMode::DCPred
1294 };
1295 let top_idx = top_mode.to_b_index();
1296 let left_idx = left_mode.to_b_index();
1297 let bmode = bc.read_tree(B_MODE_TREE, &KF_B_MODE_TREE_PROBS[top_idx][left_idx]);
1298 self.ymodes[iidx + x] = bmode;
1299 }
1300 iidx += self.ymode_stride;
1301 }
1302 } else {
1303 self.fill_ymode(mb_x, mb_y, ymode.to_b_mode());
1304 }
1305 let uvmode = bc.read_tree(UV_MODE_TREE, KF_UV_MODE_TREE_PROBS);
1306 self.mb_info[mb_idx].mb_type = VPMBType::Intra;
1307 self.mb_info[mb_idx].ymode = ymode;
1308 self.mb_info[mb_idx].uvmode = uvmode;
1309 } else if !bc.read_prob(self.dstate.prob_intra_pred) {
1310 let ymode = bc.read_tree(Y_MODE_TREE, &self.dstate.kf_ymode_prob);
1311 if ymode == PredMode::BPred {
1312 self.dstate.has_y2 = false;
1313 let mut iidx = mb_x * 4 + mb_y * 4 * self.ymode_stride;
1314 for _y in 0..4 {
1315 for x in 0..4 {
1316 let bmode = bc.read_tree(B_MODE_TREE, B_MODE_TREE_PROBS);
1317 self.ymodes[iidx + x] = bmode;
1318 }
1319 iidx += self.ymode_stride;
1320 }
1321 } else {
1322 self.fill_ymode(mb_x, mb_y, PredMode::Inter);
1323 }
1324 let uvmode = bc.read_tree(UV_MODE_TREE, &self.dstate.kf_uvmode_prob);
1325 self.mb_info[mb_idx].mb_type = VPMBType::Intra;
1326 self.mb_info[mb_idx].ymode = ymode;
1327 self.mb_info[mb_idx].uvmode = uvmode;
1328 self.fill_mv(mb_x, mb_y, ZERO_MV);
1329 } else {
1330 use_last = !bc.read_prob(self.dstate.prob_last_pred);
1331
1332 let (mvprobs, nearest_mv, near_mv, pred_mv) = self.find_mv_pred(mb_x, mb_y);
1333 let mbtype = bc.read_tree(MV_REF_TREE, &mvprobs);
1334
1335 match mbtype {
1336 VPMBType::InterNearest => {
1337 self.fill_mv(mb_x, mb_y, nearest_mv);
1338 },
1339 VPMBType::InterNear => {
1340 self.fill_mv(mb_x, mb_y, near_mv);
1341 },
1342 VPMBType::InterNoMV => {
1343 self.fill_mv(mb_x, mb_y, ZERO_MV);
1344 },
1345 VPMBType::InterMV => {
1346 let dmy = decode_mv_component(&mut bc, &self.dstate.mv_probs[0]);
1347 let dmx = decode_mv_component(&mut bc, &self.dstate.mv_probs[1]);
1348 let new_mv = pred_mv + MV{ x: dmx, y: dmy };
1349 self.fill_mv(mb_x, mb_y, new_mv);
1350 },
1351 VPMBType::InterFourMV => {
1352 self.do_split_mv(&mut bc, mb_x, mb_y, pred_mv)?;
1353 },
1354 _ => unreachable!(),
1355 };
1356
1357 self.fill_ymode(mb_x, mb_y, PredMode::Inter);
1358 self.mb_info[mb_idx].mb_type = mbtype;
1359 self.mb_info[mb_idx].ymode = PredMode::Inter;
1360 self.mb_info[mb_idx].uvmode = PredMode::Inter;
1361 }
99cc55ef 1362 self.decode_residue(&mut bc_main, mb_x, mb_idx, use_last);
587a6d78
KS
1363 match self.mb_info[mb_idx].mb_type {
1364 VPMBType::Intra => {
1365 self.recon_intra_mb(&mut dframe, mb_x, mb_y)?;
1366 },
1367 _ => {
1368 self.recon_inter_mb(&mut dframe, mb_x, mb_y, use_last);
1369 },
1370 }
1371 if let Some(loop_str) = self.dstate.force_loop_str {
1372 self.mb_info[mb_idx].loop_str = loop_str;
1373 } else {
1374 self.mb_info[mb_idx].loop_str = self.dstate.loop_filter_level;
1375 }
1376 self.mb_info[mb_idx].upd_gf = self.dstate.force_gf_update;
1377 mb_idx += 1;
1378 }
1379 self.pcache.update_row();
1380 }
1381 let mut mb_idx = 0;
1382 for mb_y in 0..self.mb_h {
1383 for mb_x in 0..self.mb_w {
1384 let loop_str = self.mb_info[mb_idx].loop_str;
1385 self.loop_filter_mb(&mut dframe, mb_x, mb_y, loop_str);
1386 mb_idx += 1;
1387 }
1388 }
1389 if !update_gf && self.dstate.features[2].is_some() {
1390 let gf = self.shuf.get_golden().unwrap();
1391 let mut new_gf = supp.pool_u8.get_copy(&gf).unwrap();
1392 let dframe = NASimpleVideoFrame::from_video_buf(&mut new_gf).unwrap();
1393 let mut mb_idx = 0;
1394 let mut mc_buf = self.mc_buf.get_data_mut().unwrap();
1395 for mb_y in 0..self.mb_h {
1396 for mb_x in 0..self.mb_w {
1397 if self.mb_info[mb_idx].upd_gf {
1398 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);
1399 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);
1400 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);
1401 }
1402 mb_idx += 1;
1403 }
1404 }
1405 self.shuf.add_golden_frame(new_gf);
1406 }
1407
1408 if !keep_probs {
1409 self.scan.copy_from_slice(&self.tmp_scan);
1410 }
1411 if update_gf {
1412 self.shuf.add_golden_frame(buf.clone());
1413 }
1414 self.shuf.add_frame(buf.clone());
1415
1416 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1417 frm.set_keyframe(self.dstate.is_intra);
1418 frm.set_frame_type(if self.dstate.is_intra { FrameType::I } else { FrameType::P });
1419 Ok(frm.into_ref())
1420 }
f9be4e75
KS
1421 fn flush(&mut self) {
1422 self.shuf.clear();
1423 }
587a6d78
KS
1424}
1425
08a1fab7 1426pub fn get_decoder() -> Box<NADecoder + Send> {
587a6d78
KS
1427 Box::new(VP7Decoder::new())
1428}
1429
1430#[cfg(test)]
1431mod test {
1432 use nihav_core::codecs::RegisteredDecoders;
1433 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 1434 use nihav_codec_support::test::dec_video::*;
e64739f8
KS
1435 use crate::duck_register_all_codecs;
1436 use nihav_commonfmt::generic_register_all_demuxers;
587a6d78
KS
1437
1438 #[test]
1439 fn test_vp7() {
1440 let mut dmx_reg = RegisteredDemuxers::new();
1441 generic_register_all_demuxers(&mut dmx_reg);
1442 let mut dec_reg = RegisteredDecoders::new();
1443 duck_register_all_codecs(&mut dec_reg);
1444
d24468d9 1445 test_decoding("avi", "vp7", "assets/Duck/interlaced_blit_pitch.avi", Some(12), &dmx_reg,
d9dcff04
KS
1446 &dec_reg, ExpectedTestResult::MD5Frames(vec![
1447 [0xb79fb6f8, 0xed51ac9e, 0x9e423456, 0xc0918e7f],
1448 [0xbf8d1274, 0x83515e15, 0x8c0887de, 0xfbfd05d3],
1449 [0x8ad00466, 0x80b6cbfb, 0x54de408e, 0x9efbc05e],
1450 [0x144122c5, 0x6897b553, 0x93474d29, 0x1a1274ec],
1451 [0x06ff5d07, 0x55825d38, 0x072b0a78, 0xfcb5020f],
1452 [0xfd01591b, 0xc42113e7, 0xc5a5550f, 0xb30f3b02],
1453 [0x155e0d6e, 0x96d75e06, 0x9bd7ce87, 0xacf868e1],
1454 [0xfd79103a, 0x695d21d3, 0xfeacb5b4, 0x1d869d08],
1455 [0xf4bcfeac, 0x0d2c305c, 0x11416c96, 0x626a5ef6],
1456 [0x3579b66c, 0x0a7d7dc0, 0xe80b0395, 0xf6a70661],
1457 [0x5773768c, 0x813442e9, 0x4dd6f793, 0xb10fe55f],
1458 [0xcaaf0ddb, 0x65c2410e, 0x95da5bba, 0x3b90128e],
1459 [0x74773773, 0xe1dbadeb, 0x57aaf64b, 0x9c21e3c7]]));
587a6d78
KS
1460 }
1461}
1462
1463/*const DEFAULT_ZIGZAG: [usize; 16] = [
1464 0, 1, 5, 6,
1465 2, 4, 7, 12,
1466 3, 8, 11, 13,
1467 9, 10, 14, 15
1468];*/
1469const DEFAULT_SCAN_ORDER: [usize; 16] = [
1470 0, 1, 4, 8,
1471 5, 2, 3, 6,
1472 9, 12, 13, 10,
1473 7, 11, 14, 15
1474];
1475
1476const Y_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1477 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Index(2),
1478 VPTreeDef::Index(4), VPTreeDef::Index(6),
1479 VPTreeDef::Value(PredMode::VPred), VPTreeDef::Value(PredMode::HPred),
1480 VPTreeDef::Value(PredMode::TMPred), VPTreeDef::Value(PredMode::BPred),
1481];
1482const KF_Y_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1483 VPTreeDef::Value(PredMode::BPred), VPTreeDef::Index(2),
1484 VPTreeDef::Index(4), VPTreeDef::Index(6),
1485 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Value(PredMode::VPred),
1486 VPTreeDef::Value(PredMode::HPred), VPTreeDef::Value(PredMode::TMPred),
1487];
1488const UV_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1489 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Index(2),
1490 VPTreeDef::Value(PredMode::VPred), VPTreeDef::Index(4),
1491 VPTreeDef::Value(PredMode::HPred), VPTreeDef::Value(PredMode::TMPred)
1492];
1493const B_MODE_TREE: &[VPTreeDef<PredMode>] = &[
1494 VPTreeDef::Value(PredMode::DCPred), VPTreeDef::Index(2),
1495 VPTreeDef::Value(PredMode::TMPred), VPTreeDef::Index(4),
1496 VPTreeDef::Value(PredMode::VPred), VPTreeDef::Index(6),
1497 VPTreeDef::Index(8), VPTreeDef::Index(12),
1498 VPTreeDef::Value(PredMode::HPred), VPTreeDef::Index(10),
1499 VPTreeDef::Value(PredMode::RDPred), VPTreeDef::Value(PredMode::VRPred),
1500 VPTreeDef::Value(PredMode::LDPred), VPTreeDef::Index(14),
1501 VPTreeDef::Value(PredMode::VLPred), VPTreeDef::Index(16),
1502 VPTreeDef::Value(PredMode::HDPred), VPTreeDef::Value(PredMode::HUPred)
1503];
1504
1505const FEATURE_TREE: &[VPTreeDef<usize>] = &[
1506 VPTreeDef::Index(2), VPTreeDef::Index(4),
1507 VPTreeDef::Value(0), VPTreeDef::Value(1),
1508 VPTreeDef::Value(2), VPTreeDef::Value(3)
1509];
1510
1511const COEF_TREE: &[VPTreeDef<DCTToken>] = &[
1512 VPTreeDef::Value(DCTToken::EOB), VPTreeDef::Index(2),
1513 VPTreeDef::Value(DCTToken::Zero), VPTreeDef::Index(4),
1514 VPTreeDef::Value(DCTToken::One), VPTreeDef::Index(6),
1515 VPTreeDef::Index(8), VPTreeDef::Index(12),
1516 VPTreeDef::Value(DCTToken::Two), VPTreeDef::Index(10),
1517 VPTreeDef::Value(DCTToken::Three), VPTreeDef::Value(DCTToken::Four),
1518 VPTreeDef::Index(14), VPTreeDef::Index(16),
1519 VPTreeDef::Value(DCTToken::Cat1), VPTreeDef::Value(DCTToken::Cat2),
1520 VPTreeDef::Index(18), VPTreeDef::Index(20),
1521 VPTreeDef::Value(DCTToken::Cat3), VPTreeDef::Value(DCTToken::Cat4),
1522 VPTreeDef::Value(DCTToken::Cat5), VPTreeDef::Value(DCTToken::Cat6)
1523];
1524
1525const MV_REF_TREE: &[VPTreeDef<VPMBType>] = &[
1526 VPTreeDef::Value(VPMBType::InterNoMV), VPTreeDef::Index(2),
1527 VPTreeDef::Value(VPMBType::InterNearest), VPTreeDef::Index(4),
1528 VPTreeDef::Value(VPMBType::InterNear), VPTreeDef::Index(6),
1529 VPTreeDef::Value(VPMBType::InterMV), VPTreeDef::Value(VPMBType::InterFourMV)
1530];
1531const SMALL_MV_TREE: &[VPTreeDef<i16>] = &[
1532 VPTreeDef::Index(2), VPTreeDef::Index(8),
1533 VPTreeDef::Index(4), VPTreeDef::Index(6),
1534 VPTreeDef::Value(0), VPTreeDef::Value(1),
1535 VPTreeDef::Value(2), VPTreeDef::Value(3),
1536 VPTreeDef::Index(10), VPTreeDef::Index(12),
1537 VPTreeDef::Value(4), VPTreeDef::Value(5),
1538 VPTreeDef::Value(6), VPTreeDef::Value(7)
1539];
1540const MV_SPLIT_MODE_TREE: &[VPTreeDef<MVSplitMode>] = &[
1541 VPTreeDef::Value(MVSplitMode::Sixteenths), VPTreeDef::Index(2),
1542 VPTreeDef::Value(MVSplitMode::Quarters), VPTreeDef::Index(4),
1543 VPTreeDef::Value(MVSplitMode::TopBottom), VPTreeDef::Value(MVSplitMode::LeftRight)
1544];
1545const SUB_MV_REF_TREE: &[VPTreeDef<SubMVRef>] = &[
1546 VPTreeDef::Value(SubMVRef::Left), VPTreeDef::Index(2),
1547 VPTreeDef::Value(SubMVRef::Above), VPTreeDef::Index(4),
1548 VPTreeDef::Value(SubMVRef::Zero), VPTreeDef::Value(SubMVRef::New)
1549];