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 = self.implicit_weights(refi0, refi1);
2148 let blend = |p: i32, q: i32| -> u8 {
2150 match weights {
2151 Some((w0, w1)) => (((p * w0 + q * w1 + 32) >> 6).clamp(0, 255)) as u8,
2152 None => ((p + q + 1) >> 1) as u8,
2153 }
2154 };
2155 let (mut a, mut b) = ([0u8; 256], [0u8; 256]);
2156 if refi0 >= 0 {
2157 let rf = &self.refs[refi0 as usize];
2158 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);
2159 }
2160 if refi1 >= 0 {
2161 let rf = &self.refs1[refi1 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, mv1.0, mv1.1, &mut b);
2163 }
2164 match (refi0 >= 0, refi1 >= 0) {
2167 (true, true) => {
2168 for dy in 0..rh {
2169 for dx in 0..rw {
2170 let (p, q) = (a[dy * rw + dx] as i32, b[dy * rw + dx] as i32);
2171 pred_y[(py + dy) * 16 + (px + dx)] = blend(p, q);
2172 }
2173 }
2174 }
2175 (true, false) => {
2176 for dy in 0..rh {
2177 let d = (py + dy) * 16 + px;
2178 pred_y[d..d + rw].copy_from_slice(&a[dy * rw..dy * rw + rw]);
2179 }
2180 }
2181 _ => {
2182 for dy in 0..rh {
2183 let d = (py + dy) * 16 + px;
2184 pred_y[d..d + rw].copy_from_slice(&b[dy * rw..dy * rw + rw]);
2185 }
2186 }
2187 }
2188 let (crx, cry, crw, crh) = (px / 2, py / 2, rw / 2, rh / 2);
2189 for c in 0..2 {
2190 let (mut ca, mut cb) = ([0u8; 64], [0u8; 64]);
2191 if refi0 >= 0 {
2192 let rf = &self.refs[refi0 as usize];
2193 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2194 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);
2195 }
2196 if refi1 >= 0 {
2197 let rf = &self.refs1[refi1 as usize];
2198 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2199 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);
2200 }
2201 match (refi0 >= 0, refi1 >= 0) {
2202 (true, true) => {
2203 for dy in 0..crh {
2204 for dx in 0..crw {
2205 let (p, q) = (ca[dy * crw + dx] as i32, cb[dy * crw + dx] as i32);
2206 c_pred[c][(cry + dy) * 8 + (crx + dx)] = blend(p, q);
2207 }
2208 }
2209 }
2210 (true, false) => {
2211 for dy in 0..crh {
2212 let d = (cry + dy) * 8 + crx;
2213 c_pred[c][d..d + crw].copy_from_slice(&ca[dy * crw..dy * crw + crw]);
2214 }
2215 }
2216 _ => {
2217 for dy in 0..crh {
2218 let d = (cry + dy) * 8 + crx;
2219 c_pred[c][d..d + crw].copy_from_slice(&cb[dy * crw..dy * crw + crw]);
2220 }
2221 }
2222 }
2223 }
2224 }
2225
2226 #[allow(clippy::too_many_arguments)]
2228 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)) {
2229 let w4 = self.mb_w * 4;
2230 for by in py / 4..(py + rh) / 4 {
2231 for bx in px / 4..(px + rw) / 4 {
2232 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2233 self.ref_idx_y[idx] = refi0;
2234 self.mv_y[idx] = if refi0 >= 0 { mv0 } else { (0, 0) };
2235 self.ref_idx1[idx] = refi1;
2236 self.mv1[idx] = if refi1 >= 0 { mv1 } else { (0, 0) };
2237 self.inter_y[idx] = true;
2238 self.coded_y[idx] = true;
2239 self.modes_y[idx] = 2;
2240 }
2241 }
2242 }
2243
2244 #[allow(clippy::too_many_arguments)]
2248 fn coalesce_region(
2253 x: usize,
2254 y: usize,
2255 w: usize,
2256 h: usize,
2257 uniform: &dyn Fn(usize, usize, usize, usize) -> bool,
2258 emit: &mut dyn FnMut(usize, usize, usize, usize),
2259 ) {
2260 if uniform(x, y, w, h) {
2261 emit(x, y, w, h);
2262 return;
2263 }
2264 if h > 1 && uniform(x, y, w, h / 2) && uniform(x, y + h / 2, w, h / 2) {
2265 emit(x, y, w, h / 2);
2266 emit(x, y + h / 2, w, h / 2);
2267 return;
2268 }
2269 if w > 1 && uniform(x, y, w / 2, h) && uniform(x + w / 2, y, w / 2, h) {
2270 emit(x, y, w / 2, h);
2271 emit(x + w / 2, y, w / 2, h);
2272 return;
2273 }
2274 match (w > 1, h > 1) {
2275 (true, true) => {
2276 for q in 0..4usize {
2277 Self::coalesce_region(x + (q % 2) * (w / 2), y + (q / 2) * (h / 2), w / 2, h / 2, uniform, emit);
2278 }
2279 }
2280 (true, false) => {
2281 Self::coalesce_region(x, y, w / 2, h, uniform, emit);
2282 Self::coalesce_region(x + w / 2, y, w / 2, h, uniform, emit);
2283 }
2284 (false, true) => {
2285 Self::coalesce_region(x, y, w, h / 2, uniform, emit);
2286 Self::coalesce_region(x, y + h / 2, w, h / 2, uniform, emit);
2287 }
2288 (false, false) => emit(x, y, 1, 1),
2289 }
2290 }
2291
2292 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]) {
2293 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDirect);
2294 if !self.direct_spatial {
2295 return self.decode_b_direct_temporal(mb_x, mb_y, px, py, rw, rh, pred_y, c_pred);
2296 }
2297 let (nbx, nby) = ((mb_x * 4) as isize, (mb_y * 4) as isize);
2299 let n0 = self.mv_neighbors_list(nbx, nby, 4, 0);
2300 let n1 = self.mv_neighbors_list(nbx, nby, 4, 1);
2301 let min_pos = |a: i32, b: i32| if a < 0 { b } else if b < 0 { a } else { a.min(b) };
2302 let rid = |n: &[MvNeighbor; 3]| min_pos(min_pos(n[0].ref_idx, n[1].ref_idx), n[2].ref_idx);
2303 let (mut refi0, mut refi1) = (rid(&n0), rid(&n1));
2304 let direct_zero = refi0 < 0 && refi1 < 0;
2305 if direct_zero {
2306 refi0 = 0;
2307 refi1 = 0;
2308 }
2309 let mv0 = if refi0 >= 0 && !direct_zero { predict_mv(n0[0], n0[1], n0[2], refi0) } else { (0, 0) };
2310 let mv1 = if refi1 >= 0 && !direct_zero { predict_mv(n1[0], n1[1], n1[2], refi1) } else { (0, 0) };
2311 let (bx0, by0, bw, bh) = (px / 4, py / 4, rw / 4, rh / 4);
2317 let mut czg = [[false; 4]; 4]; for dy in 0..bh {
2319 for dx in 0..bw {
2320 czg[dy][dx] =
2321 !direct_zero && self.col_zero(mb_x * 4 + bx0 + dx, mb_y * 4 + by0 + dy);
2322 }
2323 }
2324 let uniform = |x: usize, y: usize, w: usize, h: usize| -> bool {
2325 let t = czg[y][x];
2326 (y..y + h).all(|dy| (x..x + w).all(|dx| czg[dy][dx] == t))
2327 };
2328 let mut rects: [(usize, usize, usize, usize); 16] = [(0, 0, 0, 0); 16];
2329 let mut n = 0usize;
2330 Self::coalesce_region(0, 0, bw, bh, &uniform, &mut |x, y, w, h| {
2331 rects[n] = (x, y, w, h);
2332 n += 1;
2333 });
2334 for &(x, y, w, h) in &rects[..n] {
2335 let cz = czg[y][x];
2336 let m0 = if refi0 == 0 && cz { (0, 0) } else { mv0 };
2337 let m1 = if refi1 == 0 && cz { (0, 0) } else { mv1 };
2338 let (lx, ly, lw, lh) = ((bx0 + x) * 4, (by0 + y) * 4, w * 4, h * 4);
2339 self.b_mc(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1, pred_y, c_pred);
2340 self.b_set_motion(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1);
2341 }
2342 }
2343
2344 #[allow(clippy::too_many_arguments)]
2349 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]) {
2350 let poc1 = self.refs1.first().map_or(0, |f| f.poc);
2351 let infer = self.direct_8x8_inference;
2352 let step = if infer { 8 } else { 4 };
2358 let mut sy = py;
2359 while sy < py + rh {
2360 let mut sx = px;
2361 while sx < px + rw {
2362 let (cx4, cy4) = (sx / 4, sy / 4);
2363 let (colx, coly) = if infer {
2365 ((cx4 / 2) * 3, (cy4 / 2) * 3)
2366 } else {
2367 (cx4, cy4)
2368 };
2369 let (mvcol, refpoc) = {
2370 let col = &self.refs1[0];
2371 let idx = (mb_y * 4 + coly) * col.w4 + (mb_x * 4 + colx);
2372 if col.w4 != 0 && idx < col.mv.len() && col.ref_poc[idx] != i32::MIN {
2373 (col.mv[idx], col.ref_poc[idx])
2374 } else {
2375 ((0, 0), i32::MIN) }
2377 };
2378 let (refi0, mvc) = if refpoc == i32::MIN {
2380 (0, (0, 0))
2381 } else {
2382 let r = self.refs.iter().position(|f| f.poc == refpoc).unwrap_or(0) as i32;
2383 (r, mvcol)
2384 };
2385 let poc0 = self.refs[refi0 as usize].poc;
2386 let td = (poc1 - poc0).clamp(-128, 127);
2387 let tb = (self.cur_poc - poc0).clamp(-128, 127);
2388 let (mv0, mv1) = if td == 0 || self.refs[refi0 as usize].long_term {
2389 (mvc, (0, 0))
2390 } else {
2391 let tx = (16384 + td.abs() / 2) / td;
2392 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2393 let m0 = ((dsf * mvc.0 + 128) >> 8, (dsf * mvc.1 + 128) >> 8);
2394 (m0, (m0.0 - mvc.0, m0.1 - mvc.1))
2395 };
2396 self.b_mc(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1, pred_y, c_pred);
2397 self.b_set_motion(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1);
2398 sx += step;
2399 }
2400 sy += step;
2401 }
2402 }
2403
2404 fn read_b_ref(&self, r: &mut BitReader, list: usize) -> Result<i32, MbError> {
2407 let (active, avail) = if list == 0 {
2408 (self.num_ref_active, self.refs.len())
2409 } else {
2410 (self.num_ref_active1, self.refs1.len())
2411 };
2412 let v = if active > 1 { read_ref_idx(r, active)? } else { 0 };
2413 if v as usize >= avail {
2414 return Err(MbError::Truncated);
2415 }
2416 Ok(v)
2417 }
2418
2419 fn decode_b_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2421 if self.refs.is_empty() || self.refs1.is_empty() {
2422 return Err(MbError::Unsupported("B without references"));
2423 }
2424 let mut pred_y = [0u8; 256];
2425 let mut c_pred = [[0u8; 64]; 2];
2426 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2427 for dy in 0..16 {
2429 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2430 self.rec_y[d..d + 16].copy_from_slice(&pred_y[dy * 16..dy * 16 + 16]);
2431 }
2432 for c in 0..2 {
2433 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2434 for dy in 0..8 {
2435 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2436 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2437 }
2438 }
2439 let w4 = self.mb_w * 4;
2441 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2442 self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 0;
2443 }
2444 Ok(())
2445 }
2446
2447 fn decode_b_mb(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2450 let mb_type = r.read_ue()?;
2451 if mb_type >= 23 {
2452 return self.decode_intra_mb(r, mb_x, mb_y, mb_type - 23);
2453 }
2454 if self.refs.is_empty() || self.refs1.is_empty() {
2455 return Err(MbError::Unsupported("B without references"));
2456 }
2457 let mut pred_y = [0u8; 256];
2458 let mut c_pred = [[0u8; 64]; 2];
2459
2460 if mb_type == 0 {
2461 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2463 return self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, self.direct_8x8_inference);
2464 }
2465 if mb_type == 22 {
2466 return self.decode_b_8x8(r, mb_x, mb_y);
2467 }
2468
2469 let (layout, mvmode, preds) = b_inter_layout(mb_type);
2471 let mut refi = [[-1i32; 2]; 2]; for (p, &(_, _, _, _)) in layout.iter().enumerate() {
2474 if preds[p].uses(0) {
2475 refi[p][0] = self.read_b_ref(r, 0)?;
2476 }
2477 }
2478 for (p, _) in layout.iter().enumerate() {
2479 if preds[p].uses(1) {
2480 refi[p][1] = self.read_b_ref(r, 1)?;
2481 }
2482 }
2483 let mut mvd = [[(0i32, 0i32); 2]; 2];
2484 for (p, _) in layout.iter().enumerate() {
2485 if preds[p].uses(0) {
2486 mvd[p][0] = (r.read_se()?, r.read_se()?);
2487 }
2488 }
2489 for (p, _) in layout.iter().enumerate() {
2490 if preds[p].uses(1) {
2491 mvd[p][1] = (r.read_se()?, r.read_se()?);
2492 }
2493 }
2494 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2496 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2497 let pwb = (rw / 4) as isize;
2498 let mut mv = [(0i32, 0i32); 2];
2499 for list in 0..2 {
2500 if refi[p][list] >= 0 {
2501 let n = self.mv_neighbors_list(pbx, pby, pwb, list);
2502 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], refi[p][list]);
2503 mv[list] = (pmv.0 + mvd[p][list].0, pmv.1 + mvd[p][list].1);
2504 }
2505 }
2506 self.b_set_motion(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1]);
2507 let (mc_r0, mc_r1) = if mvmode != 0 && refi[p][0] >= 0 && refi[p][1] >= 0 {
2514 if p == 0 {
2515 (-1, refi[p][1])
2516 } else {
2517 (refi[p][0], -1)
2518 }
2519 } else {
2520 (refi[p][0], refi[p][1])
2521 };
2522 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);
2523 }
2524 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2525 }
2526
2527 fn decode_b_8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2530 let mut sub = [0u32; 4];
2531 for s in sub.iter_mut() {
2532 let v = r.read_ue()?;
2533 if v > 12 {
2534 return Err(MbError::Unsupported("invalid B sub_mb_type"));
2535 }
2536 *s = v;
2537 }
2538 let mut pred_y = [0u8; 256];
2539 let mut c_pred = [[0u8; 64]; 2];
2540 let mut refi = [[-1i32; 2]; 4];
2543 for (p, &st) in sub.iter().enumerate() {
2544 if st != 0 && b_sub_uses(st, 0) {
2545 refi[p][0] = self.read_b_ref(r, 0)?;
2546 }
2547 }
2548 for (p, &st) in sub.iter().enumerate() {
2549 if st != 0 && b_sub_uses(st, 1) {
2550 refi[p][1] = self.read_b_ref(r, 1)?;
2551 }
2552 }
2553 let mut mvd0: Vec<(i32, i32)> = Vec::new();
2555 let mut mvd1: Vec<(i32, i32)> = Vec::new();
2556 for &st in &sub {
2557 if st != 0 && b_sub_uses(st, 0) {
2558 for _ in b_sub_parts(st) {
2559 mvd0.push((r.read_se()?, r.read_se()?));
2560 }
2561 }
2562 }
2563 for &st in &sub {
2564 if st != 0 && b_sub_uses(st, 1) {
2565 for _ in b_sub_parts(st) {
2566 mvd1.push((r.read_se()?, r.read_se()?));
2567 }
2568 }
2569 }
2570 let (mut i0, mut i1) = (0usize, 0usize);
2572 for (p, &st) in sub.iter().enumerate() {
2573 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
2574 if st == 0 {
2575 self.decode_b_direct(mb_x, mb_y, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
2576 continue;
2577 }
2578 for &(sx, sy, sw, sh) in b_sub_parts(st) {
2579 let (px, py) = (b8x + sx, b8y + sy);
2580 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2581 let pwb = (sw / 4) as isize;
2582 let mut mv = [(0i32, 0i32); 2];
2583 if b_sub_uses(st, 0) {
2584 let n = self.mv_neighbors_list(pbx, pby, pwb, 0);
2585 let pmv = predict_mv(n[0], n[1], n[2], refi[p][0]);
2586 let d = mvd0[i0];
2587 i0 += 1;
2588 mv[0] = (pmv.0 + d.0, pmv.1 + d.1);
2589 }
2590 if b_sub_uses(st, 1) {
2591 let n = self.mv_neighbors_list(pbx, pby, pwb, 1);
2592 let pmv = predict_mv(n[0], n[1], n[2], refi[p][1]);
2593 let d = mvd1[i1];
2594 i1 += 1;
2595 mv[1] = (pmv.0 + d.0, pmv.1 + d.1);
2596 }
2597 self.b_set_motion(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1]);
2598 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);
2599 }
2600 }
2601 let allow_8x8 = sub
2604 .iter()
2605 .all(|&st| if st == 0 { self.direct_8x8_inference } else { st <= 3 });
2606 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2607 }
2608
2609 fn decode_p8x8(
2613 &mut self,
2614 r: &mut BitReader,
2615 mb_x: usize,
2616 mb_y: usize,
2617 ref0: bool,
2618 ) -> Result<(), MbError> {
2619 if self.refs.is_empty() {
2620 return Err(MbError::Unsupported("inter without reference"));
2621 }
2622 let w4 = self.mb_w * 4;
2623 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2624 let num_refs = self.refs.len();
2625
2626 let mut sub_types = [0u32; 4];
2629 for st in sub_types.iter_mut() {
2630 let v = r.read_ue()?;
2631 if v > 3 {
2632 return Err(MbError::Unsupported("B-slice / invalid sub_mb_type"));
2633 }
2634 *st = v;
2635 }
2636 let mut ref_idxs = [0i32; 4];
2637 if self.num_ref_active > 1 && !ref0 {
2638 for ri in ref_idxs.iter_mut() {
2639 *ri = read_ref_idx(r, self.num_ref_active)?;
2640 if *ri as usize >= num_refs {
2641 return Err(MbError::Truncated); }
2643 }
2644 }
2645
2646 let mut pred_y = [0u8; 256];
2650 let mut c_pred = [[0u8; 64]; 2];
2651 for part in 0..4usize {
2652 let refi = ref_idxs[part];
2653 let (b8x, b8y) = ((part % 2) * 8, (part / 2) * 8);
2654 for &(srx, sry, srw, srh) in sub_mb_partitions(sub_types[part]) {
2655 let (px, py) = (b8x + srx, b8y + sry);
2656 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2657 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (srw / 4) as isize);
2658 let pmv = predict_mv(a, b, c, refi);
2659 let mvd_x = r.read_se()?;
2660 let mvd_y = r.read_se()?;
2661 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2662 for by in py / 4..py / 4 + srh / 4 {
2663 for bx in px / 4..px / 4 + srw / 4 {
2664 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2665 self.mv_y[idx] = mv;
2666 self.inter_y[idx] = true;
2667 self.ref_idx_y[idx] = refi;
2668 self.coded_y[idx] = true;
2669 }
2670 }
2671 let reference = &self.refs[refi as usize];
2672 let mut tmp = [0u8; 256];
2673 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);
2674 for dy in 0..srh {
2675 for dx in 0..srw {
2676 pred_y[(py + dy) * 16 + (px + dx)] = tmp[dy * srw + dx];
2677 }
2678 }
2679 let (crx, cry, crw, crh) = (px / 2, py / 2, srw / 2, srh / 2);
2680 for cc in 0..2 {
2681 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2682 let mut tc = [0u8; 64];
2683 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);
2684 for dy in 0..crh {
2685 for dx in 0..crw {
2686 c_pred[cc][(cry + dy) * 8 + (crx + dx)] = tc[dy * crw + dx];
2687 }
2688 }
2689 }
2690 self.weight_partition(
2691 &mut pred_y, &mut c_pred, 0, refi as usize, px, py, srw, srh,
2692 );
2693 }
2694 }
2695
2696 let allow_8x8 = sub_types.iter().all(|&t| t == 0);
2698 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2699 }
2700
2701 fn decode_p_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2704 if self.refs.is_empty() {
2708 return Err(MbError::Unsupported("P_Skip without reference"));
2709 }
2710 let mv = self.skip_mv(mb_x, mb_y);
2711 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2712
2713 let mut pred = [0u8; 256];
2714 let rf0 = &self.refs[0];
2715 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);
2716 if let Some(wt) = &self.weights {
2717 for p in pred.iter_mut() {
2718 *p = wt.apply_luma(*p, 0, 0);
2719 }
2720 }
2721 {
2722 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
2723 for dy in 0..16 {
2724 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2725 self.rec_y[d..d + 16].copy_from_slice(&pred[dy * 16..dy * 16 + 16]);
2726 }
2727 }
2728 for c in 0..2 {
2729 let mut pc = [0u8; 64];
2730 let rf0 = &self.refs[0];
2731 let rc = if c == 0 { &rf0.pu } else { &rf0.pv };
2732 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);
2733 if let Some(wt) = &self.weights {
2734 for p in pc.iter_mut() {
2735 *p = wt.apply_chroma(*p, 0, 0, c);
2736 }
2737 }
2738 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2739 for dy in 0..8 {
2740 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2741 plane[d..d + 8].copy_from_slice(&pc[dy * 8..dy * 8 + 8]);
2742 }
2743 }
2744 {
2745 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
2746 self.set_mb_mv(mb_x, mb_y, mv, true, 0);
2747 let w4 = self.mb_w * 4;
2749 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2750 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
2751 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2752 }
2753 }
2754 Ok(())
2755 }
2756
2757 fn predict_i4_mode(&self, bx: usize, by: usize) -> u8 {
2761 if bx == 0 || by == 0 {
2762 return 2;
2763 }
2764 if !self.nbr_in_slice((bx - 1) / 4, by / 4)
2768 || !self.nbr_in_slice(bx / 4, (by - 1) / 4)
2769 || !self.intra_nbr_ok(bx - 1, by)
2770 || !self.intra_nbr_ok(bx, by - 1)
2771 {
2772 return 2;
2773 }
2774 let w4 = self.mb_w * 4;
2775 self.modes_y[by * w4 + (bx - 1)].min(self.modes_y[(by - 1) * w4 + bx])
2776 }
2777
2778 fn gather_i4(
2780 &self,
2781 px: usize,
2782 py: usize,
2783 avail_top: bool,
2784 avail_left: bool,
2785 bx: usize,
2786 by: usize,
2787 ) -> ([u8; 8], [u8; 4], u8) {
2788 let (cw, w4) = (self.cw, self.mb_w * 4);
2789 let mut top = [0u8; 8];
2790 let mut left = [0u8; 4];
2791 let mut corner = 0;
2792 if avail_top {
2793 for i in 0..4 {
2794 top[i] = self.rec_y[(py - 1) * cw + px + i];
2795 }
2796 let tr_avail = bx + 1 < w4
2797 && self.coded_y[(by - 1) * w4 + (bx + 1)]
2798 && self.nbr_in_slice((bx + 1) / 4, (by - 1) / 4)
2799 && self.intra_nbr_ok(bx + 1, by - 1);
2800 for i in 0..4 {
2801 top[4 + i] = if tr_avail {
2802 self.rec_y[(py - 1) * cw + px + 4 + i]
2803 } else {
2804 top[3]
2805 };
2806 }
2807 }
2808 if avail_left {
2809 for i in 0..4 {
2810 left[i] = self.rec_y[(py + i) * cw + px - 1];
2811 }
2812 }
2813 if avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1) {
2816 corner = self.rec_y[(py - 1) * cw + px - 1];
2817 }
2818 (top, left, corner)
2819 }
2820
2821 fn decode_ipcm(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2824 r.align_to_byte()?;
2825 let (lx, ly) = (mb_x * 16, mb_y * 16);
2826 for dy in 0..16 {
2827 for dx in 0..16 {
2828 self.rec_y[(ly + dy) * self.cw + (lx + dx)] = r.read_bits(8)? as u8;
2829 }
2830 }
2831 let (cx, cy) = (mb_x * 8, mb_y * 8);
2832 for plane in [&mut self.rec_u, &mut self.rec_v] {
2833 for dy in 0..8 {
2834 for dx in 0..8 {
2835 plane[(cy + dy) * self.ccw + (cx + dx)] = r.read_bits(8)? as u8;
2836 }
2837 }
2838 }
2839 let (w4, w2) = (self.mb_w * 4, self.mb_w * 2);
2842 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2843 let idx = (mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx);
2844 self.nnz_y[idx] = 16;
2845 self.modes_y[idx] = 2;
2846 self.inter_y[idx] = false;
2847 self.ref_idx_y[idx] = -1;
2848 self.mv_y[idx] = (0, 0);
2849 }
2850 for c in 0..2 {
2851 for by in 0..2 {
2852 for bx in 0..2 {
2853 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = 16;
2854 }
2855 }
2856 }
2857 Ok(())
2858 }
2859
2860 fn decode_i4x4(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2861 let w4 = self.mb_w * 4;
2862
2863 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2866 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2867 let predicted = self.predict_i4_mode(bx, by);
2868 let actual = if r.read_bit()? {
2869 predicted
2870 } else {
2871 let rem = r.read_bits(3)? as u8;
2872 if rem < predicted {
2873 rem
2874 } else {
2875 rem + 1
2876 }
2877 };
2878 self.modes_y[by * w4 + bx] = actual;
2879 modes[lby * 4 + lbx] = actual;
2880 }
2881
2882 let chroma_mode = r.read_ue()? as u8;
2883 let cbp = read_cbp_intra(r)?;
2884 let cbp_luma = cbp & 15;
2885 let cbp_chroma = cbp >> 4;
2886 if cbp != 0 {
2887 self.step_qp(r.read_se()?);
2888 }
2889 let qp = self.cur_qp;
2890
2891 let top_mb_avail = mb_y > 0
2895 && self.nbr_in_slice(mb_x, mb_y - 1)
2896 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
2897 let left_mb_avail = mb_x > 0
2898 && self.nbr_in_slice(mb_x - 1, mb_y)
2899 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
2900 self.nnz_cache_load(mb_x, mb_y);
2901 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2902 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2903 let (px, py) = (bx * 4, by * 4);
2904 let avail_top = lby > 0 || top_mb_avail;
2905 let avail_left = lbx > 0 || left_mb_avail;
2906 let mut qb = [0i32; 16];
2907 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
2908 let nc = self.nc_pred(lbx, lby);
2909 let scan16 = decode_residual_block(r, 16, nc)?;
2910 qb = un_scan_4x4_dcac(&scan16);
2911 scan16.iter().filter(|&&v| v != 0).count() as u8
2912 } else {
2913 0
2914 };
2915 self.nnz_cache_set(lbx, lby, total);
2916 self.nnz_y[by * w4 + bx] = total;
2917 let (top, left, corner) = self.gather_i4(px, py, avail_top, avail_left, bx, by);
2918 let pred = intra4x4_pred(modes[lby * 4 + lbx], avail_top, avail_left, &top, &left, corner);
2919 let mut predb = [0i32; 16];
2920 for i in 0..16 {
2921 predb[i] = pred[i] as i32;
2922 }
2923 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
2924 store(&mut self.rec_y, self.cw, px, py, &s);
2925 self.coded_y[by * w4 + bx] = true;
2926 }
2927
2928 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
2929 }
2930
2931 fn decode_i8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2935 let w4 = self.mb_w * 4;
2936 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
2937
2938 let mut modes8 = [2u8; 4];
2941 for (b8, mode) in modes8.iter_mut().enumerate() {
2942 let (b8x, b8y) = (b8 % 2, b8 / 2);
2943 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2944 let predicted = self.predict_i4_mode(bx, by);
2945 let actual = if r.read_bit()? {
2946 predicted
2947 } else {
2948 let rem = r.read_bits(3)? as u8;
2949 if rem < predicted { rem } else { rem + 1 }
2950 };
2951 *mode = actual;
2952 for sy in 0..2 {
2953 for sx in 0..2 {
2954 self.modes_y[(by + sy) * w4 + (bx + sx)] = actual;
2955 }
2956 }
2957 }
2958
2959 let chroma_mode = r.read_ue()? as u8;
2960 let cbp = read_cbp_intra(r)?;
2961 let cbp_luma = cbp & 15;
2962 let cbp_chroma = cbp >> 4;
2963 if cbp != 0 {
2964 self.step_qp(r.read_se()?);
2965 }
2966 let qp = self.cur_qp;
2967
2968 let top_mb_avail = mb_y > 0
2969 && self.nbr_in_slice(mb_x, mb_y - 1)
2970 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
2971 let left_mb_avail = mb_x > 0
2972 && self.nbr_in_slice(mb_x - 1, mb_y)
2973 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
2974 self.nnz_cache_load(mb_x, mb_y);
2975
2976 for b8 in 0..4 {
2977 let (b8x, b8y) = (b8 % 2, b8 / 2);
2978 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2979 let (px, py) = (bx * 4, by * 4);
2980
2981 let mut res8 = [0i32; 64];
2984 if cbp_luma & (1 << b8) != 0 {
2985 let mut scan8 = [0i32; 64];
2986 for sub in 0..4 {
2987 let (sx, sy) = (sub % 2, sub / 2);
2988 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
2989 let nc = self.nc_pred(cx, cy);
2990 let blk = decode_residual_block(r, 16, nc)?;
2991 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
2992 self.nnz_cache_set(cx, cy, total);
2993 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
2994 for k in 0..16 {
2995 scan8[4 * k + sub] = blk[k];
2996 }
2997 }
2998 let raster = un_scan_8x8(&scan8);
2999 res8 = self.inv_quant8(&raster, qp, 0);
3000 } else {
3001 for sub in 0..4 {
3002 let (sx, sy) = (sub % 2, sub / 2);
3003 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
3004 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
3005 }
3006 }
3007
3008 let avail_top = b8y > 0 || top_mb_avail;
3009 let avail_left = b8x > 0 || left_mb_avail;
3010 let (top, left, corner, avail_corner) =
3011 self.gather_i8(px, py, avail_top, avail_left, bx, by);
3012 let pred = intra8x8_pred(
3013 modes8[b8], avail_top, avail_left, avail_corner, &top, &left, corner,
3014 );
3015 let mut predb = [0i32; 64];
3016 for i in 0..64 {
3017 predb[i] = pred[i] as i32;
3018 }
3019 let recon = add_residual_8x8(&res8, &predb);
3020 for dy in 0..8 {
3021 for dx in 0..8 {
3022 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
3023 }
3024 }
3025 for sy in 0..2 {
3026 for sx in 0..2 {
3027 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
3028 }
3029 }
3030 }
3031
3032 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3033 }
3034
3035 fn inv_quant8(&self, raster: &[i32; 64], qp: u8, list: usize) -> [i32; 64] {
3038 match &self.scaling8 {
3039 Some(s) => inverse_quant_8x8(raster, qp, &s[list]),
3040 None => inverse_quant_8x8(raster, qp, &[16i32; 64]),
3041 }
3042 }
3043
3044 #[allow(clippy::too_many_arguments)]
3048 fn gather_i8(
3049 &self,
3050 px: usize,
3051 py: usize,
3052 avail_top: bool,
3053 avail_left: bool,
3054 bx: usize,
3055 by: usize,
3056 ) -> ([u8; 16], [u8; 8], u8, bool) {
3057 let (cw, w4) = (self.cw, self.mb_w * 4);
3058 let mut top = [0u8; 16];
3059 let mut left = [0u8; 8];
3060 let mut corner = 0;
3061 if avail_top {
3062 for i in 0..8 {
3063 top[i] = self.rec_y[(py - 1) * cw + px + i];
3064 }
3065 let tr_avail = bx + 2 < w4
3066 && self.coded_y[(by - 1) * w4 + (bx + 2)]
3067 && self.nbr_in_slice((bx + 2) / 4, (by - 1) / 4)
3068 && self.intra_nbr_ok(bx + 2, by - 1);
3069 for i in 0..8 {
3070 top[8 + i] = if tr_avail {
3071 self.rec_y[(py - 1) * cw + px + 8 + i]
3072 } else {
3073 top[7]
3074 };
3075 }
3076 }
3077 if avail_left {
3078 for i in 0..8 {
3079 left[i] = self.rec_y[(py + i) * cw + px - 1];
3080 }
3081 }
3082 let avail_corner = avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1);
3083 if avail_corner {
3084 corner = self.rec_y[(py - 1) * cw + px - 1];
3085 }
3086 (top, left, corner, avail_corner)
3087 }
3088
3089 fn decode_i16(
3090 &mut self,
3091 r: &mut BitReader,
3092 mb_x: usize,
3093 mb_y: usize,
3094 mt: u32,
3095 ) -> Result<(), MbError> {
3096 let pred_mode = I16Mode::from_id(mt % 4);
3097 let cbp_chroma = (mt % 12) / 4;
3098 let cbp_luma_15 = mt / 12 == 1;
3099 let chroma_mode = r.read_ue()? as u8;
3100 self.step_qp(r.read_se()?);
3101 let qp = self.cur_qp;
3102 let w4 = self.mb_w * 4;
3103
3104 self.nnz_cache_load(mb_x, mb_y);
3106 let nc_dc = self.nc_pred(0, 0);
3107 let dc_scan = decode_residual_block(r, 16, nc_dc)?;
3108 let dc_levels = un_scan_4x4_dcac(&dc_scan);
3109 let recon_dc = self.dequant_luma_dc(&dc_levels, qp, 0);
3110
3111 let mut q_blocks = [[0i32; 16]; 16];
3113 for &(bx, by) in &LUMA_4X4_SCAN_XY {
3114 let total = if cbp_luma_15 {
3115 let nc = self.nc_pred(bx, by);
3116 let ac = decode_residual_block(r, 15, nc)?;
3117 un_scan_4x4_ac_into(&ac, &mut q_blocks[by * 4 + bx]);
3118 ac.iter().filter(|&&v| v != 0).count() as u8
3119 } else {
3120 0
3121 };
3122 self.nnz_cache_set(bx, by, total);
3123 self.nnz_y[(mb_y * 4 + by) * w4 + (mb_x * 4 + bx)] = total;
3124 }
3125
3126 let avail_top = mb_y > 0
3128 && self.nbr_in_slice(mb_x, mb_y - 1)
3129 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3130 let avail_left = mb_x > 0
3131 && self.nbr_in_slice(mb_x - 1, mb_y)
3132 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3133 let (lx, ly) = (mb_x * 16, mb_y * 16);
3134 let mut top = [0u8; 16];
3135 let mut left = [0u8; 16];
3136 if avail_top {
3137 for i in 0..16 {
3138 top[i] = self.rec_y[(ly - 1) * self.cw + lx + i];
3139 }
3140 }
3141 if avail_left {
3142 for i in 0..16 {
3143 left[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
3144 }
3145 }
3146 let corner = if avail_top && avail_left {
3147 self.rec_y[(ly - 1) * self.cw + lx - 1]
3148 } else {
3149 0
3150 };
3151 let pred_l = luma16x16_pred(pred_mode, avail_top, avail_left, &top, &left, corner);
3152 for by in 0..4 {
3153 for bx in 0..4 {
3154 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
3155 deq[0] = recon_dc[by * 4 + bx];
3156 let mut predb = [0i32; 16];
3157 for dy in 0..4 {
3158 for dx in 0..4 {
3159 predb[dy * 4 + dx] = pred_l[(by * 4 + dy) * 16 + (bx * 4 + dx)] as i32;
3160 }
3161 }
3162 let s = reconstruct_4x4(&deq, &predb);
3163 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
3164 }
3165 }
3166 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3168 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3169 }
3170
3171 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3172 }
3173
3174 fn decode_chroma(
3176 &mut self,
3177 r: &mut BitReader,
3178 mb_x: usize,
3179 mb_y: usize,
3180 cbp_chroma: u32,
3181 chroma_mode: u8,
3182 ) -> Result<(), MbError> {
3183 let qpc = self.chroma_qp_for(self.cur_qp);
3184 let (cx, cy) = (mb_x * 8, mb_y * 8);
3185 let avail_top = mb_y > 0
3186 && self.nbr_in_slice(mb_x, mb_y - 1)
3187 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3188 let avail_left = mb_x > 0
3189 && self.nbr_in_slice(mb_x - 1, mb_y)
3190 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3191
3192 let mut c_recon_dc = [[0i32; 4]; 2];
3193 if cbp_chroma != 0 {
3194 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
3195 let dc = decode_residual_block(r, 4, -1)?;
3196 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 1 + c);
3197 }
3198 }
3199 let mut c_q_blocks = [[[0i32; 16]; 4]; 2];
3200 if cbp_chroma == 2 {
3201 self.chroma_cache_load(mb_x, mb_y);
3202 let w2 = self.mb_w * 2;
3203 for c in 0..2 {
3204 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3205 let nc = self.chroma_nc_pred(c, bx, by);
3206 let ac = decode_residual_block(r, 15, nc)?;
3207 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
3208 self.chroma_nnz_cache_set(c, bx, by, total);
3209 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
3210 un_scan_4x4_ac_into(&ac, &mut c_q_blocks[c][by * 2 + bx]);
3211 }
3212 }
3213 }
3214 for c in 0..2 {
3215 let mut ctop = [0u8; 8];
3216 let mut cleft = [0u8; 8];
3217 let mut ccorner = 0u8;
3218 {
3219 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
3220 if avail_top {
3221 for i in 0..8 {
3222 ctop[i] = rec_c[(cy - 1) * self.ccw + cx + i];
3223 }
3224 }
3225 if avail_left {
3226 for i in 0..8 {
3227 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
3228 }
3229 }
3230 if avail_top && avail_left {
3231 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
3232 }
3233 }
3234 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
3235 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3236 let mut predb = [0i32; 16];
3237 for dy in 0..4 {
3238 for dx in 0..4 {
3239 predb[dy * 4 + dx] = pred8[(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
3240 }
3241 }
3242 let mut deq = self.dequant(&c_q_blocks[c][by * 2 + bx], qpc, 1 + c);
3243 deq[0] = c_recon_dc[c][by * 2 + bx];
3244 let s = reconstruct_4x4(&deq, &predb);
3245 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3246 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
3247 }
3248 }
3249 Ok(())
3250 }
3251
3252 pub fn deblock(&mut self, offset_a: i32, offset_b: i32) {
3256 let nnz_db_storage;
3263 let nnz_db: &[u8] = if self.mb_t8x8.iter().any(|&t| t) {
3264 let mut n = self.nnz_y.clone();
3265 let w4 = self.mb_w * 4;
3266 for mb_y in 0..self.mb_h {
3267 for mb_x in 0..self.mb_w {
3268 if !self.mb_t8x8[mb_y * self.mb_w + mb_x] {
3269 continue;
3270 }
3271 for b8 in 0..4 {
3272 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, mb_y * 4 + (b8 / 2) * 2);
3273 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + (bx + sx)] > 0));
3274 for sy in 0..2 {
3275 for sx in 0..2 {
3276 n[(by + sy) * w4 + (bx + sx)] = u8::from(any);
3277 }
3278 }
3279 }
3280 }
3281 }
3282 nnz_db_storage = n;
3283 &nnz_db_storage
3284 } else {
3285 &self.nnz_y
3286 };
3287 let ref_id: Vec<i32> = self
3290 .ref_idx_y
3291 .iter()
3292 .map(|&r| if r >= 0 { self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3293 .collect();
3294 let ref_id1: Vec<i32> = if self.refs1.is_empty() {
3297 Vec::new()
3298 } else {
3299 self.ref_idx1
3300 .iter()
3301 .map(|&r| if r >= 0 { self.refs1.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3302 .collect()
3303 };
3304 let info = rusty_h264_common::deblock::BlockInfo {
3305 inter: &self.inter_y,
3306 nnz: nnz_db,
3307 mv: &self.mv_y,
3308 ref_id: &ref_id,
3309 mv1: &self.mv1,
3310 ref_id1: &ref_id1,
3311 w4: self.mb_w * 4,
3312 t8x8: &self.mb_t8x8,
3313 bs: &[],
3314 };
3315 rusty_h264_common::deblock::filter_frame(
3316 &mut self.rec_y,
3317 &mut self.rec_u,
3318 &mut self.rec_v,
3319 self.mb_w,
3320 self.mb_h,
3321 &self.mb_qp,
3322 self.chroma_qp_offset,
3323 offset_a,
3324 offset_b,
3325 &info,
3326 );
3327 }
3328
3329 pub fn into_frame(self, crop_r: usize, crop_b: usize) -> YuvFrame {
3331 if crop_r == 0 && crop_b == 0 {
3334 return YuvFrame {
3335 width: self.cw,
3336 height: self.ch,
3337 y: self.rec_y,
3338 u: self.rec_u,
3339 v: self.rec_v,
3340 };
3341 }
3342 let dw = self.cw - 2 * crop_r;
3343 let dh = self.ch - 2 * crop_b;
3344 let mut y = vec![0u8; dw * dh];
3345 for row in 0..dh {
3346 y[row * dw..row * dw + dw].copy_from_slice(&self.rec_y[row * self.cw..row * self.cw + dw]);
3347 }
3348 let (cdw, cdh) = (dw / 2, dh / 2);
3349 let mut u = vec![0u8; cdw * cdh];
3350 let mut v = vec![0u8; cdw * cdh];
3351 for row in 0..cdh {
3352 u[row * cdw..row * cdw + cdw]
3353 .copy_from_slice(&self.rec_u[row * self.ccw..row * self.ccw + cdw]);
3354 v[row * cdw..row * cdw + cdw]
3355 .copy_from_slice(&self.rec_v[row * self.ccw..row * self.ccw + cdw]);
3356 }
3357 let _ = self.cch;
3358 YuvFrame {
3359 width: dw,
3360 height: dh,
3361 y,
3362 u,
3363 v,
3364 }
3365 }
3366}
3367
3368fn cabac_unary(cab: &mut crate::cabac::Cabac, ctx: usize, off: usize) -> u32 {
3375 if cab.decode_decision(ctx) == 0 {
3376 return 0;
3377 }
3378 let mut sym = 0;
3379 loop {
3380 let bin = cab.decode_decision(ctx + off);
3381 sym += 1;
3382 if bin == 0 || sym >= 512 {
3387 break;
3388 }
3389 }
3390 sym
3391}
3392
3393fn cabac_exp_bypass(cab: &mut crate::cabac::Cabac, mut count: i32) -> u32 {
3395 let mut sym = 0u32;
3396 loop {
3397 let c = cab.decode_bypass();
3398 if c == 1 {
3399 sym += 1 << count;
3400 count += 1;
3401 }
3402 if c == 0 || count == 16 {
3403 break;
3404 }
3405 }
3406 let mut sym2 = 0u32;
3407 while count > 0 {
3408 count -= 1;
3409 if cab.decode_bypass() != 0 {
3410 sym2 |= 1 << count;
3411 }
3412 }
3413 sym + sym2
3414}
3415
3416fn cabac_ueg_level(cab: &mut crate::cabac::Cabac, ctx: usize) -> u32 {
3419 if cab.decode_decision(ctx) == 0 {
3420 return 0;
3421 }
3422 let mut code = 0u32;
3423 let mut count = 1;
3424 let mut tmp;
3425 loop {
3426 tmp = cab.decode_decision(ctx);
3427 code += 1;
3428 count += 1;
3429 if tmp == 0 || count == 13 {
3430 break;
3431 }
3432 }
3433 if tmp != 0 {
3434 code += cabac_exp_bypass(cab, 0) + 1;
3435 }
3436 code
3437}
3438
3439fn parse_mb_qp_delta_cabac(cab: &mut crate::cabac::Cabac, last_delta_qp: &mut i32) -> i32 {
3441 const O: usize = 60;
3442 let ctx_inc = (*last_delta_qp != 0) as usize;
3443 let mut qp_delta = 0;
3444 if cab.decode_decision(O + ctx_inc) != 0 {
3445 let code = cabac_unary(cab, O + 2, 1) + 1;
3446 qp_delta = ((code + 1) >> 1) as i32;
3447 if code & 1 == 0 {
3448 qp_delta = -qp_delta;
3449 }
3450 }
3451 *last_delta_qp = qp_delta;
3452 qp_delta
3453}
3454
3455const NZC_CACHE: [usize; 24] = [
3458 9, 10, 17, 18, 11, 12, 19, 20, 25, 26, 33, 34, 27, 28, 35, 36, 14, 15, 22, 23, 38, 39, 46, 47, ];
3462
3463const RES_MAXPOS: [i32; 11] = [0, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14];
3465const RES_MAXC2: [i32; 11] = [0, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4];
3466const RES_CBF: [usize; 11] = [0, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16];
3467const RES_MAP: [usize; 11] = [0, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47];
3468const RES_ONE: [usize; 11] = [0, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39];
3469const RP_I16_DC: usize = 1;
3471const RP_I16_AC: usize = 2;
3472const RP_LUMA_4X4: usize = 3;
3473const RP_CHROMA_DC: usize = 7; const RP_CHROMA_AC: usize = 9; #[allow(clippy::too_many_arguments)]
3481fn parse_residual_cabac(
3482 cab: &mut crate::cabac::Cabac,
3483 nzc: &mut [u8; 48],
3484 cbf_dc: &mut u16,
3485 iz: usize,
3486 rp: usize,
3487 is_intra: bool,
3488 ndc: (Option<u16>, Option<u16>), out: &mut [i32], ) -> u32 {
3491 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Entropy);
3494 let is_dc = rp == RP_I16_DC || rp == RP_CHROMA_DC || rp == RP_CHROMA_DC + 1;
3496 let (mut na, mut nb) = (is_intra as u8, is_intra as u8);
3497 let scan = NZC_CACHE[iz.min(23)];
3498 if is_dc {
3499 if let Some(t) = ndc.0 {
3500 nb = ((t >> rp) & 1) as u8;
3501 }
3502 if let Some(l) = ndc.1 {
3503 na = ((l >> rp) & 1) as u8;
3504 }
3505 } else {
3506 if nzc[scan - 8] != 0xff {
3507 nb = (nzc[scan - 8] != 0) as u8;
3508 }
3509 if nzc[scan - 1] != 0xff {
3510 na = (nzc[scan - 1] != 0) as u8;
3511 }
3512 }
3513 let cbf = cab.decode_decision(85 + RES_CBF[rp] + (na + (nb << 1)) as usize);
3514 if cbf == 0 {
3515 if !is_dc {
3516 nzc[scan] = 0;
3517 }
3518 return 0;
3519 }
3520 if is_dc {
3521 *cbf_dc |= 1 << rp;
3522 }
3523 let maxpos = RES_MAXPOS[rp] as usize;
3525 let map = 105 + RES_MAP[rp];
3526 let last = 166 + RES_MAP[rp];
3527 let mut sig = [0i32; 64];
3528 let mut coeff_num = 0u32;
3529 let mut last_hit = false;
3530 for i in 0..maxpos {
3531 if cab.decode_decision(map + i) != 0 {
3532 sig[i] = 1;
3533 coeff_num += 1;
3534 if cab.decode_decision(last + i) != 0 {
3535 last_hit = true;
3536 break;
3537 }
3538 }
3539 }
3540 if !last_hit {
3541 sig[maxpos] = 1;
3542 coeff_num += 1;
3543 }
3544 let one = 227 + RES_ONE[rp];
3546 let abs = 232 + RES_ONE[rp];
3547 let maxc2 = RES_MAXC2[rp];
3548 let (mut c1, mut c2) = (1i32, 0i32);
3549 for i in (0..=maxpos).rev() {
3550 if sig[i] != 0 {
3551 let mut level = sig[i] + cab.decode_decision(one + c1 as usize) as i32;
3552 if level == 2 {
3553 level += cabac_ueg_level(cab, abs + c2 as usize) as i32;
3554 c2 = (c2 + 1).min(maxc2);
3555 c1 = 0;
3556 } else if c1 != 0 {
3557 c1 = (c1 + 1).min(4);
3558 }
3559 if cab.decode_bypass() != 0 {
3560 level = -level;
3561 }
3562 sig[i] = level;
3563 }
3564 }
3565 out[..=maxpos].copy_from_slice(&sig[..=maxpos]);
3566 if !is_dc {
3567 nzc[scan] = coeff_num as u8;
3568 }
3569 coeff_num
3570}
3571
3572const CACHE30: [usize; 16] = [7, 8, 13, 14, 9, 10, 15, 16, 19, 20, 25, 26, 21, 22, 27, 28];
3575
3576const G_SCAN4: [usize; 16] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15];
3579
3580fn parse_sub_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3582 const S: usize = 21;
3583 if cab.decode_decision(S) != 0 {
3584 return 0;
3585 }
3586 if cab.decode_decision(S + 1) != 0 {
3587 3 - cab.decode_decision(S + 2)
3588 } else {
3589 1
3590 }
3591}
3592
3593fn parse_intra_mb_type_cabac(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3596 if cab.decode_decision(base) == 0 {
3597 return 0; }
3599 if cab.decode_terminate() {
3600 return 25; }
3602 let mut t = 1 + 12 * cab.decode_decision(base + 1) as u32; if cab.decode_decision(base + 2) != 0 {
3604 t += 4 + 4 * cab.decode_decision(base + 2) as u32;
3605 }
3606 t += 2 * cab.decode_decision(base + 3) as u32;
3607 t += cab.decode_decision(base + 3) as u32;
3608 t
3609}
3610
3611fn parse_mb_type_b_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3615 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3616 const B: usize = 27;
3617 if cab.decode_decision(B + ctx_inc) == 0 {
3618 return 0; }
3620 if cab.decode_decision(B + 3) == 0 {
3621 return 1 + cab.decode_decision(B + 5) as u32; }
3623 let mut m = (cab.decode_decision(B + 4) as u32) << 3;
3624 m |= (cab.decode_decision(B + 5) as u32) << 2;
3625 m |= (cab.decode_decision(B + 5) as u32) << 1;
3626 m |= cab.decode_decision(B + 5) as u32;
3627 if m < 8 {
3628 return m + 3;
3629 }
3630 if m == 13 {
3631 return parse_intra_mb_type_cabac(cab, 32) + 23;
3632 }
3633 if m == 14 {
3634 return 11; }
3636 if m == 15 {
3637 return 22; }
3639 m = (m << 1) | cab.decode_decision(B + 5) as u32;
3640 m - 4
3641}
3642
3643fn parse_sub_mb_type_b_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3646 const B: usize = 36;
3647 if cab.decode_decision(B) == 0 {
3648 return 0; }
3650 if cab.decode_decision(B + 1) == 0 {
3651 return 1 + cab.decode_decision(B + 3) as u32; }
3653 let mut st = 3u32;
3654 if cab.decode_decision(B + 2) != 0 {
3655 if cab.decode_decision(B + 3) != 0 {
3656 return 11 + cab.decode_decision(B + 3) as u32; }
3658 st += 4;
3659 }
3660 st += 2 * cab.decode_decision(B + 3) as u32;
3661 st += cab.decode_decision(B + 3) as u32;
3662 st
3663}
3664
3665fn parse_mvd_partition(
3669 cab: &mut crate::cabac::Cabac,
3670 part_idx: usize,
3671 zblocks: &[usize],
3672 mvdc: &mut [[i16; 2]; 30],
3673 refc: &mut [i8; 30],
3674 mmvd: &mut [[i16; 2]; 16],
3675 mref: &mut [i8; 16],
3676 ref_idx: i8,
3677) -> (i32, i32) {
3678 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3679 let s = CACHE30[part_idx];
3680 let ctx = |comp: usize| -> usize {
3681 let mut a = 0i32;
3682 if refc[s - 6] >= 0 {
3683 a += mvdc[s - 6][comp].unsigned_abs() as i32;
3684 }
3685 if refc[s - 1] >= 0 {
3686 a += mvdc[s - 1][comp].unsigned_abs() as i32;
3687 }
3688 if a >= 3 {
3689 1 + (a > 32) as usize
3690 } else {
3691 0
3692 }
3693 };
3694 let (cx, cy) = (ctx(0), ctx(1));
3695 let mvx = parse_mvd_cabac(cab, 0, cx);
3696 let mvy = parse_mvd_cabac(cab, 1, cy);
3697 for &zb in zblocks {
3698 mvdc[CACHE30[zb]] = [mvx, mvy];
3699 refc[CACHE30[zb]] = ref_idx;
3700 mmvd[G_SCAN4[zb]] = [mvx, mvy];
3701 mref[G_SCAN4[zb]] = ref_idx;
3702 }
3703 (mvx as i32, mvy as i32)
3704}
3705
3706fn parse_ref_idx_cabac(cab: &mut crate::cabac::Cabac, ctx0: usize) -> i8 {
3709 const B: usize = 54;
3710 let mut r = 0i8;
3711 let mut bin_idx = 0u32;
3712 while bin_idx < 32 {
3716 let ctx = match bin_idx {
3717 0 => ctx0,
3718 1 => 4,
3719 _ => 5,
3720 };
3721 if cab.decode_decision(B + ctx) == 0 {
3722 break;
3723 }
3724 r += 1;
3725 bin_idx += 1;
3726 }
3727 r
3728}
3729
3730fn decode_ueg_mv(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3733 const P2C: [usize; 8] = [0, 1, 2, 3, 3, 3, 3, 3];
3734 if cab.decode_decision(base) == 0 {
3735 return 0;
3736 }
3737 let mut code = 0u32;
3738 let mut count = 1usize;
3739 let mut tmp;
3740 loop {
3741 tmp = cab.decode_decision(base + P2C[count]);
3742 code += 1;
3743 count += 1;
3744 if tmp == 0 || count == 8 {
3745 break;
3746 }
3747 }
3748 if tmp != 0 {
3749 code += cabac_exp_bypass(cab, 3) + 1;
3750 }
3751 code
3752}
3753
3754fn parse_mvd_cabac(cab: &mut crate::cabac::Cabac, comp: usize, ctx_inc: usize) -> i16 {
3757 let base = 40 + comp * 7; if cab.decode_decision(base + ctx_inc) == 0 {
3759 return 0;
3760 }
3761 let mag = (decode_ueg_mv(cab, base + 3) + 1) as i16;
3762 if cab.decode_bypass() != 0 {
3763 -mag
3764 } else {
3765 mag
3766 }
3767}
3768
3769fn parse_mb_skip_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> bool {
3772 cab.decode_decision(ctx_inc) != 0
3773}
3774
3775fn parse_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3778 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3779 const S: usize = 11; if cab.decode_decision(S + 3) == 0 {
3781 return if cab.decode_decision(S + 4) != 0 {
3783 if cab.decode_decision(S + 6) != 0 { 1 } else { 2 }
3784 } else if cab.decode_decision(S + 5) != 0 {
3785 3
3786 } else {
3787 0
3788 };
3789 }
3790 if cab.decode_decision(S + 6) == 0 {
3792 return 5; }
3794 if cab.decode_terminate() {
3795 return 30; }
3797 let mut t = 6 + cab.decode_decision(S + 7) * 12;
3798 if cab.decode_decision(S + 8) != 0 {
3799 t += 4;
3800 if cab.decode_decision(S + 8) != 0 {
3801 t += 4;
3802 }
3803 }
3804 t += cab.decode_decision(S + 9) << 1;
3805 t += cab.decode_decision(S + 9);
3806 t
3807}
3808
3809fn parse_mb_type_i_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3814 const O: usize = 3; if cab.decode_decision(O + ctx_inc) == 0 {
3816 return 0; }
3818 if cab.decode_terminate() {
3819 return 25; }
3821 let mut t = 1 + cab.decode_decision(O + 3) * 12; if cab.decode_decision(O + 4) != 0 {
3823 t += 4; if cab.decode_decision(O + 5) != 0 {
3825 t += 4;
3826 }
3827 }
3828 t += cab.decode_decision(O + 6) << 1; t += cab.decode_decision(O + 7);
3830 t
3831}
3832
3833fn parse_intra4x4_pred_mode_cabac(cab: &mut crate::cabac::Cabac) -> i32 {
3837 const IPR: usize = 68;
3838 if cab.decode_decision(IPR) == 1 {
3839 return -1; }
3841 let mut m = cab.decode_decision(IPR + 1) as i32;
3842 m |= (cab.decode_decision(IPR + 1) as i32) << 1;
3843 m |= (cab.decode_decision(IPR + 1) as i32) << 2;
3844 m
3845}
3846
3847fn parse_intra_chroma_pred_mode_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3851 const CIPR: usize = 64;
3852 if cab.decode_decision(CIPR + ctx_inc) == 0 {
3853 return 0;
3854 }
3855 if cab.decode_decision(CIPR + 3) == 0 {
3856 return 1;
3857 }
3858 if cab.decode_decision(CIPR + 3) == 0 {
3859 return 2;
3860 }
3861 3
3862}
3863
3864fn parse_cbp_cabac(cab: &mut crate::cabac::Cabac, top: Option<u8>, left: Option<u8>) -> u32 {
3869 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
3870 const CBP: usize = 73;
3871 let t = |m: u32| top.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
3872 let l = |m: u32| left.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
3873 let nb = |x: u32| (x == 0) as u32; let b0 = cab.decode_decision(CBP + (l(1 << 1) + (t(1 << 2) << 1)) as usize);
3876 let b1 = cab.decode_decision(CBP + (nb(b0) + (t(1 << 3) << 1)) as usize);
3877 let b2 = cab.decode_decision(CBP + (l(1 << 3) + (nb(b0) << 1)) as usize);
3878 let b3 = cab.decode_decision(CBP + (nb(b2) + (nb(b1) << 1)) as usize);
3879 let mut cbp = b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
3880 let ct = top.map_or(0u32, |c| ((c >> 4) != 0) as u32);
3882 let cl = left.map_or(0u32, |c| ((c >> 4) != 0) as u32);
3883 if cab.decode_decision(CBP + 4 + (cl + (ct << 1)) as usize) != 0 {
3884 let ct2 = top.map_or(0u32, |c| ((c >> 4) == 2) as u32);
3885 let cl2 = left.map_or(0u32, |c| ((c >> 4) == 2) as u32);
3886 let c1 = cab.decode_decision(CBP + 8 + (cl2 + (ct2 << 1)) as usize);
3887 cbp |= 1 << (4 + c1);
3888 }
3889 cbp
3890}
3891
3892fn read_ref_idx(r: &mut BitReader, num_ref_active: usize) -> Result<i32, OutOfData> {
3893 if num_ref_active == 2 {
3894 Ok(if r.read_bit()? { 0 } else { 1 }) } else {
3896 Ok(r.read_ue()? as i32)
3897 }
3898}
3899
3900#[derive(Clone, Copy, PartialEq)]
3902enum BPred {
3903 L0,
3904 L1,
3905 Bi,
3906}
3907impl BPred {
3908 fn uses(self, list: usize) -> bool {
3910 matches!(
3911 (self, list),
3912 (BPred::L0, 0) | (BPred::L1, 1) | (BPred::Bi, 0) | (BPred::Bi, 1)
3913 )
3914 }
3915}
3916
3917const B16X16: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 16)];
3918const B16X8: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 8), (0, 8, 16, 8)];
3919const B8X16: &[(usize, usize, usize, usize)] = &[(0, 0, 8, 16), (8, 0, 8, 16)];
3920
3921type Region = (usize, usize, usize, usize);
3923
3924fn b_inter_layout(mb_type: u32) -> (&'static [Region], u8, [BPred; 2]) {
3927 use BPred::*;
3928 match mb_type {
3929 1 => (B16X16, 0, [L0, L0]),
3930 2 => (B16X16, 0, [L1, L1]),
3931 3 => (B16X16, 0, [Bi, Bi]),
3932 4 => (B16X8, 1, [L0, L0]),
3933 5 => (B8X16, 2, [L0, L0]),
3934 6 => (B16X8, 1, [L1, L1]),
3935 7 => (B8X16, 2, [L1, L1]),
3936 8 => (B16X8, 1, [L0, L1]),
3937 9 => (B8X16, 2, [L0, L1]),
3938 10 => (B16X8, 1, [L1, L0]),
3939 11 => (B8X16, 2, [L1, L0]),
3940 12 => (B16X8, 1, [L0, Bi]),
3941 13 => (B8X16, 2, [L0, Bi]),
3942 14 => (B16X8, 1, [L1, Bi]),
3943 15 => (B8X16, 2, [L1, Bi]),
3944 16 => (B16X8, 1, [Bi, L0]),
3945 17 => (B8X16, 2, [Bi, L0]),
3946 18 => (B16X8, 1, [Bi, L1]),
3947 19 => (B8X16, 2, [Bi, L1]),
3948 20 => (B16X8, 1, [Bi, Bi]),
3949 _ => (B8X16, 2, [Bi, Bi]), }
3951}
3952
3953fn b_sub_uses(st: u32, list: usize) -> bool {
3955 let pred = match st {
3956 1 | 4 | 5 | 10 => 0, 2 | 6 | 7 | 11 => 1, _ => 2, };
3960 (list == 0 && pred != 1) || (list == 1 && pred != 0)
3961}
3962
3963fn b_sub_parts(st: u32) -> &'static [(usize, usize, usize, usize)] {
3965 match st {
3966 1..=3 => &[(0, 0, 8, 8)],
3967 4 | 6 | 8 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
3968 5 | 7 | 9 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
3969 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)], }
3971}
3972
3973fn sub_mb_partitions(sub_type: u32) -> &'static [(usize, usize, usize, usize)] {
3976 match sub_type {
3977 0 => &[(0, 0, 8, 8)],
3978 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
3979 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
3980 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
3981 }
3982}
3983
3984fn store(plane: &mut [u8], stride: usize, x0: usize, y0: usize, s: &[u8; 16]) {
3985 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Scatter);
3986 for dy in 0..4 {
3987 for dx in 0..4 {
3988 plane[(y0 + dy) * stride + (x0 + dx)] = s[dy * 4 + dx];
3989 }
3990 }
3991}
3992
3993fn un_scan_8x8(scan: &[i32; 64]) -> [i32; 64] {
3995 const ZZ8: [usize; 64] = [
3996 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,
3997 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
3998 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
3999 ];
4000 let mut out = [0i32; 64];
4001 for k in 0..64 {
4002 out[ZZ8[k]] = scan[k];
4003 }
4004 out
4005}
4006
4007#[cfg(test)]
4008mod tests {
4009 use super::*;
4010
4011 fn fd(qp: u8, offset: i32) -> FrameDecoder {
4012 FrameDecoder::new(1, 1, qp, offset, Vec::new(), 1, false, false, true)
4013 }
4014
4015 #[test]
4016 fn mb_qp_delta_accumulates_mod_52() {
4017 let mut d = fd(26, 0);
4018 assert_eq!(d.cur_qp, 26, "QPy starts at the slice QP");
4019 d.step_qp(4);
4020 assert_eq!(d.cur_qp, 30); d.step_qp(-10);
4022 assert_eq!(d.cur_qp, 20); d.step_qp(40);
4025 assert_eq!(d.cur_qp, 8);
4026 d.step_qp(-20);
4028 assert_eq!(d.cur_qp, 40);
4029 }
4030
4031 #[test]
4032 fn chroma_qp_index_offset_applied_and_clamped() {
4033 assert_eq!(fd(0, 0).chroma_qp_for(30), 29);
4035 assert_eq!(fd(0, 2).chroma_qp_for(30), 31);
4037 assert_eq!(fd(0, -12).chroma_qp_for(5), chroma_qp(0));
4039 assert_eq!(fd(0, 99).chroma_qp_for(40), chroma_qp(51));
4040 }
4041}