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