1#![allow(clippy::needless_range_loop)]
7
8use rusty_h264_common::bit_reader::OutOfData;
9use rusty_h264_common::cavlc::{
10 decode_residual_block, read_cbp_inter, read_cbp_intra, un_scan_4x4_ac_into, un_scan_4x4_dcac,
11};
12use rusty_h264_common::inter::{
13 inter_partitions, mc_chroma_padded, mc_luma_padded, predict_mv, predict_partition_mv,
14 MvNeighbor,
15};
16use rusty_h264_common::predict::{
17 add_residual_8x8, chroma8x8_pred, chroma_qp, intra4x4_pred, intra8x8_pred, luma16x16_pred,
18 reconstruct_4x4, I16Mode, CHROMA_4X4_SCAN_XY, LUMA_4X4_SCAN_XY,
19};
20use rusty_h264_common::transform::{
21 dequantize, dequantize_weighted, inverse_quant_8x8, inverse_quant_chroma_dc,
22 inverse_quant_chroma_dc_weighted, inverse_quant_luma_dc, inverse_quant_luma_dc_weighted,
23};
24use rusty_h264_common::{BitReader, YuvFrame};
25
26pub struct MvField {
32 pub mb_w: usize,
33 pub mb_h: usize,
34 pub mv: Vec<(i32, i32)>,
35 pub ref_idx: Vec<i32>,
36 pub inter: Vec<bool>,
37}
38
39pub static MV_DUMP: std::sync::Mutex<Vec<MvField>> = std::sync::Mutex::new(Vec::new());
41
42pub fn mv_dump_on() -> bool {
43 static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
44 *ON.get_or_init(|| std::env::var("RFF_MV_DUMP").map_or(false, |v| v != "0"))
45}
46
47pub struct FrameDecoder {
49 mb_w: usize,
50 mb_h: usize,
51 qp: u8,
53 cur_qp: u8,
56 chroma_qp_offset: i32,
58 cw: usize,
59 ch: usize,
60 ccw: usize,
61 cch: usize,
62 rec_y: Vec<u8>,
63 rec_u: Vec<u8>,
64 rec_v: Vec<u8>,
65 mb_qp: Vec<u8>,
67 slice_first_mb: usize,
72 nnz_y: Vec<u8>,
73 nnz_c: [Vec<u8>; 2],
74 modes_y: Vec<u8>,
75 coded_y: Vec<bool>,
76 mv_y: Vec<(i32, i32)>,
79 inter_y: Vec<bool>,
80 ref_idx_y: Vec<i32>,
81 mv1: Vec<(i32, i32)>,
83 ref_idx1: Vec<i32>,
84 refs1: Vec<crate::Ref>,
86 num_ref_active1: usize,
87 is_b: bool,
88 b_possible: bool,
92 direct_spatial: bool,
93 nnz_l_cache: [u8; 25],
94 nnz_c_cache: [[u8; 9]; 2],
95 refs: Vec<crate::Ref>,
98 num_ref_active: usize,
102 constrained_intra: bool,
105 scaling: Option<[[i32; 16]; 6]>,
108 scaling8: Option<[[i32; 64]; 2]>,
111 transform_8x8_mode: bool,
113 mb_t8x8: Vec<bool>,
116 mb_kind: Vec<u8>,
123 weights: Option<WeightTable>,
125 cur_poc: i32,
127 weighted_bipred_idc: u8,
129 direct_8x8_inference: bool,
131}
132
133#[derive(Clone, Default)]
137pub struct WeightTable {
138 pub luma_log2_denom: i32,
139 pub chroma_log2_denom: i32,
140 pub luma: [Vec<(i32, i32)>; 2],
142 pub chroma: [Vec<[(i32, i32); 2]>; 2],
144}
145
146impl WeightTable {
147 fn apply_luma(&self, sample: u8, list: usize, refi: usize) -> u8 {
149 let (w, o) = self.luma[list][refi];
150 let lwd = self.luma_log2_denom;
151 let v = if lwd >= 1 {
152 ((sample as i32 * w + (1 << (lwd - 1))) >> lwd) + o
153 } else {
154 sample as i32 * w + o
155 };
156 v.clamp(0, 255) as u8
157 }
158
159 fn apply_chroma(&self, sample: u8, list: usize, refi: usize, cc: usize) -> u8 {
161 let (w, o) = self.chroma[list][refi][cc];
162 let cwd = self.chroma_log2_denom;
163 let v = if cwd >= 1 {
164 ((sample as i32 * w + (1 << (cwd - 1))) >> cwd) + o
165 } else {
166 sample as i32 * w + o
167 };
168 v.clamp(0, 255) as u8
169 }
170}
171
172#[derive(Debug, Clone, PartialEq, Eq)]
174pub enum MbError {
175 Truncated,
176 Unsupported(&'static str),
177}
178
179impl From<OutOfData> for MbError {
180 fn from(_: OutOfData) -> Self {
181 MbError::Truncated
182 }
183}
184
185impl FrameDecoder {
186 pub fn new(
187 mb_w: usize,
188 mb_h: usize,
189 qp: u8,
190 chroma_qp_offset: i32,
191 refs: Vec<crate::Ref>,
192 num_ref_active: usize,
193 constrained_intra: bool,
194 transform_8x8_mode: bool,
195 b_possible: bool,
196 ) -> Self {
197 let (cw, ch) = (mb_w * 16, mb_h * 16);
198 let (ccw, cch) = (cw / 2, ch / 2);
199 Self {
200 mb_w,
201 mb_h,
202 qp,
203 cur_qp: qp,
204 chroma_qp_offset,
205 cw,
206 ch,
207 ccw,
208 cch,
209 rec_y: vec![0; cw * ch],
210 rec_u: vec![0; ccw * cch],
211 rec_v: vec![0; ccw * cch],
212 mb_qp: vec![qp; mb_w * mb_h],
213 slice_first_mb: 0,
214 nnz_y: vec![0; (mb_w * 4) * (mb_h * 4)],
215 nnz_c: [vec![0; (mb_w * 2) * (mb_h * 2)], vec![0; (mb_w * 2) * (mb_h * 2)]],
216 modes_y: vec![2; (mb_w * 4) * (mb_h * 4)],
217 coded_y: vec![false; (mb_w * 4) * (mb_h * 4)],
218 mv_y: vec![(0, 0); (mb_w * 4) * (mb_h * 4)],
219 inter_y: vec![false; (mb_w * 4) * (mb_h * 4)],
220 ref_idx_y: vec![-1; (mb_w * 4) * (mb_h * 4)],
221 mv1: vec![(0, 0); (mb_w * 4) * (mb_h * 4)],
222 ref_idx1: vec![-1; (mb_w * 4) * (mb_h * 4)],
223 refs1: Vec::new(),
224 num_ref_active1: 0,
225 is_b: false,
226 b_possible,
227 direct_spatial: true,
228 nnz_l_cache: [0x80; 25],
229 nnz_c_cache: [[0x80; 9]; 2],
230 refs,
231 num_ref_active,
232 constrained_intra,
233 scaling: None,
234 scaling8: None,
235 transform_8x8_mode,
236 mb_t8x8: vec![false; mb_w * mb_h],
237 mb_kind: vec![rusty_h264_common::deblock::MB_KIND_UNSET; mb_w * mb_h],
238 weights: None,
239 cur_poc: 0,
240 weighted_bipred_idc: 0,
241 direct_8x8_inference: false,
242 }
243 }
244
245 pub fn set_weights(&mut self, weights: WeightTable) {
247 self.weights = Some(weights);
248 }
249
250 fn weight_partition(
254 &self,
255 pred_y: &mut [u8; 256],
256 c_pred: &mut [[u8; 64]; 2],
257 list: usize,
258 refi: usize,
259 rx: usize,
260 ry: usize,
261 rw: usize,
262 rh: usize,
263 ) {
264 let Some(wt) = &self.weights else { return };
265 for dy in 0..rh {
266 for dx in 0..rw {
267 let i = (ry + dy) * 16 + (rx + dx);
268 pred_y[i] = wt.apply_luma(pred_y[i], list, refi);
269 }
270 }
271 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
272 for cc in 0..2 {
273 for dy in 0..crh {
274 for dx in 0..crw {
275 let i = (cry + dy) * 8 + (crx + dx);
276 c_pred[cc][i] = wt.apply_chroma(c_pred[cc][i], list, refi, cc);
277 }
278 }
279 }
280 }
281
282 pub fn set_scaling(&mut self, scaling: [[i32; 16]; 6], scaling8: [[i32; 64]; 2]) {
285 self.scaling = Some(scaling);
286 self.scaling8 = Some(scaling8);
287 }
288
289 fn dequant(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
291 match &self.scaling {
292 Some(s) => dequantize_weighted(levels, qp, &s[list]),
293 None => dequantize(levels, qp),
294 }
295 }
296
297 fn dequant_luma_dc(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
299 match &self.scaling {
300 Some(s) => inverse_quant_luma_dc_weighted(levels, qp, s[list][0]),
301 None => inverse_quant_luma_dc(levels, qp),
302 }
303 }
304
305 fn dequant_chroma_dc(&self, levels: &[i32; 4], qp: u8, list: usize) -> [i32; 4] {
307 match &self.scaling {
308 Some(s) => inverse_quant_chroma_dc_weighted(levels, qp, s[list][0]),
309 None => inverse_quant_chroma_dc(levels, qp),
310 }
311 }
312
313 #[allow(clippy::too_many_arguments)]
316 pub fn set_b_context(
317 &mut self,
318 refs1: Vec<crate::Ref>,
319 num_ref_active1: usize,
320 direct_spatial: bool,
321 cur_poc: i32,
322 weighted_bipred_idc: u8,
323 direct_8x8_inference: bool,
324 ) {
325 self.is_b = true;
326 self.refs1 = refs1;
327 self.num_ref_active1 = num_ref_active1;
328 self.direct_spatial = direct_spatial;
329 self.cur_poc = cur_poc;
330 self.weighted_bipred_idc = weighted_bipred_idc;
331 self.direct_8x8_inference = direct_8x8_inference;
332 }
333
334 fn step_qp(&mut self, delta: i32) {
337 self.cur_qp = (self.cur_qp as i32 + delta + 52).rem_euclid(52) as u8;
338 }
339
340 fn chroma_qp_for(&self, qp_y: u8) -> u8 {
343 let qpi = (qp_y as i32 + self.chroma_qp_offset).clamp(0, 51) as u8;
344 chroma_qp(qpi)
345 }
346
347 pub fn begin_slice(&mut self, slice_qp: u8, refs: Vec<crate::Ref>, num_ref_active: usize) {
351 self.cur_qp = slice_qp;
352 self.qp = slice_qp;
353 self.refs = refs;
354 self.num_ref_active = num_ref_active;
355 self.weights = None; }
357
358 #[inline]
362 fn nbr_in_slice(&self, nbx: usize, nby: usize) -> bool {
363 nby * self.mb_w + nbx >= self.slice_first_mb
364 }
365
366 #[inline]
370 fn intra_nbr_ok(&self, nbx: usize, nby: usize) -> bool {
371 !self.constrained_intra || !self.inter_y[nby * (self.mb_w * 4) + nbx]
372 }
373
374 fn mv_neighbors(&self, mb_x: usize, mb_y: usize) -> [MvNeighbor; 3] {
375 let w4 = self.mb_w * 4;
376 let get = |avail: bool, bx: isize, by: isize| {
377 if avail {
378 let idx = by as usize * w4 + bx as usize;
379 MvNeighbor {
380 available: true,
381 mv: self.mv_y[idx],
382 ref_idx: self.ref_idx_y[idx],
383 }
384 } else {
385 MvNeighbor::NONE
386 }
387 };
388 let (bx, by) = (mb_x as isize * 4, mb_y as isize * 4);
389 let a = get(mb_x > 0 && self.nbr_in_slice(mb_x - 1, mb_y), bx - 1, by);
390 let b = get(mb_y > 0 && self.nbr_in_slice(mb_x, mb_y - 1), bx, by - 1);
391 let c = if mb_y > 0 && mb_x + 1 < self.mb_w && self.nbr_in_slice(mb_x + 1, mb_y - 1) {
392 get(true, bx + 4, by - 1)
393 } else {
394 get(mb_x > 0 && mb_y > 0 && self.nbr_in_slice(mb_x - 1, mb_y - 1), bx - 1, by - 1)
395 };
396 [a, b, c]
397 }
398
399 fn mv_neighbors_block(&self, pbx: isize, pby: isize, pwb: isize) -> [MvNeighbor; 3] {
400 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Neighbors);
401 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
402 let get = |bx: isize, by: isize| -> MvNeighbor {
403 if bx < 0
405 || by < 0
406 || bx >= w4
407 || by >= h4
408 || !self.coded_y[(by * w4 + bx) as usize]
409 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
410 {
411 MvNeighbor::NONE
412 } else {
413 let idx = (by * w4 + bx) as usize;
414 MvNeighbor { available: true, mv: self.mv_y[idx], ref_idx: self.ref_idx_y[idx] }
415 }
416 };
417 let a = get(pbx - 1, pby);
418 let b = get(pbx, pby - 1);
419 let mut c = get(pbx + pwb, pby - 1);
420 if !c.available {
421 c = get(pbx - 1, pby - 1);
422 }
423 [a, b, c]
424 }
425
426 fn skip_mv(&self, mb_x: usize, mb_y: usize) -> (i32, i32) {
427 let [a, b, c] = self.mv_neighbors(mb_x, mb_y);
428 if !a.available
429 || !b.available
430 || (a.ref_idx == 0 && a.mv == (0, 0))
431 || (b.ref_idx == 0 && b.mv == (0, 0))
432 {
433 (0, 0)
434 } else {
435 predict_mv(a, b, c, 0)
436 }
437 }
438
439 fn set_mb_mv(&mut self, mb_x: usize, mb_y: usize, mv: (i32, i32), inter: bool, refi: i32) {
440 let w4 = self.mb_w * 4;
441 for dy in 0..4 {
442 for dx in 0..4 {
443 let idx = (mb_y * 4 + dy) * w4 + (mb_x * 4 + dx);
444 self.mv_y[idx] = mv;
445 self.inter_y[idx] = inter;
446 self.ref_idx_y[idx] = if inter { refi } else { -1 };
447 }
448 }
449 }
450
451 fn commit_inter_grid(&mut self, mb_x: usize, mb_y: usize, rx: usize, ry: usize, rw: usize, rh: usize, mv: (i32, i32), refi: i8) {
455 let w4 = self.mb_w * 4;
456 for by in ry / 4..ry / 4 + rh / 4 {
457 for bx in rx / 4..rx / 4 + rw / 4 {
458 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
459 self.mv_y[idx] = mv;
460 self.inter_y[idx] = true;
461 self.ref_idx_y[idx] = refi as i32;
462 self.coded_y[idx] = true;
463 }
464 }
465 }
466
467 pub fn as_reference(&self) -> crate::RefFrame {
469 if mv_dump_on() {
473 MV_DUMP.lock().unwrap().push(MvField {
474 mb_w: self.mb_w,
475 mb_h: self.mb_h,
476 mv: self.mv_y.clone(),
477 ref_idx: self.ref_idx_y.clone(),
478 inter: self.inter_y.clone(),
479 });
480 }
481
482 let (mv, ref_idx, mv1, ref_idx1, ref_poc, w4) = if self.b_possible {
488 (
489 self.mv_y.clone(),
490 self.ref_idx_y.clone(),
491 self.mv1.clone(),
492 self.ref_idx1.clone(),
493 self.ref_idx_y
496 .iter()
497 .map(|&r| {
498 if r >= 0 {
499 self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc)
500 } else {
501 i32::MIN
502 }
503 })
504 .collect(),
505 self.mb_w * 4,
506 )
507 } else {
508 (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), 0)
509 };
510 crate::RefFrame {
511 py: rusty_h264_common::inter::pad_plane(&self.rec_y, self.cw, self.ch, crate::LPAD),
514 pu: rusty_h264_common::inter::pad_plane(&self.rec_u, self.ccw, self.ch / 2, crate::CPAD),
515 pv: rusty_h264_common::inter::pad_plane(&self.rec_v, self.ccw, self.ch / 2, crate::CPAD),
516 cw: self.cw,
517 ch: self.ch,
518 frame_num: 0, poc: 0, mv,
521 ref_idx,
522 mv1,
523 ref_idx1,
524 ref_poc,
525 w4,
526 long_term: false,
527 long_term_idx: 0,
528 }
529 }
530
531 fn nnz_cache_load(&mut self, mb_x: usize, mb_y: usize) {
532 let w4 = self.mb_w * 4;
533 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
534 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
535 for lbx in 0..4 {
536 self.nnz_l_cache[1 + lbx] =
537 if top_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 - 1) * w4 + (mb_x * 4 + lbx)] };
538 }
539 for lby in 0..4 {
540 self.nnz_l_cache[(lby + 1) * 5] =
541 if left_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 - 1)] };
542 }
543 }
544 #[inline]
545 fn nc_pred(&self, lbx: usize, lby: usize) -> i32 {
546 let left = self.nnz_l_cache[(lby + 1) * 5 + lbx] as i32;
547 let top = self.nnz_l_cache[lby * 5 + (lbx + 1)] as i32;
548 let r = left + top;
549 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
550 }
551 #[inline]
552 fn nnz_cache_set(&mut self, lbx: usize, lby: usize, total: u8) {
553 self.nnz_l_cache[(lby + 1) * 5 + (lbx + 1)] = total;
554 }
555 fn chroma_cache_load(&mut self, mb_x: usize, mb_y: usize) {
556 let w2 = self.mb_w * 2;
557 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
558 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
559 for c in 0..2 {
560 for bx in 0..2 {
561 self.nnz_c_cache[c][1 + bx] =
562 if top_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 - 1) * w2 + (mb_x * 2 + bx)] };
563 }
564 for by in 0..2 {
565 self.nnz_c_cache[c][(by + 1) * 3] =
566 if left_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 - 1)] };
567 }
568 }
569 }
570 #[inline]
571 fn chroma_nc_pred(&self, c: usize, bx: usize, by: usize) -> i32 {
572 let left = self.nnz_c_cache[c][(by + 1) * 3 + bx] as i32;
573 let top = self.nnz_c_cache[c][by * 3 + (bx + 1)] as i32;
574 let r = left + top;
575 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
576 }
577 #[inline]
578 fn chroma_nnz_cache_set(&mut self, c: usize, bx: usize, by: usize, total: u8) {
579 self.nnz_c_cache[c][(by + 1) * 3 + (bx + 1)] = total;
580 }
581
582 #[allow(clippy::too_many_arguments)]
590 pub fn decode_slice_data_cabac(
591 &mut self,
592 rbsp: &[u8],
593 start_byte: usize,
594 slice_qp: u8,
595 cabac_init_idc: u32,
596 is_i: bool,
597 is_p: bool,
598 first_mb: usize,
599 ) -> Result<usize, MbError> {
600 let mut cab = crate::cabac::Cabac::new(rbsp, start_byte, slice_qp as i32, cabac_init_idc, is_i);
601 let (range, _offset) = cab.dbg_state();
602 let trace = std::env::var_os("RH_CABAC_TRACE").is_some();
603 debug_assert_eq!(range, 510, "CABAC init range must be 510");
604
605 const I16_CBP: [u32; 6] = [0, 16, 32, 15, 31, 47];
606 let mbw = self.mb_w;
607 let total = self.mb_w * self.mb_h;
608 let mut cat = vec![255u8; total]; let mut mb_cbp = vec![0u8; total];
611 let mut cmode = vec![-1i32; total]; let mut mb_nzc = vec![[0u8; 24]; total]; let mut cbf_dc = vec![0u16; total];
614 let mut mb_skip = vec![false; total];
615 let mut mb_ref = vec![[-1i8; 16]; total]; let mut mb_mvd = vec![[[0i16; 2]; 16]; total]; let mut mb_ref1 = vec![[-1i8; 16]; total]; let mut mb_mvd1 = vec![[[0i16; 2]; 16]; total]; let mut mb_direct = vec![false; total]; let mut last_delta_qp = 0i32;
621 let mut addr = first_mb;
622
623 loop {
624 if addr >= total {
631 return Err(MbError::Truncated);
632 }
633 let (mbx, mby) = (addr % mbw, addr / mbw);
634 let left = (mbx > 0).then(|| addr - 1);
635 let top = (mby > 0).then(|| addr - mbw);
636
637 let mb_type;
640 if is_p {
641 let sctx = 11
642 + left.map_or(0, |a| (!mb_skip[a]) as usize)
643 + top.map_or(0, |a| (!mb_skip[a]) as usize);
644 if parse_mb_skip_cabac(&mut cab, sctx) {
645 mb_skip[addr] = true;
646 cat[addr] = 100; last_delta_qp = 0; self.decode_p_skip(mbx, mby)?;
652 self.mb_qp[addr] = self.cur_qp; let eos = cab.decode_terminate();
654 addr += 1;
655 if eos || addr >= total {
656 break;
657 }
658 continue;
659 }
660 let mbt = parse_mb_type_p_cabac(&mut cab);
661 if mbt == 30 {
662 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
663 }
664 if mbt <= 3 {
665 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbP);
666 let mut allow8 = true;
669 let mut mvdc = [[0i16; 2]; 30];
672 let mut refc = [-1i8; 30];
673 if let Some(l) = left {
674 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
675 refc[ci] = mb_ref[l][bi];
676 mvdc[ci] = mb_mvd[l][bi];
677 }
678 }
679 if let Some(t) = top {
680 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
681 refc[ci] = mb_ref[t][bi];
682 mvdc[ci] = mb_mvd[t][bi];
683 }
684 }
685 if mbx > 0 && mby > 0 {
686 let a = addr - mbw - 1;
687 (refc[0], mvdc[0]) = (mb_ref[a][15], mb_mvd[a][15]);
688 }
689 if mby > 0 && mbx + 1 < mbw {
690 let a = addr - mbw + 1;
691 (refc[5], mvdc[5]) = (mb_ref[a][12], mb_mvd[a][12]);
692 }
693 let mut mmvd = [[0i16; 2]; 16];
694 let mut mref = [0i8; 16];
695 macro_rules! refidx {
701 ($pi:expr, $zb:expr) => {{
702 if self.num_ref_active > 1 {
703 let s = CACHE30[$pi];
704 let c0 = (refc[s - 1] > 0) as usize + 2 * (refc[s - 6] > 0) as usize;
705 let r = parse_ref_idx_cabac(&mut cab, c0);
706 for &zb in $zb.iter() {
707 refc[CACHE30[zb]] = r;
708 }
709 r
710 } else {
711 0i8
712 }
713 }};
714 }
715 macro_rules! part {
716 ($pi:expr, $zb:expr, $pred:expr, $rx:expr, $ry:expr, $rw:expr, $rh:expr, $refi:expr) => {{
717 let (mvx, mvy) = parse_mvd_partition(&mut cab, $pi, $zb, &mut mvdc, &mut refc, &mut mmvd, &mut mref, $refi);
718 let [na, nb, nc] = self.mv_neighbors_block(
719 (mbx * 4 + $rx / 4) as isize,
720 (mby * 4 + $ry / 4) as isize,
721 ($rw / 4) as isize,
722 );
723 let pmv = $pred(na, nb, nc);
724 self.commit_inter_grid(mbx, mby, $rx, $ry, $rw, $rh, (pmv.0 + mvx, pmv.1 + mvy), $refi);
725 }};
726 }
727 match mbt {
728 0 => {
729 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
730 part!(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], |a, b, c| predict_partition_mv(0, 0, a, b, c, r0 as i32), 0, 0, 16, 16, r0);
731 }
732 1 => {
733 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7]);
734 let r1 = refidx!(8, &[8, 9, 10, 11, 12, 13, 14, 15]);
735 part!(0, &[0, 1, 2, 3, 4, 5, 6, 7], |a, b, c| predict_partition_mv(1, 0, a, b, c, r0 as i32), 0, 0, 16, 8, r0);
736 part!(8, &[8, 9, 10, 11, 12, 13, 14, 15], |a, b, c| predict_partition_mv(1, 1, a, b, c, r1 as i32), 0, 8, 16, 8, r1);
737 }
738 2 => {
739 let r0 = refidx!(0, &[0, 1, 2, 3, 8, 9, 10, 11]);
740 let r1 = refidx!(4, &[4, 5, 6, 7, 12, 13, 14, 15]);
741 part!(0, &[0, 1, 2, 3, 8, 9, 10, 11], |a, b, c| predict_partition_mv(2, 0, a, b, c, r0 as i32), 0, 0, 8, 16, r0);
742 part!(4, &[4, 5, 6, 7, 12, 13, 14, 15], |a, b, c| predict_partition_mv(2, 1, a, b, c, r1 as i32), 8, 0, 8, 16, r1);
743 }
744 _ => {
745 let mut subt = [0u32; 4];
747 for st in &mut subt {
748 *st = parse_sub_mb_type_p_cabac(&mut cab);
749 }
750 allow8 = subt.iter().all(|&t| t == 0);
751 let mut pr = [0i8; 4];
752 for (i, r) in pr.iter_mut().enumerate() {
753 let b = i * 4;
754 *r = refidx!(b, &[b, b + 1, b + 2, b + 3]);
755 }
756 for i in 0..4usize {
757 let b = i * 4;
758 let (ox, oy) = ((i % 2) * 8, (i / 2) * 8); let ri = pr[i];
760 match subt[i] {
761 0 => part!(b, &[b, b + 1, b + 2, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 8, 8, ri),
762 1 => {
763 part!(b, &[b, b + 1], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 8, 4, ri);
764 part!(b + 2, &[b + 2, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy + 4, 8, 4, ri);
765 }
766 2 => {
767 part!(b, &[b, b + 2], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 4, 8, ri);
768 part!(b + 1, &[b + 1, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox + 4, oy, 4, 8, ri);
769 }
770 _ => {
771 for j in 0..4usize {
772 let (sx, sy) = ((j % 2) * 4, (j / 2) * 4);
773 part!(b + j, &[b + j], |a, b, c| predict_mv(a, b, c, ri as i32), ox + sx, oy + sy, 4, 4, ri);
774 }
775 }
776 }
777 }
778 }
779 }
780 mb_ref[addr] = mref;
781 mb_mvd[addr] = mmvd;
782 cat[addr] = 100;
783
784 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
786 mb_cbp[addr] = cbp as u8;
787 let t8 = self.transform_8x8_mode && (cbp & 15) != 0 && allow8 && {
791 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
792 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
793 cab.decode_decision(399 + a + b) != 0
794 };
795 self.mb_t8x8[addr] = t8;
796 let mut luma8 = [[0i32; 64]; 4]; let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
798 let mut nzc = [0xffu8; 48];
799 if let Some(t) = top {
800 let tnz = mb_nzc[t];
801 nzc[1..5].copy_from_slice(&tnz[12..16]);
802 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
803 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
804 }
805 if let Some(l) = left {
806 let lnz = mb_nzc[l];
807 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
808 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
809 }
810 let mut cbfdc = 0u16;
811 let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
816 last_delta_qp = 0;
817 }
818 if cbp != 0 {
819 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
820 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
821 self.step_qp(qpd);
822 for id8 in 0..4usize {
823 if cbp_luma & (1 << id8) != 0 {
824 if t8 {
825 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, false, ndc, &mut luma8[id8]);
826 } else {
827 for id4 in 0..4usize {
828 let iz = id8 * 4 + id4;
829 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
830 }
831 }
832 } else {
833 for k in 0..4 {
834 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
835 }
836 }
837 }
838 if cbp_chroma >= 1 {
839 for i in 0..2usize {
840 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
841 }
842 }
843 if cbp_chroma == 2 {
844 for i in 0..2usize {
845 for id4 in 0..4usize {
846 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
847 }
848 }
849 }
850 }
851 self.mb_qp[addr] = self.cur_qp;
852 cbf_dc[addr] = cbfdc;
853 let mut mn = [0u8; 24];
854 for k in 0..4 {
855 mn[k] = nzc[9 + k];
856 mn[4 + k] = nzc[17 + k];
857 mn[8 + k] = nzc[25 + k];
858 mn[12 + k] = nzc[33 + k];
859 }
860 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
861 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
862 for v in mn.iter_mut() {
866 if *v == 0xff {
867 *v = 0;
868 }
869 }
870 mb_nzc[addr] = mn;
871
872 if self.refs.is_empty() {
877 return Err(MbError::Unsupported("inter without reference"));
878 }
879 let qp = self.cur_qp;
880 let qpc = self.chroma_qp_for(qp);
881 let (w4r, w2r) = (mbw * 4, mbw * 2);
882 let mut pred_y = [0u8; 256];
883 let mut c_pred = [[0u8; 64]; 2];
884 {
885 let (rh16, cch) = (self.mb_h * 16, self.mb_h * 8);
893 let mut gmv = [(0i32, 0i32); 16];
894 let mut gref = [0usize; 16];
895 for by in 0..4usize {
896 for bx in 0..4usize {
897 let bidx = (mby * 4 + by) * w4r + (mbx * 4 + bx);
898 gmv[by * 4 + bx] = self.mv_y[bidx];
899 gref[by * 4 + bx] =
902 (self.ref_idx_y[bidx].max(0) as usize).min(self.refs.len() - 1);
903 }
904 }
905 let rect_eq = |x4: usize, y4: usize, w4: usize, h4: usize| -> bool {
907 let t = y4 * 4 + x4;
908 (0..h4).all(|dy| {
909 (0..w4).all(|dx| {
910 let b = (y4 + dy) * 4 + (x4 + dx);
911 gmv[b] == gmv[t] && gref[b] == gref[t]
912 })
913 })
914 };
915 let refs = &self.refs;
916 let (cw, ccw) = (self.cw, self.ccw);
917 let mut mc_rect = |x4: usize,
918 y4: usize,
919 w4: usize,
920 h4: usize,
921 pred_y: &mut [u8; 256],
922 c_pred: &mut [[u8; 64]; 2]| {
923 let b = y4 * 4 + x4;
924 let (mv, reference) = (gmv[b], &refs[gref[b]]);
925 let (w, h) = (w4 * 4, h4 * 4);
926 let mut t = [0u8; 256];
927 mc_luma_padded(&reference.py, reference.lstride(), crate::LPAD, cw, rh16, mbx * 16 + x4 * 4, mby * 16 + y4 * 4, w, h, mv.0, mv.1, &mut t[..w * h]);
928 for dy in 0..h {
929 pred_y[(y4 * 4 + dy) * 16 + x4 * 4..][..w]
930 .copy_from_slice(&t[dy * w..dy * w + w]);
931 }
932 let (cw4, ch4) = (w4 * 2, h4 * 2);
933 for cc in 0..2 {
934 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
935 let mut tc = [0u8; 64];
936 mc_chroma_padded(rc, reference.cstride(), crate::CPAD, ccw, cch, mbx * 8 + x4 * 2, mby * 8 + y4 * 2, cw4, ch4, mv.0, mv.1, &mut tc[..cw4 * ch4]);
937 for dy in 0..ch4 {
938 c_pred[cc][(y4 * 2 + dy) * 8 + x4 * 2..][..cw4]
939 .copy_from_slice(&tc[dy * cw4..dy * cw4 + cw4]);
940 }
941 }
942 };
943 if rect_eq(0, 0, 4, 4) {
944 mc_rect(0, 0, 4, 4, &mut pred_y, &mut c_pred);
945 } else if rect_eq(0, 0, 4, 2) && rect_eq(0, 2, 4, 2) {
946 mc_rect(0, 0, 4, 2, &mut pred_y, &mut c_pred);
947 mc_rect(0, 2, 4, 2, &mut pred_y, &mut c_pred);
948 } else if rect_eq(0, 0, 2, 4) && rect_eq(2, 0, 2, 4) {
949 mc_rect(0, 0, 2, 4, &mut pred_y, &mut c_pred);
950 mc_rect(2, 0, 2, 4, &mut pred_y, &mut c_pred);
951 } else {
952 for q in 0..4usize {
953 let (qx, qy) = ((q % 2) * 2, (q / 2) * 2);
954 if rect_eq(qx, qy, 2, 2) {
955 mc_rect(qx, qy, 2, 2, &mut pred_y, &mut c_pred);
956 } else if rect_eq(qx, qy, 2, 1) && rect_eq(qx, qy + 1, 2, 1) {
957 mc_rect(qx, qy, 2, 1, &mut pred_y, &mut c_pred);
958 mc_rect(qx, qy + 1, 2, 1, &mut pred_y, &mut c_pred);
959 } else if rect_eq(qx, qy, 1, 2) && rect_eq(qx + 1, qy, 1, 2) {
960 mc_rect(qx, qy, 1, 2, &mut pred_y, &mut c_pred);
961 mc_rect(qx + 1, qy, 1, 2, &mut pred_y, &mut c_pred);
962 } else {
963 for j in 0..4usize {
964 mc_rect(qx + (j % 2), qy + (j / 2), 1, 1, &mut pred_y, &mut c_pred);
965 }
966 }
967 }
968 }
969 if self.weights.is_some() {
983 for by in 0..4usize {
984 for bx in 0..4usize {
985 let refi = gref[by * 4 + bx];
986 self.weight_partition(
987 &mut pred_y, &mut c_pred, 0, refi, bx * 4, by * 4, 4, 4,
988 );
989 }
990 }
991 }
992 }
993 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, if t8 { Some(&luma8) } else { None }, &cdc, &cac, cbp_chroma);
997
998 let eos = cab.decode_terminate();
999 addr += 1;
1000 if eos || addr >= total {
1001 break;
1002 }
1003 continue;
1004 }
1005 mb_type = mbt - 5; } else if self.is_b {
1007 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbB);
1008 let mut allow8 = true;
1011 let sctx = 24
1013 + left.map_or(0, |a| (!mb_skip[a]) as usize)
1014 + top.map_or(0, |a| (!mb_skip[a]) as usize);
1015 if parse_mb_skip_cabac(&mut cab, sctx) {
1016 mb_skip[addr] = true;
1017 cat[addr] = 100;
1018 mb_direct[addr] = true;
1019 last_delta_qp = 0; self.decode_b_skip(mbx, mby)?;
1023 self.mb_qp[addr] = self.cur_qp;
1024 mb_ref[addr] = [0i8; 16];
1027 mb_ref1[addr] = [0i8; 16];
1028 let eos = cab.decode_terminate();
1029 addr += 1;
1030 if eos || addr >= total {
1031 break;
1032 }
1033 continue;
1034 }
1035 let bci = left.map_or(0, |a| (!mb_direct[a]) as usize)
1036 + top.map_or(0, |a| (!mb_direct[a]) as usize);
1037 let bmt = parse_mb_type_b_cabac(&mut cab, bci);
1038 if bmt < 23 {
1039 let mut mvdc0 = [[0i16; 2]; 30];
1042 let mut refc0 = [-1i8; 30];
1043 let mut mvdc1 = [[0i16; 2]; 30];
1044 let mut refc1 = [-1i8; 30];
1045 macro_rules! fill {
1047 ($mrf:expr, $mmv:expr, $rc:expr, $mc:expr) => {{
1048 if let Some(l) = left {
1049 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
1050 $rc[ci] = $mrf[l][bi];
1051 $mc[ci] = $mmv[l][bi];
1052 }
1053 }
1054 if let Some(t) = top {
1055 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
1056 $rc[ci] = $mrf[t][bi];
1057 $mc[ci] = $mmv[t][bi];
1058 }
1059 }
1060 if mbx > 0 && mby > 0 {
1061 let a = addr - mbw - 1;
1062 ($rc[0], $mc[0]) = ($mrf[a][15], $mmv[a][15]);
1063 }
1064 if mby > 0 && mbx + 1 < mbw {
1065 let a = addr - mbw + 1;
1066 ($rc[5], $mc[5]) = ($mrf[a][12], $mmv[a][12]);
1067 }
1068 }};
1069 }
1070 fill!(mb_ref, mb_mvd, refc0, mvdc0);
1071 fill!(mb_ref1, mb_mvd1, refc1, mvdc1);
1072 let mut mmvd0 = [[0i16; 2]; 16];
1073 let mut mref0 = [-1i8; 16];
1074 let mut mmvd1 = [[0i16; 2]; 16];
1075 let mut mref1 = [-1i8; 16];
1076 if self.refs.is_empty() || self.refs1.is_empty() {
1077 return Err(MbError::Unsupported("B without references"));
1078 }
1079 let mut pred_y = [0u8; 256];
1084 let mut c_pred = [[0u8; 64]; 2];
1085
1086 if bmt == 0 {
1087 mb_direct[addr] = true;
1090 allow8 = self.direct_8x8_inference;
1091 (mref0, mref1) = ([0i8; 16], [0i8; 16]);
1092 self.decode_b_direct(mbx, mby, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
1093 } else if bmt == 22 {
1094 let mut subt = [0u32; 4];
1097 for s in &mut subt {
1098 *s = parse_sub_mb_type_b_cabac(&mut cab);
1099 }
1100 allow8 = subt.iter().all(|&t| if t == 0 { self.direct_8x8_inference } else { (1..=3).contains(&t) });
1101 for i in 0..4usize {
1105 if subt[i] == 0 {
1106 let b = i * 4;
1107 for &zb in &[b, b + 1, b + 2, b + 3] {
1108 (mref0[G_SCAN4[zb]], mref1[G_SCAN4[zb]]) = (0, 0);
1109 (refc0[CACHE30[zb]], refc1[CACHE30[zb]]) = (0, 0);
1110 }
1111 }
1112 }
1113 let mut sref = [[0i8; 2]; 4]; for list in 0..2usize {
1118 let active = if list == 0 { self.num_ref_active } else { self.num_ref_active1 };
1119 if active <= 1 {
1120 continue;
1121 }
1122 let rc = if list == 0 { &mut refc0 } else { &mut refc1 };
1123 for i in 0..4usize {
1124 let st = subt[i];
1125 if st == 0 || !b_sub_uses(st, list) {
1126 continue;
1127 }
1128 let b = i * 4;
1129 let s = CACHE30[b];
1130 let c0 = (rc[s - 1] > 0) as usize + 2 * (rc[s - 6] > 0) as usize;
1131 let r = parse_ref_idx_cabac(&mut cab, c0);
1132 for &zb in &[b, b + 1, b + 2, b + 3] {
1133 rc[CACHE30[zb]] = r;
1134 }
1135 sref[i][list] = r;
1136 }
1137 }
1138 for list in 0..2usize {
1139 let (mmv, mrf, mc, rc) = if list == 0 {
1140 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1141 } else {
1142 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1143 };
1144 for i in 0..4usize {
1145 let st = subt[i];
1146 if st == 0 || !b_sub_uses(st, list) {
1147 continue;
1148 }
1149 let b = i * 4;
1150 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1151 let mut zb = [0usize; 4];
1152 let mut n = 0;
1153 for ly in sy / 4..sy / 4 + sh / 4 {
1154 for lx in sx / 4..sx / 4 + sw / 4 {
1155 zb[n] = b + ly * 2 + lx;
1156 n += 1;
1157 }
1158 }
1159 parse_mvd_partition(&mut cab, zb[0], &zb[..n], mc, rc, mmv, mrf, sref[i][list]);
1160 }
1161 }
1162 }
1163 for (p, &st) in subt.iter().enumerate() {
1166 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
1167 if st == 0 {
1168 self.decode_b_direct(mbx, mby, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
1169 continue;
1170 }
1171 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1172 let (px, py) = (b8x + sx, b8y + sy);
1173 let mut mv = [(0i32, 0i32); 2];
1174 for list in 0..2usize {
1175 if b_sub_uses(st, list) {
1176 let d = if list == 0 { mmvd0 } else { mmvd1 }[(py / 4) * 4 + px / 4];
1177 let n = self.mv_neighbors_list((mbx * 4 + px / 4) as isize, (mby * 4 + py / 4) as isize, (sw / 4) as isize, list);
1178 let pmv = predict_mv(n[0], n[1], n[2], sref[p][list] as i32);
1179 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1180 }
1181 }
1182 let refi0 = if b_sub_uses(st, 0) { sref[p][0] as i32 } else { -1 };
1183 let refi1 = if b_sub_uses(st, 1) { sref[p][1] as i32 } else { -1 };
1184 self.b_set_motion(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1]);
1185 self.b_mc(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1186 }
1187 }
1188 } else {
1189 let (layout, mvmode, preds) = b_inter_layout(bmt);
1190 let parts: &[(usize, &[usize])] = match mvmode {
1191 0 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])],
1192 1 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7]), (8, &[8, 9, 10, 11, 12, 13, 14, 15])],
1193 _ => &[(0, &[0, 1, 2, 3, 8, 9, 10, 11]), (4, &[4, 5, 6, 7, 12, 13, 14, 15])],
1194 };
1195 let mut pref = [[0i8; 2]; 2]; for list in 0..2usize {
1203 let active = if list == 0 { self.num_ref_active } else { self.num_ref_active1 };
1204 if active <= 1 {
1205 continue;
1206 }
1207 let rc = if list == 0 { &mut refc0 } else { &mut refc1 };
1208 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1209 if !preds[p].uses(list) {
1210 continue;
1211 }
1212 let s = CACHE30[pidx];
1213 let c0 = (rc[s - 1] > 0) as usize + 2 * (rc[s - 6] > 0) as usize;
1214 let r = parse_ref_idx_cabac(&mut cab, c0);
1215 for &zbi in zb.iter() {
1217 rc[CACHE30[zbi]] = r;
1218 }
1219 pref[p][list] = r;
1220 }
1221 }
1222 for list in 0..2usize {
1225 let (mmv, mrf, mc, rc) = if list == 0 {
1226 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1227 } else {
1228 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1229 };
1230 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1231 if preds[p].uses(list) {
1232 parse_mvd_partition(&mut cab, pidx, zb, mc, rc, mmv, mrf, pref[p][list]);
1233 }
1234 }
1235 }
1236 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1238 let mut mv = [(0i32, 0i32); 2];
1239 for list in 0..2usize {
1240 if preds[p].uses(list) {
1241 let d = if list == 0 { mmvd0 } else { mmvd1 }[(ry / 4) * 4 + rx / 4];
1242 let n = self.mv_neighbors_list((mbx * 4 + rx / 4) as isize, (mby * 4 + ry / 4) as isize, (rw / 4) as isize, list);
1243 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], pref[p][list] as i32);
1244 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1245 }
1246 }
1247 let refi0 = if preds[p].uses(0) { pref[p][0] as i32 } else { -1 };
1248 let refi1 = if preds[p].uses(1) { pref[p][1] as i32 } else { -1 };
1249 self.b_set_motion(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1]);
1250 self.b_mc(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1254 }
1255 }
1256 mb_ref[addr] = mref0;
1257 mb_mvd[addr] = mmvd0;
1258 mb_ref1[addr] = mref1;
1259 mb_mvd1[addr] = mmvd1;
1260 cat[addr] = 100;
1261
1262 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1264 mb_cbp[addr] = cbp as u8;
1265 let t8 = self.transform_8x8_mode && (cbp & 15) != 0 && allow8 && {
1269 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1270 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1271 cab.decode_decision(399 + a + b) != 0
1272 };
1273 self.mb_t8x8[addr] = t8;
1274 let mut luma8 = [[0i32; 64]; 4]; let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1276 let mut nzc = [0xffu8; 48];
1277 if let Some(t) = top {
1278 let tnz = mb_nzc[t];
1279 nzc[1..5].copy_from_slice(&tnz[12..16]);
1280 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1281 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
1282 }
1283 if let Some(l) = left {
1284 let lnz = mb_nzc[l];
1285 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
1286 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
1287 }
1288 let mut cbfdc = 0u16;
1289 let mut luma_scan = [[0i32; 16]; 16];
1290 let mut cdc = [[0i32; 4]; 2];
1291 let mut cac = [[[0i32; 16]; 4]; 2];
1292 if cbp == 0 {
1293 last_delta_qp = 0;
1294 }
1295 if cbp != 0 {
1296 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1297 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1298 self.step_qp(qpd);
1299 for id8 in 0..4usize {
1300 if cbp_luma & (1 << id8) != 0 {
1301 if t8 {
1302 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, false, ndc, &mut luma8[id8]);
1303 } else {
1304 for id4 in 0..4usize {
1305 let iz = id8 * 4 + id4;
1306 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
1307 }
1308 }
1309 } else {
1310 for k in 0..4 {
1311 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1312 }
1313 }
1314 }
1315 if cbp_chroma >= 1 {
1316 for i in 0..2usize {
1317 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
1318 }
1319 }
1320 if cbp_chroma == 2 {
1321 for i in 0..2usize {
1322 for id4 in 0..4usize {
1323 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
1324 }
1325 }
1326 }
1327 }
1328 self.mb_qp[addr] = self.cur_qp;
1329 cbf_dc[addr] = cbfdc;
1330 let mut mn = [0u8; 24];
1331 for k in 0..4 {
1332 mn[k] = nzc[9 + k];
1333 mn[4 + k] = nzc[17 + k];
1334 mn[8 + k] = nzc[25 + k];
1335 mn[12 + k] = nzc[33 + k];
1336 }
1337 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1338 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1339 for v in mn.iter_mut() {
1343 if *v == 0xff {
1344 *v = 0;
1345 }
1346 }
1347 mb_nzc[addr] = mn;
1348 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, if t8 { Some(&luma8) } else { None }, &cdc, &cac, cbp_chroma);
1349
1350 let eos = cab.decode_terminate();
1351 addr += 1;
1352 if eos || addr >= total {
1353 break;
1354 }
1355 continue;
1356 }
1357 mb_type = bmt - 23; if mb_type == 25 {
1359 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1360 }
1361 } else {
1362 let li = left.map_or(0, |a| (cat[a] >= 2) as usize);
1363 let ti = top.map_or(0, |a| (cat[a] >= 2) as usize);
1364 mb_type = parse_mb_type_i_cabac(&mut cab, li + ti);
1365 if mb_type == 25 {
1366 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1367 }
1368 }
1369 let _gi = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbI);
1375 let cci = left.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize)
1377 + top.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize);
1378
1379 if mb_type != 0 {
1380 let mt = mb_type - 1;
1385 let pred_mode = I16Mode::from_id(mt % 4);
1386 let cbp_chroma = (mt % 12) / 4;
1387 let cbp_luma_15 = mt / 12 == 1;
1388 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1389 cmode[addr] = chroma_mode as i32;
1390 cat[addr] = 2;
1391 mb_cbp[addr] = ((cbp_chroma as u8) << 4) | if cbp_luma_15 { 15 } else { 0 };
1392 let w4 = self.mb_w * 4;
1393
1394 let mut nzc = [0xffu8; 48];
1395 if let Some(t) = top {
1396 let tn = mb_nzc[t];
1397 nzc[1..5].copy_from_slice(&tn[12..16]);
1398 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1399 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1400 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1401 }
1402 if let Some(l) = left {
1403 let ln = mb_nzc[l];
1404 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1405 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1406 }
1407
1408 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1409 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1410 self.step_qp(qpd);
1411 let qp = self.cur_qp;
1412 let mut cbfdc = 0u16;
1413
1414 let mut dc_scan = [0i32; 16];
1416 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 0, RP_I16_DC, true, ndc, &mut dc_scan);
1417 let recon_dc = self.dequant_luma_dc(&un_scan_4x4_dcac(&dc_scan), qp, 0);
1418
1419 let mut q_blocks = [[0i32; 16]; 16];
1421 for (iz, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1422 let total = if cbp_luma_15 {
1423 let mut ac = [0i32; 16];
1424 let t = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_I16_AC, true, ndc, &mut ac);
1425 un_scan_4x4_ac_into(&ac, &mut q_blocks[lby * 4 + lbx]);
1426 t as u8
1427 } else {
1428 nzc[NZC_CACHE[iz]] = 0;
1429 0
1430 };
1431 self.nnz_y[(mby * 4 + lby) * w4 + (mbx * 4 + lbx)] = total;
1432 }
1433
1434 let mut cdc = [[0i32; 4]; 2];
1435 let mut cac = [[[0i32; 16]; 4]; 2];
1436 if cbp_chroma >= 1 {
1437 for i in 0..2usize {
1438 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1439 }
1440 }
1441 if cbp_chroma == 2 {
1442 for i in 0..2usize {
1443 for id4 in 0..4usize {
1444 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1445 }
1446 }
1447 }
1448
1449 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1451 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1452 let (lx, ly) = (mbx * 16, mby * 16);
1453 let mut t16 = [0u8; 16];
1454 let mut l16 = [0u8; 16];
1455 if top_ok {
1456 t16.copy_from_slice(&self.rec_y[(ly - 1) * self.cw + lx..][..16]);
1457 }
1458 if left_ok {
1459 for i in 0..16 {
1460 l16[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
1461 }
1462 }
1463 let corner = if top_ok && left_ok { self.rec_y[(ly - 1) * self.cw + lx - 1] } else { 0 };
1464 let pred_l = luma16x16_pred(pred_mode, top_ok, left_ok, &t16, &l16, corner);
1465 for by in 0..4 {
1466 for bx in 0..4 {
1467 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
1468 deq[0] = recon_dc[by * 4 + bx];
1469 let predb: [i32; 16] = std::array::from_fn(|i| pred_l[(by * 4 + i / 4) * 16 + (bx * 4 + i % 4)] as i32);
1470 let s = reconstruct_4x4(&deq, &predb);
1471 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
1472 self.modes_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = 2;
1476 self.coded_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = true;
1477 }
1478 }
1479 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1480
1481 self.mb_qp[addr] = self.cur_qp;
1482 cbf_dc[addr] = cbfdc;
1483 let mut mn = [0u8; 24];
1484 for k in 0..4 {
1485 mn[k] = nzc[9 + k];
1486 mn[4 + k] = nzc[17 + k];
1487 mn[8 + k] = nzc[25 + k];
1488 mn[12 + k] = nzc[33 + k];
1489 }
1490 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1491 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1492 for v in mn.iter_mut() {
1493 if *v == 0xff {
1494 *v = 0;
1495 }
1496 }
1497 mb_nzc[addr] = mn;
1498
1499 let eos = cab.decode_terminate();
1500 addr += 1;
1501 if eos || addr >= total {
1502 break;
1503 }
1504 continue;
1505 }
1506 cat[addr] = 0;
1507 let w4 = self.mb_w * 4;
1508 let t8 = self.transform_8x8_mode && {
1513 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1514 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1515 cab.decode_decision(399 + a + b) != 0
1516 };
1517 self.mb_t8x8[addr] = t8;
1518 let mut modes = [2u8; 16]; let mut modes8 = [2u8; 4]; if t8 {
1523 for b8 in 0..4usize {
1526 let (b8x, b8y) = (b8 % 2, b8 / 2);
1527 let (bx, by) = (mbx * 4 + b8x * 2, mby * 4 + b8y * 2);
1528 let predicted = self.predict_i4_mode(bx, by);
1529 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1530 let actual = if rr < 0 {
1531 predicted
1532 } else {
1533 let rem = rr as u8;
1534 if rem < predicted { rem } else { rem + 1 }
1535 };
1536 modes8[b8] = actual;
1537 for dy in 0..2 {
1538 for dx in 0..2 {
1539 self.modes_y[(by + dy) * w4 + (bx + dx)] = actual;
1540 modes[(b8y * 2 + dy) * 4 + (b8x * 2 + dx)] = actual;
1541 }
1542 }
1543 }
1544 } else {
1545 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1546 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1547 let predicted = self.predict_i4_mode(bx, by);
1548 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1549 let actual = if rr < 0 {
1550 predicted
1551 } else {
1552 let rem = rr as u8;
1553 if rem < predicted { rem } else { rem + 1 }
1554 };
1555 self.modes_y[by * w4 + bx] = actual;
1556 modes[lby * 4 + lbx] = actual;
1557 }
1558 }
1559 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1560 cmode[addr] = chroma_mode as i32;
1561 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1562 mb_cbp[addr] = cbp as u8;
1563 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1564
1565 let mut nzc = [0xffu8; 48];
1567 if let Some(t) = top {
1568 let tn = mb_nzc[t];
1569 nzc[1..5].copy_from_slice(&tn[12..16]);
1570 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1571 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1572 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1573 }
1574 if let Some(l) = left {
1575 let ln = mb_nzc[l];
1576 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1577 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1578 }
1579
1580 let mut cbfdc = 0u16;
1583 let mut luma_scan = [[0i32; 16]; 16]; let mut luma8 = [[0i32; 64]; 4]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
1588 last_delta_qp = 0;
1589 }
1590 if cbp != 0 {
1591 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1592 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1593 self.step_qp(qpd);
1594 for id8 in 0..4usize {
1595 if cbp_luma & (1 << id8) != 0 {
1596 if t8 {
1597 let n = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, true, ndc, &mut luma8[id8]);
1600 let (b8x, b8y) = (id8 % 2, id8 / 2);
1601 for sy in 0..2 {
1602 for sx in 0..2 {
1603 self.nnz_y[(mby * 4 + b8y * 2 + sy) * w4 + (mbx * 4 + b8x * 2 + sx)] = n as u8;
1604 }
1605 }
1606 } else {
1607 for id4 in 0..4usize {
1608 let iz = id8 * 4 + id4;
1609 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, true, ndc, &mut luma_scan[iz]);
1610 }
1611 }
1612 } else {
1613 for k in 0..4 {
1614 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1615 }
1616 if t8 {
1617 let (b8x, b8y) = (id8 % 2, id8 / 2);
1618 for sy in 0..2 {
1619 for sx in 0..2 {
1620 self.nnz_y[(mby * 4 + b8y * 2 + sy) * w4 + (mbx * 4 + b8x * 2 + sx)] = 0;
1621 }
1622 }
1623 }
1624 }
1625 }
1626 if cbp_chroma >= 1 {
1627 for i in 0..2usize {
1628 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1629 }
1630 }
1631 if cbp_chroma == 2 {
1632 for i in 0..2usize {
1633 for id4 in 0..4usize {
1634 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1635 }
1636 }
1637 }
1638 }
1639 self.mb_qp[addr] = self.cur_qp;
1640 cbf_dc[addr] = cbfdc;
1641 let mut mn = [0u8; 24];
1643 for k in 0..4 {
1644 mn[k] = nzc[9 + k];
1645 mn[4 + k] = nzc[17 + k];
1646 mn[8 + k] = nzc[25 + k];
1647 mn[12 + k] = nzc[33 + k];
1648 }
1649 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1650 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1651 for v in mn.iter_mut() {
1652 if *v == 0xff {
1653 *v = 0;
1654 }
1655 }
1656 mb_nzc[addr] = mn;
1657
1658 let qp = self.cur_qp;
1660 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1661 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1662 if t8 {
1663 for b8 in 0..4usize {
1667 let (b8x, b8y) = (b8 % 2, b8 / 2);
1668 let (bx, by) = (mbx * 4 + b8x * 2, mby * 4 + b8y * 2);
1669 let (px, py) = (bx * 4, by * 4);
1670 let res8 = if cbp_luma & (1 << b8) != 0 {
1671 let raster = un_scan_8x8(&luma8[b8]);
1672 self.inv_quant8(&raster, qp, 0)
1673 } else {
1674 [0i32; 64]
1675 };
1676 let avail_top = b8y > 0 || top_ok;
1677 let avail_left = b8x > 0 || left_ok;
1678 let (t, l, corner, avail_corner) =
1679 self.gather_i8(px, py, avail_top, avail_left, bx, by);
1680 let pred =
1681 intra8x8_pred(modes8[b8], avail_top, avail_left, avail_corner, &t, &l, corner);
1682 let mut predb = [0i32; 64];
1683 for i in 0..64 {
1684 predb[i] = pred[i] as i32;
1685 }
1686 let recon = add_residual_8x8(&res8, &predb);
1687 for dy in 0..8 {
1688 for dx in 0..8 {
1689 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
1690 }
1691 }
1692 for sy in 0..2 {
1693 for sx in 0..2 {
1694 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
1695 }
1696 }
1697 }
1698 }
1699 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1700 if t8 {
1701 break;
1702 }
1703 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1704 let (px, py) = (bx * 4, by * 4);
1705 let at = lby > 0 || top_ok;
1706 let al = lbx > 0 || left_ok;
1707 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1708 self.nnz_y[by * w4 + bx] = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1709 let (t, l, corner) = self.gather_i4(px, py, at, al, bx, by);
1710 let pred = intra4x4_pred(modes[lby * 4 + lbx], at, al, &t, &l, corner);
1711 let predb = std::array::from_fn(|i| pred[i] as i32);
1712 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
1713 store(&mut self.rec_y, self.cw, px, py, &s);
1714 self.coded_y[by * w4 + bx] = true;
1715 }
1716 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1717
1718 let eos = cab.decode_terminate();
1720 addr += 1;
1721 if eos || addr >= total {
1722 break;
1723 }
1724 }
1725 if trace {
1726 eprintln!("# CABAC decoded {} MBs (of {total})", addr - first_mb);
1727 }
1728 Ok(addr)
1729 }
1730
1731 #[allow(clippy::too_many_arguments)]
1735 #[allow(clippy::too_many_arguments)]
1741 fn add_inter_residual(
1742 &mut self,
1743 mb_x: usize,
1744 mb_y: usize,
1745 pred_y: &[u8; 256],
1746 c_pred: &[[u8; 64]; 2],
1747 luma_scan: &[[i32; 16]; 16],
1748 luma8: Option<&[[i32; 64]; 4]>,
1751 cdc: &[[i32; 4]; 2],
1752 cac: &[[[i32; 16]; 4]; 2],
1753 cbp_chroma: u32,
1754 ) {
1755 let qp = self.cur_qp;
1756 let qpc = self.chroma_qp_for(qp);
1757 let (w4r, w2r) = (self.mb_w * 4, self.mb_w * 2);
1758 if let Some(l8) = luma8 {
1759 for b8 in 0..4usize {
1761 let (b8x, b8y) = (b8 % 2, b8 / 2);
1762 let nnz = l8[b8].iter().filter(|&&v| v != 0).count() as u8;
1763 for sy in 0..2 {
1764 for sx in 0..2 {
1765 self.nnz_y[(mb_y * 4 + b8y * 2 + sy) * w4r + (mb_x * 4 + b8x * 2 + sx)] = nnz;
1766 }
1767 }
1768 let res8 = if nnz == 0 {
1769 [0i32; 64]
1770 } else {
1771 let raster = un_scan_8x8(&l8[b8]);
1772 self.inv_quant8(&raster, qp, 1)
1774 };
1775 for sy in 0..2 {
1778 for sx in 0..2 {
1779 self.coded_y[(mb_y * 4 + b8y * 2 + sy) * w4r + (mb_x * 4 + b8x * 2 + sx)] = true;
1780 }
1781 }
1782 let predb: [i32; 64] =
1783 std::array::from_fn(|i| pred_y[(b8y * 8 + i / 8) * 16 + (b8x * 8 + i % 8)] as i32);
1784 let recon = add_residual_8x8(&res8, &predb);
1785 let (px, py) = (mb_x * 16 + b8x * 8, mb_y * 16 + b8y * 8);
1786 for dy in 0..8 {
1787 for dx in 0..8 {
1788 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
1789 }
1790 }
1791 }
1792 }
1793 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1794 if luma8.is_some() {
1795 break;
1796 }
1797 let nnz = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1798 self.nnz_y[(mb_y * 4 + lby) * w4r + (mb_x * 4 + lbx)] = nnz;
1799 if nnz == 0 {
1800 let mut s = [0u8; 16];
1805 for r in 0..4 {
1806 s[r * 4..r * 4 + 4]
1807 .copy_from_slice(&pred_y[(lby * 4 + r) * 16 + lbx * 4..][..4]);
1808 }
1809 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1810 continue;
1811 }
1812 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1813 let deq = self.dequant(&qb, qp, 3);
1814 let predb: [i32; 16] = std::array::from_fn(|i| pred_y[(lby * 4 + i / 4) * 16 + (lbx * 4 + i % 4)] as i32);
1815 let s = reconstruct_4x4(&deq, &predb);
1816 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1817 }
1818 let mut c_dc = [[0i32; 4]; 2];
1819 if cbp_chroma != 0 {
1820 for c in 0..2 {
1821 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 4 + c);
1822 }
1823 }
1824 for c in 0..2 {
1825 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1826 let mut ac_nz = false;
1827 let mut ac = [0i32; 16];
1828 if cbp_chroma == 2 {
1829 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1830 let n = cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1831 self.nnz_c[c][(mb_y * 2 + by) * w2r + (mb_x * 2 + bx)] = n;
1832 ac_nz = n != 0;
1833 }
1834 let dc = c_dc[c][by * 2 + bx];
1835 if dc == 0 && !ac_nz {
1836 let mut s = [0u8; 16];
1838 for r in 0..4 {
1839 s[r * 4..r * 4 + 4]
1840 .copy_from_slice(&c_pred[c][(by * 4 + r) * 8 + bx * 4..][..4]);
1841 }
1842 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1843 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1844 continue;
1845 }
1846 let mut deq = self.dequant(&ac, qpc, 4 + c);
1847 deq[0] = dc;
1848 let predb: [i32; 16] =
1849 std::array::from_fn(|i| c_pred[c][(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1850 let s = reconstruct_4x4(&deq, &predb);
1851 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1852 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1853 }
1854 }
1855 }
1856
1857 fn recon_chroma_cabac(
1858 &mut self,
1859 mb_x: usize,
1860 mb_y: usize,
1861 chroma_mode: u8,
1862 cdc: &[[i32; 4]; 2],
1863 cac: &[[[i32; 16]; 4]; 2],
1864 cbp_chroma: u32,
1865 avail_top: bool,
1866 avail_left: bool,
1867 ) {
1868 let qpc = self.chroma_qp_for(self.cur_qp);
1869 let (cx, cy) = (mb_x * 8, mb_y * 8);
1870 let mut c_dc = [[0i32; 4]; 2];
1871 if cbp_chroma != 0 {
1872 for c in 0..2 {
1873 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 1 + c);
1874 }
1875 }
1876 let w2 = self.mb_w * 2;
1877 for c in 0..2 {
1878 let mut ctop = [0u8; 8];
1879 let mut cleft = [0u8; 8];
1880 let mut ccorner = 0u8;
1881 {
1882 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
1883 if avail_top {
1884 ctop.copy_from_slice(&rec_c[(cy - 1) * self.ccw + cx..][..8]);
1885 }
1886 if avail_left {
1887 for i in 0..8 {
1888 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
1889 }
1890 }
1891 if avail_top && avail_left {
1892 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
1893 }
1894 }
1895 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
1896 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1897 let mut ac = [0i32; 16];
1898 if cbp_chroma == 2 {
1899 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1900 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] =
1901 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1902 }
1903 let mut deq = self.dequant(&ac, qpc, 1 + c);
1904 deq[0] = c_dc[c][by * 2 + bx];
1905 let predb: [i32; 16] =
1906 std::array::from_fn(|i| pred8[(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1907 let s = reconstruct_4x4(&deq, &predb);
1908 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1909 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
1910 }
1911 }
1912 }
1913
1914 pub fn decode_slice_data(
1915 &mut self,
1916 r: &mut BitReader,
1917 is_p: bool,
1918 first_mb: usize,
1919 ) -> Result<usize, MbError> {
1920 let total = self.mb_w * self.mb_h;
1921 self.slice_first_mb = first_mb;
1922 let mut addr = first_mb;
1923 while addr < total {
1924 if is_p || self.is_b {
1925 let skip_run = {
1926 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1927 r.read_ue()?
1928 } as usize;
1929 for _ in 0..skip_run {
1930 if addr >= total {
1931 break;
1932 }
1933 if self.is_b {
1934 self.decode_b_skip(addr % self.mb_w, addr / self.mb_w)?;
1935 } else {
1936 self.decode_p_skip(addr % self.mb_w, addr / self.mb_w)?;
1937 }
1938 self.mb_qp[addr] = self.cur_qp; addr += 1;
1940 }
1941 if addr >= total {
1942 break;
1943 }
1944 if skip_run > 0 && !r.more_rbsp_data() {
1946 break;
1947 }
1948 }
1949 if self.is_b {
1950 self.decode_b_mb(r, addr % self.mb_w, addr / self.mb_w)?;
1951 } else {
1952 self.decode_mb(r, addr % self.mb_w, addr / self.mb_w, is_p)?;
1953 }
1954 self.mb_qp[addr] = self.cur_qp;
1955 addr += 1;
1956 if !r.more_rbsp_data() {
1958 break;
1959 }
1960 }
1961 Ok(addr)
1962 }
1963
1964 fn decode_mb(
1965 &mut self,
1966 r: &mut BitReader,
1967 mb_x: usize,
1968 mb_y: usize,
1969 is_p: bool,
1970 ) -> Result<(), MbError> {
1971 let mut mb_type = {
1972 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1973 r.read_ue()?
1974 };
1975 if is_p {
1976 if mb_type <= 2 {
1979 return self.decode_inter(r, mb_x, mb_y, mb_type as u8);
1980 }
1981 if mb_type == 3 || mb_type == 4 {
1982 return self.decode_p8x8(r, mb_x, mb_y, mb_type == 4);
1983 }
1984 mb_type -= 5;
1985 }
1986 self.decode_intra_mb(r, mb_x, mb_y, mb_type)
1987 }
1988
1989 fn decode_intra_mb(
1992 &mut self,
1993 r: &mut BitReader,
1994 mb_x: usize,
1995 mb_y: usize,
1996 mb_type: u32,
1997 ) -> Result<(), MbError> {
1998 let _gi = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbI);
2002 if mb_type == 0 {
2003 if self.transform_8x8_mode && r.read_bit()? {
2005 self.decode_i8x8(r, mb_x, mb_y)?;
2006 } else {
2007 self.decode_i4x4(r, mb_x, mb_y)?;
2008 }
2009 } else if (1..=24).contains(&mb_type) {
2010 self.decode_i16(r, mb_x, mb_y, mb_type - 1)?;
2011 } else if mb_type == 25 {
2012 self.decode_ipcm(r, mb_x, mb_y)?;
2013 } else {
2014 return Err(MbError::Unsupported("only I_4x4 / I_16x16 / I_PCM macroblocks"));
2015 }
2016 let w4 = self.mb_w * 4;
2018 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2019 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
2020 }
2021 Ok(())
2022 }
2023
2024 fn decode_inter(
2028 &mut self,
2029 r: &mut BitReader,
2030 mb_x: usize,
2031 mb_y: usize,
2032 mode: u8,
2033 ) -> Result<(), MbError> {
2034 if self.refs.is_empty() {
2035 return Err(MbError::Unsupported("inter without reference"));
2036 }
2037 if mode == 0 {
2044 self.mb_kind[mb_y * self.mb_w + mb_x] =
2045 rusty_h264_common::deblock::MB_KIND_INTER_UNIFORM;
2046 }
2047 let w4 = self.mb_w * 4;
2049 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2050 let num_refs = self.refs.len();
2051 let layout = inter_partitions(mode);
2052
2053 let nparts = layout.len();
2056 let mut ref_idxs = [0i32; 4];
2057 if self.num_ref_active > 1 {
2058 for ri in ref_idxs[..nparts].iter_mut() {
2059 *ri = read_ref_idx(r, self.num_ref_active)?;
2060 if *ri as usize >= num_refs {
2061 return Err(MbError::Truncated); }
2063 }
2064 }
2065
2066 let mut part_mv = [(0i32, (0i32, 0i32)); 4];
2069 {
2070 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::MvGrid);
2071 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2072 let refi = ref_idxs[part];
2073 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2074 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (rw / 4) as isize);
2075 let pmv = predict_partition_mv(mode, part, a, b, c, refi);
2076 let mvd_x = r.read_se()?;
2077 let mvd_y = r.read_se()?;
2078 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2079 part_mv[part] = (refi, mv);
2080 for by in ry / 4..ry / 4 + rh / 4 {
2081 for bx in rx / 4..rx / 4 + rw / 4 {
2082 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2083 self.mv_y[idx] = mv;
2084 self.inter_y[idx] = true;
2085 self.ref_idx_y[idx] = refi;
2086 self.coded_y[idx] = true;
2087 }
2088 }
2089 }
2090 }
2091
2092 let mut pred_y = [0u8; 256];
2094 let mut c_pred = [[0u8; 64]; 2];
2095 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2096 let (refi, mv) = part_mv[part];
2097 let reference = &self.refs[refi as usize];
2098 let mut tmp = [0u8; 256];
2099 mc_luma_padded(&reference.py, reference.lstride(), crate::LPAD, self.cw, ch, mb_x * 16 + rx, mb_y * 16 + ry, rw, rh, mv.0, mv.1, &mut tmp);
2100 {
2101 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
2102 restride(&mut pred_y, 16, rx, ry, &tmp, rw, rh);
2103 }
2104 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
2105 for cc in 0..2 {
2106 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2107 let mut tc = [0u8; 64];
2108 mc_chroma_padded(rc, reference.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv.0, mv.1, &mut tc);
2109 {
2110 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
2111 restride(&mut c_pred[cc], 8, crx, cry, &tc, crw, crh);
2112 }
2113 }
2114 self.weight_partition(&mut pred_y, &mut c_pred, 0, refi as usize, rx, ry, rw, rh);
2115 }
2116
2117 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2119 }
2120
2121 fn inter_finish(
2125 &mut self,
2126 r: &mut BitReader,
2127 mb_x: usize,
2128 mb_y: usize,
2129 pred_y: &[u8; 256],
2130 c_pred: &[[u8; 64]; 2],
2131 allow_8x8: bool,
2132 ) -> Result<(), MbError> {
2133 let w4 = self.mb_w * 4;
2134 let cbp = {
2135 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
2136 read_cbp_inter(r)?
2137 };
2138 let cbp_luma = cbp & 15;
2139 let cbp_chroma = cbp >> 4;
2140 let t8x8 = cbp_luma > 0 && self.transform_8x8_mode && allow_8x8 && r.read_bit()?;
2143 if t8x8 {
2144 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
2145 }
2146 if cbp != 0 {
2147 self.step_qp(r.read_se()?);
2148 }
2149 let (qp, qpc) = (self.cur_qp, self.chroma_qp_for(self.cur_qp));
2150
2151 self.nnz_cache_load(mb_x, mb_y);
2153 let mut q_blocks = [[0i32; 16]; 16];
2154 let mut luma8 = [[0i32; 64]; 4]; if t8x8 {
2156 for b8 in 0..4 {
2157 let (b8x, b8y) = (b8 % 2, b8 / 2);
2158 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2159 if cbp_luma & (1 << b8) != 0 {
2160 let mut scan8 = [0i32; 64];
2161 for sub in 0..4 {
2162 let (sx, sy) = (sub % 2, sub / 2);
2163 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
2164 let nc = self.nc_pred(cx, cy);
2165 let blk = decode_residual_block(r, 16, nc)?;
2166 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
2167 self.nnz_cache_set(cx, cy, total);
2168 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
2169 for k in 0..16 {
2170 scan8[4 * k + sub] = blk[k];
2171 }
2172 }
2173 luma8[b8] = self.inv_quant8(&un_scan_8x8(&scan8), qp, 1);
2174 } else {
2175 for sub in 0..4 {
2176 let (sx, sy) = (sub % 2, sub / 2);
2177 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
2178 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
2179 }
2180 }
2181 }
2182 } else {
2183 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2184 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2185 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
2186 let nc = self.nc_pred(lbx, lby);
2187 let scan16 = decode_residual_block(r, 16, nc)?;
2188 q_blocks[lby * 4 + lbx] = un_scan_4x4_dcac(&scan16);
2189 scan16.iter().filter(|&&v| v != 0).count() as u8
2190 } else {
2191 0
2192 };
2193 self.nnz_cache_set(lbx, lby, total);
2194 self.nnz_y[by * w4 + bx] = total;
2195 }
2196 }
2197
2198 let mut c_recon_dc = [[0i32; 4]; 2];
2200 if cbp_chroma != 0 {
2201 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
2202 let dc = decode_residual_block(r, 4, -1)?;
2203 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 4 + c);
2204 }
2205 }
2206 let mut c_q = [[[0i32; 16]; 4]; 2];
2207 if cbp_chroma == 2 {
2208 self.chroma_cache_load(mb_x, mb_y);
2209 let w2 = self.mb_w * 2;
2210 for c in 0..2 {
2211 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2212 let nc = self.chroma_nc_pred(c, bx, by);
2213 let ac = decode_residual_block(r, 15, nc)?;
2214 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
2215 self.chroma_nnz_cache_set(c, bx, by, total);
2216 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
2217 un_scan_4x4_ac_into(&ac, &mut c_q[c][by * 2 + bx]);
2218 }
2219 }
2220 }
2221
2222 if t8x8 {
2224 for b8 in 0..4 {
2225 let (b8x, b8y) = (b8 % 2, b8 / 2);
2226 let (px, py) = (b8x * 8, b8y * 8);
2227 for dy in 0..8 {
2228 for dx in 0..8 {
2229 let p = pred_y[(py + dy) * 16 + (px + dx)] as i32;
2230 let v = (p + luma8[b8][dy * 8 + dx]).clamp(0, 255) as u8;
2231 self.rec_y[(mb_y * 16 + py + dy) * self.cw + (mb_x * 16 + px + dx)] = v;
2232 }
2233 }
2234 }
2235 } else {
2236 for b8 in 0..4 {
2243 let (b8x, b8y) = (b8 % 2, b8 / 2);
2244 let pred_off = (b8y * 8) * 16 + b8x * 8;
2245 let rec_off = (mb_y * 16 + b8y * 8) * self.cw + (mb_x * 16 + b8x * 8);
2246 if cbp_luma & (1 << b8) == 0 {
2247 for r in 0..8 {
2248 let (s, d) = (pred_off + r * 16, rec_off + r * self.cw);
2249 self.rec_y[d..d + 8].copy_from_slice(&pred_y[s..s + 8]);
2250 }
2251 continue;
2252 }
2253 #[cfg(accel)]
2254 {
2255 let mut dct = [0i16; 64];
2256 for (i, (sx, sy)) in [(0, 0), (1, 0), (0, 1), (1, 1)].into_iter().enumerate() {
2257 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2258 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2259 for k in 0..16 {
2260 dct[i * 16 + k] = deq[k] as i16;
2261 }
2262 }
2263 rusty_h264_accel::idct_four_t4_rec(
2264 &mut self.rec_y[rec_off..],
2265 self.cw,
2266 &pred_y[pred_off..],
2267 16,
2268 &dct,
2269 );
2270 }
2271 #[cfg(not(accel))]
2272 for (sx, sy) in [(0, 0), (1, 0), (0, 1), (1, 1)] {
2273 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2274 let mut predb = [0i32; 16];
2275 for dy in 0..4 {
2276 for dx in 0..4 {
2277 predb[dy * 4 + dx] = pred_y[(lby * 4 + dy) * 16 + (lbx * 4 + dx)] as i32;
2278 }
2279 }
2280 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2281 let s = reconstruct_4x4(&deq, &predb);
2282 store(&mut self.rec_y, self.cw, mb_x * 16 + lbx * 4, mb_y * 16 + lby * 4, &s);
2283 }
2284 }
2285 }
2286 if cbp_chroma == 0 {
2289 for c in 0..2 {
2290 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2291 for dy in 0..8 {
2292 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2293 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2294 }
2295 }
2296 } else {
2297 for c in 0..2 {
2298 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2299 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2300 let mut predb = [0i32; 16];
2301 for dy in 0..4 {
2302 for dx in 0..4 {
2303 predb[dy * 4 + dx] = c_pred[c][(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
2304 }
2305 }
2306 let mut deq = match &self.scaling {
2307 Some(s) => dequantize_weighted(&c_q[c][by * 2 + bx], qpc, &s[4 + c]),
2308 None => dequantize(&c_q[c][by * 2 + bx], qpc),
2309 };
2310 deq[0] = c_recon_dc[c][by * 2 + bx];
2311 let s = reconstruct_4x4(&deq, &predb);
2312 store(plane, self.ccw, mb_x * 8 + bx * 4, mb_y * 8 + by * 4, &s);
2313 }
2314 }
2315 }
2316
2317 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2319 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2320 }
2321 Ok(())
2322 }
2323
2324 fn mv_neighbors_list(&self, pbx: isize, pby: isize, pwb: isize, list: usize) -> [MvNeighbor; 3] {
2332 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
2333 let (mvg, refg) = if list == 0 {
2334 (&self.mv_y, &self.ref_idx_y)
2335 } else {
2336 (&self.mv1, &self.ref_idx1)
2337 };
2338 let get = |bx: isize, by: isize| -> MvNeighbor {
2339 if bx < 0
2340 || by < 0
2341 || bx >= w4
2342 || by >= h4
2343 || !self.coded_y[(by * w4 + bx) as usize]
2344 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
2345 {
2346 MvNeighbor::NONE
2347 } else {
2348 let idx = (by * w4 + bx) as usize;
2349 MvNeighbor { available: true, mv: mvg[idx], ref_idx: refg[idx] }
2350 }
2351 };
2352 let a = get(pbx - 1, pby);
2353 let b = get(pbx, pby - 1);
2354 let mut c = get(pbx + pwb, pby - 1);
2355 if !c.available {
2356 c = get(pbx - 1, pby - 1);
2357 }
2358 [a, b, c]
2359 }
2360
2361 #[inline]
2375 fn col_block(&self, bx4: usize, by4: usize) -> (usize, usize) {
2376 if self.direct_8x8_inference {
2377 ((bx4 / 2) * 3, (by4 / 2) * 3)
2378 } else {
2379 (bx4, by4)
2380 }
2381 }
2382
2383 fn col_zero(&self, bx: usize, by: usize) -> bool {
2384 let Some(col) = self.refs1.first() else { return false };
2385 if col.long_term || col.w4 == 0 {
2386 return false;
2387 }
2388 let idx = by * col.w4 + bx;
2389 if idx >= col.ref_idx.len() {
2390 return false;
2391 }
2392 let (cref, cmv) = if col.ref_idx[idx] >= 0 {
2400 (col.ref_idx[idx], col.mv[idx])
2401 } else if idx < col.ref_idx1.len() && col.ref_idx1[idx] >= 0 {
2402 (col.ref_idx1[idx], col.mv1[idx])
2403 } else {
2404 return false;
2405 };
2406 cref == 0 && cmv.0.abs() <= 1 && cmv.1.abs() <= 1
2407 }
2408
2409 fn implicit_weights(&self, refi0: i32, refi1: i32) -> Option<(i32, i32)> {
2413 if self.weighted_bipred_idc != 2 || refi0 < 0 || refi1 < 0 {
2414 return None;
2415 }
2416 let r0 = &self.refs[refi0 as usize];
2417 let r1 = &self.refs1[refi1 as usize];
2418 let td = (r1.poc - r0.poc).clamp(-128, 127);
2419 let tb = (self.cur_poc - r0.poc).clamp(-128, 127);
2420 if td == 0 || r0.long_term || r1.long_term {
2421 return None; }
2423 let tx = (16384 + td.abs() / 2) / td;
2424 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2425 let w1 = dsf >> 2;
2426 if !(-64..=128).contains(&w1) {
2427 return None; }
2429 Some((64 - w1, w1))
2430 }
2431
2432 #[allow(clippy::too_many_arguments)]
2436 fn b_mc(
2437 &self,
2438 mb_x: usize,
2439 mb_y: usize,
2440 px: usize,
2441 py: usize,
2442 rw: usize,
2443 rh: usize,
2444 refi0: i32,
2445 mv0: (i32, i32),
2446 refi1: i32,
2447 mv1: (i32, i32),
2448 pred_y: &mut [u8; 256],
2449 c_pred: &mut [[u8; 64]; 2],
2450 ) {
2451 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBMc);
2452 let refi0 = if refi0 >= 0 { (refi0 as usize).min(self.refs.len().saturating_sub(1)) as i32 } else { -1 };
2458 let refi1 = if refi1 >= 0 { (refi1 as usize).min(self.refs1.len().saturating_sub(1)) as i32 } else { -1 };
2459 if (refi0 >= 0 && self.refs.is_empty()) || (refi1 >= 0 && self.refs1.is_empty()) {
2460 return;
2461 }
2462 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2463 let weights = {
2464 let _gw = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBWeights);
2465 self.implicit_weights(refi0, refi1)
2466 };
2467 let blend = |p: i32, q: i32| -> u8 {
2469 match weights {
2470 Some((w0, w1)) => (((p * w0 + q * w1 + 32) >> 6).clamp(0, 255)) as u8,
2471 None => ((p + q + 1) >> 1) as u8,
2472 }
2473 };
2474 let (mut a, mut b) = ([0u8; 256], [0u8; 256]);
2475 let _gl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBLuma);
2476 if refi0 >= 0 {
2477 let rf = &self.refs[refi0 as usize];
2478 mc_luma_padded(&rf.py, rf.lstride(), crate::LPAD, self.cw, ch, mb_x * 16 + px, mb_y * 16 + py, rw, rh, mv0.0, mv0.1, &mut a);
2479 }
2480 if refi1 >= 0 {
2481 let rf = &self.refs1[refi1 as usize];
2482 mc_luma_padded(&rf.py, rf.lstride(), crate::LPAD, self.cw, ch, mb_x * 16 + px, mb_y * 16 + py, rw, rh, mv1.0, mv1.1, &mut b);
2483 }
2484 drop(_gl);
2485 let _gbl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBBlend);
2486 match (refi0 >= 0, refi1 >= 0) {
2489 (true, true) => {
2490 for dy in 0..rh {
2491 for dx in 0..rw {
2492 let (p, q) = (a[dy * rw + dx] as i32, b[dy * rw + dx] as i32);
2493 pred_y[(py + dy) * 16 + (px + dx)] = blend(p, q);
2494 }
2495 }
2496 }
2497 (true, false) => {
2498 for dy in 0..rh {
2499 let d = (py + dy) * 16 + px;
2500 pred_y[d..d + rw].copy_from_slice(&a[dy * rw..dy * rw + rw]);
2501 }
2502 }
2503 _ => {
2504 for dy in 0..rh {
2505 let d = (py + dy) * 16 + px;
2506 pred_y[d..d + rw].copy_from_slice(&b[dy * rw..dy * rw + rw]);
2507 }
2508 }
2509 }
2510 drop(_gbl);
2511 let _gc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBChroma);
2512 let (crx, cry, crw, crh) = (px / 2, py / 2, rw / 2, rh / 2);
2513 for c in 0..2 {
2514 let (mut ca, mut cb) = ([0u8; 64], [0u8; 64]);
2515 if refi0 >= 0 {
2516 let rf = &self.refs[refi0 as usize];
2517 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2518 mc_chroma_padded(pl, rf.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv0.0, mv0.1, &mut ca);
2519 }
2520 if refi1 >= 0 {
2521 let rf = &self.refs1[refi1 as usize];
2522 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2523 mc_chroma_padded(pl, rf.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv1.0, mv1.1, &mut cb);
2524 }
2525 match (refi0 >= 0, refi1 >= 0) {
2526 (true, true) => {
2527 for dy in 0..crh {
2528 for dx in 0..crw {
2529 let (p, q) = (ca[dy * crw + dx] as i32, cb[dy * crw + dx] as i32);
2530 c_pred[c][(cry + dy) * 8 + (crx + dx)] = blend(p, q);
2531 }
2532 }
2533 }
2534 (true, false) => {
2535 for dy in 0..crh {
2536 let d = (cry + dy) * 8 + crx;
2537 c_pred[c][d..d + crw].copy_from_slice(&ca[dy * crw..dy * crw + crw]);
2538 }
2539 }
2540 _ => {
2541 for dy in 0..crh {
2542 let d = (cry + dy) * 8 + crx;
2543 c_pred[c][d..d + crw].copy_from_slice(&cb[dy * crw..dy * crw + crw]);
2544 }
2545 }
2546 }
2547 }
2548 }
2549
2550 #[allow(clippy::too_many_arguments)]
2552 fn b_set_motion(&mut self, mb_x: usize, mb_y: usize, px: usize, py: usize, rw: usize, rh: usize, refi0: i32, mv0: (i32, i32), refi1: i32, mv1: (i32, i32)) {
2553 let _gs = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBSet);
2554 let w4 = self.mb_w * 4;
2555 for by in py / 4..(py + rh) / 4 {
2556 for bx in px / 4..(px + rw) / 4 {
2557 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2558 self.ref_idx_y[idx] = refi0;
2559 self.mv_y[idx] = if refi0 >= 0 { mv0 } else { (0, 0) };
2560 self.ref_idx1[idx] = refi1;
2561 self.mv1[idx] = if refi1 >= 0 { mv1 } else { (0, 0) };
2562 self.inter_y[idx] = true;
2563 self.coded_y[idx] = true;
2564 self.modes_y[idx] = 2;
2565 }
2566 }
2567 }
2568
2569 #[allow(clippy::too_many_arguments)]
2573 fn coalesce_region(
2578 x: usize,
2579 y: usize,
2580 w: usize,
2581 h: usize,
2582 uniform: &dyn Fn(usize, usize, usize, usize) -> bool,
2583 emit: &mut dyn FnMut(usize, usize, usize, usize),
2584 ) {
2585 if uniform(x, y, w, h) {
2586 emit(x, y, w, h);
2587 return;
2588 }
2589 if h > 1 && uniform(x, y, w, h / 2) && uniform(x, y + h / 2, w, h / 2) {
2590 emit(x, y, w, h / 2);
2591 emit(x, y + h / 2, w, h / 2);
2592 return;
2593 }
2594 if w > 1 && uniform(x, y, w / 2, h) && uniform(x + w / 2, y, w / 2, h) {
2595 emit(x, y, w / 2, h);
2596 emit(x + w / 2, y, w / 2, h);
2597 return;
2598 }
2599 match (w > 1, h > 1) {
2600 (true, true) => {
2601 for q in 0..4usize {
2602 Self::coalesce_region(x + (q % 2) * (w / 2), y + (q / 2) * (h / 2), w / 2, h / 2, uniform, emit);
2603 }
2604 }
2605 (true, false) => {
2606 Self::coalesce_region(x, y, w / 2, h, uniform, emit);
2607 Self::coalesce_region(x + w / 2, y, w / 2, h, uniform, emit);
2608 }
2609 (false, true) => {
2610 Self::coalesce_region(x, y, w, h / 2, uniform, emit);
2611 Self::coalesce_region(x, y + h / 2, w, h / 2, uniform, emit);
2612 }
2613 (false, false) => emit(x, y, 1, 1),
2614 }
2615 }
2616
2617 fn decode_b_direct(&mut self, mb_x: usize, mb_y: usize, px: usize, py: usize, rw: usize, rh: usize, pred_y: &mut [u8; 256], c_pred: &mut [[u8; 64]; 2]) {
2618 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDirect);
2619 if !self.direct_spatial {
2620 return self.decode_b_direct_temporal(mb_x, mb_y, px, py, rw, rh, pred_y, c_pred);
2621 }
2622 let gd = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDeriv);
2627 let (nbx, nby) = ((mb_x * 4) as isize, (mb_y * 4) as isize);
2629 let n0 = self.mv_neighbors_list(nbx, nby, 4, 0);
2630 let n1 = self.mv_neighbors_list(nbx, nby, 4, 1);
2631 let min_pos = |a: i32, b: i32| if a < 0 { b } else if b < 0 { a } else { a.min(b) };
2632 let rid = |n: &[MvNeighbor; 3]| min_pos(min_pos(n[0].ref_idx, n[1].ref_idx), n[2].ref_idx);
2633 let (mut refi0, mut refi1) = (rid(&n0), rid(&n1));
2634 let direct_zero = refi0 < 0 && refi1 < 0;
2635 if direct_zero {
2636 refi0 = 0;
2637 refi1 = 0;
2638 }
2639 let mv0 = if refi0 >= 0 && !direct_zero { predict_mv(n0[0], n0[1], n0[2], refi0) } else { (0, 0) };
2640 let mv1 = if refi1 >= 0 && !direct_zero { predict_mv(n1[0], n1[1], n1[2], refi1) } else { (0, 0) };
2641 let (bx0, by0, bw, bh) = (px / 4, py / 4, rw / 4, rh / 4);
2647 let mut czg = [[false; 4]; 4]; for dy in 0..bh {
2649 for dx in 0..bw {
2650 let (colx, coly) = self.col_block(bx0 + dx, by0 + dy);
2651 czg[dy][dx] = !direct_zero && self.col_zero(mb_x * 4 + colx, mb_y * 4 + coly);
2652 }
2653 }
2654 let uniform = |x: usize, y: usize, w: usize, h: usize| -> bool {
2655 let t = czg[y][x];
2656 (y..y + h).all(|dy| (x..x + w).all(|dx| czg[dy][dx] == t))
2657 };
2658 let mut rects: [(usize, usize, usize, usize); 16] = [(0, 0, 0, 0); 16];
2659 let mut n = 0usize;
2660 Self::coalesce_region(0, 0, bw, bh, &uniform, &mut |x, y, w, h| {
2661 rects[n] = (x, y, w, h);
2662 n += 1;
2663 });
2664 drop(gd); for &(x, y, w, h) in &rects[..n] {
2666 let cz = czg[y][x];
2667 let m0 = if refi0 == 0 && cz { (0, 0) } else { mv0 };
2668 let m1 = if refi1 == 0 && cz { (0, 0) } else { mv1 };
2669 let (lx, ly, lw, lh) = ((bx0 + x) * 4, (by0 + y) * 4, w * 4, h * 4);
2670 self.b_mc(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1, pred_y, c_pred);
2671 self.b_set_motion(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1);
2672 }
2673 }
2674
2675 #[allow(clippy::too_many_arguments)]
2680 fn decode_b_direct_temporal(&mut self, mb_x: usize, mb_y: usize, px: usize, py: usize, rw: usize, rh: usize, pred_y: &mut [u8; 256], c_pred: &mut [[u8; 64]; 2]) {
2681 let poc1 = self.refs1.first().map_or(0, |f| f.poc);
2682 let infer = self.direct_8x8_inference;
2683 let step = if infer { 8 } else { 4 };
2689 let mut sy = py;
2690 while sy < py + rh {
2691 let mut sx = px;
2692 while sx < px + rw {
2693 let (colx, coly) = self.col_block(sx / 4, sy / 4);
2696 let (mvcol, refpoc) = {
2697 let col = &self.refs1[0];
2698 let idx = (mb_y * 4 + coly) * col.w4 + (mb_x * 4 + colx);
2699 if col.w4 != 0 && idx < col.mv.len() && col.ref_poc[idx] != i32::MIN {
2700 (col.mv[idx], col.ref_poc[idx])
2701 } else {
2702 ((0, 0), i32::MIN) }
2704 };
2705 let (refi0, mvc) = if refpoc == i32::MIN {
2707 (0, (0, 0))
2708 } else {
2709 let r = self.refs.iter().position(|f| f.poc == refpoc).unwrap_or(0) as i32;
2710 (r, mvcol)
2711 };
2712 let poc0 = self.refs[refi0 as usize].poc;
2713 let td = (poc1 - poc0).clamp(-128, 127);
2714 let tb = (self.cur_poc - poc0).clamp(-128, 127);
2715 let (mv0, mv1) = if td == 0 || self.refs[refi0 as usize].long_term {
2716 (mvc, (0, 0))
2717 } else {
2718 let tx = (16384 + td.abs() / 2) / td;
2719 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2720 let m0 = ((dsf * mvc.0 + 128) >> 8, (dsf * mvc.1 + 128) >> 8);
2721 (m0, (m0.0 - mvc.0, m0.1 - mvc.1))
2722 };
2723 self.b_mc(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1, pred_y, c_pred);
2724 self.b_set_motion(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1);
2725 sx += step;
2726 }
2727 sy += step;
2728 }
2729 }
2730
2731 fn read_b_ref(&self, r: &mut BitReader, list: usize) -> Result<i32, MbError> {
2734 let (active, avail) = if list == 0 {
2735 (self.num_ref_active, self.refs.len())
2736 } else {
2737 (self.num_ref_active1, self.refs1.len())
2738 };
2739 let v = if active > 1 { read_ref_idx(r, active)? } else { 0 };
2740 if v as usize >= avail {
2741 return Err(MbError::Truncated);
2742 }
2743 Ok(v)
2744 }
2745
2746 fn decode_b_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2748 if self.refs.is_empty() || self.refs1.is_empty() {
2749 return Err(MbError::Unsupported("B without references"));
2750 }
2751 let mut pred_y = [0u8; 256];
2752 let mut c_pred = [[0u8; 64]; 2];
2753 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2754 for dy in 0..16 {
2756 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2757 self.rec_y[d..d + 16].copy_from_slice(&pred_y[dy * 16..dy * 16 + 16]);
2758 }
2759 for c in 0..2 {
2760 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2761 for dy in 0..8 {
2762 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2763 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2764 }
2765 }
2766 let w4 = self.mb_w * 4;
2768 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2769 self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 0;
2770 }
2771 Ok(())
2772 }
2773
2774 fn decode_b_mb(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2777 let mb_type = r.read_ue()?;
2778 if mb_type >= 23 {
2779 return self.decode_intra_mb(r, mb_x, mb_y, mb_type - 23);
2780 }
2781 if self.refs.is_empty() || self.refs1.is_empty() {
2782 return Err(MbError::Unsupported("B without references"));
2783 }
2784 let mut pred_y = [0u8; 256];
2785 let mut c_pred = [[0u8; 64]; 2];
2786
2787 if mb_type == 0 {
2788 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2790 return self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, self.direct_8x8_inference);
2791 }
2792 if mb_type == 22 {
2793 return self.decode_b_8x8(r, mb_x, mb_y);
2794 }
2795
2796 let (layout, mvmode, preds) = b_inter_layout(mb_type);
2798 let mut refi = [[-1i32; 2]; 2]; for (p, &(_, _, _, _)) in layout.iter().enumerate() {
2801 if preds[p].uses(0) {
2802 refi[p][0] = self.read_b_ref(r, 0)?;
2803 }
2804 }
2805 for (p, _) in layout.iter().enumerate() {
2806 if preds[p].uses(1) {
2807 refi[p][1] = self.read_b_ref(r, 1)?;
2808 }
2809 }
2810 let mut mvd = [[(0i32, 0i32); 2]; 2];
2811 for (p, _) in layout.iter().enumerate() {
2812 if preds[p].uses(0) {
2813 mvd[p][0] = (r.read_se()?, r.read_se()?);
2814 }
2815 }
2816 for (p, _) in layout.iter().enumerate() {
2817 if preds[p].uses(1) {
2818 mvd[p][1] = (r.read_se()?, r.read_se()?);
2819 }
2820 }
2821 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2823 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2824 let pwb = (rw / 4) as isize;
2825 let mut mv = [(0i32, 0i32); 2];
2826 for list in 0..2 {
2827 if refi[p][list] >= 0 {
2828 let n = self.mv_neighbors_list(pbx, pby, pwb, list);
2829 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], refi[p][list]);
2830 mv[list] = (pmv.0 + mvd[p][list].0, pmv.1 + mvd[p][list].1);
2831 }
2832 }
2833 self.b_set_motion(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1]);
2834 self.b_mc(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1], &mut pred_y, &mut c_pred);
2844 }
2845 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2846 }
2847
2848 fn decode_b_8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2851 let mut sub = [0u32; 4];
2852 for s in sub.iter_mut() {
2853 let v = r.read_ue()?;
2854 if v > 12 {
2855 return Err(MbError::Unsupported("invalid B sub_mb_type"));
2856 }
2857 *s = v;
2858 }
2859 let mut pred_y = [0u8; 256];
2860 let mut c_pred = [[0u8; 64]; 2];
2861 let mut refi = [[-1i32; 2]; 4];
2864 for (p, &st) in sub.iter().enumerate() {
2865 if st != 0 && b_sub_uses(st, 0) {
2866 refi[p][0] = self.read_b_ref(r, 0)?;
2867 }
2868 }
2869 for (p, &st) in sub.iter().enumerate() {
2870 if st != 0 && b_sub_uses(st, 1) {
2871 refi[p][1] = self.read_b_ref(r, 1)?;
2872 }
2873 }
2874 let mut mvd0: Vec<(i32, i32)> = Vec::new();
2876 let mut mvd1: Vec<(i32, i32)> = Vec::new();
2877 for &st in &sub {
2878 if st != 0 && b_sub_uses(st, 0) {
2879 for _ in b_sub_parts(st) {
2880 mvd0.push((r.read_se()?, r.read_se()?));
2881 }
2882 }
2883 }
2884 for &st in &sub {
2885 if st != 0 && b_sub_uses(st, 1) {
2886 for _ in b_sub_parts(st) {
2887 mvd1.push((r.read_se()?, r.read_se()?));
2888 }
2889 }
2890 }
2891 let (mut i0, mut i1) = (0usize, 0usize);
2893 for (p, &st) in sub.iter().enumerate() {
2894 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
2895 if st == 0 {
2896 self.decode_b_direct(mb_x, mb_y, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
2897 continue;
2898 }
2899 for &(sx, sy, sw, sh) in b_sub_parts(st) {
2900 let (px, py) = (b8x + sx, b8y + sy);
2901 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2902 let pwb = (sw / 4) as isize;
2903 let mut mv = [(0i32, 0i32); 2];
2904 if b_sub_uses(st, 0) {
2905 let n = self.mv_neighbors_list(pbx, pby, pwb, 0);
2906 let pmv = predict_mv(n[0], n[1], n[2], refi[p][0]);
2907 let d = mvd0[i0];
2908 i0 += 1;
2909 mv[0] = (pmv.0 + d.0, pmv.1 + d.1);
2910 }
2911 if b_sub_uses(st, 1) {
2912 let n = self.mv_neighbors_list(pbx, pby, pwb, 1);
2913 let pmv = predict_mv(n[0], n[1], n[2], refi[p][1]);
2914 let d = mvd1[i1];
2915 i1 += 1;
2916 mv[1] = (pmv.0 + d.0, pmv.1 + d.1);
2917 }
2918 self.b_set_motion(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1]);
2919 self.b_mc(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1], &mut pred_y, &mut c_pred);
2920 }
2921 }
2922 let allow_8x8 = sub
2925 .iter()
2926 .all(|&st| if st == 0 { self.direct_8x8_inference } else { st <= 3 });
2927 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2928 }
2929
2930 fn decode_p8x8(
2934 &mut self,
2935 r: &mut BitReader,
2936 mb_x: usize,
2937 mb_y: usize,
2938 ref0: bool,
2939 ) -> Result<(), MbError> {
2940 if self.refs.is_empty() {
2941 return Err(MbError::Unsupported("inter without reference"));
2942 }
2943 let w4 = self.mb_w * 4;
2944 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2945 let num_refs = self.refs.len();
2946
2947 let mut sub_types = [0u32; 4];
2950 for st in sub_types.iter_mut() {
2951 let v = r.read_ue()?;
2952 if v > 3 {
2953 return Err(MbError::Unsupported("B-slice / invalid sub_mb_type"));
2954 }
2955 *st = v;
2956 }
2957 let mut ref_idxs = [0i32; 4];
2958 if self.num_ref_active > 1 && !ref0 {
2959 for ri in ref_idxs.iter_mut() {
2960 *ri = read_ref_idx(r, self.num_ref_active)?;
2961 if *ri as usize >= num_refs {
2962 return Err(MbError::Truncated); }
2964 }
2965 }
2966
2967 let mut pred_y = [0u8; 256];
2971 let mut c_pred = [[0u8; 64]; 2];
2972 for part in 0..4usize {
2973 let refi = ref_idxs[part];
2974 let (b8x, b8y) = ((part % 2) * 8, (part / 2) * 8);
2975 for &(srx, sry, srw, srh) in sub_mb_partitions(sub_types[part]) {
2976 let (px, py) = (b8x + srx, b8y + sry);
2977 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2978 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (srw / 4) as isize);
2979 let pmv = predict_mv(a, b, c, refi);
2980 let mvd_x = r.read_se()?;
2981 let mvd_y = r.read_se()?;
2982 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2983 for by in py / 4..py / 4 + srh / 4 {
2984 for bx in px / 4..px / 4 + srw / 4 {
2985 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2986 self.mv_y[idx] = mv;
2987 self.inter_y[idx] = true;
2988 self.ref_idx_y[idx] = refi;
2989 self.coded_y[idx] = true;
2990 }
2991 }
2992 let reference = &self.refs[refi as usize];
2993 let mut tmp = [0u8; 256];
2994 mc_luma_padded(&reference.py, reference.lstride(), crate::LPAD, self.cw, ch, mb_x * 16 + px, mb_y * 16 + py, srw, srh, mv.0, mv.1, &mut tmp);
2995 restride(&mut pred_y, 16, px, py, &tmp, srw, srh);
2996 let (crx, cry, crw, crh) = (px / 2, py / 2, srw / 2, srh / 2);
2997 for cc in 0..2 {
2998 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2999 let mut tc = [0u8; 64];
3000 mc_chroma_padded(rc, reference.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv.0, mv.1, &mut tc);
3001 restride(&mut c_pred[cc], 8, crx, cry, &tc, crw, crh);
3002 }
3003 self.weight_partition(
3004 &mut pred_y, &mut c_pred, 0, refi as usize, px, py, srw, srh,
3005 );
3006 }
3007 }
3008
3009 let allow_8x8 = sub_types.iter().all(|&t| t == 0);
3011 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
3012 }
3013
3014 fn decode_p_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3017 self.mb_kind[mb_y * self.mb_w + mb_x] = rusty_h264_common::deblock::MB_KIND_SKIP;
3029 if self.refs.is_empty() {
3033 return Err(MbError::Unsupported("P_Skip without reference"));
3034 }
3035 let mv = self.skip_mv(mb_x, mb_y);
3036 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
3037
3038 let mut pred = [0u8; 256];
3039 let rf0 = &self.refs[0];
3040 mc_luma_padded(&rf0.py, rf0.lstride(), crate::LPAD, self.cw, ch, mb_x * 16, mb_y * 16, 16, 16, mv.0, mv.1, &mut pred);
3041 if let Some(wt) = &self.weights {
3042 for p in pred.iter_mut() {
3043 *p = wt.apply_luma(*p, 0, 0);
3044 }
3045 }
3046 {
3047 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
3048 for dy in 0..16 {
3049 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
3050 self.rec_y[d..d + 16].copy_from_slice(&pred[dy * 16..dy * 16 + 16]);
3051 }
3052 }
3053 for c in 0..2 {
3054 let mut pc = [0u8; 64];
3055 let rf0 = &self.refs[0];
3056 let rc = if c == 0 { &rf0.pu } else { &rf0.pv };
3057 mc_chroma_padded(rc, rf0.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8, mb_y * 8, 8, 8, mv.0, mv.1, &mut pc);
3058 if let Some(wt) = &self.weights {
3059 for p in pc.iter_mut() {
3060 *p = wt.apply_chroma(*p, 0, 0, c);
3061 }
3062 }
3063 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3064 for dy in 0..8 {
3065 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
3066 plane[d..d + 8].copy_from_slice(&pc[dy * 8..dy * 8 + 8]);
3067 }
3068 }
3069 {
3070 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
3071 self.set_mb_mv(mb_x, mb_y, mv, true, 0);
3072 let w4 = self.mb_w * 4;
3074 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3075 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
3076 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3077 }
3078 }
3079 Ok(())
3080 }
3081
3082 fn predict_i4_mode(&self, bx: usize, by: usize) -> u8 {
3086 if bx == 0 || by == 0 {
3087 return 2;
3088 }
3089 if !self.nbr_in_slice((bx - 1) / 4, by / 4)
3093 || !self.nbr_in_slice(bx / 4, (by - 1) / 4)
3094 || !self.intra_nbr_ok(bx - 1, by)
3095 || !self.intra_nbr_ok(bx, by - 1)
3096 {
3097 return 2;
3098 }
3099 let w4 = self.mb_w * 4;
3100 self.modes_y[by * w4 + (bx - 1)].min(self.modes_y[(by - 1) * w4 + bx])
3101 }
3102
3103 fn gather_i4(
3105 &self,
3106 px: usize,
3107 py: usize,
3108 avail_top: bool,
3109 avail_left: bool,
3110 bx: usize,
3111 by: usize,
3112 ) -> ([u8; 8], [u8; 4], u8) {
3113 let (cw, w4) = (self.cw, self.mb_w * 4);
3114 let mut top = [0u8; 8];
3115 let mut left = [0u8; 4];
3116 let mut corner = 0;
3117 if avail_top {
3118 for i in 0..4 {
3119 top[i] = self.rec_y[(py - 1) * cw + px + i];
3120 }
3121 let tr_avail = bx + 1 < w4
3122 && self.coded_y[(by - 1) * w4 + (bx + 1)]
3123 && self.nbr_in_slice((bx + 1) / 4, (by - 1) / 4)
3124 && self.intra_nbr_ok(bx + 1, by - 1);
3125 for i in 0..4 {
3126 top[4 + i] = if tr_avail {
3127 self.rec_y[(py - 1) * cw + px + 4 + i]
3128 } else {
3129 top[3]
3130 };
3131 }
3132 }
3133 if avail_left {
3134 for i in 0..4 {
3135 left[i] = self.rec_y[(py + i) * cw + px - 1];
3136 }
3137 }
3138 if avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1) {
3141 corner = self.rec_y[(py - 1) * cw + px - 1];
3142 }
3143 (top, left, corner)
3144 }
3145
3146 fn decode_ipcm(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3149 r.align_to_byte()?;
3150 let (lx, ly) = (mb_x * 16, mb_y * 16);
3151 for dy in 0..16 {
3152 for dx in 0..16 {
3153 self.rec_y[(ly + dy) * self.cw + (lx + dx)] = r.read_bits(8)? as u8;
3154 }
3155 }
3156 let (cx, cy) = (mb_x * 8, mb_y * 8);
3157 for plane in [&mut self.rec_u, &mut self.rec_v] {
3158 for dy in 0..8 {
3159 for dx in 0..8 {
3160 plane[(cy + dy) * self.ccw + (cx + dx)] = r.read_bits(8)? as u8;
3161 }
3162 }
3163 }
3164 let (w4, w2) = (self.mb_w * 4, self.mb_w * 2);
3167 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3168 let idx = (mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx);
3169 self.nnz_y[idx] = 16;
3170 self.modes_y[idx] = 2;
3171 self.inter_y[idx] = false;
3172 self.ref_idx_y[idx] = -1;
3173 self.mv_y[idx] = (0, 0);
3174 }
3175 for c in 0..2 {
3176 for by in 0..2 {
3177 for bx in 0..2 {
3178 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = 16;
3179 }
3180 }
3181 }
3182 Ok(())
3183 }
3184
3185 fn decode_i4x4(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3186 let w4 = self.mb_w * 4;
3187
3188 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3191 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
3192 let predicted = self.predict_i4_mode(bx, by);
3193 let actual = if r.read_bit()? {
3194 predicted
3195 } else {
3196 let rem = r.read_bits(3)? as u8;
3197 if rem < predicted {
3198 rem
3199 } else {
3200 rem + 1
3201 }
3202 };
3203 self.modes_y[by * w4 + bx] = actual;
3204 modes[lby * 4 + lbx] = actual;
3205 }
3206
3207 let chroma_mode = r.read_ue()? as u8;
3208 let cbp = read_cbp_intra(r)?;
3209 let cbp_luma = cbp & 15;
3210 let cbp_chroma = cbp >> 4;
3211 if cbp != 0 {
3212 self.step_qp(r.read_se()?);
3213 }
3214 let qp = self.cur_qp;
3215
3216 let top_mb_avail = mb_y > 0
3220 && self.nbr_in_slice(mb_x, mb_y - 1)
3221 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3222 let left_mb_avail = mb_x > 0
3223 && self.nbr_in_slice(mb_x - 1, mb_y)
3224 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3225 self.nnz_cache_load(mb_x, mb_y);
3226 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
3227 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
3228 let (px, py) = (bx * 4, by * 4);
3229 let avail_top = lby > 0 || top_mb_avail;
3230 let avail_left = lbx > 0 || left_mb_avail;
3231 let mut qb = [0i32; 16];
3232 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
3233 let nc = self.nc_pred(lbx, lby);
3234 let scan16 = decode_residual_block(r, 16, nc)?;
3235 qb = un_scan_4x4_dcac(&scan16);
3236 scan16.iter().filter(|&&v| v != 0).count() as u8
3237 } else {
3238 0
3239 };
3240 self.nnz_cache_set(lbx, lby, total);
3241 self.nnz_y[by * w4 + bx] = total;
3242 let (top, left, corner) = self.gather_i4(px, py, avail_top, avail_left, bx, by);
3243 let pred = intra4x4_pred(modes[lby * 4 + lbx], avail_top, avail_left, &top, &left, corner);
3244 let mut predb = [0i32; 16];
3245 for i in 0..16 {
3246 predb[i] = pred[i] as i32;
3247 }
3248 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
3249 store(&mut self.rec_y, self.cw, px, py, &s);
3250 self.coded_y[by * w4 + bx] = true;
3251 }
3252
3253 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3254 }
3255
3256 fn decode_i8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3260 let w4 = self.mb_w * 4;
3261 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
3262
3263 let mut modes8 = [2u8; 4];
3266 for (b8, mode) in modes8.iter_mut().enumerate() {
3267 let (b8x, b8y) = (b8 % 2, b8 / 2);
3268 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
3269 let predicted = self.predict_i4_mode(bx, by);
3270 let actual = if r.read_bit()? {
3271 predicted
3272 } else {
3273 let rem = r.read_bits(3)? as u8;
3274 if rem < predicted { rem } else { rem + 1 }
3275 };
3276 *mode = actual;
3277 for sy in 0..2 {
3278 for sx in 0..2 {
3279 self.modes_y[(by + sy) * w4 + (bx + sx)] = actual;
3280 }
3281 }
3282 }
3283
3284 let chroma_mode = r.read_ue()? as u8;
3285 let cbp = read_cbp_intra(r)?;
3286 let cbp_luma = cbp & 15;
3287 let cbp_chroma = cbp >> 4;
3288 if cbp != 0 {
3289 self.step_qp(r.read_se()?);
3290 }
3291 let qp = self.cur_qp;
3292
3293 let top_mb_avail = mb_y > 0
3294 && self.nbr_in_slice(mb_x, mb_y - 1)
3295 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3296 let left_mb_avail = mb_x > 0
3297 && self.nbr_in_slice(mb_x - 1, mb_y)
3298 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3299 self.nnz_cache_load(mb_x, mb_y);
3300
3301 for b8 in 0..4 {
3302 let (b8x, b8y) = (b8 % 2, b8 / 2);
3303 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
3304 let (px, py) = (bx * 4, by * 4);
3305
3306 let mut res8 = [0i32; 64];
3309 if cbp_luma & (1 << b8) != 0 {
3310 let mut scan8 = [0i32; 64];
3311 for sub in 0..4 {
3312 let (sx, sy) = (sub % 2, sub / 2);
3313 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
3314 let nc = self.nc_pred(cx, cy);
3315 let blk = decode_residual_block(r, 16, nc)?;
3316 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
3317 self.nnz_cache_set(cx, cy, total);
3318 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
3319 for k in 0..16 {
3320 scan8[4 * k + sub] = blk[k];
3321 }
3322 }
3323 let raster = un_scan_8x8(&scan8);
3324 res8 = self.inv_quant8(&raster, qp, 0);
3325 } else {
3326 for sub in 0..4 {
3327 let (sx, sy) = (sub % 2, sub / 2);
3328 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
3329 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
3330 }
3331 }
3332
3333 let avail_top = b8y > 0 || top_mb_avail;
3334 let avail_left = b8x > 0 || left_mb_avail;
3335 let (top, left, corner, avail_corner) =
3336 self.gather_i8(px, py, avail_top, avail_left, bx, by);
3337 let pred = intra8x8_pred(
3338 modes8[b8], avail_top, avail_left, avail_corner, &top, &left, corner,
3339 );
3340 let mut predb = [0i32; 64];
3341 for i in 0..64 {
3342 predb[i] = pred[i] as i32;
3343 }
3344 let recon = add_residual_8x8(&res8, &predb);
3345 for dy in 0..8 {
3346 for dx in 0..8 {
3347 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
3348 }
3349 }
3350 for sy in 0..2 {
3351 for sx in 0..2 {
3352 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
3353 }
3354 }
3355 }
3356
3357 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3358 }
3359
3360 fn inv_quant8(&self, raster: &[i32; 64], qp: u8, list: usize) -> [i32; 64] {
3363 match &self.scaling8 {
3364 Some(s) => inverse_quant_8x8(raster, qp, &s[list]),
3365 None => inverse_quant_8x8(raster, qp, &[16i32; 64]),
3366 }
3367 }
3368
3369 #[allow(clippy::too_many_arguments)]
3373 fn gather_i8(
3374 &self,
3375 px: usize,
3376 py: usize,
3377 avail_top: bool,
3378 avail_left: bool,
3379 bx: usize,
3380 by: usize,
3381 ) -> ([u8; 16], [u8; 8], u8, bool) {
3382 let (cw, w4) = (self.cw, self.mb_w * 4);
3383 let mut top = [0u8; 16];
3384 let mut left = [0u8; 8];
3385 let mut corner = 0;
3386 if avail_top {
3387 for i in 0..8 {
3388 top[i] = self.rec_y[(py - 1) * cw + px + i];
3389 }
3390 let tr_avail = bx + 2 < w4
3391 && self.coded_y[(by - 1) * w4 + (bx + 2)]
3392 && self.nbr_in_slice((bx + 2) / 4, (by - 1) / 4)
3393 && self.intra_nbr_ok(bx + 2, by - 1);
3394 for i in 0..8 {
3395 top[8 + i] = if tr_avail {
3396 self.rec_y[(py - 1) * cw + px + 8 + i]
3397 } else {
3398 top[7]
3399 };
3400 }
3401 }
3402 if avail_left {
3403 for i in 0..8 {
3404 left[i] = self.rec_y[(py + i) * cw + px - 1];
3405 }
3406 }
3407 let avail_corner = avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1);
3408 if avail_corner {
3409 corner = self.rec_y[(py - 1) * cw + px - 1];
3410 }
3411 (top, left, corner, avail_corner)
3412 }
3413
3414 fn decode_i16(
3415 &mut self,
3416 r: &mut BitReader,
3417 mb_x: usize,
3418 mb_y: usize,
3419 mt: u32,
3420 ) -> Result<(), MbError> {
3421 let pred_mode = I16Mode::from_id(mt % 4);
3422 let cbp_chroma = (mt % 12) / 4;
3423 let cbp_luma_15 = mt / 12 == 1;
3424 let chroma_mode = r.read_ue()? as u8;
3425 self.step_qp(r.read_se()?);
3426 let qp = self.cur_qp;
3427 let w4 = self.mb_w * 4;
3428
3429 self.nnz_cache_load(mb_x, mb_y);
3431 let nc_dc = self.nc_pred(0, 0);
3432 let dc_scan = decode_residual_block(r, 16, nc_dc)?;
3433 let dc_levels = un_scan_4x4_dcac(&dc_scan);
3434 let recon_dc = self.dequant_luma_dc(&dc_levels, qp, 0);
3435
3436 let mut q_blocks = [[0i32; 16]; 16];
3438 for &(bx, by) in &LUMA_4X4_SCAN_XY {
3439 let total = if cbp_luma_15 {
3440 let nc = self.nc_pred(bx, by);
3441 let ac = decode_residual_block(r, 15, nc)?;
3442 un_scan_4x4_ac_into(&ac, &mut q_blocks[by * 4 + bx]);
3443 ac.iter().filter(|&&v| v != 0).count() as u8
3444 } else {
3445 0
3446 };
3447 self.nnz_cache_set(bx, by, total);
3448 self.nnz_y[(mb_y * 4 + by) * w4 + (mb_x * 4 + bx)] = total;
3449 }
3450
3451 let avail_top = mb_y > 0
3453 && self.nbr_in_slice(mb_x, mb_y - 1)
3454 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3455 let avail_left = mb_x > 0
3456 && self.nbr_in_slice(mb_x - 1, mb_y)
3457 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3458 let (lx, ly) = (mb_x * 16, mb_y * 16);
3459 let mut top = [0u8; 16];
3460 let mut left = [0u8; 16];
3461 if avail_top {
3462 for i in 0..16 {
3463 top[i] = self.rec_y[(ly - 1) * self.cw + lx + i];
3464 }
3465 }
3466 if avail_left {
3467 for i in 0..16 {
3468 left[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
3469 }
3470 }
3471 let corner = if avail_top && avail_left {
3472 self.rec_y[(ly - 1) * self.cw + lx - 1]
3473 } else {
3474 0
3475 };
3476 let pred_l = luma16x16_pred(pred_mode, avail_top, avail_left, &top, &left, corner);
3477 for by in 0..4 {
3478 for bx in 0..4 {
3479 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
3480 deq[0] = recon_dc[by * 4 + bx];
3481 let mut predb = [0i32; 16];
3482 for dy in 0..4 {
3483 for dx in 0..4 {
3484 predb[dy * 4 + dx] = pred_l[(by * 4 + dy) * 16 + (bx * 4 + dx)] as i32;
3485 }
3486 }
3487 let s = reconstruct_4x4(&deq, &predb);
3488 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
3489 }
3490 }
3491 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3493 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3494 }
3495
3496 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3497 }
3498
3499 fn decode_chroma(
3501 &mut self,
3502 r: &mut BitReader,
3503 mb_x: usize,
3504 mb_y: usize,
3505 cbp_chroma: u32,
3506 chroma_mode: u8,
3507 ) -> Result<(), MbError> {
3508 let qpc = self.chroma_qp_for(self.cur_qp);
3509 let (cx, cy) = (mb_x * 8, mb_y * 8);
3510 let avail_top = mb_y > 0
3511 && self.nbr_in_slice(mb_x, mb_y - 1)
3512 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3513 let avail_left = mb_x > 0
3514 && self.nbr_in_slice(mb_x - 1, mb_y)
3515 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3516
3517 let mut c_recon_dc = [[0i32; 4]; 2];
3518 if cbp_chroma != 0 {
3519 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
3520 let dc = decode_residual_block(r, 4, -1)?;
3521 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 1 + c);
3522 }
3523 }
3524 let mut c_q_blocks = [[[0i32; 16]; 4]; 2];
3525 if cbp_chroma == 2 {
3526 self.chroma_cache_load(mb_x, mb_y);
3527 let w2 = self.mb_w * 2;
3528 for c in 0..2 {
3529 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3530 let nc = self.chroma_nc_pred(c, bx, by);
3531 let ac = decode_residual_block(r, 15, nc)?;
3532 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
3533 self.chroma_nnz_cache_set(c, bx, by, total);
3534 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
3535 un_scan_4x4_ac_into(&ac, &mut c_q_blocks[c][by * 2 + bx]);
3536 }
3537 }
3538 }
3539 for c in 0..2 {
3540 let mut ctop = [0u8; 8];
3541 let mut cleft = [0u8; 8];
3542 let mut ccorner = 0u8;
3543 {
3544 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
3545 if avail_top {
3546 for i in 0..8 {
3547 ctop[i] = rec_c[(cy - 1) * self.ccw + cx + i];
3548 }
3549 }
3550 if avail_left {
3551 for i in 0..8 {
3552 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
3553 }
3554 }
3555 if avail_top && avail_left {
3556 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
3557 }
3558 }
3559 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
3560 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3561 let mut predb = [0i32; 16];
3562 for dy in 0..4 {
3563 for dx in 0..4 {
3564 predb[dy * 4 + dx] = pred8[(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
3565 }
3566 }
3567 let mut deq = self.dequant(&c_q_blocks[c][by * 2 + bx], qpc, 1 + c);
3568 deq[0] = c_recon_dc[c][by * 2 + bx];
3569 let s = reconstruct_4x4(&deq, &predb);
3570 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3571 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
3572 }
3573 }
3574 Ok(())
3575 }
3576
3577 fn dump_mb_map(&self) {
3586 if std::env::var_os("RH264_DUMP_MB").is_none() {
3587 return;
3588 }
3589 let w4 = self.mb_w * 4;
3590 let mut hist = [0usize; 4];
3591 eprintln!("--- frame poc {} ---", self.cur_poc);
3592 for mb_y in 0..self.mb_h {
3593 let mut row = String::new();
3594 for mb_x in 0..self.mb_w {
3595 let b = (mb_y * 4) * w4 + mb_x * 4;
3596 let r = self.ref_idx_y[b];
3597 if r < 0 {
3598 row.push('i');
3599 } else {
3600 if (r as usize) < 4 {
3601 hist[r as usize] += 1;
3602 }
3603 row.push((b'0' + (r as u8).min(9)) as char);
3604 }
3605 }
3606 eprintln!("{row}");
3607 }
3608 eprintln!(
3609 "ref histogram: {hist:?} num_ref_active={} refs.len()={} OUT-OF-RANGE={}",
3610 self.num_ref_active,
3611 self.refs.len(),
3612 hist.iter().skip(self.refs.len()).sum::<usize>()
3613 );
3614 let list: Vec<String> = self
3615 .refs
3616 .iter()
3617 .enumerate()
3618 .map(|(i, f)| {
3619 let synth = if f.w4 == 0 { " SYNTH-GREY" } else { "" };
3622 format!("[{i}] poc={} fn={}{synth}", f.poc, f.frame_num)
3623 })
3624 .collect();
3625 eprintln!(" RefPicList0: {}", list.join(" "));
3626 }
3627
3628 pub fn deblock(&mut self, offset_a: i32, offset_b: i32) {
3629 self.dump_mb_map();
3630 let nnz_db_storage;
3637 let nnz_db: &[u8] = if self.mb_t8x8.iter().any(|&t| t) {
3638 let mut n = self.nnz_y.clone();
3639 let w4 = self.mb_w * 4;
3640 for mb_y in 0..self.mb_h {
3641 for mb_x in 0..self.mb_w {
3642 if !self.mb_t8x8[mb_y * self.mb_w + mb_x] {
3643 continue;
3644 }
3645 for b8 in 0..4 {
3646 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, mb_y * 4 + (b8 / 2) * 2);
3647 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + (bx + sx)] > 0));
3648 for sy in 0..2 {
3649 for sx in 0..2 {
3650 n[(by + sy) * w4 + (bx + sx)] = u8::from(any);
3651 }
3652 }
3653 }
3654 }
3655 }
3656 nnz_db_storage = n;
3657 &nnz_db_storage
3658 } else {
3659 &self.nnz_y
3660 };
3661 let ref_id: Vec<i32> = self
3664 .ref_idx_y
3665 .iter()
3666 .map(|&r| if r >= 0 { self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3667 .collect();
3668 let ref_id1: Vec<i32> = if self.refs1.is_empty() {
3671 Vec::new()
3672 } else {
3673 self.ref_idx1
3674 .iter()
3675 .map(|&r| if r >= 0 { self.refs1.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3676 .collect()
3677 };
3678 let info = rusty_h264_common::deblock::BlockInfo {
3679 inter: &self.inter_y,
3680 nnz: nnz_db,
3681 mv: &self.mv_y,
3682 ref_id: &ref_id,
3683 mv1: &self.mv1,
3684 ref_id1: &ref_id1,
3685 w4: self.mb_w * 4,
3686 t8x8: &self.mb_t8x8,
3687 bs: &[],
3688 kind: &self.mb_kind,
3689 };
3690 rusty_h264_common::deblock::filter_frame(
3691 &mut self.rec_y,
3692 &mut self.rec_u,
3693 &mut self.rec_v,
3694 self.mb_w,
3695 self.mb_h,
3696 &self.mb_qp,
3697 self.chroma_qp_offset,
3698 offset_a,
3699 offset_b,
3700 &info,
3701 );
3702 }
3703
3704 pub fn into_frame(self, crop_r: usize, crop_b: usize) -> YuvFrame {
3706 if crop_r == 0 && crop_b == 0 {
3709 return YuvFrame {
3710 width: self.cw,
3711 height: self.ch,
3712 y: self.rec_y,
3713 u: self.rec_u,
3714 v: self.rec_v,
3715 };
3716 }
3717 let dw = self.cw - 2 * crop_r;
3718 let dh = self.ch - 2 * crop_b;
3719 let mut y = vec![0u8; dw * dh];
3720 for row in 0..dh {
3721 y[row * dw..row * dw + dw].copy_from_slice(&self.rec_y[row * self.cw..row * self.cw + dw]);
3722 }
3723 let (cdw, cdh) = (dw / 2, dh / 2);
3724 let mut u = vec![0u8; cdw * cdh];
3725 let mut v = vec![0u8; cdw * cdh];
3726 for row in 0..cdh {
3727 u[row * cdw..row * cdw + cdw]
3728 .copy_from_slice(&self.rec_u[row * self.ccw..row * self.ccw + cdw]);
3729 v[row * cdw..row * cdw + cdw]
3730 .copy_from_slice(&self.rec_v[row * self.ccw..row * self.ccw + cdw]);
3731 }
3732 let _ = self.cch;
3733 YuvFrame {
3734 width: dw,
3735 height: dh,
3736 y,
3737 u,
3738 v,
3739 }
3740 }
3741}
3742
3743fn cabac_unary(cab: &mut crate::cabac::Cabac, ctx: usize, off: usize) -> u32 {
3750 if cab.decode_decision(ctx) == 0 {
3751 return 0;
3752 }
3753 let mut sym = 0;
3754 loop {
3755 let bin = cab.decode_decision(ctx + off);
3756 sym += 1;
3757 if bin == 0 || sym >= 512 {
3762 break;
3763 }
3764 }
3765 sym
3766}
3767
3768fn cabac_exp_bypass(cab: &mut crate::cabac::Cabac, mut count: i32) -> u32 {
3770 let mut sym = 0u32;
3771 loop {
3772 let c = cab.decode_bypass();
3773 if c == 1 {
3774 sym += 1 << count;
3775 count += 1;
3776 }
3777 if c == 0 || count == 16 {
3778 break;
3779 }
3780 }
3781 let mut sym2 = 0u32;
3782 while count > 0 {
3783 count -= 1;
3784 if cab.decode_bypass() != 0 {
3785 sym2 |= 1 << count;
3786 }
3787 }
3788 sym + sym2
3789}
3790
3791fn cabac_ueg_level(cab: &mut crate::cabac::Cabac, ctx: usize) -> u32 {
3794 if cab.decode_decision(ctx) == 0 {
3795 return 0;
3796 }
3797 let mut code = 0u32;
3798 let mut count = 1;
3799 let mut tmp;
3800 loop {
3801 tmp = cab.decode_decision(ctx);
3802 code += 1;
3803 count += 1;
3804 if tmp == 0 || count == 13 {
3805 break;
3806 }
3807 }
3808 if tmp != 0 {
3809 code += cabac_exp_bypass(cab, 0) + 1;
3810 }
3811 code
3812}
3813
3814fn parse_mb_qp_delta_cabac(cab: &mut crate::cabac::Cabac, last_delta_qp: &mut i32) -> i32 {
3816 const O: usize = 60;
3817 let ctx_inc = (*last_delta_qp != 0) as usize;
3818 let mut qp_delta = 0;
3819 if cab.decode_decision(O + ctx_inc) != 0 {
3820 let code = cabac_unary(cab, O + 2, 1) + 1;
3821 qp_delta = ((code + 1) >> 1) as i32;
3822 if code & 1 == 0 {
3823 qp_delta = -qp_delta;
3824 }
3825 }
3826 *last_delta_qp = qp_delta;
3827 qp_delta
3828}
3829
3830const NZC_CACHE: [usize; 24] = [
3833 9, 10, 17, 18, 11, 12, 19, 20, 25, 26, 33, 34, 27, 28, 35, 36, 14, 15, 22, 23, 38, 39, 46, 47, ];
3837
3838const RES_MAXPOS: [i32; 11] = [0, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14];
3840const RES_MAXC2: [i32; 11] = [0, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4];
3841const RES_CBF: [usize; 11] = [0, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16];
3842const RES_MAP: [usize; 11] = [0, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47];
3843const RES_ONE: [usize; 11] = [0, 0, 10, 20, 30, 39, 199, 30, 30, 39, 39];
3846const RP_I16_DC: usize = 1;
3848const RP_I16_AC: usize = 2;
3849const RP_LUMA_4X4: usize = 3;
3850const RP_CHROMA_DC: usize = 7; const RP_CHROMA_AC: usize = 9; const RP_LUMA_8X8: usize = 6;
3859
3860const SIG8X8: [u8; 64] = [
3864 0, 1, 2, 3, 4, 5, 5, 4, 4, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 4, 3, 3, 6, 7, 7, 7, 8, 9, 10, 9, 8, 7, 7, 6, 11, 12, 13, 11, 6, 7, 8, 9, 14, 10, 9, 8, 6, 11, 12, 13, 11, 6, 9, 14, 10, 9, 11, 12, 13, 11, 14, 10, 12, 14,
3868];
3869const LAST8X8: [u8; 64] = [
3872 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
3876];
3877
3878#[allow(clippy::too_many_arguments)]
3883fn parse_residual_cabac(
3884 cab: &mut crate::cabac::Cabac,
3885 nzc: &mut [u8; 48],
3886 cbf_dc: &mut u16,
3887 iz: usize,
3888 rp: usize,
3889 is_intra: bool,
3890 ndc: (Option<u16>, Option<u16>), out: &mut [i32], ) -> u32 {
3893 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Entropy);
3896 let is8 = rp == RP_LUMA_8X8;
3900 let is_dc = rp == RP_I16_DC || rp == RP_CHROMA_DC || rp == RP_CHROMA_DC + 1;
3901 let (mut na, mut nb) = (is_intra as u8, is_intra as u8);
3902 let scan = NZC_CACHE[iz.min(23)];
3903 if is_dc {
3904 if let Some(t) = ndc.0 {
3905 nb = ((t >> rp) & 1) as u8;
3906 }
3907 if let Some(l) = ndc.1 {
3908 na = ((l >> rp) & 1) as u8;
3909 }
3910 } else {
3911 if nzc[scan - 8] != 0xff {
3912 nb = (nzc[scan - 8] != 0) as u8;
3913 }
3914 if nzc[scan - 1] != 0xff {
3915 na = (nzc[scan - 1] != 0) as u8;
3916 }
3917 }
3918 if !is8 {
3919 let cbf = cab.decode_decision(85 + RES_CBF[rp] + (na + (nb << 1)) as usize);
3920 if cbf == 0 {
3921 if !is_dc {
3922 nzc[scan] = 0;
3923 }
3924 return 0;
3925 }
3926 if is_dc {
3927 *cbf_dc |= 1 << rp;
3928 }
3929 }
3930 let maxpos = RES_MAXPOS[rp] as usize;
3932 let (map, last) = if is8 { (402, 417) } else { (105 + RES_MAP[rp], 166 + RES_MAP[rp]) };
3934 let mut sig = [0i32; 64];
3935 let mut coeff_num = 0u32;
3936 let mut last_hit = false;
3937 for i in 0..maxpos {
3938 let (mi, li) = if is8 { (SIG8X8[i] as usize, LAST8X8[i] as usize) } else { (i, i) };
3940 if cab.decode_decision(map + mi) != 0 {
3941 sig[i] = 1;
3942 coeff_num += 1;
3943 if cab.decode_decision(last + li) != 0 {
3944 last_hit = true;
3945 break;
3946 }
3947 }
3948 }
3949 if !last_hit {
3950 sig[maxpos] = 1;
3951 coeff_num += 1;
3952 }
3953 let one = 227 + RES_ONE[rp];
3955 let abs = 232 + RES_ONE[rp];
3956 let maxc2 = RES_MAXC2[rp];
3957 let (mut c1, mut c2) = (1i32, 0i32);
3958 for i in (0..=maxpos).rev() {
3959 if sig[i] != 0 {
3960 let mut level = sig[i] + cab.decode_decision(one + c1 as usize) as i32;
3961 if level == 2 {
3962 level += cabac_ueg_level(cab, abs + c2 as usize) as i32;
3963 c2 = (c2 + 1).min(maxc2);
3964 c1 = 0;
3965 } else if c1 != 0 {
3966 c1 = (c1 + 1).min(4);
3967 }
3968 if cab.decode_bypass() != 0 {
3969 level = -level;
3970 }
3971 sig[i] = level;
3972 }
3973 }
3974 out[..=maxpos].copy_from_slice(&sig[..=maxpos]);
3975 if is8 {
3976 for k in 0..4 {
3980 nzc[NZC_CACHE[(iz + k).min(23)]] = coeff_num as u8;
3981 }
3982 } else if !is_dc {
3983 nzc[scan] = coeff_num as u8;
3984 }
3985 coeff_num
3986}
3987
3988const CACHE30: [usize; 16] = [7, 8, 13, 14, 9, 10, 15, 16, 19, 20, 25, 26, 21, 22, 27, 28];
3991
3992const G_SCAN4: [usize; 16] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15];
3995
3996fn parse_sub_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3998 const S: usize = 21;
3999 if cab.decode_decision(S) != 0 {
4000 return 0;
4001 }
4002 if cab.decode_decision(S + 1) != 0 {
4003 3 - cab.decode_decision(S + 2)
4004 } else {
4005 1
4006 }
4007}
4008
4009fn parse_intra_mb_type_cabac(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
4012 if cab.decode_decision(base) == 0 {
4013 return 0; }
4015 if cab.decode_terminate() {
4016 return 25; }
4018 let mut t = 1 + 12 * cab.decode_decision(base + 1) as u32; if cab.decode_decision(base + 2) != 0 {
4020 t += 4 + 4 * cab.decode_decision(base + 2) as u32;
4021 }
4022 t += 2 * cab.decode_decision(base + 3) as u32;
4023 t += cab.decode_decision(base + 3) as u32;
4024 t
4025}
4026
4027#[doc(hidden)]
4033pub fn parse_mb_type_b(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4034 parse_mb_type_b_cabac(cab, ctx_inc)
4035}
4036
4037fn parse_mb_type_b_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4038 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4039 const B: usize = 27;
4040 if cab.decode_decision(B + ctx_inc) == 0 {
4041 return 0; }
4043 if cab.decode_decision(B + 3) == 0 {
4044 return 1 + cab.decode_decision(B + 5) as u32; }
4046 let mut m = (cab.decode_decision(B + 4) as u32) << 3;
4047 m |= (cab.decode_decision(B + 5) as u32) << 2;
4048 m |= (cab.decode_decision(B + 5) as u32) << 1;
4049 m |= cab.decode_decision(B + 5) as u32;
4050 if m < 8 {
4051 return m + 3;
4052 }
4053 if m == 13 {
4054 return parse_intra_mb_type_cabac(cab, 32) + 23;
4055 }
4056 if m == 14 {
4057 return 11; }
4059 if m == 15 {
4060 return 22; }
4062 m = (m << 1) | cab.decode_decision(B + 5) as u32;
4063 m - 4
4064}
4065
4066fn parse_sub_mb_type_b_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4069 const B: usize = 36;
4070 if cab.decode_decision(B) == 0 {
4071 return 0; }
4073 if cab.decode_decision(B + 1) == 0 {
4074 return 1 + cab.decode_decision(B + 3) as u32; }
4076 let mut st = 3u32;
4077 if cab.decode_decision(B + 2) != 0 {
4078 if cab.decode_decision(B + 3) != 0 {
4079 return 11 + cab.decode_decision(B + 3) as u32; }
4081 st += 4;
4082 }
4083 st += 2 * cab.decode_decision(B + 3) as u32;
4084 st += cab.decode_decision(B + 3) as u32;
4085 st
4086}
4087
4088fn parse_mvd_partition(
4092 cab: &mut crate::cabac::Cabac,
4093 part_idx: usize,
4094 zblocks: &[usize],
4095 mvdc: &mut [[i16; 2]; 30],
4096 refc: &mut [i8; 30],
4097 mmvd: &mut [[i16; 2]; 16],
4098 mref: &mut [i8; 16],
4099 ref_idx: i8,
4100) -> (i32, i32) {
4101 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4102 let s = CACHE30[part_idx];
4103 let ctx = |comp: usize| -> usize {
4104 let mut a = 0i32;
4105 if refc[s - 6] >= 0 {
4106 a += mvdc[s - 6][comp].unsigned_abs() as i32;
4107 }
4108 if refc[s - 1] >= 0 {
4109 a += mvdc[s - 1][comp].unsigned_abs() as i32;
4110 }
4111 if a >= 3 {
4112 1 + (a > 32) as usize
4113 } else {
4114 0
4115 }
4116 };
4117 let (cx, cy) = (ctx(0), ctx(1));
4118 let mvx = parse_mvd_cabac(cab, 0, cx);
4119 let mvy = parse_mvd_cabac(cab, 1, cy);
4120 for &zb in zblocks {
4121 mvdc[CACHE30[zb]] = [mvx, mvy];
4122 refc[CACHE30[zb]] = ref_idx;
4123 mmvd[G_SCAN4[zb]] = [mvx, mvy];
4124 mref[G_SCAN4[zb]] = ref_idx;
4125 }
4126 (mvx as i32, mvy as i32)
4127}
4128
4129fn parse_ref_idx_cabac(cab: &mut crate::cabac::Cabac, ctx0: usize) -> i8 {
4132 const B: usize = 54;
4133 let mut r = 0i8;
4134 let mut bin_idx = 0u32;
4135 while bin_idx < 32 {
4139 let ctx = match bin_idx {
4140 0 => ctx0,
4141 1 => 4,
4142 _ => 5,
4143 };
4144 if cab.decode_decision(B + ctx) == 0 {
4145 break;
4146 }
4147 r += 1;
4148 bin_idx += 1;
4149 }
4150 r
4151}
4152
4153fn decode_ueg_mv(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
4156 const P2C: [usize; 8] = [0, 1, 2, 3, 3, 3, 3, 3];
4157 if cab.decode_decision(base) == 0 {
4158 return 0;
4159 }
4160 let mut code = 0u32;
4161 let mut count = 1usize;
4162 let mut tmp;
4163 loop {
4164 tmp = cab.decode_decision(base + P2C[count]);
4165 code += 1;
4166 count += 1;
4167 if tmp == 0 || count == 8 {
4168 break;
4169 }
4170 }
4171 if tmp != 0 {
4172 code += cabac_exp_bypass(cab, 3) + 1;
4173 }
4174 code
4175}
4176
4177fn parse_mvd_cabac(cab: &mut crate::cabac::Cabac, comp: usize, ctx_inc: usize) -> i16 {
4180 let base = 40 + comp * 7; if cab.decode_decision(base + ctx_inc) == 0 {
4182 return 0;
4183 }
4184 let mag = (decode_ueg_mv(cab, base + 3) + 1) as i16;
4185 if cab.decode_bypass() != 0 {
4186 -mag
4187 } else {
4188 mag
4189 }
4190}
4191
4192fn parse_mb_skip_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> bool {
4195 cab.decode_decision(ctx_inc) != 0
4196}
4197
4198fn parse_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4201 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4202 const S: usize = 11; if cab.decode_decision(S + 3) == 0 {
4204 return if cab.decode_decision(S + 4) != 0 {
4206 if cab.decode_decision(S + 6) != 0 { 1 } else { 2 }
4207 } else if cab.decode_decision(S + 5) != 0 {
4208 3
4209 } else {
4210 0
4211 };
4212 }
4213 if cab.decode_decision(S + 6) == 0 {
4215 return 5; }
4217 if cab.decode_terminate() {
4218 return 30; }
4220 let mut t = 6 + cab.decode_decision(S + 7) * 12;
4221 if cab.decode_decision(S + 8) != 0 {
4222 t += 4;
4223 if cab.decode_decision(S + 8) != 0 {
4224 t += 4;
4225 }
4226 }
4227 t += cab.decode_decision(S + 9) << 1;
4228 t += cab.decode_decision(S + 9);
4229 t
4230}
4231
4232fn parse_mb_type_i_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4237 const O: usize = 3; if cab.decode_decision(O + ctx_inc) == 0 {
4239 return 0; }
4241 if cab.decode_terminate() {
4242 return 25; }
4244 let mut t = 1 + cab.decode_decision(O + 3) * 12; if cab.decode_decision(O + 4) != 0 {
4246 t += 4; if cab.decode_decision(O + 5) != 0 {
4248 t += 4;
4249 }
4250 }
4251 t += cab.decode_decision(O + 6) << 1; t += cab.decode_decision(O + 7);
4253 t
4254}
4255
4256fn parse_intra4x4_pred_mode_cabac(cab: &mut crate::cabac::Cabac) -> i32 {
4260 const IPR: usize = 68;
4261 if cab.decode_decision(IPR) == 1 {
4262 return -1; }
4264 let mut m = cab.decode_decision(IPR + 1) as i32;
4265 m |= (cab.decode_decision(IPR + 1) as i32) << 1;
4266 m |= (cab.decode_decision(IPR + 1) as i32) << 2;
4267 m
4268}
4269
4270fn parse_intra_chroma_pred_mode_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4274 const CIPR: usize = 64;
4275 if cab.decode_decision(CIPR + ctx_inc) == 0 {
4276 return 0;
4277 }
4278 if cab.decode_decision(CIPR + 3) == 0 {
4279 return 1;
4280 }
4281 if cab.decode_decision(CIPR + 3) == 0 {
4282 return 2;
4283 }
4284 3
4285}
4286
4287fn parse_cbp_cabac(cab: &mut crate::cabac::Cabac, top: Option<u8>, left: Option<u8>) -> u32 {
4292 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4293 const CBP: usize = 73;
4294 let t = |m: u32| top.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
4295 let l = |m: u32| left.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
4296 let nb = |x: u32| (x == 0) as u32; let b0 = cab.decode_decision(CBP + (l(1 << 1) + (t(1 << 2) << 1)) as usize);
4299 let b1 = cab.decode_decision(CBP + (nb(b0) + (t(1 << 3) << 1)) as usize);
4300 let b2 = cab.decode_decision(CBP + (l(1 << 3) + (nb(b0) << 1)) as usize);
4301 let b3 = cab.decode_decision(CBP + (nb(b2) + (nb(b1) << 1)) as usize);
4302 let mut cbp = b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
4303 let ct = top.map_or(0u32, |c| ((c >> 4) != 0) as u32);
4305 let cl = left.map_or(0u32, |c| ((c >> 4) != 0) as u32);
4306 if cab.decode_decision(CBP + 4 + (cl + (ct << 1)) as usize) != 0 {
4307 let ct2 = top.map_or(0u32, |c| ((c >> 4) == 2) as u32);
4308 let cl2 = left.map_or(0u32, |c| ((c >> 4) == 2) as u32);
4309 let c1 = cab.decode_decision(CBP + 8 + (cl2 + (ct2 << 1)) as usize);
4310 cbp |= 1 << (4 + c1);
4311 }
4312 cbp
4313}
4314
4315fn read_ref_idx(r: &mut BitReader, num_ref_active: usize) -> Result<i32, OutOfData> {
4316 if num_ref_active == 2 {
4317 Ok(if r.read_bit()? { 0 } else { 1 }) } else {
4319 Ok(r.read_ue()? as i32)
4320 }
4321}
4322
4323#[derive(Clone, Copy, PartialEq)]
4325enum BPred {
4326 L0,
4327 L1,
4328 Bi,
4329}
4330impl BPred {
4331 fn uses(self, list: usize) -> bool {
4333 matches!(
4334 (self, list),
4335 (BPred::L0, 0) | (BPred::L1, 1) | (BPred::Bi, 0) | (BPred::Bi, 1)
4336 )
4337 }
4338}
4339
4340const B16X16: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 16)];
4341const B16X8: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 8), (0, 8, 16, 8)];
4342const B8X16: &[(usize, usize, usize, usize)] = &[(0, 0, 8, 16), (8, 0, 8, 16)];
4343
4344type Region = (usize, usize, usize, usize);
4346
4347pub fn b_inter_shape(mb_type: u32) -> (u8, u8, u8) {
4353 let (_, mvmode, preds) = b_inter_layout(mb_type);
4354 let code = |p: BPred| match (p.uses(0), p.uses(1)) {
4355 (true, true) => 3,
4356 (true, false) => 1,
4357 _ => 2,
4358 };
4359 (mvmode, code(preds[0]), code(preds[1]))
4360}
4361
4362fn b_inter_layout(mb_type: u32) -> (&'static [Region], u8, [BPred; 2]) {
4363 use BPred::*;
4364 match mb_type {
4365 1 => (B16X16, 0, [L0, L0]),
4366 2 => (B16X16, 0, [L1, L1]),
4367 3 => (B16X16, 0, [Bi, Bi]),
4368 4 => (B16X8, 1, [L0, L0]),
4369 5 => (B8X16, 2, [L0, L0]),
4370 6 => (B16X8, 1, [L1, L1]),
4371 7 => (B8X16, 2, [L1, L1]),
4372 8 => (B16X8, 1, [L0, L1]),
4373 9 => (B8X16, 2, [L0, L1]),
4374 10 => (B16X8, 1, [L1, L0]),
4375 11 => (B8X16, 2, [L1, L0]),
4376 12 => (B16X8, 1, [L0, Bi]),
4377 13 => (B8X16, 2, [L0, Bi]),
4378 14 => (B16X8, 1, [L1, Bi]),
4379 15 => (B8X16, 2, [L1, Bi]),
4380 16 => (B16X8, 1, [Bi, L0]),
4381 17 => (B8X16, 2, [Bi, L0]),
4382 18 => (B16X8, 1, [Bi, L1]),
4383 19 => (B8X16, 2, [Bi, L1]),
4384 20 => (B16X8, 1, [Bi, Bi]),
4385 _ => (B8X16, 2, [Bi, Bi]), }
4387}
4388
4389fn b_sub_uses(st: u32, list: usize) -> bool {
4391 let pred = match st {
4392 1 | 4 | 5 | 10 => 0, 2 | 6 | 7 | 11 => 1, _ => 2, };
4396 (list == 0 && pred != 1) || (list == 1 && pred != 0)
4397}
4398
4399fn b_sub_parts(st: u32) -> &'static [(usize, usize, usize, usize)] {
4401 match st {
4402 1..=3 => &[(0, 0, 8, 8)],
4403 4 | 6 | 8 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
4404 5 | 7 | 9 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
4405 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)], }
4407}
4408
4409fn sub_mb_partitions(sub_type: u32) -> &'static [(usize, usize, usize, usize)] {
4412 match sub_type {
4413 0 => &[(0, 0, 8, 8)],
4414 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
4415 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
4416 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
4417 }
4418}
4419
4420#[inline]
4430fn restride(dst: &mut [u8], dst_stride: usize, x0: usize, y0: usize, src: &[u8], w: usize, h: usize) {
4431 macro_rules! rows {
4432 ($n:expr) => {{
4433 for dy in 0..h {
4434 dst[(y0 + dy) * dst_stride + x0..][..$n].copy_from_slice(&src[dy * $n..][..$n]);
4435 }
4436 }};
4437 }
4438 match w {
4439 16 => rows!(16),
4440 8 => rows!(8),
4441 4 => rows!(4),
4442 2 => rows!(2),
4443 _ => {
4444 for dy in 0..h {
4445 dst[(y0 + dy) * dst_stride + x0..][..w].copy_from_slice(&src[dy * w..][..w]);
4446 }
4447 }
4448 }
4449}
4450
4451fn store(plane: &mut [u8], stride: usize, x0: usize, y0: usize, s: &[u8; 16]) {
4452 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Scatter);
4453 for dy in 0..4 {
4454 for dx in 0..4 {
4455 plane[(y0 + dy) * stride + (x0 + dx)] = s[dy * 4 + dx];
4456 }
4457 }
4458}
4459
4460fn un_scan_8x8(scan: &[i32; 64]) -> [i32; 64] {
4462 const ZZ8: [usize; 64] = [
4463 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27,
4464 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
4465 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
4466 ];
4467 let mut out = [0i32; 64];
4468 for k in 0..64 {
4469 out[ZZ8[k]] = scan[k];
4470 }
4471 out
4472}
4473
4474#[cfg(test)]
4475mod tests {
4476 use super::*;
4477
4478 fn fd(qp: u8, offset: i32) -> FrameDecoder {
4479 FrameDecoder::new(1, 1, qp, offset, Vec::new(), 1, false, false, true)
4480 }
4481
4482 #[test]
4483 fn mb_qp_delta_accumulates_mod_52() {
4484 let mut d = fd(26, 0);
4485 assert_eq!(d.cur_qp, 26, "QPy starts at the slice QP");
4486 d.step_qp(4);
4487 assert_eq!(d.cur_qp, 30); d.step_qp(-10);
4489 assert_eq!(d.cur_qp, 20); d.step_qp(40);
4492 assert_eq!(d.cur_qp, 8);
4493 d.step_qp(-20);
4495 assert_eq!(d.cur_qp, 40);
4496 }
4497
4498 #[test]
4499 fn chroma_qp_index_offset_applied_and_clamped() {
4500 assert_eq!(fd(0, 0).chroma_qp_for(30), 29);
4502 assert_eq!(fd(0, 2).chroma_qp_for(30), 31);
4504 assert_eq!(fd(0, -12).chroma_qp_for(5), chroma_qp(0));
4506 assert_eq!(fd(0, 99).chroma_qp_for(40), chroma_qp(51));
4507 }
4508}