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