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 weights: Option<WeightTable>,
118 cur_poc: i32,
120 weighted_bipred_idc: u8,
122 direct_8x8_inference: bool,
124}
125
126#[derive(Clone, Default)]
130pub struct WeightTable {
131 pub luma_log2_denom: i32,
132 pub chroma_log2_denom: i32,
133 pub luma: [Vec<(i32, i32)>; 2],
135 pub chroma: [Vec<[(i32, i32); 2]>; 2],
137}
138
139impl WeightTable {
140 fn apply_luma(&self, sample: u8, list: usize, refi: usize) -> u8 {
142 let (w, o) = self.luma[list][refi];
143 let lwd = self.luma_log2_denom;
144 let v = if lwd >= 1 {
145 ((sample as i32 * w + (1 << (lwd - 1))) >> lwd) + o
146 } else {
147 sample as i32 * w + o
148 };
149 v.clamp(0, 255) as u8
150 }
151
152 fn apply_chroma(&self, sample: u8, list: usize, refi: usize, cc: usize) -> u8 {
154 let (w, o) = self.chroma[list][refi][cc];
155 let cwd = self.chroma_log2_denom;
156 let v = if cwd >= 1 {
157 ((sample as i32 * w + (1 << (cwd - 1))) >> cwd) + o
158 } else {
159 sample as i32 * w + o
160 };
161 v.clamp(0, 255) as u8
162 }
163}
164
165#[derive(Debug, Clone, PartialEq, Eq)]
167pub enum MbError {
168 Truncated,
169 Unsupported(&'static str),
170}
171
172impl From<OutOfData> for MbError {
173 fn from(_: OutOfData) -> Self {
174 MbError::Truncated
175 }
176}
177
178impl FrameDecoder {
179 pub fn new(
180 mb_w: usize,
181 mb_h: usize,
182 qp: u8,
183 chroma_qp_offset: i32,
184 refs: Vec<crate::Ref>,
185 num_ref_active: usize,
186 constrained_intra: bool,
187 transform_8x8_mode: bool,
188 b_possible: bool,
189 ) -> Self {
190 let (cw, ch) = (mb_w * 16, mb_h * 16);
191 let (ccw, cch) = (cw / 2, ch / 2);
192 Self {
193 mb_w,
194 mb_h,
195 qp,
196 cur_qp: qp,
197 chroma_qp_offset,
198 cw,
199 ch,
200 ccw,
201 cch,
202 rec_y: vec![0; cw * ch],
203 rec_u: vec![0; ccw * cch],
204 rec_v: vec![0; ccw * cch],
205 mb_qp: vec![qp; mb_w * mb_h],
206 slice_first_mb: 0,
207 nnz_y: vec![0; (mb_w * 4) * (mb_h * 4)],
208 nnz_c: [vec![0; (mb_w * 2) * (mb_h * 2)], vec![0; (mb_w * 2) * (mb_h * 2)]],
209 modes_y: vec![2; (mb_w * 4) * (mb_h * 4)],
210 coded_y: vec![false; (mb_w * 4) * (mb_h * 4)],
211 mv_y: vec![(0, 0); (mb_w * 4) * (mb_h * 4)],
212 inter_y: vec![false; (mb_w * 4) * (mb_h * 4)],
213 ref_idx_y: vec![-1; (mb_w * 4) * (mb_h * 4)],
214 mv1: vec![(0, 0); (mb_w * 4) * (mb_h * 4)],
215 ref_idx1: vec![-1; (mb_w * 4) * (mb_h * 4)],
216 refs1: Vec::new(),
217 num_ref_active1: 0,
218 is_b: false,
219 b_possible,
220 direct_spatial: true,
221 nnz_l_cache: [0x80; 25],
222 nnz_c_cache: [[0x80; 9]; 2],
223 refs,
224 num_ref_active,
225 constrained_intra,
226 scaling: None,
227 scaling8: None,
228 transform_8x8_mode,
229 mb_t8x8: vec![false; mb_w * mb_h],
230 weights: None,
231 cur_poc: 0,
232 weighted_bipred_idc: 0,
233 direct_8x8_inference: false,
234 }
235 }
236
237 pub fn set_weights(&mut self, weights: WeightTable) {
239 self.weights = Some(weights);
240 }
241
242 fn weight_partition(
246 &self,
247 pred_y: &mut [u8; 256],
248 c_pred: &mut [[u8; 64]; 2],
249 list: usize,
250 refi: usize,
251 rx: usize,
252 ry: usize,
253 rw: usize,
254 rh: usize,
255 ) {
256 let Some(wt) = &self.weights else { return };
257 for dy in 0..rh {
258 for dx in 0..rw {
259 let i = (ry + dy) * 16 + (rx + dx);
260 pred_y[i] = wt.apply_luma(pred_y[i], list, refi);
261 }
262 }
263 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
264 for cc in 0..2 {
265 for dy in 0..crh {
266 for dx in 0..crw {
267 let i = (cry + dy) * 8 + (crx + dx);
268 c_pred[cc][i] = wt.apply_chroma(c_pred[cc][i], list, refi, cc);
269 }
270 }
271 }
272 }
273
274 pub fn set_scaling(&mut self, scaling: [[i32; 16]; 6], scaling8: [[i32; 64]; 2]) {
277 self.scaling = Some(scaling);
278 self.scaling8 = Some(scaling8);
279 }
280
281 fn dequant(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
283 match &self.scaling {
284 Some(s) => dequantize_weighted(levels, qp, &s[list]),
285 None => dequantize(levels, qp),
286 }
287 }
288
289 fn dequant_luma_dc(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
291 match &self.scaling {
292 Some(s) => inverse_quant_luma_dc_weighted(levels, qp, s[list][0]),
293 None => inverse_quant_luma_dc(levels, qp),
294 }
295 }
296
297 fn dequant_chroma_dc(&self, levels: &[i32; 4], qp: u8, list: usize) -> [i32; 4] {
299 match &self.scaling {
300 Some(s) => inverse_quant_chroma_dc_weighted(levels, qp, s[list][0]),
301 None => inverse_quant_chroma_dc(levels, qp),
302 }
303 }
304
305 #[allow(clippy::too_many_arguments)]
308 pub fn set_b_context(
309 &mut self,
310 refs1: Vec<crate::Ref>,
311 num_ref_active1: usize,
312 direct_spatial: bool,
313 cur_poc: i32,
314 weighted_bipred_idc: u8,
315 direct_8x8_inference: bool,
316 ) {
317 self.is_b = true;
318 self.refs1 = refs1;
319 self.num_ref_active1 = num_ref_active1;
320 self.direct_spatial = direct_spatial;
321 self.cur_poc = cur_poc;
322 self.weighted_bipred_idc = weighted_bipred_idc;
323 self.direct_8x8_inference = direct_8x8_inference;
324 }
325
326 fn step_qp(&mut self, delta: i32) {
329 self.cur_qp = (self.cur_qp as i32 + delta + 52).rem_euclid(52) as u8;
330 }
331
332 fn chroma_qp_for(&self, qp_y: u8) -> u8 {
335 let qpi = (qp_y as i32 + self.chroma_qp_offset).clamp(0, 51) as u8;
336 chroma_qp(qpi)
337 }
338
339 pub fn begin_slice(&mut self, slice_qp: u8, refs: Vec<crate::Ref>, num_ref_active: usize) {
343 self.cur_qp = slice_qp;
344 self.qp = slice_qp;
345 self.refs = refs;
346 self.num_ref_active = num_ref_active;
347 self.weights = None; }
349
350 #[inline]
354 fn nbr_in_slice(&self, nbx: usize, nby: usize) -> bool {
355 nby * self.mb_w + nbx >= self.slice_first_mb
356 }
357
358 #[inline]
362 fn intra_nbr_ok(&self, nbx: usize, nby: usize) -> bool {
363 !self.constrained_intra || !self.inter_y[nby * (self.mb_w * 4) + nbx]
364 }
365
366 fn mv_neighbors(&self, mb_x: usize, mb_y: usize) -> [MvNeighbor; 3] {
367 let w4 = self.mb_w * 4;
368 let get = |avail: bool, bx: isize, by: isize| {
369 if avail {
370 let idx = by as usize * w4 + bx as usize;
371 MvNeighbor {
372 available: true,
373 mv: self.mv_y[idx],
374 ref_idx: self.ref_idx_y[idx],
375 }
376 } else {
377 MvNeighbor::NONE
378 }
379 };
380 let (bx, by) = (mb_x as isize * 4, mb_y as isize * 4);
381 let a = get(mb_x > 0 && self.nbr_in_slice(mb_x - 1, mb_y), bx - 1, by);
382 let b = get(mb_y > 0 && self.nbr_in_slice(mb_x, mb_y - 1), bx, by - 1);
383 let c = if mb_y > 0 && mb_x + 1 < self.mb_w && self.nbr_in_slice(mb_x + 1, mb_y - 1) {
384 get(true, bx + 4, by - 1)
385 } else {
386 get(mb_x > 0 && mb_y > 0 && self.nbr_in_slice(mb_x - 1, mb_y - 1), bx - 1, by - 1)
387 };
388 [a, b, c]
389 }
390
391 fn mv_neighbors_block(&self, pbx: isize, pby: isize, pwb: isize) -> [MvNeighbor; 3] {
392 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Neighbors);
393 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
394 let get = |bx: isize, by: isize| -> MvNeighbor {
395 if bx < 0
397 || by < 0
398 || bx >= w4
399 || by >= h4
400 || !self.coded_y[(by * w4 + bx) as usize]
401 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
402 {
403 MvNeighbor::NONE
404 } else {
405 let idx = (by * w4 + bx) as usize;
406 MvNeighbor { available: true, mv: self.mv_y[idx], ref_idx: self.ref_idx_y[idx] }
407 }
408 };
409 let a = get(pbx - 1, pby);
410 let b = get(pbx, pby - 1);
411 let mut c = get(pbx + pwb, pby - 1);
412 if !c.available {
413 c = get(pbx - 1, pby - 1);
414 }
415 [a, b, c]
416 }
417
418 fn skip_mv(&self, mb_x: usize, mb_y: usize) -> (i32, i32) {
419 let [a, b, c] = self.mv_neighbors(mb_x, mb_y);
420 if !a.available
421 || !b.available
422 || (a.ref_idx == 0 && a.mv == (0, 0))
423 || (b.ref_idx == 0 && b.mv == (0, 0))
424 {
425 (0, 0)
426 } else {
427 predict_mv(a, b, c, 0)
428 }
429 }
430
431 fn set_mb_mv(&mut self, mb_x: usize, mb_y: usize, mv: (i32, i32), inter: bool, refi: i32) {
432 let w4 = self.mb_w * 4;
433 for dy in 0..4 {
434 for dx in 0..4 {
435 let idx = (mb_y * 4 + dy) * w4 + (mb_x * 4 + dx);
436 self.mv_y[idx] = mv;
437 self.inter_y[idx] = inter;
438 self.ref_idx_y[idx] = if inter { refi } else { -1 };
439 }
440 }
441 }
442
443 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) {
447 let w4 = self.mb_w * 4;
448 for by in ry / 4..ry / 4 + rh / 4 {
449 for bx in rx / 4..rx / 4 + rw / 4 {
450 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
451 self.mv_y[idx] = mv;
452 self.inter_y[idx] = true;
453 self.ref_idx_y[idx] = refi as i32;
454 self.coded_y[idx] = true;
455 }
456 }
457 }
458
459 pub fn as_reference(&self) -> crate::RefFrame {
461 if mv_dump_on() {
465 MV_DUMP.lock().unwrap().push(MvField {
466 mb_w: self.mb_w,
467 mb_h: self.mb_h,
468 mv: self.mv_y.clone(),
469 ref_idx: self.ref_idx_y.clone(),
470 inter: self.inter_y.clone(),
471 });
472 }
473
474 let (mv, ref_idx, mv1, ref_idx1, ref_poc, w4) = if self.b_possible {
480 (
481 self.mv_y.clone(),
482 self.ref_idx_y.clone(),
483 self.mv1.clone(),
484 self.ref_idx1.clone(),
485 self.ref_idx_y
488 .iter()
489 .map(|&r| {
490 if r >= 0 {
491 self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc)
492 } else {
493 i32::MIN
494 }
495 })
496 .collect(),
497 self.mb_w * 4,
498 )
499 } else {
500 (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), 0)
501 };
502 crate::RefFrame {
503 py: rusty_h264_common::inter::pad_plane(&self.rec_y, self.cw, self.ch, crate::LPAD),
506 pu: rusty_h264_common::inter::pad_plane(&self.rec_u, self.ccw, self.ch / 2, crate::CPAD),
507 pv: rusty_h264_common::inter::pad_plane(&self.rec_v, self.ccw, self.ch / 2, crate::CPAD),
508 cw: self.cw,
509 ch: self.ch,
510 frame_num: 0, poc: 0, mv,
513 ref_idx,
514 mv1,
515 ref_idx1,
516 ref_poc,
517 w4,
518 long_term: false,
519 long_term_idx: 0,
520 }
521 }
522
523 fn nnz_cache_load(&mut self, mb_x: usize, mb_y: usize) {
524 let w4 = self.mb_w * 4;
525 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
526 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
527 for lbx in 0..4 {
528 self.nnz_l_cache[1 + lbx] =
529 if top_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 - 1) * w4 + (mb_x * 4 + lbx)] };
530 }
531 for lby in 0..4 {
532 self.nnz_l_cache[(lby + 1) * 5] =
533 if left_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 - 1)] };
534 }
535 }
536 #[inline]
537 fn nc_pred(&self, lbx: usize, lby: usize) -> i32 {
538 let left = self.nnz_l_cache[(lby + 1) * 5 + lbx] as i32;
539 let top = self.nnz_l_cache[lby * 5 + (lbx + 1)] as i32;
540 let r = left + top;
541 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
542 }
543 #[inline]
544 fn nnz_cache_set(&mut self, lbx: usize, lby: usize, total: u8) {
545 self.nnz_l_cache[(lby + 1) * 5 + (lbx + 1)] = total;
546 }
547 fn chroma_cache_load(&mut self, mb_x: usize, mb_y: usize) {
548 let w2 = self.mb_w * 2;
549 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
550 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
551 for c in 0..2 {
552 for bx in 0..2 {
553 self.nnz_c_cache[c][1 + bx] =
554 if top_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 - 1) * w2 + (mb_x * 2 + bx)] };
555 }
556 for by in 0..2 {
557 self.nnz_c_cache[c][(by + 1) * 3] =
558 if left_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 - 1)] };
559 }
560 }
561 }
562 #[inline]
563 fn chroma_nc_pred(&self, c: usize, bx: usize, by: usize) -> i32 {
564 let left = self.nnz_c_cache[c][(by + 1) * 3 + bx] as i32;
565 let top = self.nnz_c_cache[c][by * 3 + (bx + 1)] as i32;
566 let r = left + top;
567 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
568 }
569 #[inline]
570 fn chroma_nnz_cache_set(&mut self, c: usize, bx: usize, by: usize, total: u8) {
571 self.nnz_c_cache[c][(by + 1) * 3 + (bx + 1)] = total;
572 }
573
574 #[allow(clippy::too_many_arguments)]
582 pub fn decode_slice_data_cabac(
583 &mut self,
584 rbsp: &[u8],
585 start_byte: usize,
586 slice_qp: u8,
587 cabac_init_idc: u32,
588 is_i: bool,
589 is_p: bool,
590 first_mb: usize,
591 ) -> Result<usize, MbError> {
592 let mut cab = crate::cabac::Cabac::new(rbsp, start_byte, slice_qp as i32, cabac_init_idc, is_i);
593 let (range, _offset) = cab.dbg_state();
594 let trace = std::env::var_os("RH_CABAC_TRACE").is_some();
595 debug_assert_eq!(range, 510, "CABAC init range must be 510");
596
597 const I16_CBP: [u32; 6] = [0, 16, 32, 15, 31, 47];
598 let mbw = self.mb_w;
599 let total = self.mb_w * self.mb_h;
600 let mut cat = vec![255u8; total]; let mut mb_cbp = vec![0u8; total];
603 let mut cmode = vec![-1i32; total]; let mut mb_nzc = vec![[0u8; 24]; total]; let mut cbf_dc = vec![0u16; total];
606 let mut mb_skip = vec![false; total];
607 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;
613 let mut addr = first_mb;
614
615 loop {
616 if addr >= total {
623 return Err(MbError::Truncated);
624 }
625 let (mbx, mby) = (addr % mbw, addr / mbw);
626 let left = (mbx > 0).then(|| addr - 1);
627 let top = (mby > 0).then(|| addr - mbw);
628
629 let mb_type;
632 if is_p {
633 let sctx = 11
634 + left.map_or(0, |a| (!mb_skip[a]) as usize)
635 + top.map_or(0, |a| (!mb_skip[a]) as usize);
636 if parse_mb_skip_cabac(&mut cab, sctx) {
637 mb_skip[addr] = true;
638 cat[addr] = 100; last_delta_qp = 0; self.decode_p_skip(mbx, mby)?;
644 self.mb_qp[addr] = self.cur_qp; let eos = cab.decode_terminate();
646 addr += 1;
647 if eos || addr >= total {
648 break;
649 }
650 continue;
651 }
652 let mbt = parse_mb_type_p_cabac(&mut cab);
653 if mbt == 30 {
654 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
655 }
656 if mbt <= 3 {
657 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbP);
658 let mut allow8 = true;
661 let mut mvdc = [[0i16; 2]; 30];
664 let mut refc = [-1i8; 30];
665 if let Some(l) = left {
666 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
667 refc[ci] = mb_ref[l][bi];
668 mvdc[ci] = mb_mvd[l][bi];
669 }
670 }
671 if let Some(t) = top {
672 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
673 refc[ci] = mb_ref[t][bi];
674 mvdc[ci] = mb_mvd[t][bi];
675 }
676 }
677 if mbx > 0 && mby > 0 {
678 let a = addr - mbw - 1;
679 (refc[0], mvdc[0]) = (mb_ref[a][15], mb_mvd[a][15]);
680 }
681 if mby > 0 && mbx + 1 < mbw {
682 let a = addr - mbw + 1;
683 (refc[5], mvdc[5]) = (mb_ref[a][12], mb_mvd[a][12]);
684 }
685 let mut mmvd = [[0i16; 2]; 16];
686 let mut mref = [0i8; 16];
687 macro_rules! refidx {
693 ($pi:expr, $zb:expr) => {{
694 if self.num_ref_active > 1 {
695 let s = CACHE30[$pi];
696 let c0 = (refc[s - 1] > 0) as usize + 2 * (refc[s - 6] > 0) as usize;
697 let r = parse_ref_idx_cabac(&mut cab, c0);
698 for &zb in $zb.iter() {
699 refc[CACHE30[zb]] = r;
700 }
701 r
702 } else {
703 0i8
704 }
705 }};
706 }
707 macro_rules! part {
708 ($pi:expr, $zb:expr, $pred:expr, $rx:expr, $ry:expr, $rw:expr, $rh:expr, $refi:expr) => {{
709 let (mvx, mvy) = parse_mvd_partition(&mut cab, $pi, $zb, &mut mvdc, &mut refc, &mut mmvd, &mut mref, $refi);
710 let [na, nb, nc] = self.mv_neighbors_block(
711 (mbx * 4 + $rx / 4) as isize,
712 (mby * 4 + $ry / 4) as isize,
713 ($rw / 4) as isize,
714 );
715 let pmv = $pred(na, nb, nc);
716 self.commit_inter_grid(mbx, mby, $rx, $ry, $rw, $rh, (pmv.0 + mvx, pmv.1 + mvy), $refi);
717 }};
718 }
719 match mbt {
720 0 => {
721 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
722 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);
723 }
724 1 => {
725 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7]);
726 let r1 = refidx!(8, &[8, 9, 10, 11, 12, 13, 14, 15]);
727 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);
728 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);
729 }
730 2 => {
731 let r0 = refidx!(0, &[0, 1, 2, 3, 8, 9, 10, 11]);
732 let r1 = refidx!(4, &[4, 5, 6, 7, 12, 13, 14, 15]);
733 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);
734 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);
735 }
736 _ => {
737 let mut subt = [0u32; 4];
739 for st in &mut subt {
740 *st = parse_sub_mb_type_p_cabac(&mut cab);
741 }
742 allow8 = subt.iter().all(|&t| t == 0);
743 let mut pr = [0i8; 4];
744 for (i, r) in pr.iter_mut().enumerate() {
745 let b = i * 4;
746 *r = refidx!(b, &[b, b + 1, b + 2, b + 3]);
747 }
748 for i in 0..4usize {
749 let b = i * 4;
750 let (ox, oy) = ((i % 2) * 8, (i / 2) * 8); let ri = pr[i];
752 match subt[i] {
753 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),
754 1 => {
755 part!(b, &[b, b + 1], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 8, 4, ri);
756 part!(b + 2, &[b + 2, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy + 4, 8, 4, ri);
757 }
758 2 => {
759 part!(b, &[b, b + 2], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 4, 8, ri);
760 part!(b + 1, &[b + 1, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox + 4, oy, 4, 8, ri);
761 }
762 _ => {
763 for j in 0..4usize {
764 let (sx, sy) = ((j % 2) * 4, (j / 2) * 4);
765 part!(b + j, &[b + j], |a, b, c| predict_mv(a, b, c, ri as i32), ox + sx, oy + sy, 4, 4, ri);
766 }
767 }
768 }
769 }
770 }
771 }
772 mb_ref[addr] = mref;
773 mb_mvd[addr] = mmvd;
774 cat[addr] = 100;
775
776 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
778 mb_cbp[addr] = cbp as u8;
779 let t8 = self.transform_8x8_mode && (cbp & 15) != 0 && allow8 && {
783 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
784 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
785 cab.decode_decision(399 + a + b) != 0
786 };
787 self.mb_t8x8[addr] = t8;
788 let mut luma8 = [[0i32; 64]; 4]; let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
790 let mut nzc = [0xffu8; 48];
791 if let Some(t) = top {
792 let tnz = mb_nzc[t];
793 nzc[1..5].copy_from_slice(&tnz[12..16]);
794 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
795 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
796 }
797 if let Some(l) = left {
798 let lnz = mb_nzc[l];
799 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
800 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
801 }
802 let mut cbfdc = 0u16;
803 let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
808 last_delta_qp = 0;
809 }
810 if cbp != 0 {
811 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
812 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
813 self.step_qp(qpd);
814 for id8 in 0..4usize {
815 if cbp_luma & (1 << id8) != 0 {
816 if t8 {
817 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, false, ndc, &mut luma8[id8]);
818 } else {
819 for id4 in 0..4usize {
820 let iz = id8 * 4 + id4;
821 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
822 }
823 }
824 } else {
825 for k in 0..4 {
826 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
827 }
828 }
829 }
830 if cbp_chroma >= 1 {
831 for i in 0..2usize {
832 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
833 }
834 }
835 if cbp_chroma == 2 {
836 for i in 0..2usize {
837 for id4 in 0..4usize {
838 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
839 }
840 }
841 }
842 }
843 self.mb_qp[addr] = self.cur_qp;
844 cbf_dc[addr] = cbfdc;
845 let mut mn = [0u8; 24];
846 for k in 0..4 {
847 mn[k] = nzc[9 + k];
848 mn[4 + k] = nzc[17 + k];
849 mn[8 + k] = nzc[25 + k];
850 mn[12 + k] = nzc[33 + k];
851 }
852 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
853 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
854 for v in mn.iter_mut() {
858 if *v == 0xff {
859 *v = 0;
860 }
861 }
862 mb_nzc[addr] = mn;
863
864 if self.refs.is_empty() {
869 return Err(MbError::Unsupported("inter without reference"));
870 }
871 let qp = self.cur_qp;
872 let qpc = self.chroma_qp_for(qp);
873 let (w4r, w2r) = (mbw * 4, mbw * 2);
874 let mut pred_y = [0u8; 256];
875 let mut c_pred = [[0u8; 64]; 2];
876 {
877 let (rh16, cch) = (self.mb_h * 16, self.mb_h * 8);
885 let mut gmv = [(0i32, 0i32); 16];
886 let mut gref = [0usize; 16];
887 for by in 0..4usize {
888 for bx in 0..4usize {
889 let bidx = (mby * 4 + by) * w4r + (mbx * 4 + bx);
890 gmv[by * 4 + bx] = self.mv_y[bidx];
891 gref[by * 4 + bx] =
894 (self.ref_idx_y[bidx].max(0) as usize).min(self.refs.len() - 1);
895 }
896 }
897 let rect_eq = |x4: usize, y4: usize, w4: usize, h4: usize| -> bool {
899 let t = y4 * 4 + x4;
900 (0..h4).all(|dy| {
901 (0..w4).all(|dx| {
902 let b = (y4 + dy) * 4 + (x4 + dx);
903 gmv[b] == gmv[t] && gref[b] == gref[t]
904 })
905 })
906 };
907 let refs = &self.refs;
908 let (cw, ccw) = (self.cw, self.ccw);
909 let mut mc_rect = |x4: usize,
910 y4: usize,
911 w4: usize,
912 h4: usize,
913 pred_y: &mut [u8; 256],
914 c_pred: &mut [[u8; 64]; 2]| {
915 let b = y4 * 4 + x4;
916 let (mv, reference) = (gmv[b], &refs[gref[b]]);
917 let (w, h) = (w4 * 4, h4 * 4);
918 let mut t = [0u8; 256];
919 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]);
920 for dy in 0..h {
921 pred_y[(y4 * 4 + dy) * 16 + x4 * 4..][..w]
922 .copy_from_slice(&t[dy * w..dy * w + w]);
923 }
924 let (cw4, ch4) = (w4 * 2, h4 * 2);
925 for cc in 0..2 {
926 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
927 let mut tc = [0u8; 64];
928 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]);
929 for dy in 0..ch4 {
930 c_pred[cc][(y4 * 2 + dy) * 8 + x4 * 2..][..cw4]
931 .copy_from_slice(&tc[dy * cw4..dy * cw4 + cw4]);
932 }
933 }
934 };
935 if rect_eq(0, 0, 4, 4) {
936 mc_rect(0, 0, 4, 4, &mut pred_y, &mut c_pred);
937 } else if rect_eq(0, 0, 4, 2) && rect_eq(0, 2, 4, 2) {
938 mc_rect(0, 0, 4, 2, &mut pred_y, &mut c_pred);
939 mc_rect(0, 2, 4, 2, &mut pred_y, &mut c_pred);
940 } else if rect_eq(0, 0, 2, 4) && rect_eq(2, 0, 2, 4) {
941 mc_rect(0, 0, 2, 4, &mut pred_y, &mut c_pred);
942 mc_rect(2, 0, 2, 4, &mut pred_y, &mut c_pred);
943 } else {
944 for q in 0..4usize {
945 let (qx, qy) = ((q % 2) * 2, (q / 2) * 2);
946 if rect_eq(qx, qy, 2, 2) {
947 mc_rect(qx, qy, 2, 2, &mut pred_y, &mut c_pred);
948 } else if rect_eq(qx, qy, 2, 1) && rect_eq(qx, qy + 1, 2, 1) {
949 mc_rect(qx, qy, 2, 1, &mut pred_y, &mut c_pred);
950 mc_rect(qx, qy + 1, 2, 1, &mut pred_y, &mut c_pred);
951 } else if rect_eq(qx, qy, 1, 2) && rect_eq(qx + 1, qy, 1, 2) {
952 mc_rect(qx, qy, 1, 2, &mut pred_y, &mut c_pred);
953 mc_rect(qx + 1, qy, 1, 2, &mut pred_y, &mut c_pred);
954 } else {
955 for j in 0..4usize {
956 mc_rect(qx + (j % 2), qy + (j / 2), 1, 1, &mut pred_y, &mut c_pred);
957 }
958 }
959 }
960 }
961 if self.weights.is_some() {
975 for by in 0..4usize {
976 for bx in 0..4usize {
977 let refi = gref[by * 4 + bx];
978 self.weight_partition(
979 &mut pred_y, &mut c_pred, 0, refi, bx * 4, by * 4, 4, 4,
980 );
981 }
982 }
983 }
984 }
985 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, if t8 { Some(&luma8) } else { None }, &cdc, &cac, cbp_chroma);
989
990 let eos = cab.decode_terminate();
991 addr += 1;
992 if eos || addr >= total {
993 break;
994 }
995 continue;
996 }
997 mb_type = mbt - 5; } else if self.is_b {
999 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbB);
1000 let mut allow8 = true;
1003 let sctx = 24
1005 + left.map_or(0, |a| (!mb_skip[a]) as usize)
1006 + top.map_or(0, |a| (!mb_skip[a]) as usize);
1007 if parse_mb_skip_cabac(&mut cab, sctx) {
1008 mb_skip[addr] = true;
1009 cat[addr] = 100;
1010 mb_direct[addr] = true;
1011 last_delta_qp = 0; self.decode_b_skip(mbx, mby)?;
1015 self.mb_qp[addr] = self.cur_qp;
1016 mb_ref[addr] = [0i8; 16];
1019 mb_ref1[addr] = [0i8; 16];
1020 let eos = cab.decode_terminate();
1021 addr += 1;
1022 if eos || addr >= total {
1023 break;
1024 }
1025 continue;
1026 }
1027 let bci = left.map_or(0, |a| (!mb_direct[a]) as usize)
1028 + top.map_or(0, |a| (!mb_direct[a]) as usize);
1029 let bmt = parse_mb_type_b_cabac(&mut cab, bci);
1030 if bmt < 23 {
1031 let mut mvdc0 = [[0i16; 2]; 30];
1034 let mut refc0 = [-1i8; 30];
1035 let mut mvdc1 = [[0i16; 2]; 30];
1036 let mut refc1 = [-1i8; 30];
1037 macro_rules! fill {
1039 ($mrf:expr, $mmv:expr, $rc:expr, $mc:expr) => {{
1040 if let Some(l) = left {
1041 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
1042 $rc[ci] = $mrf[l][bi];
1043 $mc[ci] = $mmv[l][bi];
1044 }
1045 }
1046 if let Some(t) = top {
1047 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
1048 $rc[ci] = $mrf[t][bi];
1049 $mc[ci] = $mmv[t][bi];
1050 }
1051 }
1052 if mbx > 0 && mby > 0 {
1053 let a = addr - mbw - 1;
1054 ($rc[0], $mc[0]) = ($mrf[a][15], $mmv[a][15]);
1055 }
1056 if mby > 0 && mbx + 1 < mbw {
1057 let a = addr - mbw + 1;
1058 ($rc[5], $mc[5]) = ($mrf[a][12], $mmv[a][12]);
1059 }
1060 }};
1061 }
1062 fill!(mb_ref, mb_mvd, refc0, mvdc0);
1063 fill!(mb_ref1, mb_mvd1, refc1, mvdc1);
1064 let mut mmvd0 = [[0i16; 2]; 16];
1065 let mut mref0 = [-1i8; 16];
1066 let mut mmvd1 = [[0i16; 2]; 16];
1067 let mut mref1 = [-1i8; 16];
1068 if self.refs.is_empty() || self.refs1.is_empty() {
1069 return Err(MbError::Unsupported("B without references"));
1070 }
1071 let mut pred_y = [0u8; 256];
1076 let mut c_pred = [[0u8; 64]; 2];
1077
1078 if bmt == 0 {
1079 mb_direct[addr] = true;
1082 allow8 = self.direct_8x8_inference;
1083 (mref0, mref1) = ([0i8; 16], [0i8; 16]);
1084 self.decode_b_direct(mbx, mby, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
1085 } else if bmt == 22 {
1086 let mut subt = [0u32; 4];
1089 for s in &mut subt {
1090 *s = parse_sub_mb_type_b_cabac(&mut cab);
1091 }
1092 allow8 = subt.iter().all(|&t| if t == 0 { self.direct_8x8_inference } else { (1..=3).contains(&t) });
1093 for i in 0..4usize {
1097 if subt[i] == 0 {
1098 let b = i * 4;
1099 for &zb in &[b, b + 1, b + 2, b + 3] {
1100 (mref0[G_SCAN4[zb]], mref1[G_SCAN4[zb]]) = (0, 0);
1101 (refc0[CACHE30[zb]], refc1[CACHE30[zb]]) = (0, 0);
1102 }
1103 }
1104 }
1105 let mut sref = [[0i8; 2]; 4]; for list in 0..2usize {
1110 let active = if list == 0 { self.num_ref_active } else { self.num_ref_active1 };
1111 if active <= 1 {
1112 continue;
1113 }
1114 let rc = if list == 0 { &mut refc0 } else { &mut refc1 };
1115 for i in 0..4usize {
1116 let st = subt[i];
1117 if st == 0 || !b_sub_uses(st, list) {
1118 continue;
1119 }
1120 let b = i * 4;
1121 let s = CACHE30[b];
1122 let c0 = (rc[s - 1] > 0) as usize + 2 * (rc[s - 6] > 0) as usize;
1123 let r = parse_ref_idx_cabac(&mut cab, c0);
1124 for &zb in &[b, b + 1, b + 2, b + 3] {
1125 rc[CACHE30[zb]] = r;
1126 }
1127 sref[i][list] = r;
1128 }
1129 }
1130 for list in 0..2usize {
1131 let (mmv, mrf, mc, rc) = if list == 0 {
1132 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1133 } else {
1134 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1135 };
1136 for i in 0..4usize {
1137 let st = subt[i];
1138 if st == 0 || !b_sub_uses(st, list) {
1139 continue;
1140 }
1141 let b = i * 4;
1142 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1143 let mut zb = [0usize; 4];
1144 let mut n = 0;
1145 for ly in sy / 4..sy / 4 + sh / 4 {
1146 for lx in sx / 4..sx / 4 + sw / 4 {
1147 zb[n] = b + ly * 2 + lx;
1148 n += 1;
1149 }
1150 }
1151 parse_mvd_partition(&mut cab, zb[0], &zb[..n], mc, rc, mmv, mrf, sref[i][list]);
1152 }
1153 }
1154 }
1155 for (p, &st) in subt.iter().enumerate() {
1158 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
1159 if st == 0 {
1160 self.decode_b_direct(mbx, mby, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
1161 continue;
1162 }
1163 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1164 let (px, py) = (b8x + sx, b8y + sy);
1165 let mut mv = [(0i32, 0i32); 2];
1166 for list in 0..2usize {
1167 if b_sub_uses(st, list) {
1168 let d = if list == 0 { mmvd0 } else { mmvd1 }[(py / 4) * 4 + px / 4];
1169 let n = self.mv_neighbors_list((mbx * 4 + px / 4) as isize, (mby * 4 + py / 4) as isize, (sw / 4) as isize, list);
1170 let pmv = predict_mv(n[0], n[1], n[2], sref[p][list] as i32);
1171 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1172 }
1173 }
1174 let refi0 = if b_sub_uses(st, 0) { sref[p][0] as i32 } else { -1 };
1175 let refi1 = if b_sub_uses(st, 1) { sref[p][1] as i32 } else { -1 };
1176 self.b_set_motion(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1]);
1177 self.b_mc(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1178 }
1179 }
1180 } else {
1181 let (layout, mvmode, preds) = b_inter_layout(bmt);
1182 let parts: &[(usize, &[usize])] = match mvmode {
1183 0 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])],
1184 1 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7]), (8, &[8, 9, 10, 11, 12, 13, 14, 15])],
1185 _ => &[(0, &[0, 1, 2, 3, 8, 9, 10, 11]), (4, &[4, 5, 6, 7, 12, 13, 14, 15])],
1186 };
1187 let mut pref = [[0i8; 2]; 2]; for list in 0..2usize {
1195 let active = if list == 0 { self.num_ref_active } else { self.num_ref_active1 };
1196 if active <= 1 {
1197 continue;
1198 }
1199 let rc = if list == 0 { &mut refc0 } else { &mut refc1 };
1200 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1201 if !preds[p].uses(list) {
1202 continue;
1203 }
1204 let s = CACHE30[pidx];
1205 let c0 = (rc[s - 1] > 0) as usize + 2 * (rc[s - 6] > 0) as usize;
1206 let r = parse_ref_idx_cabac(&mut cab, c0);
1207 for &zbi in zb.iter() {
1209 rc[CACHE30[zbi]] = r;
1210 }
1211 pref[p][list] = r;
1212 }
1213 }
1214 for list in 0..2usize {
1217 let (mmv, mrf, mc, rc) = if list == 0 {
1218 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1219 } else {
1220 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1221 };
1222 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1223 if preds[p].uses(list) {
1224 parse_mvd_partition(&mut cab, pidx, zb, mc, rc, mmv, mrf, pref[p][list]);
1225 }
1226 }
1227 }
1228 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1230 let mut mv = [(0i32, 0i32); 2];
1231 for list in 0..2usize {
1232 if preds[p].uses(list) {
1233 let d = if list == 0 { mmvd0 } else { mmvd1 }[(ry / 4) * 4 + rx / 4];
1234 let n = self.mv_neighbors_list((mbx * 4 + rx / 4) as isize, (mby * 4 + ry / 4) as isize, (rw / 4) as isize, list);
1235 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], pref[p][list] as i32);
1236 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1237 }
1238 }
1239 let refi0 = if preds[p].uses(0) { pref[p][0] as i32 } else { -1 };
1240 let refi1 = if preds[p].uses(1) { pref[p][1] as i32 } else { -1 };
1241 self.b_set_motion(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1]);
1242 self.b_mc(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1246 }
1247 }
1248 mb_ref[addr] = mref0;
1249 mb_mvd[addr] = mmvd0;
1250 mb_ref1[addr] = mref1;
1251 mb_mvd1[addr] = mmvd1;
1252 cat[addr] = 100;
1253
1254 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1256 mb_cbp[addr] = cbp as u8;
1257 let t8 = self.transform_8x8_mode && (cbp & 15) != 0 && allow8 && {
1261 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1262 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1263 cab.decode_decision(399 + a + b) != 0
1264 };
1265 self.mb_t8x8[addr] = t8;
1266 let mut luma8 = [[0i32; 64]; 4]; let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1268 let mut nzc = [0xffu8; 48];
1269 if let Some(t) = top {
1270 let tnz = mb_nzc[t];
1271 nzc[1..5].copy_from_slice(&tnz[12..16]);
1272 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1273 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
1274 }
1275 if let Some(l) = left {
1276 let lnz = mb_nzc[l];
1277 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
1278 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
1279 }
1280 let mut cbfdc = 0u16;
1281 let mut luma_scan = [[0i32; 16]; 16];
1282 let mut cdc = [[0i32; 4]; 2];
1283 let mut cac = [[[0i32; 16]; 4]; 2];
1284 if cbp == 0 {
1285 last_delta_qp = 0;
1286 }
1287 if cbp != 0 {
1288 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1289 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1290 self.step_qp(qpd);
1291 for id8 in 0..4usize {
1292 if cbp_luma & (1 << id8) != 0 {
1293 if t8 {
1294 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, false, ndc, &mut luma8[id8]);
1295 } else {
1296 for id4 in 0..4usize {
1297 let iz = id8 * 4 + id4;
1298 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
1299 }
1300 }
1301 } else {
1302 for k in 0..4 {
1303 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1304 }
1305 }
1306 }
1307 if cbp_chroma >= 1 {
1308 for i in 0..2usize {
1309 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
1310 }
1311 }
1312 if cbp_chroma == 2 {
1313 for i in 0..2usize {
1314 for id4 in 0..4usize {
1315 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
1316 }
1317 }
1318 }
1319 }
1320 self.mb_qp[addr] = self.cur_qp;
1321 cbf_dc[addr] = cbfdc;
1322 let mut mn = [0u8; 24];
1323 for k in 0..4 {
1324 mn[k] = nzc[9 + k];
1325 mn[4 + k] = nzc[17 + k];
1326 mn[8 + k] = nzc[25 + k];
1327 mn[12 + k] = nzc[33 + k];
1328 }
1329 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1330 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1331 for v in mn.iter_mut() {
1335 if *v == 0xff {
1336 *v = 0;
1337 }
1338 }
1339 mb_nzc[addr] = mn;
1340 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, if t8 { Some(&luma8) } else { None }, &cdc, &cac, cbp_chroma);
1341
1342 let eos = cab.decode_terminate();
1343 addr += 1;
1344 if eos || addr >= total {
1345 break;
1346 }
1347 continue;
1348 }
1349 mb_type = bmt - 23; if mb_type == 25 {
1351 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1352 }
1353 } else {
1354 let li = left.map_or(0, |a| (cat[a] >= 2) as usize);
1355 let ti = top.map_or(0, |a| (cat[a] >= 2) as usize);
1356 mb_type = parse_mb_type_i_cabac(&mut cab, li + ti);
1357 if mb_type == 25 {
1358 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1359 }
1360 }
1361 let _gi = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbI);
1367 let cci = left.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize)
1369 + top.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize);
1370
1371 if mb_type != 0 {
1372 let mt = mb_type - 1;
1377 let pred_mode = I16Mode::from_id(mt % 4);
1378 let cbp_chroma = (mt % 12) / 4;
1379 let cbp_luma_15 = mt / 12 == 1;
1380 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1381 cmode[addr] = chroma_mode as i32;
1382 cat[addr] = 2;
1383 mb_cbp[addr] = ((cbp_chroma as u8) << 4) | if cbp_luma_15 { 15 } else { 0 };
1384 let w4 = self.mb_w * 4;
1385
1386 let mut nzc = [0xffu8; 48];
1387 if let Some(t) = top {
1388 let tn = mb_nzc[t];
1389 nzc[1..5].copy_from_slice(&tn[12..16]);
1390 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1391 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1392 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1393 }
1394 if let Some(l) = left {
1395 let ln = mb_nzc[l];
1396 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1397 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1398 }
1399
1400 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1401 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1402 self.step_qp(qpd);
1403 let qp = self.cur_qp;
1404 let mut cbfdc = 0u16;
1405
1406 let mut dc_scan = [0i32; 16];
1408 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 0, RP_I16_DC, true, ndc, &mut dc_scan);
1409 let recon_dc = self.dequant_luma_dc(&un_scan_4x4_dcac(&dc_scan), qp, 0);
1410
1411 let mut q_blocks = [[0i32; 16]; 16];
1413 for (iz, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1414 let total = if cbp_luma_15 {
1415 let mut ac = [0i32; 16];
1416 let t = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_I16_AC, true, ndc, &mut ac);
1417 un_scan_4x4_ac_into(&ac, &mut q_blocks[lby * 4 + lbx]);
1418 t as u8
1419 } else {
1420 nzc[NZC_CACHE[iz]] = 0;
1421 0
1422 };
1423 self.nnz_y[(mby * 4 + lby) * w4 + (mbx * 4 + lbx)] = total;
1424 }
1425
1426 let mut cdc = [[0i32; 4]; 2];
1427 let mut cac = [[[0i32; 16]; 4]; 2];
1428 if cbp_chroma >= 1 {
1429 for i in 0..2usize {
1430 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1431 }
1432 }
1433 if cbp_chroma == 2 {
1434 for i in 0..2usize {
1435 for id4 in 0..4usize {
1436 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1437 }
1438 }
1439 }
1440
1441 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1443 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1444 let (lx, ly) = (mbx * 16, mby * 16);
1445 let mut t16 = [0u8; 16];
1446 let mut l16 = [0u8; 16];
1447 if top_ok {
1448 t16.copy_from_slice(&self.rec_y[(ly - 1) * self.cw + lx..][..16]);
1449 }
1450 if left_ok {
1451 for i in 0..16 {
1452 l16[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
1453 }
1454 }
1455 let corner = if top_ok && left_ok { self.rec_y[(ly - 1) * self.cw + lx - 1] } else { 0 };
1456 let pred_l = luma16x16_pred(pred_mode, top_ok, left_ok, &t16, &l16, corner);
1457 for by in 0..4 {
1458 for bx in 0..4 {
1459 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
1460 deq[0] = recon_dc[by * 4 + bx];
1461 let predb: [i32; 16] = std::array::from_fn(|i| pred_l[(by * 4 + i / 4) * 16 + (bx * 4 + i % 4)] as i32);
1462 let s = reconstruct_4x4(&deq, &predb);
1463 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
1464 self.modes_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = 2;
1468 self.coded_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = true;
1469 }
1470 }
1471 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1472
1473 self.mb_qp[addr] = self.cur_qp;
1474 cbf_dc[addr] = cbfdc;
1475 let mut mn = [0u8; 24];
1476 for k in 0..4 {
1477 mn[k] = nzc[9 + k];
1478 mn[4 + k] = nzc[17 + k];
1479 mn[8 + k] = nzc[25 + k];
1480 mn[12 + k] = nzc[33 + k];
1481 }
1482 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1483 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1484 for v in mn.iter_mut() {
1485 if *v == 0xff {
1486 *v = 0;
1487 }
1488 }
1489 mb_nzc[addr] = mn;
1490
1491 let eos = cab.decode_terminate();
1492 addr += 1;
1493 if eos || addr >= total {
1494 break;
1495 }
1496 continue;
1497 }
1498 cat[addr] = 0;
1499 let w4 = self.mb_w * 4;
1500 let t8 = self.transform_8x8_mode && {
1505 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1506 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1507 cab.decode_decision(399 + a + b) != 0
1508 };
1509 self.mb_t8x8[addr] = t8;
1510 let mut modes = [2u8; 16]; let mut modes8 = [2u8; 4]; if t8 {
1515 for b8 in 0..4usize {
1518 let (b8x, b8y) = (b8 % 2, b8 / 2);
1519 let (bx, by) = (mbx * 4 + b8x * 2, mby * 4 + b8y * 2);
1520 let predicted = self.predict_i4_mode(bx, by);
1521 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1522 let actual = if rr < 0 {
1523 predicted
1524 } else {
1525 let rem = rr as u8;
1526 if rem < predicted { rem } else { rem + 1 }
1527 };
1528 modes8[b8] = actual;
1529 for dy in 0..2 {
1530 for dx in 0..2 {
1531 self.modes_y[(by + dy) * w4 + (bx + dx)] = actual;
1532 modes[(b8y * 2 + dy) * 4 + (b8x * 2 + dx)] = actual;
1533 }
1534 }
1535 }
1536 } else {
1537 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1538 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1539 let predicted = self.predict_i4_mode(bx, by);
1540 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1541 let actual = if rr < 0 {
1542 predicted
1543 } else {
1544 let rem = rr as u8;
1545 if rem < predicted { rem } else { rem + 1 }
1546 };
1547 self.modes_y[by * w4 + bx] = actual;
1548 modes[lby * 4 + lbx] = actual;
1549 }
1550 }
1551 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1552 cmode[addr] = chroma_mode as i32;
1553 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1554 mb_cbp[addr] = cbp as u8;
1555 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1556
1557 let mut nzc = [0xffu8; 48];
1559 if let Some(t) = top {
1560 let tn = mb_nzc[t];
1561 nzc[1..5].copy_from_slice(&tn[12..16]);
1562 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1563 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1564 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1565 }
1566 if let Some(l) = left {
1567 let ln = mb_nzc[l];
1568 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1569 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1570 }
1571
1572 let mut cbfdc = 0u16;
1575 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 {
1580 last_delta_qp = 0;
1581 }
1582 if cbp != 0 {
1583 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1584 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1585 self.step_qp(qpd);
1586 for id8 in 0..4usize {
1587 if cbp_luma & (1 << id8) != 0 {
1588 if t8 {
1589 let n = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, true, ndc, &mut luma8[id8]);
1592 let (b8x, b8y) = (id8 % 2, id8 / 2);
1593 for sy in 0..2 {
1594 for sx in 0..2 {
1595 self.nnz_y[(mby * 4 + b8y * 2 + sy) * w4 + (mbx * 4 + b8x * 2 + sx)] = n as u8;
1596 }
1597 }
1598 } else {
1599 for id4 in 0..4usize {
1600 let iz = id8 * 4 + id4;
1601 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, true, ndc, &mut luma_scan[iz]);
1602 }
1603 }
1604 } else {
1605 for k in 0..4 {
1606 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1607 }
1608 if t8 {
1609 let (b8x, b8y) = (id8 % 2, id8 / 2);
1610 for sy in 0..2 {
1611 for sx in 0..2 {
1612 self.nnz_y[(mby * 4 + b8y * 2 + sy) * w4 + (mbx * 4 + b8x * 2 + sx)] = 0;
1613 }
1614 }
1615 }
1616 }
1617 }
1618 if cbp_chroma >= 1 {
1619 for i in 0..2usize {
1620 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1621 }
1622 }
1623 if cbp_chroma == 2 {
1624 for i in 0..2usize {
1625 for id4 in 0..4usize {
1626 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1627 }
1628 }
1629 }
1630 }
1631 self.mb_qp[addr] = self.cur_qp;
1632 cbf_dc[addr] = cbfdc;
1633 let mut mn = [0u8; 24];
1635 for k in 0..4 {
1636 mn[k] = nzc[9 + k];
1637 mn[4 + k] = nzc[17 + k];
1638 mn[8 + k] = nzc[25 + k];
1639 mn[12 + k] = nzc[33 + k];
1640 }
1641 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1642 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1643 for v in mn.iter_mut() {
1644 if *v == 0xff {
1645 *v = 0;
1646 }
1647 }
1648 mb_nzc[addr] = mn;
1649
1650 let qp = self.cur_qp;
1652 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1653 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1654 if t8 {
1655 for b8 in 0..4usize {
1659 let (b8x, b8y) = (b8 % 2, b8 / 2);
1660 let (bx, by) = (mbx * 4 + b8x * 2, mby * 4 + b8y * 2);
1661 let (px, py) = (bx * 4, by * 4);
1662 let res8 = if cbp_luma & (1 << b8) != 0 {
1663 let raster = un_scan_8x8(&luma8[b8]);
1664 self.inv_quant8(&raster, qp, 0)
1665 } else {
1666 [0i32; 64]
1667 };
1668 let avail_top = b8y > 0 || top_ok;
1669 let avail_left = b8x > 0 || left_ok;
1670 let (t, l, corner, avail_corner) =
1671 self.gather_i8(px, py, avail_top, avail_left, bx, by);
1672 let pred =
1673 intra8x8_pred(modes8[b8], avail_top, avail_left, avail_corner, &t, &l, corner);
1674 let mut predb = [0i32; 64];
1675 for i in 0..64 {
1676 predb[i] = pred[i] as i32;
1677 }
1678 let recon = add_residual_8x8(&res8, &predb);
1679 for dy in 0..8 {
1680 for dx in 0..8 {
1681 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
1682 }
1683 }
1684 for sy in 0..2 {
1685 for sx in 0..2 {
1686 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
1687 }
1688 }
1689 }
1690 }
1691 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1692 if t8 {
1693 break;
1694 }
1695 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1696 let (px, py) = (bx * 4, by * 4);
1697 let at = lby > 0 || top_ok;
1698 let al = lbx > 0 || left_ok;
1699 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1700 self.nnz_y[by * w4 + bx] = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1701 let (t, l, corner) = self.gather_i4(px, py, at, al, bx, by);
1702 let pred = intra4x4_pred(modes[lby * 4 + lbx], at, al, &t, &l, corner);
1703 let predb = std::array::from_fn(|i| pred[i] as i32);
1704 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
1705 store(&mut self.rec_y, self.cw, px, py, &s);
1706 self.coded_y[by * w4 + bx] = true;
1707 }
1708 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1709
1710 let eos = cab.decode_terminate();
1712 addr += 1;
1713 if eos || addr >= total {
1714 break;
1715 }
1716 }
1717 if trace {
1718 eprintln!("# CABAC decoded {} MBs (of {total})", addr - first_mb);
1719 }
1720 Ok(addr)
1721 }
1722
1723 #[allow(clippy::too_many_arguments)]
1727 #[allow(clippy::too_many_arguments)]
1733 fn add_inter_residual(
1734 &mut self,
1735 mb_x: usize,
1736 mb_y: usize,
1737 pred_y: &[u8; 256],
1738 c_pred: &[[u8; 64]; 2],
1739 luma_scan: &[[i32; 16]; 16],
1740 luma8: Option<&[[i32; 64]; 4]>,
1743 cdc: &[[i32; 4]; 2],
1744 cac: &[[[i32; 16]; 4]; 2],
1745 cbp_chroma: u32,
1746 ) {
1747 let qp = self.cur_qp;
1748 let qpc = self.chroma_qp_for(qp);
1749 let (w4r, w2r) = (self.mb_w * 4, self.mb_w * 2);
1750 if let Some(l8) = luma8 {
1751 for b8 in 0..4usize {
1753 let (b8x, b8y) = (b8 % 2, b8 / 2);
1754 let nnz = l8[b8].iter().filter(|&&v| v != 0).count() as u8;
1755 for sy in 0..2 {
1756 for sx in 0..2 {
1757 self.nnz_y[(mb_y * 4 + b8y * 2 + sy) * w4r + (mb_x * 4 + b8x * 2 + sx)] = nnz;
1758 }
1759 }
1760 let res8 = if nnz == 0 {
1761 [0i32; 64]
1762 } else {
1763 let raster = un_scan_8x8(&l8[b8]);
1764 self.inv_quant8(&raster, qp, 1)
1766 };
1767 for sy in 0..2 {
1770 for sx in 0..2 {
1771 self.coded_y[(mb_y * 4 + b8y * 2 + sy) * w4r + (mb_x * 4 + b8x * 2 + sx)] = true;
1772 }
1773 }
1774 let predb: [i32; 64] =
1775 std::array::from_fn(|i| pred_y[(b8y * 8 + i / 8) * 16 + (b8x * 8 + i % 8)] as i32);
1776 let recon = add_residual_8x8(&res8, &predb);
1777 let (px, py) = (mb_x * 16 + b8x * 8, mb_y * 16 + b8y * 8);
1778 for dy in 0..8 {
1779 for dx in 0..8 {
1780 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
1781 }
1782 }
1783 }
1784 }
1785 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1786 if luma8.is_some() {
1787 break;
1788 }
1789 let nnz = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1790 self.nnz_y[(mb_y * 4 + lby) * w4r + (mb_x * 4 + lbx)] = nnz;
1791 if nnz == 0 {
1792 let mut s = [0u8; 16];
1797 for r in 0..4 {
1798 s[r * 4..r * 4 + 4]
1799 .copy_from_slice(&pred_y[(lby * 4 + r) * 16 + lbx * 4..][..4]);
1800 }
1801 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1802 continue;
1803 }
1804 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1805 let deq = self.dequant(&qb, qp, 3);
1806 let predb: [i32; 16] = std::array::from_fn(|i| pred_y[(lby * 4 + i / 4) * 16 + (lbx * 4 + i % 4)] as i32);
1807 let s = reconstruct_4x4(&deq, &predb);
1808 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1809 }
1810 let mut c_dc = [[0i32; 4]; 2];
1811 if cbp_chroma != 0 {
1812 for c in 0..2 {
1813 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 4 + c);
1814 }
1815 }
1816 for c in 0..2 {
1817 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1818 let mut ac_nz = false;
1819 let mut ac = [0i32; 16];
1820 if cbp_chroma == 2 {
1821 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1822 let n = cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1823 self.nnz_c[c][(mb_y * 2 + by) * w2r + (mb_x * 2 + bx)] = n;
1824 ac_nz = n != 0;
1825 }
1826 let dc = c_dc[c][by * 2 + bx];
1827 if dc == 0 && !ac_nz {
1828 let mut s = [0u8; 16];
1830 for r in 0..4 {
1831 s[r * 4..r * 4 + 4]
1832 .copy_from_slice(&c_pred[c][(by * 4 + r) * 8 + bx * 4..][..4]);
1833 }
1834 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1835 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1836 continue;
1837 }
1838 let mut deq = self.dequant(&ac, qpc, 4 + c);
1839 deq[0] = dc;
1840 let predb: [i32; 16] =
1841 std::array::from_fn(|i| c_pred[c][(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1842 let s = reconstruct_4x4(&deq, &predb);
1843 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1844 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1845 }
1846 }
1847 }
1848
1849 fn recon_chroma_cabac(
1850 &mut self,
1851 mb_x: usize,
1852 mb_y: usize,
1853 chroma_mode: u8,
1854 cdc: &[[i32; 4]; 2],
1855 cac: &[[[i32; 16]; 4]; 2],
1856 cbp_chroma: u32,
1857 avail_top: bool,
1858 avail_left: bool,
1859 ) {
1860 let qpc = self.chroma_qp_for(self.cur_qp);
1861 let (cx, cy) = (mb_x * 8, mb_y * 8);
1862 let mut c_dc = [[0i32; 4]; 2];
1863 if cbp_chroma != 0 {
1864 for c in 0..2 {
1865 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 1 + c);
1866 }
1867 }
1868 let w2 = self.mb_w * 2;
1869 for c in 0..2 {
1870 let mut ctop = [0u8; 8];
1871 let mut cleft = [0u8; 8];
1872 let mut ccorner = 0u8;
1873 {
1874 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
1875 if avail_top {
1876 ctop.copy_from_slice(&rec_c[(cy - 1) * self.ccw + cx..][..8]);
1877 }
1878 if avail_left {
1879 for i in 0..8 {
1880 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
1881 }
1882 }
1883 if avail_top && avail_left {
1884 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
1885 }
1886 }
1887 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
1888 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1889 let mut ac = [0i32; 16];
1890 if cbp_chroma == 2 {
1891 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1892 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] =
1893 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1894 }
1895 let mut deq = self.dequant(&ac, qpc, 1 + c);
1896 deq[0] = c_dc[c][by * 2 + bx];
1897 let predb: [i32; 16] =
1898 std::array::from_fn(|i| pred8[(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1899 let s = reconstruct_4x4(&deq, &predb);
1900 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1901 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
1902 }
1903 }
1904 }
1905
1906 pub fn decode_slice_data(
1907 &mut self,
1908 r: &mut BitReader,
1909 is_p: bool,
1910 first_mb: usize,
1911 ) -> Result<usize, MbError> {
1912 let total = self.mb_w * self.mb_h;
1913 self.slice_first_mb = first_mb;
1914 let mut addr = first_mb;
1915 while addr < total {
1916 if is_p || self.is_b {
1917 let skip_run = {
1918 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1919 r.read_ue()?
1920 } as usize;
1921 for _ in 0..skip_run {
1922 if addr >= total {
1923 break;
1924 }
1925 if self.is_b {
1926 self.decode_b_skip(addr % self.mb_w, addr / self.mb_w)?;
1927 } else {
1928 self.decode_p_skip(addr % self.mb_w, addr / self.mb_w)?;
1929 }
1930 self.mb_qp[addr] = self.cur_qp; addr += 1;
1932 }
1933 if addr >= total {
1934 break;
1935 }
1936 if skip_run > 0 && !r.more_rbsp_data() {
1938 break;
1939 }
1940 }
1941 if self.is_b {
1942 self.decode_b_mb(r, addr % self.mb_w, addr / self.mb_w)?;
1943 } else {
1944 self.decode_mb(r, addr % self.mb_w, addr / self.mb_w, is_p)?;
1945 }
1946 self.mb_qp[addr] = self.cur_qp;
1947 addr += 1;
1948 if !r.more_rbsp_data() {
1950 break;
1951 }
1952 }
1953 Ok(addr)
1954 }
1955
1956 fn decode_mb(
1957 &mut self,
1958 r: &mut BitReader,
1959 mb_x: usize,
1960 mb_y: usize,
1961 is_p: bool,
1962 ) -> Result<(), MbError> {
1963 let mut mb_type = {
1964 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1965 r.read_ue()?
1966 };
1967 if is_p {
1968 if mb_type <= 2 {
1971 return self.decode_inter(r, mb_x, mb_y, mb_type as u8);
1972 }
1973 if mb_type == 3 || mb_type == 4 {
1974 return self.decode_p8x8(r, mb_x, mb_y, mb_type == 4);
1975 }
1976 mb_type -= 5;
1977 }
1978 self.decode_intra_mb(r, mb_x, mb_y, mb_type)
1979 }
1980
1981 fn decode_intra_mb(
1984 &mut self,
1985 r: &mut BitReader,
1986 mb_x: usize,
1987 mb_y: usize,
1988 mb_type: u32,
1989 ) -> Result<(), MbError> {
1990 let _gi = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbI);
1994 if mb_type == 0 {
1995 if self.transform_8x8_mode && r.read_bit()? {
1997 self.decode_i8x8(r, mb_x, mb_y)?;
1998 } else {
1999 self.decode_i4x4(r, mb_x, mb_y)?;
2000 }
2001 } else if (1..=24).contains(&mb_type) {
2002 self.decode_i16(r, mb_x, mb_y, mb_type - 1)?;
2003 } else if mb_type == 25 {
2004 self.decode_ipcm(r, mb_x, mb_y)?;
2005 } else {
2006 return Err(MbError::Unsupported("only I_4x4 / I_16x16 / I_PCM macroblocks"));
2007 }
2008 let w4 = self.mb_w * 4;
2010 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2011 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
2012 }
2013 Ok(())
2014 }
2015
2016 fn decode_inter(
2020 &mut self,
2021 r: &mut BitReader,
2022 mb_x: usize,
2023 mb_y: usize,
2024 mode: u8,
2025 ) -> Result<(), MbError> {
2026 if self.refs.is_empty() {
2027 return Err(MbError::Unsupported("inter without reference"));
2028 }
2029 let w4 = self.mb_w * 4;
2031 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2032 let num_refs = self.refs.len();
2033 let layout = inter_partitions(mode);
2034
2035 let nparts = layout.len();
2038 let mut ref_idxs = [0i32; 4];
2039 if self.num_ref_active > 1 {
2040 for ri in ref_idxs[..nparts].iter_mut() {
2041 *ri = read_ref_idx(r, self.num_ref_active)?;
2042 if *ri as usize >= num_refs {
2043 return Err(MbError::Truncated); }
2045 }
2046 }
2047
2048 let mut part_mv = [(0i32, (0i32, 0i32)); 4];
2051 {
2052 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::MvGrid);
2053 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2054 let refi = ref_idxs[part];
2055 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2056 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (rw / 4) as isize);
2057 let pmv = predict_partition_mv(mode, part, a, b, c, refi);
2058 let mvd_x = r.read_se()?;
2059 let mvd_y = r.read_se()?;
2060 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2061 part_mv[part] = (refi, mv);
2062 for by in ry / 4..ry / 4 + rh / 4 {
2063 for bx in rx / 4..rx / 4 + rw / 4 {
2064 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2065 self.mv_y[idx] = mv;
2066 self.inter_y[idx] = true;
2067 self.ref_idx_y[idx] = refi;
2068 self.coded_y[idx] = true;
2069 }
2070 }
2071 }
2072 }
2073
2074 let mut pred_y = [0u8; 256];
2076 let mut c_pred = [[0u8; 64]; 2];
2077 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2078 let (refi, mv) = part_mv[part];
2079 let reference = &self.refs[refi as usize];
2080 let mut tmp = [0u8; 256];
2081 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);
2082 {
2083 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
2084 restride(&mut pred_y, 16, rx, ry, &tmp, rw, rh);
2085 }
2086 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
2087 for cc in 0..2 {
2088 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2089 let mut tc = [0u8; 64];
2090 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);
2091 {
2092 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
2093 restride(&mut c_pred[cc], 8, crx, cry, &tc, crw, crh);
2094 }
2095 }
2096 self.weight_partition(&mut pred_y, &mut c_pred, 0, refi as usize, rx, ry, rw, rh);
2097 }
2098
2099 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2101 }
2102
2103 fn inter_finish(
2107 &mut self,
2108 r: &mut BitReader,
2109 mb_x: usize,
2110 mb_y: usize,
2111 pred_y: &[u8; 256],
2112 c_pred: &[[u8; 64]; 2],
2113 allow_8x8: bool,
2114 ) -> Result<(), MbError> {
2115 let w4 = self.mb_w * 4;
2116 let cbp = {
2117 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
2118 read_cbp_inter(r)?
2119 };
2120 let cbp_luma = cbp & 15;
2121 let cbp_chroma = cbp >> 4;
2122 let t8x8 = cbp_luma > 0 && self.transform_8x8_mode && allow_8x8 && r.read_bit()?;
2125 if t8x8 {
2126 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
2127 }
2128 if cbp != 0 {
2129 self.step_qp(r.read_se()?);
2130 }
2131 let (qp, qpc) = (self.cur_qp, self.chroma_qp_for(self.cur_qp));
2132
2133 self.nnz_cache_load(mb_x, mb_y);
2135 let mut q_blocks = [[0i32; 16]; 16];
2136 let mut luma8 = [[0i32; 64]; 4]; if t8x8 {
2138 for b8 in 0..4 {
2139 let (b8x, b8y) = (b8 % 2, b8 / 2);
2140 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2141 if cbp_luma & (1 << b8) != 0 {
2142 let mut scan8 = [0i32; 64];
2143 for sub in 0..4 {
2144 let (sx, sy) = (sub % 2, sub / 2);
2145 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
2146 let nc = self.nc_pred(cx, cy);
2147 let blk = decode_residual_block(r, 16, nc)?;
2148 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
2149 self.nnz_cache_set(cx, cy, total);
2150 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
2151 for k in 0..16 {
2152 scan8[4 * k + sub] = blk[k];
2153 }
2154 }
2155 luma8[b8] = self.inv_quant8(&un_scan_8x8(&scan8), qp, 1);
2156 } else {
2157 for sub in 0..4 {
2158 let (sx, sy) = (sub % 2, sub / 2);
2159 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
2160 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
2161 }
2162 }
2163 }
2164 } else {
2165 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2166 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2167 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
2168 let nc = self.nc_pred(lbx, lby);
2169 let scan16 = decode_residual_block(r, 16, nc)?;
2170 q_blocks[lby * 4 + lbx] = un_scan_4x4_dcac(&scan16);
2171 scan16.iter().filter(|&&v| v != 0).count() as u8
2172 } else {
2173 0
2174 };
2175 self.nnz_cache_set(lbx, lby, total);
2176 self.nnz_y[by * w4 + bx] = total;
2177 }
2178 }
2179
2180 let mut c_recon_dc = [[0i32; 4]; 2];
2182 if cbp_chroma != 0 {
2183 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
2184 let dc = decode_residual_block(r, 4, -1)?;
2185 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 4 + c);
2186 }
2187 }
2188 let mut c_q = [[[0i32; 16]; 4]; 2];
2189 if cbp_chroma == 2 {
2190 self.chroma_cache_load(mb_x, mb_y);
2191 let w2 = self.mb_w * 2;
2192 for c in 0..2 {
2193 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2194 let nc = self.chroma_nc_pred(c, bx, by);
2195 let ac = decode_residual_block(r, 15, nc)?;
2196 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
2197 self.chroma_nnz_cache_set(c, bx, by, total);
2198 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
2199 un_scan_4x4_ac_into(&ac, &mut c_q[c][by * 2 + bx]);
2200 }
2201 }
2202 }
2203
2204 if t8x8 {
2206 for b8 in 0..4 {
2207 let (b8x, b8y) = (b8 % 2, b8 / 2);
2208 let (px, py) = (b8x * 8, b8y * 8);
2209 for dy in 0..8 {
2210 for dx in 0..8 {
2211 let p = pred_y[(py + dy) * 16 + (px + dx)] as i32;
2212 let v = (p + luma8[b8][dy * 8 + dx]).clamp(0, 255) as u8;
2213 self.rec_y[(mb_y * 16 + py + dy) * self.cw + (mb_x * 16 + px + dx)] = v;
2214 }
2215 }
2216 }
2217 } else {
2218 for b8 in 0..4 {
2225 let (b8x, b8y) = (b8 % 2, b8 / 2);
2226 let pred_off = (b8y * 8) * 16 + b8x * 8;
2227 let rec_off = (mb_y * 16 + b8y * 8) * self.cw + (mb_x * 16 + b8x * 8);
2228 if cbp_luma & (1 << b8) == 0 {
2229 for r in 0..8 {
2230 let (s, d) = (pred_off + r * 16, rec_off + r * self.cw);
2231 self.rec_y[d..d + 8].copy_from_slice(&pred_y[s..s + 8]);
2232 }
2233 continue;
2234 }
2235 #[cfg(accel)]
2236 {
2237 let mut dct = [0i16; 64];
2238 for (i, (sx, sy)) in [(0, 0), (1, 0), (0, 1), (1, 1)].into_iter().enumerate() {
2239 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2240 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2241 for k in 0..16 {
2242 dct[i * 16 + k] = deq[k] as i16;
2243 }
2244 }
2245 rusty_h264_accel::idct_four_t4_rec(
2246 &mut self.rec_y[rec_off..],
2247 self.cw,
2248 &pred_y[pred_off..],
2249 16,
2250 &dct,
2251 );
2252 }
2253 #[cfg(not(accel))]
2254 for (sx, sy) in [(0, 0), (1, 0), (0, 1), (1, 1)] {
2255 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2256 let mut predb = [0i32; 16];
2257 for dy in 0..4 {
2258 for dx in 0..4 {
2259 predb[dy * 4 + dx] = pred_y[(lby * 4 + dy) * 16 + (lbx * 4 + dx)] as i32;
2260 }
2261 }
2262 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2263 let s = reconstruct_4x4(&deq, &predb);
2264 store(&mut self.rec_y, self.cw, mb_x * 16 + lbx * 4, mb_y * 16 + lby * 4, &s);
2265 }
2266 }
2267 }
2268 if cbp_chroma == 0 {
2271 for c in 0..2 {
2272 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2273 for dy in 0..8 {
2274 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2275 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2276 }
2277 }
2278 } else {
2279 for c in 0..2 {
2280 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2281 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2282 let mut predb = [0i32; 16];
2283 for dy in 0..4 {
2284 for dx in 0..4 {
2285 predb[dy * 4 + dx] = c_pred[c][(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
2286 }
2287 }
2288 let mut deq = match &self.scaling {
2289 Some(s) => dequantize_weighted(&c_q[c][by * 2 + bx], qpc, &s[4 + c]),
2290 None => dequantize(&c_q[c][by * 2 + bx], qpc),
2291 };
2292 deq[0] = c_recon_dc[c][by * 2 + bx];
2293 let s = reconstruct_4x4(&deq, &predb);
2294 store(plane, self.ccw, mb_x * 8 + bx * 4, mb_y * 8 + by * 4, &s);
2295 }
2296 }
2297 }
2298
2299 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2301 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2302 }
2303 Ok(())
2304 }
2305
2306 fn mv_neighbors_list(&self, pbx: isize, pby: isize, pwb: isize, list: usize) -> [MvNeighbor; 3] {
2314 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
2315 let (mvg, refg) = if list == 0 {
2316 (&self.mv_y, &self.ref_idx_y)
2317 } else {
2318 (&self.mv1, &self.ref_idx1)
2319 };
2320 let get = |bx: isize, by: isize| -> MvNeighbor {
2321 if bx < 0
2322 || by < 0
2323 || bx >= w4
2324 || by >= h4
2325 || !self.coded_y[(by * w4 + bx) as usize]
2326 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
2327 {
2328 MvNeighbor::NONE
2329 } else {
2330 let idx = (by * w4 + bx) as usize;
2331 MvNeighbor { available: true, mv: mvg[idx], ref_idx: refg[idx] }
2332 }
2333 };
2334 let a = get(pbx - 1, pby);
2335 let b = get(pbx, pby - 1);
2336 let mut c = get(pbx + pwb, pby - 1);
2337 if !c.available {
2338 c = get(pbx - 1, pby - 1);
2339 }
2340 [a, b, c]
2341 }
2342
2343 #[inline]
2357 fn col_block(&self, bx4: usize, by4: usize) -> (usize, usize) {
2358 if self.direct_8x8_inference {
2359 ((bx4 / 2) * 3, (by4 / 2) * 3)
2360 } else {
2361 (bx4, by4)
2362 }
2363 }
2364
2365 fn col_zero(&self, bx: usize, by: usize) -> bool {
2366 let Some(col) = self.refs1.first() else { return false };
2367 if col.long_term || col.w4 == 0 {
2368 return false;
2369 }
2370 let idx = by * col.w4 + bx;
2371 if idx >= col.ref_idx.len() {
2372 return false;
2373 }
2374 let (cref, cmv) = if col.ref_idx[idx] >= 0 {
2382 (col.ref_idx[idx], col.mv[idx])
2383 } else if idx < col.ref_idx1.len() && col.ref_idx1[idx] >= 0 {
2384 (col.ref_idx1[idx], col.mv1[idx])
2385 } else {
2386 return false;
2387 };
2388 cref == 0 && cmv.0.abs() <= 1 && cmv.1.abs() <= 1
2389 }
2390
2391 fn implicit_weights(&self, refi0: i32, refi1: i32) -> Option<(i32, i32)> {
2395 if self.weighted_bipred_idc != 2 || refi0 < 0 || refi1 < 0 {
2396 return None;
2397 }
2398 let r0 = &self.refs[refi0 as usize];
2399 let r1 = &self.refs1[refi1 as usize];
2400 let td = (r1.poc - r0.poc).clamp(-128, 127);
2401 let tb = (self.cur_poc - r0.poc).clamp(-128, 127);
2402 if td == 0 || r0.long_term || r1.long_term {
2403 return None; }
2405 let tx = (16384 + td.abs() / 2) / td;
2406 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2407 let w1 = dsf >> 2;
2408 if !(-64..=128).contains(&w1) {
2409 return None; }
2411 Some((64 - w1, w1))
2412 }
2413
2414 #[allow(clippy::too_many_arguments)]
2418 fn b_mc(
2419 &self,
2420 mb_x: usize,
2421 mb_y: usize,
2422 px: usize,
2423 py: usize,
2424 rw: usize,
2425 rh: usize,
2426 refi0: i32,
2427 mv0: (i32, i32),
2428 refi1: i32,
2429 mv1: (i32, i32),
2430 pred_y: &mut [u8; 256],
2431 c_pred: &mut [[u8; 64]; 2],
2432 ) {
2433 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBMc);
2434 let refi0 = if refi0 >= 0 { (refi0 as usize).min(self.refs.len().saturating_sub(1)) as i32 } else { -1 };
2440 let refi1 = if refi1 >= 0 { (refi1 as usize).min(self.refs1.len().saturating_sub(1)) as i32 } else { -1 };
2441 if (refi0 >= 0 && self.refs.is_empty()) || (refi1 >= 0 && self.refs1.is_empty()) {
2442 return;
2443 }
2444 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2445 let weights = {
2446 let _gw = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBWeights);
2447 self.implicit_weights(refi0, refi1)
2448 };
2449 let blend = |p: i32, q: i32| -> u8 {
2451 match weights {
2452 Some((w0, w1)) => (((p * w0 + q * w1 + 32) >> 6).clamp(0, 255)) as u8,
2453 None => ((p + q + 1) >> 1) as u8,
2454 }
2455 };
2456 let (mut a, mut b) = ([0u8; 256], [0u8; 256]);
2457 let _gl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBLuma);
2458 if refi0 >= 0 {
2459 let rf = &self.refs[refi0 as usize];
2460 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);
2461 }
2462 if refi1 >= 0 {
2463 let rf = &self.refs1[refi1 as usize];
2464 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);
2465 }
2466 drop(_gl);
2467 let _gbl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBBlend);
2468 match (refi0 >= 0, refi1 >= 0) {
2471 (true, true) => {
2472 for dy in 0..rh {
2473 for dx in 0..rw {
2474 let (p, q) = (a[dy * rw + dx] as i32, b[dy * rw + dx] as i32);
2475 pred_y[(py + dy) * 16 + (px + dx)] = blend(p, q);
2476 }
2477 }
2478 }
2479 (true, false) => {
2480 for dy in 0..rh {
2481 let d = (py + dy) * 16 + px;
2482 pred_y[d..d + rw].copy_from_slice(&a[dy * rw..dy * rw + rw]);
2483 }
2484 }
2485 _ => {
2486 for dy in 0..rh {
2487 let d = (py + dy) * 16 + px;
2488 pred_y[d..d + rw].copy_from_slice(&b[dy * rw..dy * rw + rw]);
2489 }
2490 }
2491 }
2492 drop(_gbl);
2493 let _gc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBChroma);
2494 let (crx, cry, crw, crh) = (px / 2, py / 2, rw / 2, rh / 2);
2495 for c in 0..2 {
2496 let (mut ca, mut cb) = ([0u8; 64], [0u8; 64]);
2497 if refi0 >= 0 {
2498 let rf = &self.refs[refi0 as usize];
2499 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2500 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);
2501 }
2502 if refi1 >= 0 {
2503 let rf = &self.refs1[refi1 as usize];
2504 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2505 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);
2506 }
2507 match (refi0 >= 0, refi1 >= 0) {
2508 (true, true) => {
2509 for dy in 0..crh {
2510 for dx in 0..crw {
2511 let (p, q) = (ca[dy * crw + dx] as i32, cb[dy * crw + dx] as i32);
2512 c_pred[c][(cry + dy) * 8 + (crx + dx)] = blend(p, q);
2513 }
2514 }
2515 }
2516 (true, false) => {
2517 for dy in 0..crh {
2518 let d = (cry + dy) * 8 + crx;
2519 c_pred[c][d..d + crw].copy_from_slice(&ca[dy * crw..dy * crw + crw]);
2520 }
2521 }
2522 _ => {
2523 for dy in 0..crh {
2524 let d = (cry + dy) * 8 + crx;
2525 c_pred[c][d..d + crw].copy_from_slice(&cb[dy * crw..dy * crw + crw]);
2526 }
2527 }
2528 }
2529 }
2530 }
2531
2532 #[allow(clippy::too_many_arguments)]
2534 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)) {
2535 let _gs = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBSet);
2536 let w4 = self.mb_w * 4;
2537 for by in py / 4..(py + rh) / 4 {
2538 for bx in px / 4..(px + rw) / 4 {
2539 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2540 self.ref_idx_y[idx] = refi0;
2541 self.mv_y[idx] = if refi0 >= 0 { mv0 } else { (0, 0) };
2542 self.ref_idx1[idx] = refi1;
2543 self.mv1[idx] = if refi1 >= 0 { mv1 } else { (0, 0) };
2544 self.inter_y[idx] = true;
2545 self.coded_y[idx] = true;
2546 self.modes_y[idx] = 2;
2547 }
2548 }
2549 }
2550
2551 #[allow(clippy::too_many_arguments)]
2555 fn coalesce_region(
2560 x: usize,
2561 y: usize,
2562 w: usize,
2563 h: usize,
2564 uniform: &dyn Fn(usize, usize, usize, usize) -> bool,
2565 emit: &mut dyn FnMut(usize, usize, usize, usize),
2566 ) {
2567 if uniform(x, y, w, h) {
2568 emit(x, y, w, h);
2569 return;
2570 }
2571 if h > 1 && uniform(x, y, w, h / 2) && uniform(x, y + h / 2, w, h / 2) {
2572 emit(x, y, w, h / 2);
2573 emit(x, y + h / 2, w, h / 2);
2574 return;
2575 }
2576 if w > 1 && uniform(x, y, w / 2, h) && uniform(x + w / 2, y, w / 2, h) {
2577 emit(x, y, w / 2, h);
2578 emit(x + w / 2, y, w / 2, h);
2579 return;
2580 }
2581 match (w > 1, h > 1) {
2582 (true, true) => {
2583 for q in 0..4usize {
2584 Self::coalesce_region(x + (q % 2) * (w / 2), y + (q / 2) * (h / 2), w / 2, h / 2, uniform, emit);
2585 }
2586 }
2587 (true, false) => {
2588 Self::coalesce_region(x, y, w / 2, h, uniform, emit);
2589 Self::coalesce_region(x + w / 2, y, w / 2, h, uniform, emit);
2590 }
2591 (false, true) => {
2592 Self::coalesce_region(x, y, w, h / 2, uniform, emit);
2593 Self::coalesce_region(x, y + h / 2, w, h / 2, uniform, emit);
2594 }
2595 (false, false) => emit(x, y, 1, 1),
2596 }
2597 }
2598
2599 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]) {
2600 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDirect);
2601 if !self.direct_spatial {
2602 return self.decode_b_direct_temporal(mb_x, mb_y, px, py, rw, rh, pred_y, c_pred);
2603 }
2604 let gd = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDeriv);
2609 let (nbx, nby) = ((mb_x * 4) as isize, (mb_y * 4) as isize);
2611 let n0 = self.mv_neighbors_list(nbx, nby, 4, 0);
2612 let n1 = self.mv_neighbors_list(nbx, nby, 4, 1);
2613 let min_pos = |a: i32, b: i32| if a < 0 { b } else if b < 0 { a } else { a.min(b) };
2614 let rid = |n: &[MvNeighbor; 3]| min_pos(min_pos(n[0].ref_idx, n[1].ref_idx), n[2].ref_idx);
2615 let (mut refi0, mut refi1) = (rid(&n0), rid(&n1));
2616 let direct_zero = refi0 < 0 && refi1 < 0;
2617 if direct_zero {
2618 refi0 = 0;
2619 refi1 = 0;
2620 }
2621 let mv0 = if refi0 >= 0 && !direct_zero { predict_mv(n0[0], n0[1], n0[2], refi0) } else { (0, 0) };
2622 let mv1 = if refi1 >= 0 && !direct_zero { predict_mv(n1[0], n1[1], n1[2], refi1) } else { (0, 0) };
2623 let (bx0, by0, bw, bh) = (px / 4, py / 4, rw / 4, rh / 4);
2629 let mut czg = [[false; 4]; 4]; for dy in 0..bh {
2631 for dx in 0..bw {
2632 let (colx, coly) = self.col_block(bx0 + dx, by0 + dy);
2633 czg[dy][dx] = !direct_zero && self.col_zero(mb_x * 4 + colx, mb_y * 4 + coly);
2634 }
2635 }
2636 let uniform = |x: usize, y: usize, w: usize, h: usize| -> bool {
2637 let t = czg[y][x];
2638 (y..y + h).all(|dy| (x..x + w).all(|dx| czg[dy][dx] == t))
2639 };
2640 let mut rects: [(usize, usize, usize, usize); 16] = [(0, 0, 0, 0); 16];
2641 let mut n = 0usize;
2642 Self::coalesce_region(0, 0, bw, bh, &uniform, &mut |x, y, w, h| {
2643 rects[n] = (x, y, w, h);
2644 n += 1;
2645 });
2646 drop(gd); for &(x, y, w, h) in &rects[..n] {
2648 let cz = czg[y][x];
2649 let m0 = if refi0 == 0 && cz { (0, 0) } else { mv0 };
2650 let m1 = if refi1 == 0 && cz { (0, 0) } else { mv1 };
2651 let (lx, ly, lw, lh) = ((bx0 + x) * 4, (by0 + y) * 4, w * 4, h * 4);
2652 self.b_mc(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1, pred_y, c_pred);
2653 self.b_set_motion(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1);
2654 }
2655 }
2656
2657 #[allow(clippy::too_many_arguments)]
2662 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]) {
2663 let poc1 = self.refs1.first().map_or(0, |f| f.poc);
2664 let infer = self.direct_8x8_inference;
2665 let step = if infer { 8 } else { 4 };
2671 let mut sy = py;
2672 while sy < py + rh {
2673 let mut sx = px;
2674 while sx < px + rw {
2675 let (colx, coly) = self.col_block(sx / 4, sy / 4);
2678 let (mvcol, refpoc) = {
2679 let col = &self.refs1[0];
2680 let idx = (mb_y * 4 + coly) * col.w4 + (mb_x * 4 + colx);
2681 if col.w4 != 0 && idx < col.mv.len() && col.ref_poc[idx] != i32::MIN {
2682 (col.mv[idx], col.ref_poc[idx])
2683 } else {
2684 ((0, 0), i32::MIN) }
2686 };
2687 let (refi0, mvc) = if refpoc == i32::MIN {
2689 (0, (0, 0))
2690 } else {
2691 let r = self.refs.iter().position(|f| f.poc == refpoc).unwrap_or(0) as i32;
2692 (r, mvcol)
2693 };
2694 let poc0 = self.refs[refi0 as usize].poc;
2695 let td = (poc1 - poc0).clamp(-128, 127);
2696 let tb = (self.cur_poc - poc0).clamp(-128, 127);
2697 let (mv0, mv1) = if td == 0 || self.refs[refi0 as usize].long_term {
2698 (mvc, (0, 0))
2699 } else {
2700 let tx = (16384 + td.abs() / 2) / td;
2701 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2702 let m0 = ((dsf * mvc.0 + 128) >> 8, (dsf * mvc.1 + 128) >> 8);
2703 (m0, (m0.0 - mvc.0, m0.1 - mvc.1))
2704 };
2705 self.b_mc(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1, pred_y, c_pred);
2706 self.b_set_motion(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1);
2707 sx += step;
2708 }
2709 sy += step;
2710 }
2711 }
2712
2713 fn read_b_ref(&self, r: &mut BitReader, list: usize) -> Result<i32, MbError> {
2716 let (active, avail) = if list == 0 {
2717 (self.num_ref_active, self.refs.len())
2718 } else {
2719 (self.num_ref_active1, self.refs1.len())
2720 };
2721 let v = if active > 1 { read_ref_idx(r, active)? } else { 0 };
2722 if v as usize >= avail {
2723 return Err(MbError::Truncated);
2724 }
2725 Ok(v)
2726 }
2727
2728 fn decode_b_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2730 if self.refs.is_empty() || self.refs1.is_empty() {
2731 return Err(MbError::Unsupported("B without references"));
2732 }
2733 let mut pred_y = [0u8; 256];
2734 let mut c_pred = [[0u8; 64]; 2];
2735 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2736 for dy in 0..16 {
2738 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2739 self.rec_y[d..d + 16].copy_from_slice(&pred_y[dy * 16..dy * 16 + 16]);
2740 }
2741 for c in 0..2 {
2742 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2743 for dy in 0..8 {
2744 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2745 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2746 }
2747 }
2748 let w4 = self.mb_w * 4;
2750 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2751 self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 0;
2752 }
2753 Ok(())
2754 }
2755
2756 fn decode_b_mb(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2759 let mb_type = r.read_ue()?;
2760 if mb_type >= 23 {
2761 return self.decode_intra_mb(r, mb_x, mb_y, mb_type - 23);
2762 }
2763 if self.refs.is_empty() || self.refs1.is_empty() {
2764 return Err(MbError::Unsupported("B without references"));
2765 }
2766 let mut pred_y = [0u8; 256];
2767 let mut c_pred = [[0u8; 64]; 2];
2768
2769 if mb_type == 0 {
2770 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2772 return self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, self.direct_8x8_inference);
2773 }
2774 if mb_type == 22 {
2775 return self.decode_b_8x8(r, mb_x, mb_y);
2776 }
2777
2778 let (layout, mvmode, preds) = b_inter_layout(mb_type);
2780 let mut refi = [[-1i32; 2]; 2]; for (p, &(_, _, _, _)) in layout.iter().enumerate() {
2783 if preds[p].uses(0) {
2784 refi[p][0] = self.read_b_ref(r, 0)?;
2785 }
2786 }
2787 for (p, _) in layout.iter().enumerate() {
2788 if preds[p].uses(1) {
2789 refi[p][1] = self.read_b_ref(r, 1)?;
2790 }
2791 }
2792 let mut mvd = [[(0i32, 0i32); 2]; 2];
2793 for (p, _) in layout.iter().enumerate() {
2794 if preds[p].uses(0) {
2795 mvd[p][0] = (r.read_se()?, r.read_se()?);
2796 }
2797 }
2798 for (p, _) in layout.iter().enumerate() {
2799 if preds[p].uses(1) {
2800 mvd[p][1] = (r.read_se()?, r.read_se()?);
2801 }
2802 }
2803 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2805 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2806 let pwb = (rw / 4) as isize;
2807 let mut mv = [(0i32, 0i32); 2];
2808 for list in 0..2 {
2809 if refi[p][list] >= 0 {
2810 let n = self.mv_neighbors_list(pbx, pby, pwb, list);
2811 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], refi[p][list]);
2812 mv[list] = (pmv.0 + mvd[p][list].0, pmv.1 + mvd[p][list].1);
2813 }
2814 }
2815 self.b_set_motion(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1]);
2816 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);
2826 }
2827 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2828 }
2829
2830 fn decode_b_8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2833 let mut sub = [0u32; 4];
2834 for s in sub.iter_mut() {
2835 let v = r.read_ue()?;
2836 if v > 12 {
2837 return Err(MbError::Unsupported("invalid B sub_mb_type"));
2838 }
2839 *s = v;
2840 }
2841 let mut pred_y = [0u8; 256];
2842 let mut c_pred = [[0u8; 64]; 2];
2843 let mut refi = [[-1i32; 2]; 4];
2846 for (p, &st) in sub.iter().enumerate() {
2847 if st != 0 && b_sub_uses(st, 0) {
2848 refi[p][0] = self.read_b_ref(r, 0)?;
2849 }
2850 }
2851 for (p, &st) in sub.iter().enumerate() {
2852 if st != 0 && b_sub_uses(st, 1) {
2853 refi[p][1] = self.read_b_ref(r, 1)?;
2854 }
2855 }
2856 let mut mvd0: Vec<(i32, i32)> = Vec::new();
2858 let mut mvd1: Vec<(i32, i32)> = Vec::new();
2859 for &st in &sub {
2860 if st != 0 && b_sub_uses(st, 0) {
2861 for _ in b_sub_parts(st) {
2862 mvd0.push((r.read_se()?, r.read_se()?));
2863 }
2864 }
2865 }
2866 for &st in &sub {
2867 if st != 0 && b_sub_uses(st, 1) {
2868 for _ in b_sub_parts(st) {
2869 mvd1.push((r.read_se()?, r.read_se()?));
2870 }
2871 }
2872 }
2873 let (mut i0, mut i1) = (0usize, 0usize);
2875 for (p, &st) in sub.iter().enumerate() {
2876 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
2877 if st == 0 {
2878 self.decode_b_direct(mb_x, mb_y, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
2879 continue;
2880 }
2881 for &(sx, sy, sw, sh) in b_sub_parts(st) {
2882 let (px, py) = (b8x + sx, b8y + sy);
2883 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2884 let pwb = (sw / 4) as isize;
2885 let mut mv = [(0i32, 0i32); 2];
2886 if b_sub_uses(st, 0) {
2887 let n = self.mv_neighbors_list(pbx, pby, pwb, 0);
2888 let pmv = predict_mv(n[0], n[1], n[2], refi[p][0]);
2889 let d = mvd0[i0];
2890 i0 += 1;
2891 mv[0] = (pmv.0 + d.0, pmv.1 + d.1);
2892 }
2893 if b_sub_uses(st, 1) {
2894 let n = self.mv_neighbors_list(pbx, pby, pwb, 1);
2895 let pmv = predict_mv(n[0], n[1], n[2], refi[p][1]);
2896 let d = mvd1[i1];
2897 i1 += 1;
2898 mv[1] = (pmv.0 + d.0, pmv.1 + d.1);
2899 }
2900 self.b_set_motion(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1]);
2901 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);
2902 }
2903 }
2904 let allow_8x8 = sub
2907 .iter()
2908 .all(|&st| if st == 0 { self.direct_8x8_inference } else { st <= 3 });
2909 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2910 }
2911
2912 fn decode_p8x8(
2916 &mut self,
2917 r: &mut BitReader,
2918 mb_x: usize,
2919 mb_y: usize,
2920 ref0: bool,
2921 ) -> Result<(), MbError> {
2922 if self.refs.is_empty() {
2923 return Err(MbError::Unsupported("inter without reference"));
2924 }
2925 let w4 = self.mb_w * 4;
2926 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2927 let num_refs = self.refs.len();
2928
2929 let mut sub_types = [0u32; 4];
2932 for st in sub_types.iter_mut() {
2933 let v = r.read_ue()?;
2934 if v > 3 {
2935 return Err(MbError::Unsupported("B-slice / invalid sub_mb_type"));
2936 }
2937 *st = v;
2938 }
2939 let mut ref_idxs = [0i32; 4];
2940 if self.num_ref_active > 1 && !ref0 {
2941 for ri in ref_idxs.iter_mut() {
2942 *ri = read_ref_idx(r, self.num_ref_active)?;
2943 if *ri as usize >= num_refs {
2944 return Err(MbError::Truncated); }
2946 }
2947 }
2948
2949 let mut pred_y = [0u8; 256];
2953 let mut c_pred = [[0u8; 64]; 2];
2954 for part in 0..4usize {
2955 let refi = ref_idxs[part];
2956 let (b8x, b8y) = ((part % 2) * 8, (part / 2) * 8);
2957 for &(srx, sry, srw, srh) in sub_mb_partitions(sub_types[part]) {
2958 let (px, py) = (b8x + srx, b8y + sry);
2959 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2960 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (srw / 4) as isize);
2961 let pmv = predict_mv(a, b, c, refi);
2962 let mvd_x = r.read_se()?;
2963 let mvd_y = r.read_se()?;
2964 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2965 for by in py / 4..py / 4 + srh / 4 {
2966 for bx in px / 4..px / 4 + srw / 4 {
2967 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2968 self.mv_y[idx] = mv;
2969 self.inter_y[idx] = true;
2970 self.ref_idx_y[idx] = refi;
2971 self.coded_y[idx] = true;
2972 }
2973 }
2974 let reference = &self.refs[refi as usize];
2975 let mut tmp = [0u8; 256];
2976 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);
2977 restride(&mut pred_y, 16, px, py, &tmp, srw, srh);
2978 let (crx, cry, crw, crh) = (px / 2, py / 2, srw / 2, srh / 2);
2979 for cc in 0..2 {
2980 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2981 let mut tc = [0u8; 64];
2982 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);
2983 restride(&mut c_pred[cc], 8, crx, cry, &tc, crw, crh);
2984 }
2985 self.weight_partition(
2986 &mut pred_y, &mut c_pred, 0, refi as usize, px, py, srw, srh,
2987 );
2988 }
2989 }
2990
2991 let allow_8x8 = sub_types.iter().all(|&t| t == 0);
2993 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2994 }
2995
2996 fn decode_p_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2999 if self.refs.is_empty() {
3003 return Err(MbError::Unsupported("P_Skip without reference"));
3004 }
3005 let mv = self.skip_mv(mb_x, mb_y);
3006 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
3007
3008 let mut pred = [0u8; 256];
3009 let rf0 = &self.refs[0];
3010 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);
3011 if let Some(wt) = &self.weights {
3012 for p in pred.iter_mut() {
3013 *p = wt.apply_luma(*p, 0, 0);
3014 }
3015 }
3016 {
3017 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
3018 for dy in 0..16 {
3019 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
3020 self.rec_y[d..d + 16].copy_from_slice(&pred[dy * 16..dy * 16 + 16]);
3021 }
3022 }
3023 for c in 0..2 {
3024 let mut pc = [0u8; 64];
3025 let rf0 = &self.refs[0];
3026 let rc = if c == 0 { &rf0.pu } else { &rf0.pv };
3027 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);
3028 if let Some(wt) = &self.weights {
3029 for p in pc.iter_mut() {
3030 *p = wt.apply_chroma(*p, 0, 0, c);
3031 }
3032 }
3033 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3034 for dy in 0..8 {
3035 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
3036 plane[d..d + 8].copy_from_slice(&pc[dy * 8..dy * 8 + 8]);
3037 }
3038 }
3039 {
3040 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
3041 self.set_mb_mv(mb_x, mb_y, mv, true, 0);
3042 let w4 = self.mb_w * 4;
3044 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3045 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
3046 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3047 }
3048 }
3049 Ok(())
3050 }
3051
3052 fn predict_i4_mode(&self, bx: usize, by: usize) -> u8 {
3056 if bx == 0 || by == 0 {
3057 return 2;
3058 }
3059 if !self.nbr_in_slice((bx - 1) / 4, by / 4)
3063 || !self.nbr_in_slice(bx / 4, (by - 1) / 4)
3064 || !self.intra_nbr_ok(bx - 1, by)
3065 || !self.intra_nbr_ok(bx, by - 1)
3066 {
3067 return 2;
3068 }
3069 let w4 = self.mb_w * 4;
3070 self.modes_y[by * w4 + (bx - 1)].min(self.modes_y[(by - 1) * w4 + bx])
3071 }
3072
3073 fn gather_i4(
3075 &self,
3076 px: usize,
3077 py: usize,
3078 avail_top: bool,
3079 avail_left: bool,
3080 bx: usize,
3081 by: usize,
3082 ) -> ([u8; 8], [u8; 4], u8) {
3083 let (cw, w4) = (self.cw, self.mb_w * 4);
3084 let mut top = [0u8; 8];
3085 let mut left = [0u8; 4];
3086 let mut corner = 0;
3087 if avail_top {
3088 for i in 0..4 {
3089 top[i] = self.rec_y[(py - 1) * cw + px + i];
3090 }
3091 let tr_avail = bx + 1 < w4
3092 && self.coded_y[(by - 1) * w4 + (bx + 1)]
3093 && self.nbr_in_slice((bx + 1) / 4, (by - 1) / 4)
3094 && self.intra_nbr_ok(bx + 1, by - 1);
3095 for i in 0..4 {
3096 top[4 + i] = if tr_avail {
3097 self.rec_y[(py - 1) * cw + px + 4 + i]
3098 } else {
3099 top[3]
3100 };
3101 }
3102 }
3103 if avail_left {
3104 for i in 0..4 {
3105 left[i] = self.rec_y[(py + i) * cw + px - 1];
3106 }
3107 }
3108 if avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1) {
3111 corner = self.rec_y[(py - 1) * cw + px - 1];
3112 }
3113 (top, left, corner)
3114 }
3115
3116 fn decode_ipcm(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3119 r.align_to_byte()?;
3120 let (lx, ly) = (mb_x * 16, mb_y * 16);
3121 for dy in 0..16 {
3122 for dx in 0..16 {
3123 self.rec_y[(ly + dy) * self.cw + (lx + dx)] = r.read_bits(8)? as u8;
3124 }
3125 }
3126 let (cx, cy) = (mb_x * 8, mb_y * 8);
3127 for plane in [&mut self.rec_u, &mut self.rec_v] {
3128 for dy in 0..8 {
3129 for dx in 0..8 {
3130 plane[(cy + dy) * self.ccw + (cx + dx)] = r.read_bits(8)? as u8;
3131 }
3132 }
3133 }
3134 let (w4, w2) = (self.mb_w * 4, self.mb_w * 2);
3137 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3138 let idx = (mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx);
3139 self.nnz_y[idx] = 16;
3140 self.modes_y[idx] = 2;
3141 self.inter_y[idx] = false;
3142 self.ref_idx_y[idx] = -1;
3143 self.mv_y[idx] = (0, 0);
3144 }
3145 for c in 0..2 {
3146 for by in 0..2 {
3147 for bx in 0..2 {
3148 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = 16;
3149 }
3150 }
3151 }
3152 Ok(())
3153 }
3154
3155 fn decode_i4x4(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3156 let w4 = self.mb_w * 4;
3157
3158 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3161 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
3162 let predicted = self.predict_i4_mode(bx, by);
3163 let actual = if r.read_bit()? {
3164 predicted
3165 } else {
3166 let rem = r.read_bits(3)? as u8;
3167 if rem < predicted {
3168 rem
3169 } else {
3170 rem + 1
3171 }
3172 };
3173 self.modes_y[by * w4 + bx] = actual;
3174 modes[lby * 4 + lbx] = actual;
3175 }
3176
3177 let chroma_mode = r.read_ue()? as u8;
3178 let cbp = read_cbp_intra(r)?;
3179 let cbp_luma = cbp & 15;
3180 let cbp_chroma = cbp >> 4;
3181 if cbp != 0 {
3182 self.step_qp(r.read_se()?);
3183 }
3184 let qp = self.cur_qp;
3185
3186 let top_mb_avail = mb_y > 0
3190 && self.nbr_in_slice(mb_x, mb_y - 1)
3191 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3192 let left_mb_avail = mb_x > 0
3193 && self.nbr_in_slice(mb_x - 1, mb_y)
3194 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3195 self.nnz_cache_load(mb_x, mb_y);
3196 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
3197 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
3198 let (px, py) = (bx * 4, by * 4);
3199 let avail_top = lby > 0 || top_mb_avail;
3200 let avail_left = lbx > 0 || left_mb_avail;
3201 let mut qb = [0i32; 16];
3202 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
3203 let nc = self.nc_pred(lbx, lby);
3204 let scan16 = decode_residual_block(r, 16, nc)?;
3205 qb = un_scan_4x4_dcac(&scan16);
3206 scan16.iter().filter(|&&v| v != 0).count() as u8
3207 } else {
3208 0
3209 };
3210 self.nnz_cache_set(lbx, lby, total);
3211 self.nnz_y[by * w4 + bx] = total;
3212 let (top, left, corner) = self.gather_i4(px, py, avail_top, avail_left, bx, by);
3213 let pred = intra4x4_pred(modes[lby * 4 + lbx], avail_top, avail_left, &top, &left, corner);
3214 let mut predb = [0i32; 16];
3215 for i in 0..16 {
3216 predb[i] = pred[i] as i32;
3217 }
3218 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
3219 store(&mut self.rec_y, self.cw, px, py, &s);
3220 self.coded_y[by * w4 + bx] = true;
3221 }
3222
3223 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3224 }
3225
3226 fn decode_i8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3230 let w4 = self.mb_w * 4;
3231 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
3232
3233 let mut modes8 = [2u8; 4];
3236 for (b8, mode) in modes8.iter_mut().enumerate() {
3237 let (b8x, b8y) = (b8 % 2, b8 / 2);
3238 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
3239 let predicted = self.predict_i4_mode(bx, by);
3240 let actual = if r.read_bit()? {
3241 predicted
3242 } else {
3243 let rem = r.read_bits(3)? as u8;
3244 if rem < predicted { rem } else { rem + 1 }
3245 };
3246 *mode = actual;
3247 for sy in 0..2 {
3248 for sx in 0..2 {
3249 self.modes_y[(by + sy) * w4 + (bx + sx)] = actual;
3250 }
3251 }
3252 }
3253
3254 let chroma_mode = r.read_ue()? as u8;
3255 let cbp = read_cbp_intra(r)?;
3256 let cbp_luma = cbp & 15;
3257 let cbp_chroma = cbp >> 4;
3258 if cbp != 0 {
3259 self.step_qp(r.read_se()?);
3260 }
3261 let qp = self.cur_qp;
3262
3263 let top_mb_avail = mb_y > 0
3264 && self.nbr_in_slice(mb_x, mb_y - 1)
3265 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3266 let left_mb_avail = mb_x > 0
3267 && self.nbr_in_slice(mb_x - 1, mb_y)
3268 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3269 self.nnz_cache_load(mb_x, mb_y);
3270
3271 for b8 in 0..4 {
3272 let (b8x, b8y) = (b8 % 2, b8 / 2);
3273 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
3274 let (px, py) = (bx * 4, by * 4);
3275
3276 let mut res8 = [0i32; 64];
3279 if cbp_luma & (1 << b8) != 0 {
3280 let mut scan8 = [0i32; 64];
3281 for sub in 0..4 {
3282 let (sx, sy) = (sub % 2, sub / 2);
3283 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
3284 let nc = self.nc_pred(cx, cy);
3285 let blk = decode_residual_block(r, 16, nc)?;
3286 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
3287 self.nnz_cache_set(cx, cy, total);
3288 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
3289 for k in 0..16 {
3290 scan8[4 * k + sub] = blk[k];
3291 }
3292 }
3293 let raster = un_scan_8x8(&scan8);
3294 res8 = self.inv_quant8(&raster, qp, 0);
3295 } else {
3296 for sub in 0..4 {
3297 let (sx, sy) = (sub % 2, sub / 2);
3298 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
3299 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
3300 }
3301 }
3302
3303 let avail_top = b8y > 0 || top_mb_avail;
3304 let avail_left = b8x > 0 || left_mb_avail;
3305 let (top, left, corner, avail_corner) =
3306 self.gather_i8(px, py, avail_top, avail_left, bx, by);
3307 let pred = intra8x8_pred(
3308 modes8[b8], avail_top, avail_left, avail_corner, &top, &left, corner,
3309 );
3310 let mut predb = [0i32; 64];
3311 for i in 0..64 {
3312 predb[i] = pred[i] as i32;
3313 }
3314 let recon = add_residual_8x8(&res8, &predb);
3315 for dy in 0..8 {
3316 for dx in 0..8 {
3317 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
3318 }
3319 }
3320 for sy in 0..2 {
3321 for sx in 0..2 {
3322 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
3323 }
3324 }
3325 }
3326
3327 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3328 }
3329
3330 fn inv_quant8(&self, raster: &[i32; 64], qp: u8, list: usize) -> [i32; 64] {
3333 match &self.scaling8 {
3334 Some(s) => inverse_quant_8x8(raster, qp, &s[list]),
3335 None => inverse_quant_8x8(raster, qp, &[16i32; 64]),
3336 }
3337 }
3338
3339 #[allow(clippy::too_many_arguments)]
3343 fn gather_i8(
3344 &self,
3345 px: usize,
3346 py: usize,
3347 avail_top: bool,
3348 avail_left: bool,
3349 bx: usize,
3350 by: usize,
3351 ) -> ([u8; 16], [u8; 8], u8, bool) {
3352 let (cw, w4) = (self.cw, self.mb_w * 4);
3353 let mut top = [0u8; 16];
3354 let mut left = [0u8; 8];
3355 let mut corner = 0;
3356 if avail_top {
3357 for i in 0..8 {
3358 top[i] = self.rec_y[(py - 1) * cw + px + i];
3359 }
3360 let tr_avail = bx + 2 < w4
3361 && self.coded_y[(by - 1) * w4 + (bx + 2)]
3362 && self.nbr_in_slice((bx + 2) / 4, (by - 1) / 4)
3363 && self.intra_nbr_ok(bx + 2, by - 1);
3364 for i in 0..8 {
3365 top[8 + i] = if tr_avail {
3366 self.rec_y[(py - 1) * cw + px + 8 + i]
3367 } else {
3368 top[7]
3369 };
3370 }
3371 }
3372 if avail_left {
3373 for i in 0..8 {
3374 left[i] = self.rec_y[(py + i) * cw + px - 1];
3375 }
3376 }
3377 let avail_corner = avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1);
3378 if avail_corner {
3379 corner = self.rec_y[(py - 1) * cw + px - 1];
3380 }
3381 (top, left, corner, avail_corner)
3382 }
3383
3384 fn decode_i16(
3385 &mut self,
3386 r: &mut BitReader,
3387 mb_x: usize,
3388 mb_y: usize,
3389 mt: u32,
3390 ) -> Result<(), MbError> {
3391 let pred_mode = I16Mode::from_id(mt % 4);
3392 let cbp_chroma = (mt % 12) / 4;
3393 let cbp_luma_15 = mt / 12 == 1;
3394 let chroma_mode = r.read_ue()? as u8;
3395 self.step_qp(r.read_se()?);
3396 let qp = self.cur_qp;
3397 let w4 = self.mb_w * 4;
3398
3399 self.nnz_cache_load(mb_x, mb_y);
3401 let nc_dc = self.nc_pred(0, 0);
3402 let dc_scan = decode_residual_block(r, 16, nc_dc)?;
3403 let dc_levels = un_scan_4x4_dcac(&dc_scan);
3404 let recon_dc = self.dequant_luma_dc(&dc_levels, qp, 0);
3405
3406 let mut q_blocks = [[0i32; 16]; 16];
3408 for &(bx, by) in &LUMA_4X4_SCAN_XY {
3409 let total = if cbp_luma_15 {
3410 let nc = self.nc_pred(bx, by);
3411 let ac = decode_residual_block(r, 15, nc)?;
3412 un_scan_4x4_ac_into(&ac, &mut q_blocks[by * 4 + bx]);
3413 ac.iter().filter(|&&v| v != 0).count() as u8
3414 } else {
3415 0
3416 };
3417 self.nnz_cache_set(bx, by, total);
3418 self.nnz_y[(mb_y * 4 + by) * w4 + (mb_x * 4 + bx)] = total;
3419 }
3420
3421 let avail_top = mb_y > 0
3423 && self.nbr_in_slice(mb_x, mb_y - 1)
3424 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3425 let avail_left = mb_x > 0
3426 && self.nbr_in_slice(mb_x - 1, mb_y)
3427 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3428 let (lx, ly) = (mb_x * 16, mb_y * 16);
3429 let mut top = [0u8; 16];
3430 let mut left = [0u8; 16];
3431 if avail_top {
3432 for i in 0..16 {
3433 top[i] = self.rec_y[(ly - 1) * self.cw + lx + i];
3434 }
3435 }
3436 if avail_left {
3437 for i in 0..16 {
3438 left[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
3439 }
3440 }
3441 let corner = if avail_top && avail_left {
3442 self.rec_y[(ly - 1) * self.cw + lx - 1]
3443 } else {
3444 0
3445 };
3446 let pred_l = luma16x16_pred(pred_mode, avail_top, avail_left, &top, &left, corner);
3447 for by in 0..4 {
3448 for bx in 0..4 {
3449 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
3450 deq[0] = recon_dc[by * 4 + bx];
3451 let mut predb = [0i32; 16];
3452 for dy in 0..4 {
3453 for dx in 0..4 {
3454 predb[dy * 4 + dx] = pred_l[(by * 4 + dy) * 16 + (bx * 4 + dx)] as i32;
3455 }
3456 }
3457 let s = reconstruct_4x4(&deq, &predb);
3458 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
3459 }
3460 }
3461 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3463 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3464 }
3465
3466 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3467 }
3468
3469 fn decode_chroma(
3471 &mut self,
3472 r: &mut BitReader,
3473 mb_x: usize,
3474 mb_y: usize,
3475 cbp_chroma: u32,
3476 chroma_mode: u8,
3477 ) -> Result<(), MbError> {
3478 let qpc = self.chroma_qp_for(self.cur_qp);
3479 let (cx, cy) = (mb_x * 8, mb_y * 8);
3480 let avail_top = mb_y > 0
3481 && self.nbr_in_slice(mb_x, mb_y - 1)
3482 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3483 let avail_left = mb_x > 0
3484 && self.nbr_in_slice(mb_x - 1, mb_y)
3485 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3486
3487 let mut c_recon_dc = [[0i32; 4]; 2];
3488 if cbp_chroma != 0 {
3489 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
3490 let dc = decode_residual_block(r, 4, -1)?;
3491 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 1 + c);
3492 }
3493 }
3494 let mut c_q_blocks = [[[0i32; 16]; 4]; 2];
3495 if cbp_chroma == 2 {
3496 self.chroma_cache_load(mb_x, mb_y);
3497 let w2 = self.mb_w * 2;
3498 for c in 0..2 {
3499 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3500 let nc = self.chroma_nc_pred(c, bx, by);
3501 let ac = decode_residual_block(r, 15, nc)?;
3502 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
3503 self.chroma_nnz_cache_set(c, bx, by, total);
3504 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
3505 un_scan_4x4_ac_into(&ac, &mut c_q_blocks[c][by * 2 + bx]);
3506 }
3507 }
3508 }
3509 for c in 0..2 {
3510 let mut ctop = [0u8; 8];
3511 let mut cleft = [0u8; 8];
3512 let mut ccorner = 0u8;
3513 {
3514 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
3515 if avail_top {
3516 for i in 0..8 {
3517 ctop[i] = rec_c[(cy - 1) * self.ccw + cx + i];
3518 }
3519 }
3520 if avail_left {
3521 for i in 0..8 {
3522 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
3523 }
3524 }
3525 if avail_top && avail_left {
3526 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
3527 }
3528 }
3529 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
3530 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3531 let mut predb = [0i32; 16];
3532 for dy in 0..4 {
3533 for dx in 0..4 {
3534 predb[dy * 4 + dx] = pred8[(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
3535 }
3536 }
3537 let mut deq = self.dequant(&c_q_blocks[c][by * 2 + bx], qpc, 1 + c);
3538 deq[0] = c_recon_dc[c][by * 2 + bx];
3539 let s = reconstruct_4x4(&deq, &predb);
3540 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3541 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
3542 }
3543 }
3544 Ok(())
3545 }
3546
3547 fn dump_mb_map(&self) {
3556 if std::env::var_os("RH264_DUMP_MB").is_none() {
3557 return;
3558 }
3559 let w4 = self.mb_w * 4;
3560 let mut hist = [0usize; 4];
3561 eprintln!("--- frame poc {} ---", self.cur_poc);
3562 for mb_y in 0..self.mb_h {
3563 let mut row = String::new();
3564 for mb_x in 0..self.mb_w {
3565 let b = (mb_y * 4) * w4 + mb_x * 4;
3566 let r = self.ref_idx_y[b];
3567 if r < 0 {
3568 row.push('i');
3569 } else {
3570 if (r as usize) < 4 {
3571 hist[r as usize] += 1;
3572 }
3573 row.push((b'0' + (r as u8).min(9)) as char);
3574 }
3575 }
3576 eprintln!("{row}");
3577 }
3578 eprintln!(
3579 "ref histogram: {hist:?} num_ref_active={} refs.len()={} OUT-OF-RANGE={}",
3580 self.num_ref_active,
3581 self.refs.len(),
3582 hist.iter().skip(self.refs.len()).sum::<usize>()
3583 );
3584 let list: Vec<String> = self
3585 .refs
3586 .iter()
3587 .enumerate()
3588 .map(|(i, f)| {
3589 let synth = if f.w4 == 0 { " SYNTH-GREY" } else { "" };
3592 format!("[{i}] poc={} fn={}{synth}", f.poc, f.frame_num)
3593 })
3594 .collect();
3595 eprintln!(" RefPicList0: {}", list.join(" "));
3596 }
3597
3598 pub fn deblock(&mut self, offset_a: i32, offset_b: i32) {
3599 self.dump_mb_map();
3600 let nnz_db_storage;
3607 let nnz_db: &[u8] = if self.mb_t8x8.iter().any(|&t| t) {
3608 let mut n = self.nnz_y.clone();
3609 let w4 = self.mb_w * 4;
3610 for mb_y in 0..self.mb_h {
3611 for mb_x in 0..self.mb_w {
3612 if !self.mb_t8x8[mb_y * self.mb_w + mb_x] {
3613 continue;
3614 }
3615 for b8 in 0..4 {
3616 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, mb_y * 4 + (b8 / 2) * 2);
3617 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + (bx + sx)] > 0));
3618 for sy in 0..2 {
3619 for sx in 0..2 {
3620 n[(by + sy) * w4 + (bx + sx)] = u8::from(any);
3621 }
3622 }
3623 }
3624 }
3625 }
3626 nnz_db_storage = n;
3627 &nnz_db_storage
3628 } else {
3629 &self.nnz_y
3630 };
3631 let ref_id: Vec<i32> = self
3634 .ref_idx_y
3635 .iter()
3636 .map(|&r| if r >= 0 { self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3637 .collect();
3638 let ref_id1: Vec<i32> = if self.refs1.is_empty() {
3641 Vec::new()
3642 } else {
3643 self.ref_idx1
3644 .iter()
3645 .map(|&r| if r >= 0 { self.refs1.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3646 .collect()
3647 };
3648 let info = rusty_h264_common::deblock::BlockInfo {
3649 inter: &self.inter_y,
3650 nnz: nnz_db,
3651 mv: &self.mv_y,
3652 ref_id: &ref_id,
3653 mv1: &self.mv1,
3654 ref_id1: &ref_id1,
3655 w4: self.mb_w * 4,
3656 t8x8: &self.mb_t8x8,
3657 bs: &[],
3658 };
3659 rusty_h264_common::deblock::filter_frame(
3660 &mut self.rec_y,
3661 &mut self.rec_u,
3662 &mut self.rec_v,
3663 self.mb_w,
3664 self.mb_h,
3665 &self.mb_qp,
3666 self.chroma_qp_offset,
3667 offset_a,
3668 offset_b,
3669 &info,
3670 );
3671 }
3672
3673 pub fn into_frame(self, crop_r: usize, crop_b: usize) -> YuvFrame {
3675 if crop_r == 0 && crop_b == 0 {
3678 return YuvFrame {
3679 width: self.cw,
3680 height: self.ch,
3681 y: self.rec_y,
3682 u: self.rec_u,
3683 v: self.rec_v,
3684 };
3685 }
3686 let dw = self.cw - 2 * crop_r;
3687 let dh = self.ch - 2 * crop_b;
3688 let mut y = vec![0u8; dw * dh];
3689 for row in 0..dh {
3690 y[row * dw..row * dw + dw].copy_from_slice(&self.rec_y[row * self.cw..row * self.cw + dw]);
3691 }
3692 let (cdw, cdh) = (dw / 2, dh / 2);
3693 let mut u = vec![0u8; cdw * cdh];
3694 let mut v = vec![0u8; cdw * cdh];
3695 for row in 0..cdh {
3696 u[row * cdw..row * cdw + cdw]
3697 .copy_from_slice(&self.rec_u[row * self.ccw..row * self.ccw + cdw]);
3698 v[row * cdw..row * cdw + cdw]
3699 .copy_from_slice(&self.rec_v[row * self.ccw..row * self.ccw + cdw]);
3700 }
3701 let _ = self.cch;
3702 YuvFrame {
3703 width: dw,
3704 height: dh,
3705 y,
3706 u,
3707 v,
3708 }
3709 }
3710}
3711
3712fn cabac_unary(cab: &mut crate::cabac::Cabac, ctx: usize, off: usize) -> u32 {
3719 if cab.decode_decision(ctx) == 0 {
3720 return 0;
3721 }
3722 let mut sym = 0;
3723 loop {
3724 let bin = cab.decode_decision(ctx + off);
3725 sym += 1;
3726 if bin == 0 || sym >= 512 {
3731 break;
3732 }
3733 }
3734 sym
3735}
3736
3737fn cabac_exp_bypass(cab: &mut crate::cabac::Cabac, mut count: i32) -> u32 {
3739 let mut sym = 0u32;
3740 loop {
3741 let c = cab.decode_bypass();
3742 if c == 1 {
3743 sym += 1 << count;
3744 count += 1;
3745 }
3746 if c == 0 || count == 16 {
3747 break;
3748 }
3749 }
3750 let mut sym2 = 0u32;
3751 while count > 0 {
3752 count -= 1;
3753 if cab.decode_bypass() != 0 {
3754 sym2 |= 1 << count;
3755 }
3756 }
3757 sym + sym2
3758}
3759
3760fn cabac_ueg_level(cab: &mut crate::cabac::Cabac, ctx: usize) -> u32 {
3763 if cab.decode_decision(ctx) == 0 {
3764 return 0;
3765 }
3766 let mut code = 0u32;
3767 let mut count = 1;
3768 let mut tmp;
3769 loop {
3770 tmp = cab.decode_decision(ctx);
3771 code += 1;
3772 count += 1;
3773 if tmp == 0 || count == 13 {
3774 break;
3775 }
3776 }
3777 if tmp != 0 {
3778 code += cabac_exp_bypass(cab, 0) + 1;
3779 }
3780 code
3781}
3782
3783fn parse_mb_qp_delta_cabac(cab: &mut crate::cabac::Cabac, last_delta_qp: &mut i32) -> i32 {
3785 const O: usize = 60;
3786 let ctx_inc = (*last_delta_qp != 0) as usize;
3787 let mut qp_delta = 0;
3788 if cab.decode_decision(O + ctx_inc) != 0 {
3789 let code = cabac_unary(cab, O + 2, 1) + 1;
3790 qp_delta = ((code + 1) >> 1) as i32;
3791 if code & 1 == 0 {
3792 qp_delta = -qp_delta;
3793 }
3794 }
3795 *last_delta_qp = qp_delta;
3796 qp_delta
3797}
3798
3799const NZC_CACHE: [usize; 24] = [
3802 9, 10, 17, 18, 11, 12, 19, 20, 25, 26, 33, 34, 27, 28, 35, 36, 14, 15, 22, 23, 38, 39, 46, 47, ];
3806
3807const RES_MAXPOS: [i32; 11] = [0, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14];
3809const RES_MAXC2: [i32; 11] = [0, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4];
3810const RES_CBF: [usize; 11] = [0, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16];
3811const RES_MAP: [usize; 11] = [0, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47];
3812const RES_ONE: [usize; 11] = [0, 0, 10, 20, 30, 39, 199, 30, 30, 39, 39];
3815const RP_I16_DC: usize = 1;
3817const RP_I16_AC: usize = 2;
3818const RP_LUMA_4X4: usize = 3;
3819const RP_CHROMA_DC: usize = 7; const RP_CHROMA_AC: usize = 9; const RP_LUMA_8X8: usize = 6;
3828
3829const SIG8X8: [u8; 64] = [
3833 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,
3837];
3838const LAST8X8: [u8; 64] = [
3841 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,
3845];
3846
3847#[allow(clippy::too_many_arguments)]
3852fn parse_residual_cabac(
3853 cab: &mut crate::cabac::Cabac,
3854 nzc: &mut [u8; 48],
3855 cbf_dc: &mut u16,
3856 iz: usize,
3857 rp: usize,
3858 is_intra: bool,
3859 ndc: (Option<u16>, Option<u16>), out: &mut [i32], ) -> u32 {
3862 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Entropy);
3865 let is8 = rp == RP_LUMA_8X8;
3869 let is_dc = rp == RP_I16_DC || rp == RP_CHROMA_DC || rp == RP_CHROMA_DC + 1;
3870 let (mut na, mut nb) = (is_intra as u8, is_intra as u8);
3871 let scan = NZC_CACHE[iz.min(23)];
3872 if is_dc {
3873 if let Some(t) = ndc.0 {
3874 nb = ((t >> rp) & 1) as u8;
3875 }
3876 if let Some(l) = ndc.1 {
3877 na = ((l >> rp) & 1) as u8;
3878 }
3879 } else {
3880 if nzc[scan - 8] != 0xff {
3881 nb = (nzc[scan - 8] != 0) as u8;
3882 }
3883 if nzc[scan - 1] != 0xff {
3884 na = (nzc[scan - 1] != 0) as u8;
3885 }
3886 }
3887 if !is8 {
3888 let cbf = cab.decode_decision(85 + RES_CBF[rp] + (na + (nb << 1)) as usize);
3889 if cbf == 0 {
3890 if !is_dc {
3891 nzc[scan] = 0;
3892 }
3893 return 0;
3894 }
3895 if is_dc {
3896 *cbf_dc |= 1 << rp;
3897 }
3898 }
3899 let maxpos = RES_MAXPOS[rp] as usize;
3901 let (map, last) = if is8 { (402, 417) } else { (105 + RES_MAP[rp], 166 + RES_MAP[rp]) };
3903 let mut sig = [0i32; 64];
3904 let mut coeff_num = 0u32;
3905 let mut last_hit = false;
3906 for i in 0..maxpos {
3907 let (mi, li) = if is8 { (SIG8X8[i] as usize, LAST8X8[i] as usize) } else { (i, i) };
3909 if cab.decode_decision(map + mi) != 0 {
3910 sig[i] = 1;
3911 coeff_num += 1;
3912 if cab.decode_decision(last + li) != 0 {
3913 last_hit = true;
3914 break;
3915 }
3916 }
3917 }
3918 if !last_hit {
3919 sig[maxpos] = 1;
3920 coeff_num += 1;
3921 }
3922 let one = 227 + RES_ONE[rp];
3924 let abs = 232 + RES_ONE[rp];
3925 let maxc2 = RES_MAXC2[rp];
3926 let (mut c1, mut c2) = (1i32, 0i32);
3927 for i in (0..=maxpos).rev() {
3928 if sig[i] != 0 {
3929 let mut level = sig[i] + cab.decode_decision(one + c1 as usize) as i32;
3930 if level == 2 {
3931 level += cabac_ueg_level(cab, abs + c2 as usize) as i32;
3932 c2 = (c2 + 1).min(maxc2);
3933 c1 = 0;
3934 } else if c1 != 0 {
3935 c1 = (c1 + 1).min(4);
3936 }
3937 if cab.decode_bypass() != 0 {
3938 level = -level;
3939 }
3940 sig[i] = level;
3941 }
3942 }
3943 out[..=maxpos].copy_from_slice(&sig[..=maxpos]);
3944 if is8 {
3945 for k in 0..4 {
3949 nzc[NZC_CACHE[(iz + k).min(23)]] = coeff_num as u8;
3950 }
3951 } else if !is_dc {
3952 nzc[scan] = coeff_num as u8;
3953 }
3954 coeff_num
3955}
3956
3957const CACHE30: [usize; 16] = [7, 8, 13, 14, 9, 10, 15, 16, 19, 20, 25, 26, 21, 22, 27, 28];
3960
3961const G_SCAN4: [usize; 16] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15];
3964
3965fn parse_sub_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3967 const S: usize = 21;
3968 if cab.decode_decision(S) != 0 {
3969 return 0;
3970 }
3971 if cab.decode_decision(S + 1) != 0 {
3972 3 - cab.decode_decision(S + 2)
3973 } else {
3974 1
3975 }
3976}
3977
3978fn parse_intra_mb_type_cabac(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3981 if cab.decode_decision(base) == 0 {
3982 return 0; }
3984 if cab.decode_terminate() {
3985 return 25; }
3987 let mut t = 1 + 12 * cab.decode_decision(base + 1) as u32; if cab.decode_decision(base + 2) != 0 {
3989 t += 4 + 4 * cab.decode_decision(base + 2) as u32;
3990 }
3991 t += 2 * cab.decode_decision(base + 3) as u32;
3992 t += cab.decode_decision(base + 3) as u32;
3993 t
3994}
3995
3996#[doc(hidden)]
4002pub fn parse_mb_type_b(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4003 parse_mb_type_b_cabac(cab, ctx_inc)
4004}
4005
4006fn parse_mb_type_b_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4007 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4008 const B: usize = 27;
4009 if cab.decode_decision(B + ctx_inc) == 0 {
4010 return 0; }
4012 if cab.decode_decision(B + 3) == 0 {
4013 return 1 + cab.decode_decision(B + 5) as u32; }
4015 let mut m = (cab.decode_decision(B + 4) as u32) << 3;
4016 m |= (cab.decode_decision(B + 5) as u32) << 2;
4017 m |= (cab.decode_decision(B + 5) as u32) << 1;
4018 m |= cab.decode_decision(B + 5) as u32;
4019 if m < 8 {
4020 return m + 3;
4021 }
4022 if m == 13 {
4023 return parse_intra_mb_type_cabac(cab, 32) + 23;
4024 }
4025 if m == 14 {
4026 return 11; }
4028 if m == 15 {
4029 return 22; }
4031 m = (m << 1) | cab.decode_decision(B + 5) as u32;
4032 m - 4
4033}
4034
4035fn parse_sub_mb_type_b_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4038 const B: usize = 36;
4039 if cab.decode_decision(B) == 0 {
4040 return 0; }
4042 if cab.decode_decision(B + 1) == 0 {
4043 return 1 + cab.decode_decision(B + 3) as u32; }
4045 let mut st = 3u32;
4046 if cab.decode_decision(B + 2) != 0 {
4047 if cab.decode_decision(B + 3) != 0 {
4048 return 11 + cab.decode_decision(B + 3) as u32; }
4050 st += 4;
4051 }
4052 st += 2 * cab.decode_decision(B + 3) as u32;
4053 st += cab.decode_decision(B + 3) as u32;
4054 st
4055}
4056
4057fn parse_mvd_partition(
4061 cab: &mut crate::cabac::Cabac,
4062 part_idx: usize,
4063 zblocks: &[usize],
4064 mvdc: &mut [[i16; 2]; 30],
4065 refc: &mut [i8; 30],
4066 mmvd: &mut [[i16; 2]; 16],
4067 mref: &mut [i8; 16],
4068 ref_idx: i8,
4069) -> (i32, i32) {
4070 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4071 let s = CACHE30[part_idx];
4072 let ctx = |comp: usize| -> usize {
4073 let mut a = 0i32;
4074 if refc[s - 6] >= 0 {
4075 a += mvdc[s - 6][comp].unsigned_abs() as i32;
4076 }
4077 if refc[s - 1] >= 0 {
4078 a += mvdc[s - 1][comp].unsigned_abs() as i32;
4079 }
4080 if a >= 3 {
4081 1 + (a > 32) as usize
4082 } else {
4083 0
4084 }
4085 };
4086 let (cx, cy) = (ctx(0), ctx(1));
4087 let mvx = parse_mvd_cabac(cab, 0, cx);
4088 let mvy = parse_mvd_cabac(cab, 1, cy);
4089 for &zb in zblocks {
4090 mvdc[CACHE30[zb]] = [mvx, mvy];
4091 refc[CACHE30[zb]] = ref_idx;
4092 mmvd[G_SCAN4[zb]] = [mvx, mvy];
4093 mref[G_SCAN4[zb]] = ref_idx;
4094 }
4095 (mvx as i32, mvy as i32)
4096}
4097
4098fn parse_ref_idx_cabac(cab: &mut crate::cabac::Cabac, ctx0: usize) -> i8 {
4101 const B: usize = 54;
4102 let mut r = 0i8;
4103 let mut bin_idx = 0u32;
4104 while bin_idx < 32 {
4108 let ctx = match bin_idx {
4109 0 => ctx0,
4110 1 => 4,
4111 _ => 5,
4112 };
4113 if cab.decode_decision(B + ctx) == 0 {
4114 break;
4115 }
4116 r += 1;
4117 bin_idx += 1;
4118 }
4119 r
4120}
4121
4122fn decode_ueg_mv(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
4125 const P2C: [usize; 8] = [0, 1, 2, 3, 3, 3, 3, 3];
4126 if cab.decode_decision(base) == 0 {
4127 return 0;
4128 }
4129 let mut code = 0u32;
4130 let mut count = 1usize;
4131 let mut tmp;
4132 loop {
4133 tmp = cab.decode_decision(base + P2C[count]);
4134 code += 1;
4135 count += 1;
4136 if tmp == 0 || count == 8 {
4137 break;
4138 }
4139 }
4140 if tmp != 0 {
4141 code += cabac_exp_bypass(cab, 3) + 1;
4142 }
4143 code
4144}
4145
4146fn parse_mvd_cabac(cab: &mut crate::cabac::Cabac, comp: usize, ctx_inc: usize) -> i16 {
4149 let base = 40 + comp * 7; if cab.decode_decision(base + ctx_inc) == 0 {
4151 return 0;
4152 }
4153 let mag = (decode_ueg_mv(cab, base + 3) + 1) as i16;
4154 if cab.decode_bypass() != 0 {
4155 -mag
4156 } else {
4157 mag
4158 }
4159}
4160
4161fn parse_mb_skip_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> bool {
4164 cab.decode_decision(ctx_inc) != 0
4165}
4166
4167fn parse_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4170 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4171 const S: usize = 11; if cab.decode_decision(S + 3) == 0 {
4173 return if cab.decode_decision(S + 4) != 0 {
4175 if cab.decode_decision(S + 6) != 0 { 1 } else { 2 }
4176 } else if cab.decode_decision(S + 5) != 0 {
4177 3
4178 } else {
4179 0
4180 };
4181 }
4182 if cab.decode_decision(S + 6) == 0 {
4184 return 5; }
4186 if cab.decode_terminate() {
4187 return 30; }
4189 let mut t = 6 + cab.decode_decision(S + 7) * 12;
4190 if cab.decode_decision(S + 8) != 0 {
4191 t += 4;
4192 if cab.decode_decision(S + 8) != 0 {
4193 t += 4;
4194 }
4195 }
4196 t += cab.decode_decision(S + 9) << 1;
4197 t += cab.decode_decision(S + 9);
4198 t
4199}
4200
4201fn parse_mb_type_i_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4206 const O: usize = 3; if cab.decode_decision(O + ctx_inc) == 0 {
4208 return 0; }
4210 if cab.decode_terminate() {
4211 return 25; }
4213 let mut t = 1 + cab.decode_decision(O + 3) * 12; if cab.decode_decision(O + 4) != 0 {
4215 t += 4; if cab.decode_decision(O + 5) != 0 {
4217 t += 4;
4218 }
4219 }
4220 t += cab.decode_decision(O + 6) << 1; t += cab.decode_decision(O + 7);
4222 t
4223}
4224
4225fn parse_intra4x4_pred_mode_cabac(cab: &mut crate::cabac::Cabac) -> i32 {
4229 const IPR: usize = 68;
4230 if cab.decode_decision(IPR) == 1 {
4231 return -1; }
4233 let mut m = cab.decode_decision(IPR + 1) as i32;
4234 m |= (cab.decode_decision(IPR + 1) as i32) << 1;
4235 m |= (cab.decode_decision(IPR + 1) as i32) << 2;
4236 m
4237}
4238
4239fn parse_intra_chroma_pred_mode_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4243 const CIPR: usize = 64;
4244 if cab.decode_decision(CIPR + ctx_inc) == 0 {
4245 return 0;
4246 }
4247 if cab.decode_decision(CIPR + 3) == 0 {
4248 return 1;
4249 }
4250 if cab.decode_decision(CIPR + 3) == 0 {
4251 return 2;
4252 }
4253 3
4254}
4255
4256fn parse_cbp_cabac(cab: &mut crate::cabac::Cabac, top: Option<u8>, left: Option<u8>) -> u32 {
4261 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4262 const CBP: usize = 73;
4263 let t = |m: u32| top.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
4264 let l = |m: u32| left.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
4265 let nb = |x: u32| (x == 0) as u32; let b0 = cab.decode_decision(CBP + (l(1 << 1) + (t(1 << 2) << 1)) as usize);
4268 let b1 = cab.decode_decision(CBP + (nb(b0) + (t(1 << 3) << 1)) as usize);
4269 let b2 = cab.decode_decision(CBP + (l(1 << 3) + (nb(b0) << 1)) as usize);
4270 let b3 = cab.decode_decision(CBP + (nb(b2) + (nb(b1) << 1)) as usize);
4271 let mut cbp = b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
4272 let ct = top.map_or(0u32, |c| ((c >> 4) != 0) as u32);
4274 let cl = left.map_or(0u32, |c| ((c >> 4) != 0) as u32);
4275 if cab.decode_decision(CBP + 4 + (cl + (ct << 1)) as usize) != 0 {
4276 let ct2 = top.map_or(0u32, |c| ((c >> 4) == 2) as u32);
4277 let cl2 = left.map_or(0u32, |c| ((c >> 4) == 2) as u32);
4278 let c1 = cab.decode_decision(CBP + 8 + (cl2 + (ct2 << 1)) as usize);
4279 cbp |= 1 << (4 + c1);
4280 }
4281 cbp
4282}
4283
4284fn read_ref_idx(r: &mut BitReader, num_ref_active: usize) -> Result<i32, OutOfData> {
4285 if num_ref_active == 2 {
4286 Ok(if r.read_bit()? { 0 } else { 1 }) } else {
4288 Ok(r.read_ue()? as i32)
4289 }
4290}
4291
4292#[derive(Clone, Copy, PartialEq)]
4294enum BPred {
4295 L0,
4296 L1,
4297 Bi,
4298}
4299impl BPred {
4300 fn uses(self, list: usize) -> bool {
4302 matches!(
4303 (self, list),
4304 (BPred::L0, 0) | (BPred::L1, 1) | (BPred::Bi, 0) | (BPred::Bi, 1)
4305 )
4306 }
4307}
4308
4309const B16X16: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 16)];
4310const B16X8: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 8), (0, 8, 16, 8)];
4311const B8X16: &[(usize, usize, usize, usize)] = &[(0, 0, 8, 16), (8, 0, 8, 16)];
4312
4313type Region = (usize, usize, usize, usize);
4315
4316pub fn b_inter_shape(mb_type: u32) -> (u8, u8, u8) {
4322 let (_, mvmode, preds) = b_inter_layout(mb_type);
4323 let code = |p: BPred| match (p.uses(0), p.uses(1)) {
4324 (true, true) => 3,
4325 (true, false) => 1,
4326 _ => 2,
4327 };
4328 (mvmode, code(preds[0]), code(preds[1]))
4329}
4330
4331fn b_inter_layout(mb_type: u32) -> (&'static [Region], u8, [BPred; 2]) {
4332 use BPred::*;
4333 match mb_type {
4334 1 => (B16X16, 0, [L0, L0]),
4335 2 => (B16X16, 0, [L1, L1]),
4336 3 => (B16X16, 0, [Bi, Bi]),
4337 4 => (B16X8, 1, [L0, L0]),
4338 5 => (B8X16, 2, [L0, L0]),
4339 6 => (B16X8, 1, [L1, L1]),
4340 7 => (B8X16, 2, [L1, L1]),
4341 8 => (B16X8, 1, [L0, L1]),
4342 9 => (B8X16, 2, [L0, L1]),
4343 10 => (B16X8, 1, [L1, L0]),
4344 11 => (B8X16, 2, [L1, L0]),
4345 12 => (B16X8, 1, [L0, Bi]),
4346 13 => (B8X16, 2, [L0, Bi]),
4347 14 => (B16X8, 1, [L1, Bi]),
4348 15 => (B8X16, 2, [L1, Bi]),
4349 16 => (B16X8, 1, [Bi, L0]),
4350 17 => (B8X16, 2, [Bi, L0]),
4351 18 => (B16X8, 1, [Bi, L1]),
4352 19 => (B8X16, 2, [Bi, L1]),
4353 20 => (B16X8, 1, [Bi, Bi]),
4354 _ => (B8X16, 2, [Bi, Bi]), }
4356}
4357
4358fn b_sub_uses(st: u32, list: usize) -> bool {
4360 let pred = match st {
4361 1 | 4 | 5 | 10 => 0, 2 | 6 | 7 | 11 => 1, _ => 2, };
4365 (list == 0 && pred != 1) || (list == 1 && pred != 0)
4366}
4367
4368fn b_sub_parts(st: u32) -> &'static [(usize, usize, usize, usize)] {
4370 match st {
4371 1..=3 => &[(0, 0, 8, 8)],
4372 4 | 6 | 8 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
4373 5 | 7 | 9 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
4374 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)], }
4376}
4377
4378fn sub_mb_partitions(sub_type: u32) -> &'static [(usize, usize, usize, usize)] {
4381 match sub_type {
4382 0 => &[(0, 0, 8, 8)],
4383 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
4384 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
4385 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
4386 }
4387}
4388
4389#[inline]
4399fn restride(dst: &mut [u8], dst_stride: usize, x0: usize, y0: usize, src: &[u8], w: usize, h: usize) {
4400 macro_rules! rows {
4401 ($n:expr) => {{
4402 for dy in 0..h {
4403 dst[(y0 + dy) * dst_stride + x0..][..$n].copy_from_slice(&src[dy * $n..][..$n]);
4404 }
4405 }};
4406 }
4407 match w {
4408 16 => rows!(16),
4409 8 => rows!(8),
4410 4 => rows!(4),
4411 2 => rows!(2),
4412 _ => {
4413 for dy in 0..h {
4414 dst[(y0 + dy) * dst_stride + x0..][..w].copy_from_slice(&src[dy * w..][..w]);
4415 }
4416 }
4417 }
4418}
4419
4420fn store(plane: &mut [u8], stride: usize, x0: usize, y0: usize, s: &[u8; 16]) {
4421 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Scatter);
4422 for dy in 0..4 {
4423 for dx in 0..4 {
4424 plane[(y0 + dy) * stride + (x0 + dx)] = s[dy * 4 + dx];
4425 }
4426 }
4427}
4428
4429fn un_scan_8x8(scan: &[i32; 64]) -> [i32; 64] {
4431 const ZZ8: [usize; 64] = [
4432 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,
4433 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
4434 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
4435 ];
4436 let mut out = [0i32; 64];
4437 for k in 0..64 {
4438 out[ZZ8[k]] = scan[k];
4439 }
4440 out
4441}
4442
4443#[cfg(test)]
4444mod tests {
4445 use super::*;
4446
4447 fn fd(qp: u8, offset: i32) -> FrameDecoder {
4448 FrameDecoder::new(1, 1, qp, offset, Vec::new(), 1, false, false, true)
4449 }
4450
4451 #[test]
4452 fn mb_qp_delta_accumulates_mod_52() {
4453 let mut d = fd(26, 0);
4454 assert_eq!(d.cur_qp, 26, "QPy starts at the slice QP");
4455 d.step_qp(4);
4456 assert_eq!(d.cur_qp, 30); d.step_qp(-10);
4458 assert_eq!(d.cur_qp, 20); d.step_qp(40);
4461 assert_eq!(d.cur_qp, 8);
4462 d.step_qp(-20);
4464 assert_eq!(d.cur_qp, 40);
4465 }
4466
4467 #[test]
4468 fn chroma_qp_index_offset_applied_and_clamped() {
4469 assert_eq!(fd(0, 0).chroma_qp_for(30), 29);
4471 assert_eq!(fd(0, 2).chroma_qp_for(30), 31);
4473 assert_eq!(fd(0, -12).chroma_qp_for(5), chroma_qp(0));
4475 assert_eq!(fd(0, 99).chroma_qp_for(40), chroma_qp(51));
4476 }
4477}