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, ref_poc, w4) = if self.b_possible {
480 (
481 self.mv_y.clone(),
482 self.ref_idx_y.clone(),
483 self.ref_idx_y
486 .iter()
487 .map(|&r| {
488 if r >= 0 {
489 self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc)
490 } else {
491 i32::MIN
492 }
493 })
494 .collect(),
495 self.mb_w * 4,
496 )
497 } else {
498 (Vec::new(), Vec::new(), Vec::new(), 0)
499 };
500 crate::RefFrame {
501 py: rusty_h264_common::inter::pad_plane(&self.rec_y, self.cw, self.ch, crate::LPAD),
504 pu: rusty_h264_common::inter::pad_plane(&self.rec_u, self.ccw, self.ch / 2, crate::CPAD),
505 pv: rusty_h264_common::inter::pad_plane(&self.rec_v, self.ccw, self.ch / 2, crate::CPAD),
506 cw: self.cw,
507 ch: self.ch,
508 frame_num: 0, poc: 0, mv,
511 ref_idx,
512 ref_poc,
513 w4,
514 long_term: false,
515 long_term_idx: 0,
516 }
517 }
518
519 fn nnz_cache_load(&mut self, mb_x: usize, mb_y: usize) {
520 let w4 = self.mb_w * 4;
521 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
522 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
523 for lbx in 0..4 {
524 self.nnz_l_cache[1 + lbx] =
525 if top_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 - 1) * w4 + (mb_x * 4 + lbx)] };
526 }
527 for lby in 0..4 {
528 self.nnz_l_cache[(lby + 1) * 5] =
529 if left_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 - 1)] };
530 }
531 }
532 #[inline]
533 fn nc_pred(&self, lbx: usize, lby: usize) -> i32 {
534 let left = self.nnz_l_cache[(lby + 1) * 5 + lbx] as i32;
535 let top = self.nnz_l_cache[lby * 5 + (lbx + 1)] as i32;
536 let r = left + top;
537 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
538 }
539 #[inline]
540 fn nnz_cache_set(&mut self, lbx: usize, lby: usize, total: u8) {
541 self.nnz_l_cache[(lby + 1) * 5 + (lbx + 1)] = total;
542 }
543 fn chroma_cache_load(&mut self, mb_x: usize, mb_y: usize) {
544 let w2 = self.mb_w * 2;
545 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
546 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
547 for c in 0..2 {
548 for bx in 0..2 {
549 self.nnz_c_cache[c][1 + bx] =
550 if top_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 - 1) * w2 + (mb_x * 2 + bx)] };
551 }
552 for by in 0..2 {
553 self.nnz_c_cache[c][(by + 1) * 3] =
554 if left_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 - 1)] };
555 }
556 }
557 }
558 #[inline]
559 fn chroma_nc_pred(&self, c: usize, bx: usize, by: usize) -> i32 {
560 let left = self.nnz_c_cache[c][(by + 1) * 3 + bx] as i32;
561 let top = self.nnz_c_cache[c][by * 3 + (bx + 1)] as i32;
562 let r = left + top;
563 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
564 }
565 #[inline]
566 fn chroma_nnz_cache_set(&mut self, c: usize, bx: usize, by: usize, total: u8) {
567 self.nnz_c_cache[c][(by + 1) * 3 + (bx + 1)] = total;
568 }
569
570 #[allow(clippy::too_many_arguments)]
578 pub fn decode_slice_data_cabac(
579 &mut self,
580 rbsp: &[u8],
581 start_byte: usize,
582 slice_qp: u8,
583 cabac_init_idc: u32,
584 is_i: bool,
585 is_p: bool,
586 first_mb: usize,
587 ) -> Result<usize, MbError> {
588 let mut cab = crate::cabac::Cabac::new(rbsp, start_byte, slice_qp as i32, cabac_init_idc, is_i);
589 let (range, _offset) = cab.dbg_state();
590 let trace = std::env::var_os("RH_CABAC_TRACE").is_some();
591 debug_assert_eq!(range, 510, "CABAC init range must be 510");
592
593 const I16_CBP: [u32; 6] = [0, 16, 32, 15, 31, 47];
594 let mbw = self.mb_w;
595 let total = self.mb_w * self.mb_h;
596 let mut cat = vec![255u8; total]; let mut mb_cbp = vec![0u8; total];
599 let mut cmode = vec![-1i32; total]; let mut mb_nzc = vec![[0u8; 24]; total]; let mut cbf_dc = vec![0u16; total];
602 let mut mb_skip = vec![false; total];
603 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;
609 let mut addr = first_mb;
610
611 loop {
612 if addr >= total {
619 return Err(MbError::Truncated);
620 }
621 let (mbx, mby) = (addr % mbw, addr / mbw);
622 let left = (mbx > 0).then(|| addr - 1);
623 let top = (mby > 0).then(|| addr - mbw);
624
625 let mb_type;
628 if is_p {
629 let sctx = 11
630 + left.map_or(0, |a| (!mb_skip[a]) as usize)
631 + top.map_or(0, |a| (!mb_skip[a]) as usize);
632 if parse_mb_skip_cabac(&mut cab, sctx) {
633 mb_skip[addr] = true;
634 cat[addr] = 100; last_delta_qp = 0; self.decode_p_skip(mbx, mby)?;
640 self.mb_qp[addr] = self.cur_qp; let eos = cab.decode_terminate();
642 addr += 1;
643 if eos || addr >= total {
644 break;
645 }
646 continue;
647 }
648 let mbt = parse_mb_type_p_cabac(&mut cab);
649 if mbt == 30 {
650 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
651 }
652 if mbt <= 3 {
653 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbP);
654 let mut mvdc = [[0i16; 2]; 30];
657 let mut refc = [-1i8; 30];
658 if let Some(l) = left {
659 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
660 refc[ci] = mb_ref[l][bi];
661 mvdc[ci] = mb_mvd[l][bi];
662 }
663 }
664 if let Some(t) = top {
665 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
666 refc[ci] = mb_ref[t][bi];
667 mvdc[ci] = mb_mvd[t][bi];
668 }
669 }
670 if mbx > 0 && mby > 0 {
671 let a = addr - mbw - 1;
672 (refc[0], mvdc[0]) = (mb_ref[a][15], mb_mvd[a][15]);
673 }
674 if mby > 0 && mbx + 1 < mbw {
675 let a = addr - mbw + 1;
676 (refc[5], mvdc[5]) = (mb_ref[a][12], mb_mvd[a][12]);
677 }
678 let mut mmvd = [[0i16; 2]; 16];
679 let mut mref = [0i8; 16];
680 macro_rules! refidx {
686 ($pi:expr, $zb:expr) => {{
687 if self.num_ref_active > 1 {
688 let s = CACHE30[$pi];
689 let c0 = (refc[s - 1] > 0) as usize + 2 * (refc[s - 6] > 0) as usize;
690 let r = parse_ref_idx_cabac(&mut cab, c0);
691 for &zb in $zb.iter() {
692 refc[CACHE30[zb]] = r;
693 }
694 r
695 } else {
696 0i8
697 }
698 }};
699 }
700 macro_rules! part {
701 ($pi:expr, $zb:expr, $pred:expr, $rx:expr, $ry:expr, $rw:expr, $rh:expr, $refi:expr) => {{
702 let (mvx, mvy) = parse_mvd_partition(&mut cab, $pi, $zb, &mut mvdc, &mut refc, &mut mmvd, &mut mref, $refi);
703 let [na, nb, nc] = self.mv_neighbors_block(
704 (mbx * 4 + $rx / 4) as isize,
705 (mby * 4 + $ry / 4) as isize,
706 ($rw / 4) as isize,
707 );
708 let pmv = $pred(na, nb, nc);
709 self.commit_inter_grid(mbx, mby, $rx, $ry, $rw, $rh, (pmv.0 + mvx, pmv.1 + mvy), $refi);
710 }};
711 }
712 match mbt {
713 0 => {
714 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
715 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);
716 }
717 1 => {
718 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7]);
719 let r1 = refidx!(8, &[8, 9, 10, 11, 12, 13, 14, 15]);
720 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);
721 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);
722 }
723 2 => {
724 let r0 = refidx!(0, &[0, 1, 2, 3, 8, 9, 10, 11]);
725 let r1 = refidx!(4, &[4, 5, 6, 7, 12, 13, 14, 15]);
726 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);
727 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);
728 }
729 _ => {
730 let mut subt = [0u32; 4];
732 for st in &mut subt {
733 *st = parse_sub_mb_type_p_cabac(&mut cab);
734 }
735 let mut pr = [0i8; 4];
736 for (i, r) in pr.iter_mut().enumerate() {
737 let b = i * 4;
738 *r = refidx!(b, &[b, b + 1, b + 2, b + 3]);
739 }
740 for i in 0..4usize {
741 let b = i * 4;
742 let (ox, oy) = ((i % 2) * 8, (i / 2) * 8); let ri = pr[i];
744 match subt[i] {
745 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),
746 1 => {
747 part!(b, &[b, b + 1], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 8, 4, ri);
748 part!(b + 2, &[b + 2, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy + 4, 8, 4, ri);
749 }
750 2 => {
751 part!(b, &[b, b + 2], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 4, 8, ri);
752 part!(b + 1, &[b + 1, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox + 4, oy, 4, 8, ri);
753 }
754 _ => {
755 for j in 0..4usize {
756 let (sx, sy) = ((j % 2) * 4, (j / 2) * 4);
757 part!(b + j, &[b + j], |a, b, c| predict_mv(a, b, c, ri as i32), ox + sx, oy + sy, 4, 4, ri);
758 }
759 }
760 }
761 }
762 }
763 }
764 mb_ref[addr] = mref;
765 mb_mvd[addr] = mmvd;
766 cat[addr] = 100;
767
768 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
770 mb_cbp[addr] = cbp as u8;
771 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
772 let mut nzc = [0xffu8; 48];
773 if let Some(t) = top {
774 let tnz = mb_nzc[t];
775 nzc[1..5].copy_from_slice(&tnz[12..16]);
776 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
777 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
778 }
779 if let Some(l) = left {
780 let lnz = mb_nzc[l];
781 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
782 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
783 }
784 let mut cbfdc = 0u16;
785 let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
790 last_delta_qp = 0;
791 }
792 if cbp != 0 {
793 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
794 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
795 self.step_qp(qpd);
796 for id8 in 0..4usize {
797 if cbp_luma & (1 << id8) != 0 {
798 for id4 in 0..4usize {
799 let iz = id8 * 4 + id4;
800 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
801 }
802 } else {
803 for k in 0..4 {
804 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
805 }
806 }
807 }
808 if cbp_chroma >= 1 {
809 for i in 0..2usize {
810 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
811 }
812 }
813 if cbp_chroma == 2 {
814 for i in 0..2usize {
815 for id4 in 0..4usize {
816 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
817 }
818 }
819 }
820 }
821 self.mb_qp[addr] = self.cur_qp;
822 cbf_dc[addr] = cbfdc;
823 let mut mn = [0u8; 24];
824 for k in 0..4 {
825 mn[k] = nzc[9 + k];
826 mn[4 + k] = nzc[17 + k];
827 mn[8 + k] = nzc[25 + k];
828 mn[12 + k] = nzc[33 + k];
829 }
830 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
831 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
832 for v in mn.iter_mut() {
836 if *v == 0xff {
837 *v = 0;
838 }
839 }
840 mb_nzc[addr] = mn;
841
842 if self.refs.is_empty() {
847 return Err(MbError::Unsupported("inter without reference"));
848 }
849 let qp = self.cur_qp;
850 let qpc = self.chroma_qp_for(qp);
851 let (w4r, w2r) = (mbw * 4, mbw * 2);
852 let mut pred_y = [0u8; 256];
853 let mut c_pred = [[0u8; 64]; 2];
854 {
855 let (rh16, cch) = (self.mb_h * 16, self.mb_h * 8);
863 let mut gmv = [(0i32, 0i32); 16];
864 let mut gref = [0usize; 16];
865 for by in 0..4usize {
866 for bx in 0..4usize {
867 let bidx = (mby * 4 + by) * w4r + (mbx * 4 + bx);
868 gmv[by * 4 + bx] = self.mv_y[bidx];
869 gref[by * 4 + bx] =
872 (self.ref_idx_y[bidx].max(0) as usize).min(self.refs.len() - 1);
873 }
874 }
875 let rect_eq = |x4: usize, y4: usize, w4: usize, h4: usize| -> bool {
877 let t = y4 * 4 + x4;
878 (0..h4).all(|dy| {
879 (0..w4).all(|dx| {
880 let b = (y4 + dy) * 4 + (x4 + dx);
881 gmv[b] == gmv[t] && gref[b] == gref[t]
882 })
883 })
884 };
885 let refs = &self.refs;
886 let (cw, ccw) = (self.cw, self.ccw);
887 let mut mc_rect = |x4: usize,
888 y4: usize,
889 w4: usize,
890 h4: usize,
891 pred_y: &mut [u8; 256],
892 c_pred: &mut [[u8; 64]; 2]| {
893 let b = y4 * 4 + x4;
894 let (mv, reference) = (gmv[b], &refs[gref[b]]);
895 let (w, h) = (w4 * 4, h4 * 4);
896 let mut t = [0u8; 256];
897 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]);
898 for dy in 0..h {
899 pred_y[(y4 * 4 + dy) * 16 + x4 * 4..][..w]
900 .copy_from_slice(&t[dy * w..dy * w + w]);
901 }
902 let (cw4, ch4) = (w4 * 2, h4 * 2);
903 for cc in 0..2 {
904 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
905 let mut tc = [0u8; 64];
906 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]);
907 for dy in 0..ch4 {
908 c_pred[cc][(y4 * 2 + dy) * 8 + x4 * 2..][..cw4]
909 .copy_from_slice(&tc[dy * cw4..dy * cw4 + cw4]);
910 }
911 }
912 };
913 if rect_eq(0, 0, 4, 4) {
914 mc_rect(0, 0, 4, 4, &mut pred_y, &mut c_pred);
915 } else if rect_eq(0, 0, 4, 2) && rect_eq(0, 2, 4, 2) {
916 mc_rect(0, 0, 4, 2, &mut pred_y, &mut c_pred);
917 mc_rect(0, 2, 4, 2, &mut pred_y, &mut c_pred);
918 } else if rect_eq(0, 0, 2, 4) && rect_eq(2, 0, 2, 4) {
919 mc_rect(0, 0, 2, 4, &mut pred_y, &mut c_pred);
920 mc_rect(2, 0, 2, 4, &mut pred_y, &mut c_pred);
921 } else {
922 for q in 0..4usize {
923 let (qx, qy) = ((q % 2) * 2, (q / 2) * 2);
924 if rect_eq(qx, qy, 2, 2) {
925 mc_rect(qx, qy, 2, 2, &mut pred_y, &mut c_pred);
926 } else if rect_eq(qx, qy, 2, 1) && rect_eq(qx, qy + 1, 2, 1) {
927 mc_rect(qx, qy, 2, 1, &mut pred_y, &mut c_pred);
928 mc_rect(qx, qy + 1, 2, 1, &mut pred_y, &mut c_pred);
929 } else if rect_eq(qx, qy, 1, 2) && rect_eq(qx + 1, qy, 1, 2) {
930 mc_rect(qx, qy, 1, 2, &mut pred_y, &mut c_pred);
931 mc_rect(qx + 1, qy, 1, 2, &mut pred_y, &mut c_pred);
932 } else {
933 for j in 0..4usize {
934 mc_rect(qx + (j % 2), qy + (j / 2), 1, 1, &mut pred_y, &mut c_pred);
935 }
936 }
937 }
938 }
939 }
940 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, &cdc, &cac, cbp_chroma);
944
945 let eos = cab.decode_terminate();
946 addr += 1;
947 if eos || addr >= total {
948 break;
949 }
950 continue;
951 }
952 mb_type = mbt - 5; } else if self.is_b {
954 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbB);
955 let sctx = 24
957 + left.map_or(0, |a| (!mb_skip[a]) as usize)
958 + top.map_or(0, |a| (!mb_skip[a]) as usize);
959 if parse_mb_skip_cabac(&mut cab, sctx) {
960 mb_skip[addr] = true;
961 cat[addr] = 100;
962 mb_direct[addr] = true;
963 last_delta_qp = 0; self.decode_b_skip(mbx, mby)?;
967 self.mb_qp[addr] = self.cur_qp;
968 mb_ref[addr] = [0i8; 16];
971 mb_ref1[addr] = [0i8; 16];
972 let eos = cab.decode_terminate();
973 addr += 1;
974 if eos || addr >= total {
975 break;
976 }
977 continue;
978 }
979 let bci = left.map_or(0, |a| (!mb_direct[a]) as usize)
980 + top.map_or(0, |a| (!mb_direct[a]) as usize);
981 let bmt = parse_mb_type_b_cabac(&mut cab, bci);
982 if bmt < 23 {
983 let mut mvdc0 = [[0i16; 2]; 30];
986 let mut refc0 = [-1i8; 30];
987 let mut mvdc1 = [[0i16; 2]; 30];
988 let mut refc1 = [-1i8; 30];
989 macro_rules! fill {
991 ($mrf:expr, $mmv:expr, $rc:expr, $mc:expr) => {{
992 if let Some(l) = left {
993 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
994 $rc[ci] = $mrf[l][bi];
995 $mc[ci] = $mmv[l][bi];
996 }
997 }
998 if let Some(t) = top {
999 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
1000 $rc[ci] = $mrf[t][bi];
1001 $mc[ci] = $mmv[t][bi];
1002 }
1003 }
1004 if mbx > 0 && mby > 0 {
1005 let a = addr - mbw - 1;
1006 ($rc[0], $mc[0]) = ($mrf[a][15], $mmv[a][15]);
1007 }
1008 if mby > 0 && mbx + 1 < mbw {
1009 let a = addr - mbw + 1;
1010 ($rc[5], $mc[5]) = ($mrf[a][12], $mmv[a][12]);
1011 }
1012 }};
1013 }
1014 fill!(mb_ref, mb_mvd, refc0, mvdc0);
1015 fill!(mb_ref1, mb_mvd1, refc1, mvdc1);
1016 let mut mmvd0 = [[0i16; 2]; 16];
1017 let mut mref0 = [-1i8; 16];
1018 let mut mmvd1 = [[0i16; 2]; 16];
1019 let mut mref1 = [-1i8; 16];
1020 if self.refs.is_empty() || self.refs1.is_empty() {
1021 return Err(MbError::Unsupported("B without references"));
1022 }
1023 let mut pred_y = [0u8; 256];
1028 let mut c_pred = [[0u8; 64]; 2];
1029
1030 if bmt == 0 {
1031 mb_direct[addr] = true;
1034 (mref0, mref1) = ([0i8; 16], [0i8; 16]);
1035 self.decode_b_direct(mbx, mby, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
1036 } else if bmt == 22 {
1037 let mut subt = [0u32; 4];
1040 for s in &mut subt {
1041 *s = parse_sub_mb_type_b_cabac(&mut cab);
1042 }
1043 for i in 0..4usize {
1047 if subt[i] == 0 {
1048 let b = i * 4;
1049 for &zb in &[b, b + 1, b + 2, b + 3] {
1050 (mref0[G_SCAN4[zb]], mref1[G_SCAN4[zb]]) = (0, 0);
1051 (refc0[CACHE30[zb]], refc1[CACHE30[zb]]) = (0, 0);
1052 }
1053 }
1054 }
1055 for list in 0..2usize {
1056 let (mmv, mrf, mc, rc) = if list == 0 {
1057 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1058 } else {
1059 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1060 };
1061 for i in 0..4usize {
1062 let st = subt[i];
1063 if st == 0 || !b_sub_uses(st, list) {
1064 continue;
1065 }
1066 let b = i * 4;
1067 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1068 let mut zb = [0usize; 4];
1069 let mut n = 0;
1070 for ly in sy / 4..sy / 4 + sh / 4 {
1071 for lx in sx / 4..sx / 4 + sw / 4 {
1072 zb[n] = b + ly * 2 + lx;
1073 n += 1;
1074 }
1075 }
1076 parse_mvd_partition(&mut cab, zb[0], &zb[..n], mc, rc, mmv, mrf, 0);
1077 }
1078 }
1079 }
1080 for (p, &st) in subt.iter().enumerate() {
1083 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
1084 if st == 0 {
1085 self.decode_b_direct(mbx, mby, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
1086 continue;
1087 }
1088 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1089 let (px, py) = (b8x + sx, b8y + sy);
1090 let mut mv = [(0i32, 0i32); 2];
1091 for list in 0..2usize {
1092 if b_sub_uses(st, list) {
1093 let d = if list == 0 { mmvd0 } else { mmvd1 }[(py / 4) * 4 + px / 4];
1094 let n = self.mv_neighbors_list((mbx * 4 + px / 4) as isize, (mby * 4 + py / 4) as isize, (sw / 4) as isize, list);
1095 let pmv = predict_mv(n[0], n[1], n[2], 0);
1096 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1097 }
1098 }
1099 let refi0 = if b_sub_uses(st, 0) { 0 } else { -1 };
1100 let refi1 = if b_sub_uses(st, 1) { 0 } else { -1 };
1101 self.b_set_motion(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1]);
1102 self.b_mc(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1103 }
1104 }
1105 } else {
1106 let (layout, mvmode, preds) = b_inter_layout(bmt);
1107 let parts: &[(usize, &[usize])] = match mvmode {
1108 0 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])],
1109 1 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7]), (8, &[8, 9, 10, 11, 12, 13, 14, 15])],
1110 _ => &[(0, &[0, 1, 2, 3, 8, 9, 10, 11]), (4, &[4, 5, 6, 7, 12, 13, 14, 15])],
1111 };
1112 for list in 0..2usize {
1115 let (mmv, mrf, mc, rc) = if list == 0 {
1116 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1117 } else {
1118 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1119 };
1120 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1121 if preds[p].uses(list) {
1122 parse_mvd_partition(&mut cab, pidx, zb, mc, rc, mmv, mrf, 0);
1123 }
1124 }
1125 }
1126 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1128 let mut mv = [(0i32, 0i32); 2];
1129 for list in 0..2usize {
1130 if preds[p].uses(list) {
1131 let d = if list == 0 { mmvd0 } else { mmvd1 }[(ry / 4) * 4 + rx / 4];
1132 let n = self.mv_neighbors_list((mbx * 4 + rx / 4) as isize, (mby * 4 + ry / 4) as isize, (rw / 4) as isize, list);
1133 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], 0);
1134 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1135 }
1136 }
1137 let refi0 = if preds[p].uses(0) { 0 } else { -1 };
1138 let refi1 = if preds[p].uses(1) { 0 } else { -1 };
1139 self.b_set_motion(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1]);
1140 self.b_mc(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1144 }
1145 }
1146 mb_ref[addr] = mref0;
1147 mb_mvd[addr] = mmvd0;
1148 mb_ref1[addr] = mref1;
1149 mb_mvd1[addr] = mmvd1;
1150 cat[addr] = 100;
1151
1152 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1154 mb_cbp[addr] = cbp as u8;
1155 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1156 let mut nzc = [0xffu8; 48];
1157 if let Some(t) = top {
1158 let tnz = mb_nzc[t];
1159 nzc[1..5].copy_from_slice(&tnz[12..16]);
1160 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1161 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
1162 }
1163 if let Some(l) = left {
1164 let lnz = mb_nzc[l];
1165 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
1166 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
1167 }
1168 let mut cbfdc = 0u16;
1169 let mut luma_scan = [[0i32; 16]; 16];
1170 let mut cdc = [[0i32; 4]; 2];
1171 let mut cac = [[[0i32; 16]; 4]; 2];
1172 if cbp == 0 {
1173 last_delta_qp = 0;
1174 }
1175 if cbp != 0 {
1176 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1177 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1178 self.step_qp(qpd);
1179 for id8 in 0..4usize {
1180 if cbp_luma & (1 << id8) != 0 {
1181 for id4 in 0..4usize {
1182 let iz = id8 * 4 + id4;
1183 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
1184 }
1185 } else {
1186 for k in 0..4 {
1187 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1188 }
1189 }
1190 }
1191 if cbp_chroma >= 1 {
1192 for i in 0..2usize {
1193 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
1194 }
1195 }
1196 if cbp_chroma == 2 {
1197 for i in 0..2usize {
1198 for id4 in 0..4usize {
1199 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
1200 }
1201 }
1202 }
1203 }
1204 self.mb_qp[addr] = self.cur_qp;
1205 cbf_dc[addr] = cbfdc;
1206 let mut mn = [0u8; 24];
1207 for k in 0..4 {
1208 mn[k] = nzc[9 + k];
1209 mn[4 + k] = nzc[17 + k];
1210 mn[8 + k] = nzc[25 + k];
1211 mn[12 + k] = nzc[33 + k];
1212 }
1213 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1214 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1215 for v in mn.iter_mut() {
1219 if *v == 0xff {
1220 *v = 0;
1221 }
1222 }
1223 mb_nzc[addr] = mn;
1224 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, &cdc, &cac, cbp_chroma);
1225
1226 let eos = cab.decode_terminate();
1227 addr += 1;
1228 if eos || addr >= total {
1229 break;
1230 }
1231 continue;
1232 }
1233 mb_type = bmt - 23; if mb_type == 25 {
1235 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1236 }
1237 } else {
1238 let li = left.map_or(0, |a| (cat[a] >= 2) as usize);
1239 let ti = top.map_or(0, |a| (cat[a] >= 2) as usize);
1240 mb_type = parse_mb_type_i_cabac(&mut cab, li + ti);
1241 if mb_type == 25 {
1242 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1243 }
1244 }
1245 let cci = left.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize)
1247 + top.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize);
1248
1249 if mb_type != 0 {
1250 let mt = mb_type - 1;
1255 let pred_mode = I16Mode::from_id(mt % 4);
1256 let cbp_chroma = (mt % 12) / 4;
1257 let cbp_luma_15 = mt / 12 == 1;
1258 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1259 cmode[addr] = chroma_mode as i32;
1260 cat[addr] = 2;
1261 mb_cbp[addr] = ((cbp_chroma as u8) << 4) | if cbp_luma_15 { 15 } else { 0 };
1262 let w4 = self.mb_w * 4;
1263
1264 let mut nzc = [0xffu8; 48];
1265 if let Some(t) = top {
1266 let tn = mb_nzc[t];
1267 nzc[1..5].copy_from_slice(&tn[12..16]);
1268 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1269 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1270 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1271 }
1272 if let Some(l) = left {
1273 let ln = mb_nzc[l];
1274 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1275 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1276 }
1277
1278 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1279 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1280 self.step_qp(qpd);
1281 let qp = self.cur_qp;
1282 let mut cbfdc = 0u16;
1283
1284 let mut dc_scan = [0i32; 16];
1286 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 0, RP_I16_DC, true, ndc, &mut dc_scan);
1287 let recon_dc = self.dequant_luma_dc(&un_scan_4x4_dcac(&dc_scan), qp, 0);
1288
1289 let mut q_blocks = [[0i32; 16]; 16];
1291 for (iz, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1292 let total = if cbp_luma_15 {
1293 let mut ac = [0i32; 16];
1294 let t = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_I16_AC, true, ndc, &mut ac);
1295 un_scan_4x4_ac_into(&ac, &mut q_blocks[lby * 4 + lbx]);
1296 t as u8
1297 } else {
1298 nzc[NZC_CACHE[iz]] = 0;
1299 0
1300 };
1301 self.nnz_y[(mby * 4 + lby) * w4 + (mbx * 4 + lbx)] = total;
1302 }
1303
1304 let mut cdc = [[0i32; 4]; 2];
1305 let mut cac = [[[0i32; 16]; 4]; 2];
1306 if cbp_chroma >= 1 {
1307 for i in 0..2usize {
1308 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1309 }
1310 }
1311 if cbp_chroma == 2 {
1312 for i in 0..2usize {
1313 for id4 in 0..4usize {
1314 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1315 }
1316 }
1317 }
1318
1319 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1321 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1322 let (lx, ly) = (mbx * 16, mby * 16);
1323 let mut t16 = [0u8; 16];
1324 let mut l16 = [0u8; 16];
1325 if top_ok {
1326 t16.copy_from_slice(&self.rec_y[(ly - 1) * self.cw + lx..][..16]);
1327 }
1328 if left_ok {
1329 for i in 0..16 {
1330 l16[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
1331 }
1332 }
1333 let corner = if top_ok && left_ok { self.rec_y[(ly - 1) * self.cw + lx - 1] } else { 0 };
1334 let pred_l = luma16x16_pred(pred_mode, top_ok, left_ok, &t16, &l16, corner);
1335 for by in 0..4 {
1336 for bx in 0..4 {
1337 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
1338 deq[0] = recon_dc[by * 4 + bx];
1339 let predb: [i32; 16] = std::array::from_fn(|i| pred_l[(by * 4 + i / 4) * 16 + (bx * 4 + i % 4)] as i32);
1340 let s = reconstruct_4x4(&deq, &predb);
1341 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
1342 self.modes_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = 2;
1346 self.coded_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = true;
1347 }
1348 }
1349 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1350
1351 self.mb_qp[addr] = self.cur_qp;
1352 cbf_dc[addr] = cbfdc;
1353 let mut mn = [0u8; 24];
1354 for k in 0..4 {
1355 mn[k] = nzc[9 + k];
1356 mn[4 + k] = nzc[17 + k];
1357 mn[8 + k] = nzc[25 + k];
1358 mn[12 + k] = nzc[33 + k];
1359 }
1360 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1361 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1362 for v in mn.iter_mut() {
1363 if *v == 0xff {
1364 *v = 0;
1365 }
1366 }
1367 mb_nzc[addr] = mn;
1368
1369 let eos = cab.decode_terminate();
1370 addr += 1;
1371 if eos || addr >= total {
1372 break;
1373 }
1374 continue;
1375 }
1376 cat[addr] = 0;
1377 let w4 = self.mb_w * 4;
1378 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1382 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1383 let predicted = self.predict_i4_mode(bx, by);
1384 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1385 let actual = if rr < 0 {
1386 predicted
1387 } else {
1388 let rem = rr as u8;
1389 if rem < predicted { rem } else { rem + 1 }
1390 };
1391 self.modes_y[by * w4 + bx] = actual;
1392 modes[lby * 4 + lbx] = actual;
1393 }
1394 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1395 cmode[addr] = chroma_mode as i32;
1396 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1397 mb_cbp[addr] = cbp as u8;
1398 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1399
1400 let mut nzc = [0xffu8; 48];
1402 if let Some(t) = top {
1403 let tn = mb_nzc[t];
1404 nzc[1..5].copy_from_slice(&tn[12..16]);
1405 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1406 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1407 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1408 }
1409 if let Some(l) = left {
1410 let ln = mb_nzc[l];
1411 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1412 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1413 }
1414
1415 let mut cbfdc = 0u16;
1418 let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
1422 last_delta_qp = 0;
1423 }
1424 if cbp != 0 {
1425 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1426 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1427 self.step_qp(qpd);
1428 for id8 in 0..4usize {
1429 if cbp_luma & (1 << id8) != 0 {
1430 for id4 in 0..4usize {
1431 let iz = id8 * 4 + id4;
1432 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, true, ndc, &mut luma_scan[iz]);
1433 }
1434 } else {
1435 for k in 0..4 {
1436 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1437 }
1438 }
1439 }
1440 if cbp_chroma >= 1 {
1441 for i in 0..2usize {
1442 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1443 }
1444 }
1445 if cbp_chroma == 2 {
1446 for i in 0..2usize {
1447 for id4 in 0..4usize {
1448 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1449 }
1450 }
1451 }
1452 }
1453 self.mb_qp[addr] = self.cur_qp;
1454 cbf_dc[addr] = cbfdc;
1455 let mut mn = [0u8; 24];
1457 for k in 0..4 {
1458 mn[k] = nzc[9 + k];
1459 mn[4 + k] = nzc[17 + k];
1460 mn[8 + k] = nzc[25 + k];
1461 mn[12 + k] = nzc[33 + k];
1462 }
1463 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1464 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1465 for v in mn.iter_mut() {
1466 if *v == 0xff {
1467 *v = 0;
1468 }
1469 }
1470 mb_nzc[addr] = mn;
1471
1472 let qp = self.cur_qp;
1474 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1475 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1476 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1477 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1478 let (px, py) = (bx * 4, by * 4);
1479 let at = lby > 0 || top_ok;
1480 let al = lbx > 0 || left_ok;
1481 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1482 self.nnz_y[by * w4 + bx] = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1483 let (t, l, corner) = self.gather_i4(px, py, at, al, bx, by);
1484 let pred = intra4x4_pred(modes[lby * 4 + lbx], at, al, &t, &l, corner);
1485 let predb = std::array::from_fn(|i| pred[i] as i32);
1486 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
1487 store(&mut self.rec_y, self.cw, px, py, &s);
1488 self.coded_y[by * w4 + bx] = true;
1489 }
1490 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1491
1492 let eos = cab.decode_terminate();
1494 addr += 1;
1495 if eos || addr >= total {
1496 break;
1497 }
1498 }
1499 if trace {
1500 eprintln!("# CABAC decoded {} MBs (of {total})", addr - first_mb);
1501 }
1502 Ok(addr)
1503 }
1504
1505 #[allow(clippy::too_many_arguments)]
1509 #[allow(clippy::too_many_arguments)]
1515 fn add_inter_residual(
1516 &mut self,
1517 mb_x: usize,
1518 mb_y: usize,
1519 pred_y: &[u8; 256],
1520 c_pred: &[[u8; 64]; 2],
1521 luma_scan: &[[i32; 16]; 16],
1522 cdc: &[[i32; 4]; 2],
1523 cac: &[[[i32; 16]; 4]; 2],
1524 cbp_chroma: u32,
1525 ) {
1526 let qp = self.cur_qp;
1527 let qpc = self.chroma_qp_for(qp);
1528 let (w4r, w2r) = (self.mb_w * 4, self.mb_w * 2);
1529 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1530 let nnz = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1531 self.nnz_y[(mb_y * 4 + lby) * w4r + (mb_x * 4 + lbx)] = nnz;
1532 if nnz == 0 {
1533 let mut s = [0u8; 16];
1538 for r in 0..4 {
1539 s[r * 4..r * 4 + 4]
1540 .copy_from_slice(&pred_y[(lby * 4 + r) * 16 + lbx * 4..][..4]);
1541 }
1542 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1543 continue;
1544 }
1545 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1546 let deq = self.dequant(&qb, qp, 3);
1547 let predb: [i32; 16] = std::array::from_fn(|i| pred_y[(lby * 4 + i / 4) * 16 + (lbx * 4 + i % 4)] as i32);
1548 let s = reconstruct_4x4(&deq, &predb);
1549 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1550 }
1551 let mut c_dc = [[0i32; 4]; 2];
1552 if cbp_chroma != 0 {
1553 for c in 0..2 {
1554 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 4 + c);
1555 }
1556 }
1557 for c in 0..2 {
1558 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1559 let mut ac_nz = false;
1560 let mut ac = [0i32; 16];
1561 if cbp_chroma == 2 {
1562 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1563 let n = cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1564 self.nnz_c[c][(mb_y * 2 + by) * w2r + (mb_x * 2 + bx)] = n;
1565 ac_nz = n != 0;
1566 }
1567 let dc = c_dc[c][by * 2 + bx];
1568 if dc == 0 && !ac_nz {
1569 let mut s = [0u8; 16];
1571 for r in 0..4 {
1572 s[r * 4..r * 4 + 4]
1573 .copy_from_slice(&c_pred[c][(by * 4 + r) * 8 + bx * 4..][..4]);
1574 }
1575 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1576 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1577 continue;
1578 }
1579 let mut deq = self.dequant(&ac, qpc, 4 + c);
1580 deq[0] = dc;
1581 let predb: [i32; 16] =
1582 std::array::from_fn(|i| c_pred[c][(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1583 let s = reconstruct_4x4(&deq, &predb);
1584 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1585 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1586 }
1587 }
1588 }
1589
1590 fn recon_chroma_cabac(
1591 &mut self,
1592 mb_x: usize,
1593 mb_y: usize,
1594 chroma_mode: u8,
1595 cdc: &[[i32; 4]; 2],
1596 cac: &[[[i32; 16]; 4]; 2],
1597 cbp_chroma: u32,
1598 avail_top: bool,
1599 avail_left: bool,
1600 ) {
1601 let qpc = self.chroma_qp_for(self.cur_qp);
1602 let (cx, cy) = (mb_x * 8, mb_y * 8);
1603 let mut c_dc = [[0i32; 4]; 2];
1604 if cbp_chroma != 0 {
1605 for c in 0..2 {
1606 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 1 + c);
1607 }
1608 }
1609 let w2 = self.mb_w * 2;
1610 for c in 0..2 {
1611 let mut ctop = [0u8; 8];
1612 let mut cleft = [0u8; 8];
1613 let mut ccorner = 0u8;
1614 {
1615 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
1616 if avail_top {
1617 ctop.copy_from_slice(&rec_c[(cy - 1) * self.ccw + cx..][..8]);
1618 }
1619 if avail_left {
1620 for i in 0..8 {
1621 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
1622 }
1623 }
1624 if avail_top && avail_left {
1625 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
1626 }
1627 }
1628 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
1629 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1630 let mut ac = [0i32; 16];
1631 if cbp_chroma == 2 {
1632 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1633 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] =
1634 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1635 }
1636 let mut deq = self.dequant(&ac, qpc, 1 + c);
1637 deq[0] = c_dc[c][by * 2 + bx];
1638 let predb: [i32; 16] =
1639 std::array::from_fn(|i| pred8[(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1640 let s = reconstruct_4x4(&deq, &predb);
1641 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1642 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
1643 }
1644 }
1645 }
1646
1647 pub fn decode_slice_data(
1648 &mut self,
1649 r: &mut BitReader,
1650 is_p: bool,
1651 first_mb: usize,
1652 ) -> Result<usize, MbError> {
1653 let total = self.mb_w * self.mb_h;
1654 self.slice_first_mb = first_mb;
1655 let mut addr = first_mb;
1656 while addr < total {
1657 if is_p || self.is_b {
1658 let skip_run = {
1659 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1660 r.read_ue()?
1661 } as usize;
1662 for _ in 0..skip_run {
1663 if addr >= total {
1664 break;
1665 }
1666 if self.is_b {
1667 self.decode_b_skip(addr % self.mb_w, addr / self.mb_w)?;
1668 } else {
1669 self.decode_p_skip(addr % self.mb_w, addr / self.mb_w)?;
1670 }
1671 self.mb_qp[addr] = self.cur_qp; addr += 1;
1673 }
1674 if addr >= total {
1675 break;
1676 }
1677 if skip_run > 0 && !r.more_rbsp_data() {
1679 break;
1680 }
1681 }
1682 if self.is_b {
1683 self.decode_b_mb(r, addr % self.mb_w, addr / self.mb_w)?;
1684 } else {
1685 self.decode_mb(r, addr % self.mb_w, addr / self.mb_w, is_p)?;
1686 }
1687 self.mb_qp[addr] = self.cur_qp;
1688 addr += 1;
1689 if !r.more_rbsp_data() {
1691 break;
1692 }
1693 }
1694 Ok(addr)
1695 }
1696
1697 fn decode_mb(
1698 &mut self,
1699 r: &mut BitReader,
1700 mb_x: usize,
1701 mb_y: usize,
1702 is_p: bool,
1703 ) -> Result<(), MbError> {
1704 let mut mb_type = {
1705 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1706 r.read_ue()?
1707 };
1708 if is_p {
1709 if mb_type <= 2 {
1712 return self.decode_inter(r, mb_x, mb_y, mb_type as u8);
1713 }
1714 if mb_type == 3 || mb_type == 4 {
1715 return self.decode_p8x8(r, mb_x, mb_y, mb_type == 4);
1716 }
1717 mb_type -= 5;
1718 }
1719 self.decode_intra_mb(r, mb_x, mb_y, mb_type)
1720 }
1721
1722 fn decode_intra_mb(
1725 &mut self,
1726 r: &mut BitReader,
1727 mb_x: usize,
1728 mb_y: usize,
1729 mb_type: u32,
1730 ) -> Result<(), MbError> {
1731 if mb_type == 0 {
1732 if self.transform_8x8_mode && r.read_bit()? {
1734 self.decode_i8x8(r, mb_x, mb_y)?;
1735 } else {
1736 self.decode_i4x4(r, mb_x, mb_y)?;
1737 }
1738 } else if (1..=24).contains(&mb_type) {
1739 self.decode_i16(r, mb_x, mb_y, mb_type - 1)?;
1740 } else if mb_type == 25 {
1741 self.decode_ipcm(r, mb_x, mb_y)?;
1742 } else {
1743 return Err(MbError::Unsupported("only I_4x4 / I_16x16 / I_PCM macroblocks"));
1744 }
1745 let w4 = self.mb_w * 4;
1747 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1748 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
1749 }
1750 Ok(())
1751 }
1752
1753 fn decode_inter(
1757 &mut self,
1758 r: &mut BitReader,
1759 mb_x: usize,
1760 mb_y: usize,
1761 mode: u8,
1762 ) -> Result<(), MbError> {
1763 if self.refs.is_empty() {
1764 return Err(MbError::Unsupported("inter without reference"));
1765 }
1766 let w4 = self.mb_w * 4;
1768 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
1769 let num_refs = self.refs.len();
1770 let layout = inter_partitions(mode);
1771
1772 let nparts = layout.len();
1775 let mut ref_idxs = [0i32; 4];
1776 if self.num_ref_active > 1 {
1777 for ri in ref_idxs[..nparts].iter_mut() {
1778 *ri = read_ref_idx(r, self.num_ref_active)?;
1779 if *ri as usize >= num_refs {
1780 return Err(MbError::Truncated); }
1782 }
1783 }
1784
1785 let mut part_mv = [(0i32, (0i32, 0i32)); 4];
1788 {
1789 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::MvGrid);
1790 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1791 let refi = ref_idxs[part];
1792 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
1793 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (rw / 4) as isize);
1794 let pmv = predict_partition_mv(mode, part, a, b, c, refi);
1795 let mvd_x = r.read_se()?;
1796 let mvd_y = r.read_se()?;
1797 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
1798 part_mv[part] = (refi, mv);
1799 for by in ry / 4..ry / 4 + rh / 4 {
1800 for bx in rx / 4..rx / 4 + rw / 4 {
1801 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
1802 self.mv_y[idx] = mv;
1803 self.inter_y[idx] = true;
1804 self.ref_idx_y[idx] = refi;
1805 self.coded_y[idx] = true;
1806 }
1807 }
1808 }
1809 }
1810
1811 let mut pred_y = [0u8; 256];
1813 let mut c_pred = [[0u8; 64]; 2];
1814 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1815 let (refi, mv) = part_mv[part];
1816 let reference = &self.refs[refi as usize];
1817 let mut tmp = [0u8; 256];
1818 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);
1819 {
1820 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
1821 for dy in 0..rh {
1822 for dx in 0..rw {
1823 pred_y[(ry + dy) * 16 + (rx + dx)] = tmp[dy * rw + dx];
1824 }
1825 }
1826 }
1827 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
1828 for cc in 0..2 {
1829 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
1830 let mut tc = [0u8; 64];
1831 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);
1832 {
1833 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
1834 for dy in 0..crh {
1835 for dx in 0..crw {
1836 c_pred[cc][(cry + dy) * 8 + (crx + dx)] = tc[dy * crw + dx];
1837 }
1838 }
1839 }
1840 }
1841 self.weight_partition(&mut pred_y, &mut c_pred, 0, refi as usize, rx, ry, rw, rh);
1842 }
1843
1844 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
1846 }
1847
1848 fn inter_finish(
1852 &mut self,
1853 r: &mut BitReader,
1854 mb_x: usize,
1855 mb_y: usize,
1856 pred_y: &[u8; 256],
1857 c_pred: &[[u8; 64]; 2],
1858 allow_8x8: bool,
1859 ) -> Result<(), MbError> {
1860 let w4 = self.mb_w * 4;
1861 let cbp = {
1862 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1863 read_cbp_inter(r)?
1864 };
1865 let cbp_luma = cbp & 15;
1866 let cbp_chroma = cbp >> 4;
1867 let t8x8 = cbp_luma > 0 && self.transform_8x8_mode && allow_8x8 && r.read_bit()?;
1870 if t8x8 {
1871 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
1872 }
1873 if cbp != 0 {
1874 self.step_qp(r.read_se()?);
1875 }
1876 let (qp, qpc) = (self.cur_qp, self.chroma_qp_for(self.cur_qp));
1877
1878 self.nnz_cache_load(mb_x, mb_y);
1880 let mut q_blocks = [[0i32; 16]; 16];
1881 let mut luma8 = [[0i32; 64]; 4]; if t8x8 {
1883 for b8 in 0..4 {
1884 let (b8x, b8y) = (b8 % 2, b8 / 2);
1885 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
1886 if cbp_luma & (1 << b8) != 0 {
1887 let mut scan8 = [0i32; 64];
1888 for sub in 0..4 {
1889 let (sx, sy) = (sub % 2, sub / 2);
1890 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
1891 let nc = self.nc_pred(cx, cy);
1892 let blk = decode_residual_block(r, 16, nc)?;
1893 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
1894 self.nnz_cache_set(cx, cy, total);
1895 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
1896 for k in 0..16 {
1897 scan8[4 * k + sub] = blk[k];
1898 }
1899 }
1900 luma8[b8] = self.inv_quant8(&un_scan_8x8(&scan8), qp, 1);
1901 } else {
1902 for sub in 0..4 {
1903 let (sx, sy) = (sub % 2, sub / 2);
1904 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
1905 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
1906 }
1907 }
1908 }
1909 } else {
1910 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1911 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
1912 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
1913 let nc = self.nc_pred(lbx, lby);
1914 let scan16 = decode_residual_block(r, 16, nc)?;
1915 q_blocks[lby * 4 + lbx] = un_scan_4x4_dcac(&scan16);
1916 scan16.iter().filter(|&&v| v != 0).count() as u8
1917 } else {
1918 0
1919 };
1920 self.nnz_cache_set(lbx, lby, total);
1921 self.nnz_y[by * w4 + bx] = total;
1922 }
1923 }
1924
1925 let mut c_recon_dc = [[0i32; 4]; 2];
1927 if cbp_chroma != 0 {
1928 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
1929 let dc = decode_residual_block(r, 4, -1)?;
1930 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 4 + c);
1931 }
1932 }
1933 let mut c_q = [[[0i32; 16]; 4]; 2];
1934 if cbp_chroma == 2 {
1935 self.chroma_cache_load(mb_x, mb_y);
1936 let w2 = self.mb_w * 2;
1937 for c in 0..2 {
1938 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1939 let nc = self.chroma_nc_pred(c, bx, by);
1940 let ac = decode_residual_block(r, 15, nc)?;
1941 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
1942 self.chroma_nnz_cache_set(c, bx, by, total);
1943 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
1944 un_scan_4x4_ac_into(&ac, &mut c_q[c][by * 2 + bx]);
1945 }
1946 }
1947 }
1948
1949 if t8x8 {
1951 for b8 in 0..4 {
1952 let (b8x, b8y) = (b8 % 2, b8 / 2);
1953 let (px, py) = (b8x * 8, b8y * 8);
1954 for dy in 0..8 {
1955 for dx in 0..8 {
1956 let p = pred_y[(py + dy) * 16 + (px + dx)] as i32;
1957 let v = (p + luma8[b8][dy * 8 + dx]).clamp(0, 255) as u8;
1958 self.rec_y[(mb_y * 16 + py + dy) * self.cw + (mb_x * 16 + px + dx)] = v;
1959 }
1960 }
1961 }
1962 } else {
1963 for b8 in 0..4 {
1970 let (b8x, b8y) = (b8 % 2, b8 / 2);
1971 let pred_off = (b8y * 8) * 16 + b8x * 8;
1972 let rec_off = (mb_y * 16 + b8y * 8) * self.cw + (mb_x * 16 + b8x * 8);
1973 if cbp_luma & (1 << b8) == 0 {
1974 for r in 0..8 {
1975 let (s, d) = (pred_off + r * 16, rec_off + r * self.cw);
1976 self.rec_y[d..d + 8].copy_from_slice(&pred_y[s..s + 8]);
1977 }
1978 continue;
1979 }
1980 #[cfg(accel)]
1981 {
1982 let mut dct = [0i16; 64];
1983 for (i, (sx, sy)) in [(0, 0), (1, 0), (0, 1), (1, 1)].into_iter().enumerate() {
1984 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
1985 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
1986 for k in 0..16 {
1987 dct[i * 16 + k] = deq[k] as i16;
1988 }
1989 }
1990 rusty_h264_accel::idct_four_t4_rec(
1991 &mut self.rec_y[rec_off..],
1992 self.cw,
1993 &pred_y[pred_off..],
1994 16,
1995 &dct,
1996 );
1997 }
1998 #[cfg(not(accel))]
1999 for (sx, sy) in [(0, 0), (1, 0), (0, 1), (1, 1)] {
2000 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2001 let mut predb = [0i32; 16];
2002 for dy in 0..4 {
2003 for dx in 0..4 {
2004 predb[dy * 4 + dx] = pred_y[(lby * 4 + dy) * 16 + (lbx * 4 + dx)] as i32;
2005 }
2006 }
2007 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2008 let s = reconstruct_4x4(&deq, &predb);
2009 store(&mut self.rec_y, self.cw, mb_x * 16 + lbx * 4, mb_y * 16 + lby * 4, &s);
2010 }
2011 }
2012 }
2013 if cbp_chroma == 0 {
2016 for c in 0..2 {
2017 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2018 for dy in 0..8 {
2019 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2020 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2021 }
2022 }
2023 } else {
2024 for c in 0..2 {
2025 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2026 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2027 let mut predb = [0i32; 16];
2028 for dy in 0..4 {
2029 for dx in 0..4 {
2030 predb[dy * 4 + dx] = c_pred[c][(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
2031 }
2032 }
2033 let mut deq = match &self.scaling {
2034 Some(s) => dequantize_weighted(&c_q[c][by * 2 + bx], qpc, &s[4 + c]),
2035 None => dequantize(&c_q[c][by * 2 + bx], qpc),
2036 };
2037 deq[0] = c_recon_dc[c][by * 2 + bx];
2038 let s = reconstruct_4x4(&deq, &predb);
2039 store(plane, self.ccw, mb_x * 8 + bx * 4, mb_y * 8 + by * 4, &s);
2040 }
2041 }
2042 }
2043
2044 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2046 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2047 }
2048 Ok(())
2049 }
2050
2051 fn mv_neighbors_list(&self, pbx: isize, pby: isize, pwb: isize, list: usize) -> [MvNeighbor; 3] {
2059 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
2060 let (mvg, refg) = if list == 0 {
2061 (&self.mv_y, &self.ref_idx_y)
2062 } else {
2063 (&self.mv1, &self.ref_idx1)
2064 };
2065 let get = |bx: isize, by: isize| -> MvNeighbor {
2066 if bx < 0
2067 || by < 0
2068 || bx >= w4
2069 || by >= h4
2070 || !self.coded_y[(by * w4 + bx) as usize]
2071 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
2072 {
2073 MvNeighbor::NONE
2074 } else {
2075 let idx = (by * w4 + bx) as usize;
2076 MvNeighbor { available: true, mv: mvg[idx], ref_idx: refg[idx] }
2077 }
2078 };
2079 let a = get(pbx - 1, pby);
2080 let b = get(pbx, pby - 1);
2081 let mut c = get(pbx + pwb, pby - 1);
2082 if !c.available {
2083 c = get(pbx - 1, pby - 1);
2084 }
2085 [a, b, c]
2086 }
2087
2088 fn col_zero(&self, bx: usize, by: usize) -> bool {
2092 let Some(col) = self.refs1.first() else { return false };
2093 if col.long_term || col.w4 == 0 {
2094 return false;
2095 }
2096 let idx = by * col.w4 + bx;
2097 if idx >= col.ref_idx.len() {
2098 return false;
2099 }
2100 col.ref_idx[idx] == 0 && col.mv[idx].0.abs() <= 1 && col.mv[idx].1.abs() <= 1
2101 }
2102
2103 fn implicit_weights(&self, refi0: i32, refi1: i32) -> Option<(i32, i32)> {
2107 if self.weighted_bipred_idc != 2 || refi0 < 0 || refi1 < 0 {
2108 return None;
2109 }
2110 let r0 = &self.refs[refi0 as usize];
2111 let r1 = &self.refs1[refi1 as usize];
2112 let td = (r1.poc - r0.poc).clamp(-128, 127);
2113 let tb = (self.cur_poc - r0.poc).clamp(-128, 127);
2114 if td == 0 || r0.long_term || r1.long_term {
2115 return None; }
2117 let tx = (16384 + td.abs() / 2) / td;
2118 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2119 let w1 = dsf >> 2;
2120 if !(-64..=128).contains(&w1) {
2121 return None; }
2123 Some((64 - w1, w1))
2124 }
2125
2126 #[allow(clippy::too_many_arguments)]
2130 fn b_mc(
2131 &self,
2132 mb_x: usize,
2133 mb_y: usize,
2134 px: usize,
2135 py: usize,
2136 rw: usize,
2137 rh: usize,
2138 refi0: i32,
2139 mv0: (i32, i32),
2140 refi1: i32,
2141 mv1: (i32, i32),
2142 pred_y: &mut [u8; 256],
2143 c_pred: &mut [[u8; 64]; 2],
2144 ) {
2145 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBMc);
2146 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2147 let weights = {
2148 let _gw = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBWeights);
2149 self.implicit_weights(refi0, refi1)
2150 };
2151 let blend = |p: i32, q: i32| -> u8 {
2153 match weights {
2154 Some((w0, w1)) => (((p * w0 + q * w1 + 32) >> 6).clamp(0, 255)) as u8,
2155 None => ((p + q + 1) >> 1) as u8,
2156 }
2157 };
2158 let (mut a, mut b) = ([0u8; 256], [0u8; 256]);
2159 let _gl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBLuma);
2160 if refi0 >= 0 {
2161 let rf = &self.refs[refi0 as usize];
2162 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);
2163 }
2164 if refi1 >= 0 {
2165 let rf = &self.refs1[refi1 as usize];
2166 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);
2167 }
2168 drop(_gl);
2169 let _gbl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBBlend);
2170 match (refi0 >= 0, refi1 >= 0) {
2173 (true, true) => {
2174 for dy in 0..rh {
2175 for dx in 0..rw {
2176 let (p, q) = (a[dy * rw + dx] as i32, b[dy * rw + dx] as i32);
2177 pred_y[(py + dy) * 16 + (px + dx)] = blend(p, q);
2178 }
2179 }
2180 }
2181 (true, false) => {
2182 for dy in 0..rh {
2183 let d = (py + dy) * 16 + px;
2184 pred_y[d..d + rw].copy_from_slice(&a[dy * rw..dy * rw + rw]);
2185 }
2186 }
2187 _ => {
2188 for dy in 0..rh {
2189 let d = (py + dy) * 16 + px;
2190 pred_y[d..d + rw].copy_from_slice(&b[dy * rw..dy * rw + rw]);
2191 }
2192 }
2193 }
2194 drop(_gbl);
2195 let _gc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBChroma);
2196 let (crx, cry, crw, crh) = (px / 2, py / 2, rw / 2, rh / 2);
2197 for c in 0..2 {
2198 let (mut ca, mut cb) = ([0u8; 64], [0u8; 64]);
2199 if refi0 >= 0 {
2200 let rf = &self.refs[refi0 as usize];
2201 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2202 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);
2203 }
2204 if refi1 >= 0 {
2205 let rf = &self.refs1[refi1 as usize];
2206 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2207 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);
2208 }
2209 match (refi0 >= 0, refi1 >= 0) {
2210 (true, true) => {
2211 for dy in 0..crh {
2212 for dx in 0..crw {
2213 let (p, q) = (ca[dy * crw + dx] as i32, cb[dy * crw + dx] as i32);
2214 c_pred[c][(cry + dy) * 8 + (crx + dx)] = blend(p, q);
2215 }
2216 }
2217 }
2218 (true, false) => {
2219 for dy in 0..crh {
2220 let d = (cry + dy) * 8 + crx;
2221 c_pred[c][d..d + crw].copy_from_slice(&ca[dy * crw..dy * crw + crw]);
2222 }
2223 }
2224 _ => {
2225 for dy in 0..crh {
2226 let d = (cry + dy) * 8 + crx;
2227 c_pred[c][d..d + crw].copy_from_slice(&cb[dy * crw..dy * crw + crw]);
2228 }
2229 }
2230 }
2231 }
2232 }
2233
2234 #[allow(clippy::too_many_arguments)]
2236 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)) {
2237 let w4 = self.mb_w * 4;
2238 for by in py / 4..(py + rh) / 4 {
2239 for bx in px / 4..(px + rw) / 4 {
2240 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2241 self.ref_idx_y[idx] = refi0;
2242 self.mv_y[idx] = if refi0 >= 0 { mv0 } else { (0, 0) };
2243 self.ref_idx1[idx] = refi1;
2244 self.mv1[idx] = if refi1 >= 0 { mv1 } else { (0, 0) };
2245 self.inter_y[idx] = true;
2246 self.coded_y[idx] = true;
2247 self.modes_y[idx] = 2;
2248 }
2249 }
2250 }
2251
2252 #[allow(clippy::too_many_arguments)]
2256 fn coalesce_region(
2261 x: usize,
2262 y: usize,
2263 w: usize,
2264 h: usize,
2265 uniform: &dyn Fn(usize, usize, usize, usize) -> bool,
2266 emit: &mut dyn FnMut(usize, usize, usize, usize),
2267 ) {
2268 if uniform(x, y, w, h) {
2269 emit(x, y, w, h);
2270 return;
2271 }
2272 if h > 1 && uniform(x, y, w, h / 2) && uniform(x, y + h / 2, w, h / 2) {
2273 emit(x, y, w, h / 2);
2274 emit(x, y + h / 2, w, h / 2);
2275 return;
2276 }
2277 if w > 1 && uniform(x, y, w / 2, h) && uniform(x + w / 2, y, w / 2, h) {
2278 emit(x, y, w / 2, h);
2279 emit(x + w / 2, y, w / 2, h);
2280 return;
2281 }
2282 match (w > 1, h > 1) {
2283 (true, true) => {
2284 for q in 0..4usize {
2285 Self::coalesce_region(x + (q % 2) * (w / 2), y + (q / 2) * (h / 2), w / 2, h / 2, uniform, emit);
2286 }
2287 }
2288 (true, false) => {
2289 Self::coalesce_region(x, y, w / 2, h, uniform, emit);
2290 Self::coalesce_region(x + w / 2, y, w / 2, h, uniform, emit);
2291 }
2292 (false, true) => {
2293 Self::coalesce_region(x, y, w, h / 2, uniform, emit);
2294 Self::coalesce_region(x, y + h / 2, w, h / 2, uniform, emit);
2295 }
2296 (false, false) => emit(x, y, 1, 1),
2297 }
2298 }
2299
2300 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]) {
2301 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDirect);
2302 if !self.direct_spatial {
2303 return self.decode_b_direct_temporal(mb_x, mb_y, px, py, rw, rh, pred_y, c_pred);
2304 }
2305 let (nbx, nby) = ((mb_x * 4) as isize, (mb_y * 4) as isize);
2307 let n0 = self.mv_neighbors_list(nbx, nby, 4, 0);
2308 let n1 = self.mv_neighbors_list(nbx, nby, 4, 1);
2309 let min_pos = |a: i32, b: i32| if a < 0 { b } else if b < 0 { a } else { a.min(b) };
2310 let rid = |n: &[MvNeighbor; 3]| min_pos(min_pos(n[0].ref_idx, n[1].ref_idx), n[2].ref_idx);
2311 let (mut refi0, mut refi1) = (rid(&n0), rid(&n1));
2312 let direct_zero = refi0 < 0 && refi1 < 0;
2313 if direct_zero {
2314 refi0 = 0;
2315 refi1 = 0;
2316 }
2317 let mv0 = if refi0 >= 0 && !direct_zero { predict_mv(n0[0], n0[1], n0[2], refi0) } else { (0, 0) };
2318 let mv1 = if refi1 >= 0 && !direct_zero { predict_mv(n1[0], n1[1], n1[2], refi1) } else { (0, 0) };
2319 let (bx0, by0, bw, bh) = (px / 4, py / 4, rw / 4, rh / 4);
2325 let mut czg = [[false; 4]; 4]; for dy in 0..bh {
2327 for dx in 0..bw {
2328 czg[dy][dx] =
2329 !direct_zero && self.col_zero(mb_x * 4 + bx0 + dx, mb_y * 4 + by0 + dy);
2330 }
2331 }
2332 let uniform = |x: usize, y: usize, w: usize, h: usize| -> bool {
2333 let t = czg[y][x];
2334 (y..y + h).all(|dy| (x..x + w).all(|dx| czg[dy][dx] == t))
2335 };
2336 let mut rects: [(usize, usize, usize, usize); 16] = [(0, 0, 0, 0); 16];
2337 let mut n = 0usize;
2338 Self::coalesce_region(0, 0, bw, bh, &uniform, &mut |x, y, w, h| {
2339 rects[n] = (x, y, w, h);
2340 n += 1;
2341 });
2342 for &(x, y, w, h) in &rects[..n] {
2343 let cz = czg[y][x];
2344 let m0 = if refi0 == 0 && cz { (0, 0) } else { mv0 };
2345 let m1 = if refi1 == 0 && cz { (0, 0) } else { mv1 };
2346 let (lx, ly, lw, lh) = ((bx0 + x) * 4, (by0 + y) * 4, w * 4, h * 4);
2347 self.b_mc(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1, pred_y, c_pred);
2348 self.b_set_motion(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1);
2349 }
2350 }
2351
2352 #[allow(clippy::too_many_arguments)]
2357 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]) {
2358 let poc1 = self.refs1.first().map_or(0, |f| f.poc);
2359 let infer = self.direct_8x8_inference;
2360 let step = if infer { 8 } else { 4 };
2366 let mut sy = py;
2367 while sy < py + rh {
2368 let mut sx = px;
2369 while sx < px + rw {
2370 let (cx4, cy4) = (sx / 4, sy / 4);
2371 let (colx, coly) = if infer {
2373 ((cx4 / 2) * 3, (cy4 / 2) * 3)
2374 } else {
2375 (cx4, cy4)
2376 };
2377 let (mvcol, refpoc) = {
2378 let col = &self.refs1[0];
2379 let idx = (mb_y * 4 + coly) * col.w4 + (mb_x * 4 + colx);
2380 if col.w4 != 0 && idx < col.mv.len() && col.ref_poc[idx] != i32::MIN {
2381 (col.mv[idx], col.ref_poc[idx])
2382 } else {
2383 ((0, 0), i32::MIN) }
2385 };
2386 let (refi0, mvc) = if refpoc == i32::MIN {
2388 (0, (0, 0))
2389 } else {
2390 let r = self.refs.iter().position(|f| f.poc == refpoc).unwrap_or(0) as i32;
2391 (r, mvcol)
2392 };
2393 let poc0 = self.refs[refi0 as usize].poc;
2394 let td = (poc1 - poc0).clamp(-128, 127);
2395 let tb = (self.cur_poc - poc0).clamp(-128, 127);
2396 let (mv0, mv1) = if td == 0 || self.refs[refi0 as usize].long_term {
2397 (mvc, (0, 0))
2398 } else {
2399 let tx = (16384 + td.abs() / 2) / td;
2400 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2401 let m0 = ((dsf * mvc.0 + 128) >> 8, (dsf * mvc.1 + 128) >> 8);
2402 (m0, (m0.0 - mvc.0, m0.1 - mvc.1))
2403 };
2404 self.b_mc(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1, pred_y, c_pred);
2405 self.b_set_motion(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1);
2406 sx += step;
2407 }
2408 sy += step;
2409 }
2410 }
2411
2412 fn read_b_ref(&self, r: &mut BitReader, list: usize) -> Result<i32, MbError> {
2415 let (active, avail) = if list == 0 {
2416 (self.num_ref_active, self.refs.len())
2417 } else {
2418 (self.num_ref_active1, self.refs1.len())
2419 };
2420 let v = if active > 1 { read_ref_idx(r, active)? } else { 0 };
2421 if v as usize >= avail {
2422 return Err(MbError::Truncated);
2423 }
2424 Ok(v)
2425 }
2426
2427 fn decode_b_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2429 if self.refs.is_empty() || self.refs1.is_empty() {
2430 return Err(MbError::Unsupported("B without references"));
2431 }
2432 let mut pred_y = [0u8; 256];
2433 let mut c_pred = [[0u8; 64]; 2];
2434 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2435 for dy in 0..16 {
2437 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2438 self.rec_y[d..d + 16].copy_from_slice(&pred_y[dy * 16..dy * 16 + 16]);
2439 }
2440 for c in 0..2 {
2441 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2442 for dy in 0..8 {
2443 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2444 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2445 }
2446 }
2447 let w4 = self.mb_w * 4;
2449 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2450 self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 0;
2451 }
2452 Ok(())
2453 }
2454
2455 fn decode_b_mb(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2458 let mb_type = r.read_ue()?;
2459 if mb_type >= 23 {
2460 return self.decode_intra_mb(r, mb_x, mb_y, mb_type - 23);
2461 }
2462 if self.refs.is_empty() || self.refs1.is_empty() {
2463 return Err(MbError::Unsupported("B without references"));
2464 }
2465 let mut pred_y = [0u8; 256];
2466 let mut c_pred = [[0u8; 64]; 2];
2467
2468 if mb_type == 0 {
2469 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2471 return self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, self.direct_8x8_inference);
2472 }
2473 if mb_type == 22 {
2474 return self.decode_b_8x8(r, mb_x, mb_y);
2475 }
2476
2477 let (layout, mvmode, preds) = b_inter_layout(mb_type);
2479 let mut refi = [[-1i32; 2]; 2]; for (p, &(_, _, _, _)) in layout.iter().enumerate() {
2482 if preds[p].uses(0) {
2483 refi[p][0] = self.read_b_ref(r, 0)?;
2484 }
2485 }
2486 for (p, _) in layout.iter().enumerate() {
2487 if preds[p].uses(1) {
2488 refi[p][1] = self.read_b_ref(r, 1)?;
2489 }
2490 }
2491 let mut mvd = [[(0i32, 0i32); 2]; 2];
2492 for (p, _) in layout.iter().enumerate() {
2493 if preds[p].uses(0) {
2494 mvd[p][0] = (r.read_se()?, r.read_se()?);
2495 }
2496 }
2497 for (p, _) in layout.iter().enumerate() {
2498 if preds[p].uses(1) {
2499 mvd[p][1] = (r.read_se()?, r.read_se()?);
2500 }
2501 }
2502 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2504 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2505 let pwb = (rw / 4) as isize;
2506 let mut mv = [(0i32, 0i32); 2];
2507 for list in 0..2 {
2508 if refi[p][list] >= 0 {
2509 let n = self.mv_neighbors_list(pbx, pby, pwb, list);
2510 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], refi[p][list]);
2511 mv[list] = (pmv.0 + mvd[p][list].0, pmv.1 + mvd[p][list].1);
2512 }
2513 }
2514 self.b_set_motion(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1]);
2515 let (mc_r0, mc_r1) = if mvmode != 0 && refi[p][0] >= 0 && refi[p][1] >= 0 {
2522 if p == 0 {
2523 (-1, refi[p][1])
2524 } else {
2525 (refi[p][0], -1)
2526 }
2527 } else {
2528 (refi[p][0], refi[p][1])
2529 };
2530 self.b_mc(mb_x, mb_y, rx, ry, rw, rh, mc_r0, mv[0], mc_r1, mv[1], &mut pred_y, &mut c_pred);
2531 }
2532 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2533 }
2534
2535 fn decode_b_8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2538 let mut sub = [0u32; 4];
2539 for s in sub.iter_mut() {
2540 let v = r.read_ue()?;
2541 if v > 12 {
2542 return Err(MbError::Unsupported("invalid B sub_mb_type"));
2543 }
2544 *s = v;
2545 }
2546 let mut pred_y = [0u8; 256];
2547 let mut c_pred = [[0u8; 64]; 2];
2548 let mut refi = [[-1i32; 2]; 4];
2551 for (p, &st) in sub.iter().enumerate() {
2552 if st != 0 && b_sub_uses(st, 0) {
2553 refi[p][0] = self.read_b_ref(r, 0)?;
2554 }
2555 }
2556 for (p, &st) in sub.iter().enumerate() {
2557 if st != 0 && b_sub_uses(st, 1) {
2558 refi[p][1] = self.read_b_ref(r, 1)?;
2559 }
2560 }
2561 let mut mvd0: Vec<(i32, i32)> = Vec::new();
2563 let mut mvd1: Vec<(i32, i32)> = Vec::new();
2564 for &st in &sub {
2565 if st != 0 && b_sub_uses(st, 0) {
2566 for _ in b_sub_parts(st) {
2567 mvd0.push((r.read_se()?, r.read_se()?));
2568 }
2569 }
2570 }
2571 for &st in &sub {
2572 if st != 0 && b_sub_uses(st, 1) {
2573 for _ in b_sub_parts(st) {
2574 mvd1.push((r.read_se()?, r.read_se()?));
2575 }
2576 }
2577 }
2578 let (mut i0, mut i1) = (0usize, 0usize);
2580 for (p, &st) in sub.iter().enumerate() {
2581 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
2582 if st == 0 {
2583 self.decode_b_direct(mb_x, mb_y, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
2584 continue;
2585 }
2586 for &(sx, sy, sw, sh) in b_sub_parts(st) {
2587 let (px, py) = (b8x + sx, b8y + sy);
2588 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2589 let pwb = (sw / 4) as isize;
2590 let mut mv = [(0i32, 0i32); 2];
2591 if b_sub_uses(st, 0) {
2592 let n = self.mv_neighbors_list(pbx, pby, pwb, 0);
2593 let pmv = predict_mv(n[0], n[1], n[2], refi[p][0]);
2594 let d = mvd0[i0];
2595 i0 += 1;
2596 mv[0] = (pmv.0 + d.0, pmv.1 + d.1);
2597 }
2598 if b_sub_uses(st, 1) {
2599 let n = self.mv_neighbors_list(pbx, pby, pwb, 1);
2600 let pmv = predict_mv(n[0], n[1], n[2], refi[p][1]);
2601 let d = mvd1[i1];
2602 i1 += 1;
2603 mv[1] = (pmv.0 + d.0, pmv.1 + d.1);
2604 }
2605 self.b_set_motion(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1]);
2606 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);
2607 }
2608 }
2609 let allow_8x8 = sub
2612 .iter()
2613 .all(|&st| if st == 0 { self.direct_8x8_inference } else { st <= 3 });
2614 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2615 }
2616
2617 fn decode_p8x8(
2621 &mut self,
2622 r: &mut BitReader,
2623 mb_x: usize,
2624 mb_y: usize,
2625 ref0: bool,
2626 ) -> Result<(), MbError> {
2627 if self.refs.is_empty() {
2628 return Err(MbError::Unsupported("inter without reference"));
2629 }
2630 let w4 = self.mb_w * 4;
2631 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2632 let num_refs = self.refs.len();
2633
2634 let mut sub_types = [0u32; 4];
2637 for st in sub_types.iter_mut() {
2638 let v = r.read_ue()?;
2639 if v > 3 {
2640 return Err(MbError::Unsupported("B-slice / invalid sub_mb_type"));
2641 }
2642 *st = v;
2643 }
2644 let mut ref_idxs = [0i32; 4];
2645 if self.num_ref_active > 1 && !ref0 {
2646 for ri in ref_idxs.iter_mut() {
2647 *ri = read_ref_idx(r, self.num_ref_active)?;
2648 if *ri as usize >= num_refs {
2649 return Err(MbError::Truncated); }
2651 }
2652 }
2653
2654 let mut pred_y = [0u8; 256];
2658 let mut c_pred = [[0u8; 64]; 2];
2659 for part in 0..4usize {
2660 let refi = ref_idxs[part];
2661 let (b8x, b8y) = ((part % 2) * 8, (part / 2) * 8);
2662 for &(srx, sry, srw, srh) in sub_mb_partitions(sub_types[part]) {
2663 let (px, py) = (b8x + srx, b8y + sry);
2664 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2665 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (srw / 4) as isize);
2666 let pmv = predict_mv(a, b, c, refi);
2667 let mvd_x = r.read_se()?;
2668 let mvd_y = r.read_se()?;
2669 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2670 for by in py / 4..py / 4 + srh / 4 {
2671 for bx in px / 4..px / 4 + srw / 4 {
2672 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2673 self.mv_y[idx] = mv;
2674 self.inter_y[idx] = true;
2675 self.ref_idx_y[idx] = refi;
2676 self.coded_y[idx] = true;
2677 }
2678 }
2679 let reference = &self.refs[refi as usize];
2680 let mut tmp = [0u8; 256];
2681 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);
2682 for dy in 0..srh {
2683 for dx in 0..srw {
2684 pred_y[(py + dy) * 16 + (px + dx)] = tmp[dy * srw + dx];
2685 }
2686 }
2687 let (crx, cry, crw, crh) = (px / 2, py / 2, srw / 2, srh / 2);
2688 for cc in 0..2 {
2689 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2690 let mut tc = [0u8; 64];
2691 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);
2692 for dy in 0..crh {
2693 for dx in 0..crw {
2694 c_pred[cc][(cry + dy) * 8 + (crx + dx)] = tc[dy * crw + dx];
2695 }
2696 }
2697 }
2698 self.weight_partition(
2699 &mut pred_y, &mut c_pred, 0, refi as usize, px, py, srw, srh,
2700 );
2701 }
2702 }
2703
2704 let allow_8x8 = sub_types.iter().all(|&t| t == 0);
2706 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2707 }
2708
2709 fn decode_p_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2712 if self.refs.is_empty() {
2716 return Err(MbError::Unsupported("P_Skip without reference"));
2717 }
2718 let mv = self.skip_mv(mb_x, mb_y);
2719 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2720
2721 let mut pred = [0u8; 256];
2722 let rf0 = &self.refs[0];
2723 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);
2724 if let Some(wt) = &self.weights {
2725 for p in pred.iter_mut() {
2726 *p = wt.apply_luma(*p, 0, 0);
2727 }
2728 }
2729 {
2730 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
2731 for dy in 0..16 {
2732 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2733 self.rec_y[d..d + 16].copy_from_slice(&pred[dy * 16..dy * 16 + 16]);
2734 }
2735 }
2736 for c in 0..2 {
2737 let mut pc = [0u8; 64];
2738 let rf0 = &self.refs[0];
2739 let rc = if c == 0 { &rf0.pu } else { &rf0.pv };
2740 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);
2741 if let Some(wt) = &self.weights {
2742 for p in pc.iter_mut() {
2743 *p = wt.apply_chroma(*p, 0, 0, c);
2744 }
2745 }
2746 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2747 for dy in 0..8 {
2748 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2749 plane[d..d + 8].copy_from_slice(&pc[dy * 8..dy * 8 + 8]);
2750 }
2751 }
2752 {
2753 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
2754 self.set_mb_mv(mb_x, mb_y, mv, true, 0);
2755 let w4 = self.mb_w * 4;
2757 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2758 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
2759 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2760 }
2761 }
2762 Ok(())
2763 }
2764
2765 fn predict_i4_mode(&self, bx: usize, by: usize) -> u8 {
2769 if bx == 0 || by == 0 {
2770 return 2;
2771 }
2772 if !self.nbr_in_slice((bx - 1) / 4, by / 4)
2776 || !self.nbr_in_slice(bx / 4, (by - 1) / 4)
2777 || !self.intra_nbr_ok(bx - 1, by)
2778 || !self.intra_nbr_ok(bx, by - 1)
2779 {
2780 return 2;
2781 }
2782 let w4 = self.mb_w * 4;
2783 self.modes_y[by * w4 + (bx - 1)].min(self.modes_y[(by - 1) * w4 + bx])
2784 }
2785
2786 fn gather_i4(
2788 &self,
2789 px: usize,
2790 py: usize,
2791 avail_top: bool,
2792 avail_left: bool,
2793 bx: usize,
2794 by: usize,
2795 ) -> ([u8; 8], [u8; 4], u8) {
2796 let (cw, w4) = (self.cw, self.mb_w * 4);
2797 let mut top = [0u8; 8];
2798 let mut left = [0u8; 4];
2799 let mut corner = 0;
2800 if avail_top {
2801 for i in 0..4 {
2802 top[i] = self.rec_y[(py - 1) * cw + px + i];
2803 }
2804 let tr_avail = bx + 1 < w4
2805 && self.coded_y[(by - 1) * w4 + (bx + 1)]
2806 && self.nbr_in_slice((bx + 1) / 4, (by - 1) / 4)
2807 && self.intra_nbr_ok(bx + 1, by - 1);
2808 for i in 0..4 {
2809 top[4 + i] = if tr_avail {
2810 self.rec_y[(py - 1) * cw + px + 4 + i]
2811 } else {
2812 top[3]
2813 };
2814 }
2815 }
2816 if avail_left {
2817 for i in 0..4 {
2818 left[i] = self.rec_y[(py + i) * cw + px - 1];
2819 }
2820 }
2821 if avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1) {
2824 corner = self.rec_y[(py - 1) * cw + px - 1];
2825 }
2826 (top, left, corner)
2827 }
2828
2829 fn decode_ipcm(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2832 r.align_to_byte()?;
2833 let (lx, ly) = (mb_x * 16, mb_y * 16);
2834 for dy in 0..16 {
2835 for dx in 0..16 {
2836 self.rec_y[(ly + dy) * self.cw + (lx + dx)] = r.read_bits(8)? as u8;
2837 }
2838 }
2839 let (cx, cy) = (mb_x * 8, mb_y * 8);
2840 for plane in [&mut self.rec_u, &mut self.rec_v] {
2841 for dy in 0..8 {
2842 for dx in 0..8 {
2843 plane[(cy + dy) * self.ccw + (cx + dx)] = r.read_bits(8)? as u8;
2844 }
2845 }
2846 }
2847 let (w4, w2) = (self.mb_w * 4, self.mb_w * 2);
2850 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2851 let idx = (mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx);
2852 self.nnz_y[idx] = 16;
2853 self.modes_y[idx] = 2;
2854 self.inter_y[idx] = false;
2855 self.ref_idx_y[idx] = -1;
2856 self.mv_y[idx] = (0, 0);
2857 }
2858 for c in 0..2 {
2859 for by in 0..2 {
2860 for bx in 0..2 {
2861 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = 16;
2862 }
2863 }
2864 }
2865 Ok(())
2866 }
2867
2868 fn decode_i4x4(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2869 let w4 = self.mb_w * 4;
2870
2871 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2874 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2875 let predicted = self.predict_i4_mode(bx, by);
2876 let actual = if r.read_bit()? {
2877 predicted
2878 } else {
2879 let rem = r.read_bits(3)? as u8;
2880 if rem < predicted {
2881 rem
2882 } else {
2883 rem + 1
2884 }
2885 };
2886 self.modes_y[by * w4 + bx] = actual;
2887 modes[lby * 4 + lbx] = actual;
2888 }
2889
2890 let chroma_mode = r.read_ue()? as u8;
2891 let cbp = read_cbp_intra(r)?;
2892 let cbp_luma = cbp & 15;
2893 let cbp_chroma = cbp >> 4;
2894 if cbp != 0 {
2895 self.step_qp(r.read_se()?);
2896 }
2897 let qp = self.cur_qp;
2898
2899 let top_mb_avail = mb_y > 0
2903 && self.nbr_in_slice(mb_x, mb_y - 1)
2904 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
2905 let left_mb_avail = mb_x > 0
2906 && self.nbr_in_slice(mb_x - 1, mb_y)
2907 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
2908 self.nnz_cache_load(mb_x, mb_y);
2909 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2910 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2911 let (px, py) = (bx * 4, by * 4);
2912 let avail_top = lby > 0 || top_mb_avail;
2913 let avail_left = lbx > 0 || left_mb_avail;
2914 let mut qb = [0i32; 16];
2915 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
2916 let nc = self.nc_pred(lbx, lby);
2917 let scan16 = decode_residual_block(r, 16, nc)?;
2918 qb = un_scan_4x4_dcac(&scan16);
2919 scan16.iter().filter(|&&v| v != 0).count() as u8
2920 } else {
2921 0
2922 };
2923 self.nnz_cache_set(lbx, lby, total);
2924 self.nnz_y[by * w4 + bx] = total;
2925 let (top, left, corner) = self.gather_i4(px, py, avail_top, avail_left, bx, by);
2926 let pred = intra4x4_pred(modes[lby * 4 + lbx], avail_top, avail_left, &top, &left, corner);
2927 let mut predb = [0i32; 16];
2928 for i in 0..16 {
2929 predb[i] = pred[i] as i32;
2930 }
2931 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
2932 store(&mut self.rec_y, self.cw, px, py, &s);
2933 self.coded_y[by * w4 + bx] = true;
2934 }
2935
2936 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
2937 }
2938
2939 fn decode_i8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2943 let w4 = self.mb_w * 4;
2944 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
2945
2946 let mut modes8 = [2u8; 4];
2949 for (b8, mode) in modes8.iter_mut().enumerate() {
2950 let (b8x, b8y) = (b8 % 2, b8 / 2);
2951 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2952 let predicted = self.predict_i4_mode(bx, by);
2953 let actual = if r.read_bit()? {
2954 predicted
2955 } else {
2956 let rem = r.read_bits(3)? as u8;
2957 if rem < predicted { rem } else { rem + 1 }
2958 };
2959 *mode = actual;
2960 for sy in 0..2 {
2961 for sx in 0..2 {
2962 self.modes_y[(by + sy) * w4 + (bx + sx)] = actual;
2963 }
2964 }
2965 }
2966
2967 let chroma_mode = r.read_ue()? as u8;
2968 let cbp = read_cbp_intra(r)?;
2969 let cbp_luma = cbp & 15;
2970 let cbp_chroma = cbp >> 4;
2971 if cbp != 0 {
2972 self.step_qp(r.read_se()?);
2973 }
2974 let qp = self.cur_qp;
2975
2976 let top_mb_avail = mb_y > 0
2977 && self.nbr_in_slice(mb_x, mb_y - 1)
2978 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
2979 let left_mb_avail = mb_x > 0
2980 && self.nbr_in_slice(mb_x - 1, mb_y)
2981 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
2982 self.nnz_cache_load(mb_x, mb_y);
2983
2984 for b8 in 0..4 {
2985 let (b8x, b8y) = (b8 % 2, b8 / 2);
2986 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2987 let (px, py) = (bx * 4, by * 4);
2988
2989 let mut res8 = [0i32; 64];
2992 if cbp_luma & (1 << b8) != 0 {
2993 let mut scan8 = [0i32; 64];
2994 for sub in 0..4 {
2995 let (sx, sy) = (sub % 2, sub / 2);
2996 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
2997 let nc = self.nc_pred(cx, cy);
2998 let blk = decode_residual_block(r, 16, nc)?;
2999 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
3000 self.nnz_cache_set(cx, cy, total);
3001 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
3002 for k in 0..16 {
3003 scan8[4 * k + sub] = blk[k];
3004 }
3005 }
3006 let raster = un_scan_8x8(&scan8);
3007 res8 = self.inv_quant8(&raster, qp, 0);
3008 } else {
3009 for sub in 0..4 {
3010 let (sx, sy) = (sub % 2, sub / 2);
3011 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
3012 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
3013 }
3014 }
3015
3016 let avail_top = b8y > 0 || top_mb_avail;
3017 let avail_left = b8x > 0 || left_mb_avail;
3018 let (top, left, corner, avail_corner) =
3019 self.gather_i8(px, py, avail_top, avail_left, bx, by);
3020 let pred = intra8x8_pred(
3021 modes8[b8], avail_top, avail_left, avail_corner, &top, &left, corner,
3022 );
3023 let mut predb = [0i32; 64];
3024 for i in 0..64 {
3025 predb[i] = pred[i] as i32;
3026 }
3027 let recon = add_residual_8x8(&res8, &predb);
3028 for dy in 0..8 {
3029 for dx in 0..8 {
3030 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
3031 }
3032 }
3033 for sy in 0..2 {
3034 for sx in 0..2 {
3035 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
3036 }
3037 }
3038 }
3039
3040 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3041 }
3042
3043 fn inv_quant8(&self, raster: &[i32; 64], qp: u8, list: usize) -> [i32; 64] {
3046 match &self.scaling8 {
3047 Some(s) => inverse_quant_8x8(raster, qp, &s[list]),
3048 None => inverse_quant_8x8(raster, qp, &[16i32; 64]),
3049 }
3050 }
3051
3052 #[allow(clippy::too_many_arguments)]
3056 fn gather_i8(
3057 &self,
3058 px: usize,
3059 py: usize,
3060 avail_top: bool,
3061 avail_left: bool,
3062 bx: usize,
3063 by: usize,
3064 ) -> ([u8; 16], [u8; 8], u8, bool) {
3065 let (cw, w4) = (self.cw, self.mb_w * 4);
3066 let mut top = [0u8; 16];
3067 let mut left = [0u8; 8];
3068 let mut corner = 0;
3069 if avail_top {
3070 for i in 0..8 {
3071 top[i] = self.rec_y[(py - 1) * cw + px + i];
3072 }
3073 let tr_avail = bx + 2 < w4
3074 && self.coded_y[(by - 1) * w4 + (bx + 2)]
3075 && self.nbr_in_slice((bx + 2) / 4, (by - 1) / 4)
3076 && self.intra_nbr_ok(bx + 2, by - 1);
3077 for i in 0..8 {
3078 top[8 + i] = if tr_avail {
3079 self.rec_y[(py - 1) * cw + px + 8 + i]
3080 } else {
3081 top[7]
3082 };
3083 }
3084 }
3085 if avail_left {
3086 for i in 0..8 {
3087 left[i] = self.rec_y[(py + i) * cw + px - 1];
3088 }
3089 }
3090 let avail_corner = avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1);
3091 if avail_corner {
3092 corner = self.rec_y[(py - 1) * cw + px - 1];
3093 }
3094 (top, left, corner, avail_corner)
3095 }
3096
3097 fn decode_i16(
3098 &mut self,
3099 r: &mut BitReader,
3100 mb_x: usize,
3101 mb_y: usize,
3102 mt: u32,
3103 ) -> Result<(), MbError> {
3104 let pred_mode = I16Mode::from_id(mt % 4);
3105 let cbp_chroma = (mt % 12) / 4;
3106 let cbp_luma_15 = mt / 12 == 1;
3107 let chroma_mode = r.read_ue()? as u8;
3108 self.step_qp(r.read_se()?);
3109 let qp = self.cur_qp;
3110 let w4 = self.mb_w * 4;
3111
3112 self.nnz_cache_load(mb_x, mb_y);
3114 let nc_dc = self.nc_pred(0, 0);
3115 let dc_scan = decode_residual_block(r, 16, nc_dc)?;
3116 let dc_levels = un_scan_4x4_dcac(&dc_scan);
3117 let recon_dc = self.dequant_luma_dc(&dc_levels, qp, 0);
3118
3119 let mut q_blocks = [[0i32; 16]; 16];
3121 for &(bx, by) in &LUMA_4X4_SCAN_XY {
3122 let total = if cbp_luma_15 {
3123 let nc = self.nc_pred(bx, by);
3124 let ac = decode_residual_block(r, 15, nc)?;
3125 un_scan_4x4_ac_into(&ac, &mut q_blocks[by * 4 + bx]);
3126 ac.iter().filter(|&&v| v != 0).count() as u8
3127 } else {
3128 0
3129 };
3130 self.nnz_cache_set(bx, by, total);
3131 self.nnz_y[(mb_y * 4 + by) * w4 + (mb_x * 4 + bx)] = total;
3132 }
3133
3134 let avail_top = mb_y > 0
3136 && self.nbr_in_slice(mb_x, mb_y - 1)
3137 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3138 let avail_left = mb_x > 0
3139 && self.nbr_in_slice(mb_x - 1, mb_y)
3140 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3141 let (lx, ly) = (mb_x * 16, mb_y * 16);
3142 let mut top = [0u8; 16];
3143 let mut left = [0u8; 16];
3144 if avail_top {
3145 for i in 0..16 {
3146 top[i] = self.rec_y[(ly - 1) * self.cw + lx + i];
3147 }
3148 }
3149 if avail_left {
3150 for i in 0..16 {
3151 left[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
3152 }
3153 }
3154 let corner = if avail_top && avail_left {
3155 self.rec_y[(ly - 1) * self.cw + lx - 1]
3156 } else {
3157 0
3158 };
3159 let pred_l = luma16x16_pred(pred_mode, avail_top, avail_left, &top, &left, corner);
3160 for by in 0..4 {
3161 for bx in 0..4 {
3162 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
3163 deq[0] = recon_dc[by * 4 + bx];
3164 let mut predb = [0i32; 16];
3165 for dy in 0..4 {
3166 for dx in 0..4 {
3167 predb[dy * 4 + dx] = pred_l[(by * 4 + dy) * 16 + (bx * 4 + dx)] as i32;
3168 }
3169 }
3170 let s = reconstruct_4x4(&deq, &predb);
3171 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
3172 }
3173 }
3174 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3176 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3177 }
3178
3179 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3180 }
3181
3182 fn decode_chroma(
3184 &mut self,
3185 r: &mut BitReader,
3186 mb_x: usize,
3187 mb_y: usize,
3188 cbp_chroma: u32,
3189 chroma_mode: u8,
3190 ) -> Result<(), MbError> {
3191 let qpc = self.chroma_qp_for(self.cur_qp);
3192 let (cx, cy) = (mb_x * 8, mb_y * 8);
3193 let avail_top = mb_y > 0
3194 && self.nbr_in_slice(mb_x, mb_y - 1)
3195 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3196 let avail_left = mb_x > 0
3197 && self.nbr_in_slice(mb_x - 1, mb_y)
3198 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3199
3200 let mut c_recon_dc = [[0i32; 4]; 2];
3201 if cbp_chroma != 0 {
3202 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
3203 let dc = decode_residual_block(r, 4, -1)?;
3204 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 1 + c);
3205 }
3206 }
3207 let mut c_q_blocks = [[[0i32; 16]; 4]; 2];
3208 if cbp_chroma == 2 {
3209 self.chroma_cache_load(mb_x, mb_y);
3210 let w2 = self.mb_w * 2;
3211 for c in 0..2 {
3212 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3213 let nc = self.chroma_nc_pred(c, bx, by);
3214 let ac = decode_residual_block(r, 15, nc)?;
3215 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
3216 self.chroma_nnz_cache_set(c, bx, by, total);
3217 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
3218 un_scan_4x4_ac_into(&ac, &mut c_q_blocks[c][by * 2 + bx]);
3219 }
3220 }
3221 }
3222 for c in 0..2 {
3223 let mut ctop = [0u8; 8];
3224 let mut cleft = [0u8; 8];
3225 let mut ccorner = 0u8;
3226 {
3227 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
3228 if avail_top {
3229 for i in 0..8 {
3230 ctop[i] = rec_c[(cy - 1) * self.ccw + cx + i];
3231 }
3232 }
3233 if avail_left {
3234 for i in 0..8 {
3235 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
3236 }
3237 }
3238 if avail_top && avail_left {
3239 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
3240 }
3241 }
3242 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
3243 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3244 let mut predb = [0i32; 16];
3245 for dy in 0..4 {
3246 for dx in 0..4 {
3247 predb[dy * 4 + dx] = pred8[(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
3248 }
3249 }
3250 let mut deq = self.dequant(&c_q_blocks[c][by * 2 + bx], qpc, 1 + c);
3251 deq[0] = c_recon_dc[c][by * 2 + bx];
3252 let s = reconstruct_4x4(&deq, &predb);
3253 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3254 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
3255 }
3256 }
3257 Ok(())
3258 }
3259
3260 pub fn deblock(&mut self, offset_a: i32, offset_b: i32) {
3264 let nnz_db_storage;
3271 let nnz_db: &[u8] = if self.mb_t8x8.iter().any(|&t| t) {
3272 let mut n = self.nnz_y.clone();
3273 let w4 = self.mb_w * 4;
3274 for mb_y in 0..self.mb_h {
3275 for mb_x in 0..self.mb_w {
3276 if !self.mb_t8x8[mb_y * self.mb_w + mb_x] {
3277 continue;
3278 }
3279 for b8 in 0..4 {
3280 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, mb_y * 4 + (b8 / 2) * 2);
3281 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + (bx + sx)] > 0));
3282 for sy in 0..2 {
3283 for sx in 0..2 {
3284 n[(by + sy) * w4 + (bx + sx)] = u8::from(any);
3285 }
3286 }
3287 }
3288 }
3289 }
3290 nnz_db_storage = n;
3291 &nnz_db_storage
3292 } else {
3293 &self.nnz_y
3294 };
3295 let ref_id: Vec<i32> = self
3298 .ref_idx_y
3299 .iter()
3300 .map(|&r| if r >= 0 { self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3301 .collect();
3302 let ref_id1: Vec<i32> = if self.refs1.is_empty() {
3305 Vec::new()
3306 } else {
3307 self.ref_idx1
3308 .iter()
3309 .map(|&r| if r >= 0 { self.refs1.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3310 .collect()
3311 };
3312 let info = rusty_h264_common::deblock::BlockInfo {
3313 inter: &self.inter_y,
3314 nnz: nnz_db,
3315 mv: &self.mv_y,
3316 ref_id: &ref_id,
3317 mv1: &self.mv1,
3318 ref_id1: &ref_id1,
3319 w4: self.mb_w * 4,
3320 t8x8: &self.mb_t8x8,
3321 bs: &[],
3322 };
3323 rusty_h264_common::deblock::filter_frame(
3324 &mut self.rec_y,
3325 &mut self.rec_u,
3326 &mut self.rec_v,
3327 self.mb_w,
3328 self.mb_h,
3329 &self.mb_qp,
3330 self.chroma_qp_offset,
3331 offset_a,
3332 offset_b,
3333 &info,
3334 );
3335 }
3336
3337 pub fn into_frame(self, crop_r: usize, crop_b: usize) -> YuvFrame {
3339 if crop_r == 0 && crop_b == 0 {
3342 return YuvFrame {
3343 width: self.cw,
3344 height: self.ch,
3345 y: self.rec_y,
3346 u: self.rec_u,
3347 v: self.rec_v,
3348 };
3349 }
3350 let dw = self.cw - 2 * crop_r;
3351 let dh = self.ch - 2 * crop_b;
3352 let mut y = vec![0u8; dw * dh];
3353 for row in 0..dh {
3354 y[row * dw..row * dw + dw].copy_from_slice(&self.rec_y[row * self.cw..row * self.cw + dw]);
3355 }
3356 let (cdw, cdh) = (dw / 2, dh / 2);
3357 let mut u = vec![0u8; cdw * cdh];
3358 let mut v = vec![0u8; cdw * cdh];
3359 for row in 0..cdh {
3360 u[row * cdw..row * cdw + cdw]
3361 .copy_from_slice(&self.rec_u[row * self.ccw..row * self.ccw + cdw]);
3362 v[row * cdw..row * cdw + cdw]
3363 .copy_from_slice(&self.rec_v[row * self.ccw..row * self.ccw + cdw]);
3364 }
3365 let _ = self.cch;
3366 YuvFrame {
3367 width: dw,
3368 height: dh,
3369 y,
3370 u,
3371 v,
3372 }
3373 }
3374}
3375
3376fn cabac_unary(cab: &mut crate::cabac::Cabac, ctx: usize, off: usize) -> u32 {
3383 if cab.decode_decision(ctx) == 0 {
3384 return 0;
3385 }
3386 let mut sym = 0;
3387 loop {
3388 let bin = cab.decode_decision(ctx + off);
3389 sym += 1;
3390 if bin == 0 || sym >= 512 {
3395 break;
3396 }
3397 }
3398 sym
3399}
3400
3401fn cabac_exp_bypass(cab: &mut crate::cabac::Cabac, mut count: i32) -> u32 {
3403 let mut sym = 0u32;
3404 loop {
3405 let c = cab.decode_bypass();
3406 if c == 1 {
3407 sym += 1 << count;
3408 count += 1;
3409 }
3410 if c == 0 || count == 16 {
3411 break;
3412 }
3413 }
3414 let mut sym2 = 0u32;
3415 while count > 0 {
3416 count -= 1;
3417 if cab.decode_bypass() != 0 {
3418 sym2 |= 1 << count;
3419 }
3420 }
3421 sym + sym2
3422}
3423
3424fn cabac_ueg_level(cab: &mut crate::cabac::Cabac, ctx: usize) -> u32 {
3427 if cab.decode_decision(ctx) == 0 {
3428 return 0;
3429 }
3430 let mut code = 0u32;
3431 let mut count = 1;
3432 let mut tmp;
3433 loop {
3434 tmp = cab.decode_decision(ctx);
3435 code += 1;
3436 count += 1;
3437 if tmp == 0 || count == 13 {
3438 break;
3439 }
3440 }
3441 if tmp != 0 {
3442 code += cabac_exp_bypass(cab, 0) + 1;
3443 }
3444 code
3445}
3446
3447fn parse_mb_qp_delta_cabac(cab: &mut crate::cabac::Cabac, last_delta_qp: &mut i32) -> i32 {
3449 const O: usize = 60;
3450 let ctx_inc = (*last_delta_qp != 0) as usize;
3451 let mut qp_delta = 0;
3452 if cab.decode_decision(O + ctx_inc) != 0 {
3453 let code = cabac_unary(cab, O + 2, 1) + 1;
3454 qp_delta = ((code + 1) >> 1) as i32;
3455 if code & 1 == 0 {
3456 qp_delta = -qp_delta;
3457 }
3458 }
3459 *last_delta_qp = qp_delta;
3460 qp_delta
3461}
3462
3463const NZC_CACHE: [usize; 24] = [
3466 9, 10, 17, 18, 11, 12, 19, 20, 25, 26, 33, 34, 27, 28, 35, 36, 14, 15, 22, 23, 38, 39, 46, 47, ];
3470
3471const RES_MAXPOS: [i32; 11] = [0, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14];
3473const RES_MAXC2: [i32; 11] = [0, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4];
3474const RES_CBF: [usize; 11] = [0, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16];
3475const RES_MAP: [usize; 11] = [0, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47];
3476const RES_ONE: [usize; 11] = [0, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39];
3477const RP_I16_DC: usize = 1;
3479const RP_I16_AC: usize = 2;
3480const RP_LUMA_4X4: usize = 3;
3481const RP_CHROMA_DC: usize = 7; const RP_CHROMA_AC: usize = 9; #[allow(clippy::too_many_arguments)]
3489fn parse_residual_cabac(
3490 cab: &mut crate::cabac::Cabac,
3491 nzc: &mut [u8; 48],
3492 cbf_dc: &mut u16,
3493 iz: usize,
3494 rp: usize,
3495 is_intra: bool,
3496 ndc: (Option<u16>, Option<u16>), out: &mut [i32], ) -> u32 {
3499 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Entropy);
3502 let is_dc = rp == RP_I16_DC || rp == RP_CHROMA_DC || rp == RP_CHROMA_DC + 1;
3504 let (mut na, mut nb) = (is_intra as u8, is_intra as u8);
3505 let scan = NZC_CACHE[iz.min(23)];
3506 if is_dc {
3507 if let Some(t) = ndc.0 {
3508 nb = ((t >> rp) & 1) as u8;
3509 }
3510 if let Some(l) = ndc.1 {
3511 na = ((l >> rp) & 1) as u8;
3512 }
3513 } else {
3514 if nzc[scan - 8] != 0xff {
3515 nb = (nzc[scan - 8] != 0) as u8;
3516 }
3517 if nzc[scan - 1] != 0xff {
3518 na = (nzc[scan - 1] != 0) as u8;
3519 }
3520 }
3521 let cbf = cab.decode_decision(85 + RES_CBF[rp] + (na + (nb << 1)) as usize);
3522 if cbf == 0 {
3523 if !is_dc {
3524 nzc[scan] = 0;
3525 }
3526 return 0;
3527 }
3528 if is_dc {
3529 *cbf_dc |= 1 << rp;
3530 }
3531 let maxpos = RES_MAXPOS[rp] as usize;
3533 let map = 105 + RES_MAP[rp];
3534 let last = 166 + RES_MAP[rp];
3535 let mut sig = [0i32; 64];
3536 let mut coeff_num = 0u32;
3537 let mut last_hit = false;
3538 for i in 0..maxpos {
3539 if cab.decode_decision(map + i) != 0 {
3540 sig[i] = 1;
3541 coeff_num += 1;
3542 if cab.decode_decision(last + i) != 0 {
3543 last_hit = true;
3544 break;
3545 }
3546 }
3547 }
3548 if !last_hit {
3549 sig[maxpos] = 1;
3550 coeff_num += 1;
3551 }
3552 let one = 227 + RES_ONE[rp];
3554 let abs = 232 + RES_ONE[rp];
3555 let maxc2 = RES_MAXC2[rp];
3556 let (mut c1, mut c2) = (1i32, 0i32);
3557 for i in (0..=maxpos).rev() {
3558 if sig[i] != 0 {
3559 let mut level = sig[i] + cab.decode_decision(one + c1 as usize) as i32;
3560 if level == 2 {
3561 level += cabac_ueg_level(cab, abs + c2 as usize) as i32;
3562 c2 = (c2 + 1).min(maxc2);
3563 c1 = 0;
3564 } else if c1 != 0 {
3565 c1 = (c1 + 1).min(4);
3566 }
3567 if cab.decode_bypass() != 0 {
3568 level = -level;
3569 }
3570 sig[i] = level;
3571 }
3572 }
3573 out[..=maxpos].copy_from_slice(&sig[..=maxpos]);
3574 if !is_dc {
3575 nzc[scan] = coeff_num as u8;
3576 }
3577 coeff_num
3578}
3579
3580const CACHE30: [usize; 16] = [7, 8, 13, 14, 9, 10, 15, 16, 19, 20, 25, 26, 21, 22, 27, 28];
3583
3584const G_SCAN4: [usize; 16] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15];
3587
3588fn parse_sub_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3590 const S: usize = 21;
3591 if cab.decode_decision(S) != 0 {
3592 return 0;
3593 }
3594 if cab.decode_decision(S + 1) != 0 {
3595 3 - cab.decode_decision(S + 2)
3596 } else {
3597 1
3598 }
3599}
3600
3601fn parse_intra_mb_type_cabac(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3604 if cab.decode_decision(base) == 0 {
3605 return 0; }
3607 if cab.decode_terminate() {
3608 return 25; }
3610 let mut t = 1 + 12 * cab.decode_decision(base + 1) as u32; if cab.decode_decision(base + 2) != 0 {
3612 t += 4 + 4 * cab.decode_decision(base + 2) as u32;
3613 }
3614 t += 2 * cab.decode_decision(base + 3) as u32;
3615 t += cab.decode_decision(base + 3) as u32;
3616 t
3617}
3618
3619fn parse_mb_type_b_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3623 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3624 const B: usize = 27;
3625 if cab.decode_decision(B + ctx_inc) == 0 {
3626 return 0; }
3628 if cab.decode_decision(B + 3) == 0 {
3629 return 1 + cab.decode_decision(B + 5) as u32; }
3631 let mut m = (cab.decode_decision(B + 4) as u32) << 3;
3632 m |= (cab.decode_decision(B + 5) as u32) << 2;
3633 m |= (cab.decode_decision(B + 5) as u32) << 1;
3634 m |= cab.decode_decision(B + 5) as u32;
3635 if m < 8 {
3636 return m + 3;
3637 }
3638 if m == 13 {
3639 return parse_intra_mb_type_cabac(cab, 32) + 23;
3640 }
3641 if m == 14 {
3642 return 11; }
3644 if m == 15 {
3645 return 22; }
3647 m = (m << 1) | cab.decode_decision(B + 5) as u32;
3648 m - 4
3649}
3650
3651fn parse_sub_mb_type_b_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3654 const B: usize = 36;
3655 if cab.decode_decision(B) == 0 {
3656 return 0; }
3658 if cab.decode_decision(B + 1) == 0 {
3659 return 1 + cab.decode_decision(B + 3) as u32; }
3661 let mut st = 3u32;
3662 if cab.decode_decision(B + 2) != 0 {
3663 if cab.decode_decision(B + 3) != 0 {
3664 return 11 + cab.decode_decision(B + 3) as u32; }
3666 st += 4;
3667 }
3668 st += 2 * cab.decode_decision(B + 3) as u32;
3669 st += cab.decode_decision(B + 3) as u32;
3670 st
3671}
3672
3673fn parse_mvd_partition(
3677 cab: &mut crate::cabac::Cabac,
3678 part_idx: usize,
3679 zblocks: &[usize],
3680 mvdc: &mut [[i16; 2]; 30],
3681 refc: &mut [i8; 30],
3682 mmvd: &mut [[i16; 2]; 16],
3683 mref: &mut [i8; 16],
3684 ref_idx: i8,
3685) -> (i32, i32) {
3686 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3687 let s = CACHE30[part_idx];
3688 let ctx = |comp: usize| -> usize {
3689 let mut a = 0i32;
3690 if refc[s - 6] >= 0 {
3691 a += mvdc[s - 6][comp].unsigned_abs() as i32;
3692 }
3693 if refc[s - 1] >= 0 {
3694 a += mvdc[s - 1][comp].unsigned_abs() as i32;
3695 }
3696 if a >= 3 {
3697 1 + (a > 32) as usize
3698 } else {
3699 0
3700 }
3701 };
3702 let (cx, cy) = (ctx(0), ctx(1));
3703 let mvx = parse_mvd_cabac(cab, 0, cx);
3704 let mvy = parse_mvd_cabac(cab, 1, cy);
3705 for &zb in zblocks {
3706 mvdc[CACHE30[zb]] = [mvx, mvy];
3707 refc[CACHE30[zb]] = ref_idx;
3708 mmvd[G_SCAN4[zb]] = [mvx, mvy];
3709 mref[G_SCAN4[zb]] = ref_idx;
3710 }
3711 (mvx as i32, mvy as i32)
3712}
3713
3714fn parse_ref_idx_cabac(cab: &mut crate::cabac::Cabac, ctx0: usize) -> i8 {
3717 const B: usize = 54;
3718 let mut r = 0i8;
3719 let mut bin_idx = 0u32;
3720 while bin_idx < 32 {
3724 let ctx = match bin_idx {
3725 0 => ctx0,
3726 1 => 4,
3727 _ => 5,
3728 };
3729 if cab.decode_decision(B + ctx) == 0 {
3730 break;
3731 }
3732 r += 1;
3733 bin_idx += 1;
3734 }
3735 r
3736}
3737
3738fn decode_ueg_mv(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3741 const P2C: [usize; 8] = [0, 1, 2, 3, 3, 3, 3, 3];
3742 if cab.decode_decision(base) == 0 {
3743 return 0;
3744 }
3745 let mut code = 0u32;
3746 let mut count = 1usize;
3747 let mut tmp;
3748 loop {
3749 tmp = cab.decode_decision(base + P2C[count]);
3750 code += 1;
3751 count += 1;
3752 if tmp == 0 || count == 8 {
3753 break;
3754 }
3755 }
3756 if tmp != 0 {
3757 code += cabac_exp_bypass(cab, 3) + 1;
3758 }
3759 code
3760}
3761
3762fn parse_mvd_cabac(cab: &mut crate::cabac::Cabac, comp: usize, ctx_inc: usize) -> i16 {
3765 let base = 40 + comp * 7; if cab.decode_decision(base + ctx_inc) == 0 {
3767 return 0;
3768 }
3769 let mag = (decode_ueg_mv(cab, base + 3) + 1) as i16;
3770 if cab.decode_bypass() != 0 {
3771 -mag
3772 } else {
3773 mag
3774 }
3775}
3776
3777fn parse_mb_skip_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> bool {
3780 cab.decode_decision(ctx_inc) != 0
3781}
3782
3783fn parse_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3786 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3787 const S: usize = 11; if cab.decode_decision(S + 3) == 0 {
3789 return if cab.decode_decision(S + 4) != 0 {
3791 if cab.decode_decision(S + 6) != 0 { 1 } else { 2 }
3792 } else if cab.decode_decision(S + 5) != 0 {
3793 3
3794 } else {
3795 0
3796 };
3797 }
3798 if cab.decode_decision(S + 6) == 0 {
3800 return 5; }
3802 if cab.decode_terminate() {
3803 return 30; }
3805 let mut t = 6 + cab.decode_decision(S + 7) * 12;
3806 if cab.decode_decision(S + 8) != 0 {
3807 t += 4;
3808 if cab.decode_decision(S + 8) != 0 {
3809 t += 4;
3810 }
3811 }
3812 t += cab.decode_decision(S + 9) << 1;
3813 t += cab.decode_decision(S + 9);
3814 t
3815}
3816
3817fn parse_mb_type_i_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3822 const O: usize = 3; if cab.decode_decision(O + ctx_inc) == 0 {
3824 return 0; }
3826 if cab.decode_terminate() {
3827 return 25; }
3829 let mut t = 1 + cab.decode_decision(O + 3) * 12; if cab.decode_decision(O + 4) != 0 {
3831 t += 4; if cab.decode_decision(O + 5) != 0 {
3833 t += 4;
3834 }
3835 }
3836 t += cab.decode_decision(O + 6) << 1; t += cab.decode_decision(O + 7);
3838 t
3839}
3840
3841fn parse_intra4x4_pred_mode_cabac(cab: &mut crate::cabac::Cabac) -> i32 {
3845 const IPR: usize = 68;
3846 if cab.decode_decision(IPR) == 1 {
3847 return -1; }
3849 let mut m = cab.decode_decision(IPR + 1) as i32;
3850 m |= (cab.decode_decision(IPR + 1) as i32) << 1;
3851 m |= (cab.decode_decision(IPR + 1) as i32) << 2;
3852 m
3853}
3854
3855fn parse_intra_chroma_pred_mode_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3859 const CIPR: usize = 64;
3860 if cab.decode_decision(CIPR + ctx_inc) == 0 {
3861 return 0;
3862 }
3863 if cab.decode_decision(CIPR + 3) == 0 {
3864 return 1;
3865 }
3866 if cab.decode_decision(CIPR + 3) == 0 {
3867 return 2;
3868 }
3869 3
3870}
3871
3872fn parse_cbp_cabac(cab: &mut crate::cabac::Cabac, top: Option<u8>, left: Option<u8>) -> u32 {
3877 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3878 const CBP: usize = 73;
3879 let t = |m: u32| top.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
3880 let l = |m: u32| left.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
3881 let nb = |x: u32| (x == 0) as u32; let b0 = cab.decode_decision(CBP + (l(1 << 1) + (t(1 << 2) << 1)) as usize);
3884 let b1 = cab.decode_decision(CBP + (nb(b0) + (t(1 << 3) << 1)) as usize);
3885 let b2 = cab.decode_decision(CBP + (l(1 << 3) + (nb(b0) << 1)) as usize);
3886 let b3 = cab.decode_decision(CBP + (nb(b2) + (nb(b1) << 1)) as usize);
3887 let mut cbp = b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
3888 let ct = top.map_or(0u32, |c| ((c >> 4) != 0) as u32);
3890 let cl = left.map_or(0u32, |c| ((c >> 4) != 0) as u32);
3891 if cab.decode_decision(CBP + 4 + (cl + (ct << 1)) as usize) != 0 {
3892 let ct2 = top.map_or(0u32, |c| ((c >> 4) == 2) as u32);
3893 let cl2 = left.map_or(0u32, |c| ((c >> 4) == 2) as u32);
3894 let c1 = cab.decode_decision(CBP + 8 + (cl2 + (ct2 << 1)) as usize);
3895 cbp |= 1 << (4 + c1);
3896 }
3897 cbp
3898}
3899
3900fn read_ref_idx(r: &mut BitReader, num_ref_active: usize) -> Result<i32, OutOfData> {
3901 if num_ref_active == 2 {
3902 Ok(if r.read_bit()? { 0 } else { 1 }) } else {
3904 Ok(r.read_ue()? as i32)
3905 }
3906}
3907
3908#[derive(Clone, Copy, PartialEq)]
3910enum BPred {
3911 L0,
3912 L1,
3913 Bi,
3914}
3915impl BPred {
3916 fn uses(self, list: usize) -> bool {
3918 matches!(
3919 (self, list),
3920 (BPred::L0, 0) | (BPred::L1, 1) | (BPred::Bi, 0) | (BPred::Bi, 1)
3921 )
3922 }
3923}
3924
3925const B16X16: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 16)];
3926const B16X8: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 8), (0, 8, 16, 8)];
3927const B8X16: &[(usize, usize, usize, usize)] = &[(0, 0, 8, 16), (8, 0, 8, 16)];
3928
3929type Region = (usize, usize, usize, usize);
3931
3932fn b_inter_layout(mb_type: u32) -> (&'static [Region], u8, [BPred; 2]) {
3935 use BPred::*;
3936 match mb_type {
3937 1 => (B16X16, 0, [L0, L0]),
3938 2 => (B16X16, 0, [L1, L1]),
3939 3 => (B16X16, 0, [Bi, Bi]),
3940 4 => (B16X8, 1, [L0, L0]),
3941 5 => (B8X16, 2, [L0, L0]),
3942 6 => (B16X8, 1, [L1, L1]),
3943 7 => (B8X16, 2, [L1, L1]),
3944 8 => (B16X8, 1, [L0, L1]),
3945 9 => (B8X16, 2, [L0, L1]),
3946 10 => (B16X8, 1, [L1, L0]),
3947 11 => (B8X16, 2, [L1, L0]),
3948 12 => (B16X8, 1, [L0, Bi]),
3949 13 => (B8X16, 2, [L0, Bi]),
3950 14 => (B16X8, 1, [L1, Bi]),
3951 15 => (B8X16, 2, [L1, Bi]),
3952 16 => (B16X8, 1, [Bi, L0]),
3953 17 => (B8X16, 2, [Bi, L0]),
3954 18 => (B16X8, 1, [Bi, L1]),
3955 19 => (B8X16, 2, [Bi, L1]),
3956 20 => (B16X8, 1, [Bi, Bi]),
3957 _ => (B8X16, 2, [Bi, Bi]), }
3959}
3960
3961fn b_sub_uses(st: u32, list: usize) -> bool {
3963 let pred = match st {
3964 1 | 4 | 5 | 10 => 0, 2 | 6 | 7 | 11 => 1, _ => 2, };
3968 (list == 0 && pred != 1) || (list == 1 && pred != 0)
3969}
3970
3971fn b_sub_parts(st: u32) -> &'static [(usize, usize, usize, usize)] {
3973 match st {
3974 1..=3 => &[(0, 0, 8, 8)],
3975 4 | 6 | 8 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
3976 5 | 7 | 9 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
3977 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)], }
3979}
3980
3981fn sub_mb_partitions(sub_type: u32) -> &'static [(usize, usize, usize, usize)] {
3984 match sub_type {
3985 0 => &[(0, 0, 8, 8)],
3986 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
3987 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
3988 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
3989 }
3990}
3991
3992fn store(plane: &mut [u8], stride: usize, x0: usize, y0: usize, s: &[u8; 16]) {
3993 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Scatter);
3994 for dy in 0..4 {
3995 for dx in 0..4 {
3996 plane[(y0 + dy) * stride + (x0 + dx)] = s[dy * 4 + dx];
3997 }
3998 }
3999}
4000
4001fn un_scan_8x8(scan: &[i32; 64]) -> [i32; 64] {
4003 const ZZ8: [usize; 64] = [
4004 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,
4005 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
4006 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
4007 ];
4008 let mut out = [0i32; 64];
4009 for k in 0..64 {
4010 out[ZZ8[k]] = scan[k];
4011 }
4012 out
4013}
4014
4015#[cfg(test)]
4016mod tests {
4017 use super::*;
4018
4019 fn fd(qp: u8, offset: i32) -> FrameDecoder {
4020 FrameDecoder::new(1, 1, qp, offset, Vec::new(), 1, false, false, true)
4021 }
4022
4023 #[test]
4024 fn mb_qp_delta_accumulates_mod_52() {
4025 let mut d = fd(26, 0);
4026 assert_eq!(d.cur_qp, 26, "QPy starts at the slice QP");
4027 d.step_qp(4);
4028 assert_eq!(d.cur_qp, 30); d.step_qp(-10);
4030 assert_eq!(d.cur_qp, 20); d.step_qp(40);
4033 assert_eq!(d.cur_qp, 8);
4034 d.step_qp(-20);
4036 assert_eq!(d.cur_qp, 40);
4037 }
4038
4039 #[test]
4040 fn chroma_qp_index_offset_applied_and_clamped() {
4041 assert_eq!(fd(0, 0).chroma_qp_for(30), 29);
4043 assert_eq!(fd(0, 2).chroma_qp_for(30), 31);
4045 assert_eq!(fd(0, -12).chroma_qp_for(5), chroma_qp(0));
4047 assert_eq!(fd(0, 99).chroma_qp_for(40), chroma_qp(51));
4048 }
4049}