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