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, reconstruct_4x4_dc, reconstruct_4x4_dc_into, reconstruct_4x4_into, I16Mode,
19 CHROMA_4X4_SCAN_XY, LUMA_4X4_SCAN_XY,
20};
21use rusty_h264_common::transform::{
22 dequant_scatter_4x4, dequantize, dequantize_weighted, inverse_quant_8x8,
23 inverse_quant_chroma_dc,
24 inverse_quant_chroma_dc_weighted, inverse_quant_luma_dc, inverse_quant_luma_dc_weighted,
25};
26use rusty_h264_common::{BitReader, YuvFrame};
27
28pub struct MvField {
34 pub mb_w: usize,
35 pub mb_h: usize,
36 pub mv: Vec<(i32, i32)>,
37 pub ref_idx: Vec<i32>,
38 pub inter: Vec<bool>,
39}
40
41pub static MV_DUMP: std::sync::Mutex<Vec<MvField>> = std::sync::Mutex::new(Vec::new());
43
44pub fn mv_dump_on() -> bool {
45 static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
46 *ON.get_or_init(|| std::env::var("RFF_MV_DUMP").map_or(false, |v| v != "0"))
47}
48
49pub struct FrameDecoder {
51 mb_w: usize,
52 mb_h: usize,
53 qp: u8,
55 cur_qp: u8,
58 chroma_qp_offset: i32,
60 cw: usize,
61 ch: usize,
62 ccw: usize,
63 cch: usize,
64 rec_y: Vec<u8>,
65 rec_u: Vec<u8>,
66 rec_v: Vec<u8>,
67 mb_qp: Vec<u8>,
69 slice_first_mb: usize,
74 nnz_y: Vec<u8>,
75 nnz_c: [Vec<u8>; 2],
76 modes_y: Vec<u8>,
77 coded_y: Vec<bool>,
78 mv_y: Vec<(i32, i32)>,
81 inter_y: Vec<bool>,
82 ref_idx_y: Vec<i32>,
83 mv1: Vec<(i32, i32)>,
85 ref_idx1: Vec<i32>,
86 refs1: Vec<crate::Ref>,
88 num_ref_active1: usize,
89 is_b: bool,
90 b_possible: bool,
94 direct_spatial: bool,
95 nnz_l_cache: [u8; 25],
96 nnz_c_cache: [[u8; 9]; 2],
97 refs: Vec<crate::Ref>,
100 num_ref_active: usize,
104 constrained_intra: bool,
107 scaling: Option<[[i32; 16]; 6]>,
110 scaling8: Option<[[i32; 64]; 2]>,
113 transform_8x8_mode: bool,
115 mb_t8x8: Vec<bool>,
118 bs_frame: Vec<rusty_h264_common::deblock::MbBs>,
121 bs_rows: usize,
123 flt_rows: usize,
125 pk_prev: Vec<rusty_h264_common::deblock::MbPack>,
127 pk_cur: Vec<rusty_h264_common::deblock::MbPack>,
128 nnz_dbr: Vec<u8>,
130 bak_y: Vec<u8>,
132 bak_u: Vec<u8>,
133 bak_v: Vec<u8>,
134 edc_jobs: Vec<EdcJob>,
137 edc_active: bool,
138 db_ena: bool,
140 db_oa: i32,
141 db_ob: i32,
142 mb_kind: Vec<u8>,
149 weights: Option<WeightTable>,
151 cur_poc: i32,
153 weighted_bipred_idc: u8,
155 direct_8x8_inference: bool,
157}
158
159#[derive(Clone, Default)]
163pub struct WeightTable {
164 pub luma_log2_denom: i32,
165 pub chroma_log2_denom: i32,
166 pub luma: [Vec<(i32, i32)>; 2],
168 pub chroma: [Vec<[(i32, i32); 2]>; 2],
170}
171
172impl WeightTable {
173 fn apply_luma(&self, sample: u8, list: usize, refi: usize) -> u8 {
175 let (w, o) = self.luma[list][refi];
176 let lwd = self.luma_log2_denom;
177 let v = if lwd >= 1 {
178 ((sample as i32 * w + (1 << (lwd - 1))) >> lwd) + o
179 } else {
180 sample as i32 * w + o
181 };
182 v.clamp(0, 255) as u8
183 }
184
185 fn apply_chroma(&self, sample: u8, list: usize, refi: usize, cc: usize) -> u8 {
187 let (w, o) = self.chroma[list][refi][cc];
188 let cwd = self.chroma_log2_denom;
189 let v = if cwd >= 1 {
190 ((sample as i32 * w + (1 << (cwd - 1))) >> cwd) + o
191 } else {
192 sample as i32 * w + o
193 };
194 v.clamp(0, 255) as u8
195 }
196}
197
198#[derive(Debug, Clone, PartialEq, Eq)]
200pub enum MbError {
201 Truncated,
202 Unsupported(&'static str),
203}
204
205impl From<OutOfData> for MbError {
206 fn from(_: OutOfData) -> Self {
207 MbError::Truncated
208 }
209}
210
211#[derive(Default)]
233pub struct GridPool {
234 mb_qp: Vec<u8>,
235 bs_frame: Vec<rusty_h264_common::deblock::MbBs>,
236 pk_prev: Vec<rusty_h264_common::deblock::MbPack>,
237 pk_cur: Vec<rusty_h264_common::deblock::MbPack>,
238 nnz_dbr: Vec<u8>,
239 bak_y: Vec<u8>,
240 bak_u: Vec<u8>,
241 bak_v: Vec<u8>,
242 nnz_y: Vec<u8>,
243 nnz_c0: Vec<u8>,
244 nnz_c1: Vec<u8>,
245 modes_y: Vec<u8>,
246 coded_y: Vec<bool>,
247 mv_y: Vec<(i32, i32)>,
248 inter_y: Vec<bool>,
249 ref_idx_y: Vec<i32>,
250 mv1: Vec<(i32, i32)>,
251 ref_idx1: Vec<i32>,
252 mb_t8x8: Vec<bool>,
253 mb_kind: Vec<u8>,
254}
255
256#[inline]
260fn refill<T: Clone>(mut v: Vec<T>, n: usize, val: T) -> Vec<T> {
261 v.clear();
262 v.resize(n, val);
263 v
264}
265
266impl FrameDecoder {
267 pub fn new(
268 mb_w: usize,
269 mb_h: usize,
270 qp: u8,
271 chroma_qp_offset: i32,
272 refs: Vec<crate::Ref>,
273 num_ref_active: usize,
274 constrained_intra: bool,
275 transform_8x8_mode: bool,
276 b_possible: bool,
277 ) -> Self {
278 Self::with_pool(
279 mb_w,
280 mb_h,
281 qp,
282 chroma_qp_offset,
283 refs,
284 num_ref_active,
285 constrained_intra,
286 transform_8x8_mode,
287 b_possible,
288 GridPool::default(),
289 )
290 }
291
292 #[allow(clippy::too_many_arguments)]
294 pub fn with_pool(
295 mb_w: usize,
296 mb_h: usize,
297 qp: u8,
298 chroma_qp_offset: i32,
299 refs: Vec<crate::Ref>,
300 num_ref_active: usize,
301 constrained_intra: bool,
302 transform_8x8_mode: bool,
303 b_possible: bool,
304 pool: GridPool,
305 ) -> Self {
306 let (cw, ch) = (mb_w * 16, mb_h * 16);
307 let (ccw, cch) = (cw / 2, ch / 2);
308 Self {
309 mb_w,
310 mb_h,
311 qp,
312 cur_qp: qp,
313 chroma_qp_offset,
314 cw,
315 ch,
316 ccw,
317 cch,
318 rec_y: vec![0; cw * ch],
319 rec_u: vec![0; ccw * cch],
320 rec_v: vec![0; ccw * cch],
321 mb_qp: refill(pool.mb_qp, mb_w * mb_h, qp),
322 slice_first_mb: 0,
323 nnz_y: refill(pool.nnz_y, (mb_w * 4) * (mb_h * 4), 0),
324 nnz_c: [
325 refill(pool.nnz_c0, (mb_w * 2) * (mb_h * 2), 0),
326 refill(pool.nnz_c1, (mb_w * 2) * (mb_h * 2), 0),
327 ],
328 modes_y: refill(pool.modes_y, (mb_w * 4) * (mb_h * 4), 2),
329 coded_y: refill(pool.coded_y, (mb_w * 4) * (mb_h * 4), false),
330 mv_y: refill(pool.mv_y, (mb_w * 4) * (mb_h * 4), (0, 0)),
331 inter_y: refill(pool.inter_y, (mb_w * 4) * (mb_h * 4), false),
332 ref_idx_y: refill(pool.ref_idx_y, (mb_w * 4) * (mb_h * 4), -1),
333 mv1: refill(pool.mv1, (mb_w * 4) * (mb_h * 4), (0, 0)),
334 ref_idx1: refill(pool.ref_idx1, (mb_w * 4) * (mb_h * 4), -1),
335 refs1: Vec::new(),
336 num_ref_active1: 0,
337 is_b: false,
338 b_possible,
339 direct_spatial: true,
340 nnz_l_cache: [0x80; 25],
341 nnz_c_cache: [[0x80; 9]; 2],
342 refs,
343 num_ref_active,
344 constrained_intra,
345 scaling: None,
346 scaling8: None,
347 transform_8x8_mode,
348 mb_t8x8: refill(pool.mb_t8x8, mb_w * mb_h, false),
349 bs_frame: refill(pool.bs_frame, mb_w * mb_h, Default::default()),
350 bs_rows: 0,
351 flt_rows: 0,
352 pk_prev: {
353 let mut v = pool.pk_prev;
354 v.clear();
355 v
356 },
357 pk_cur: {
358 let mut v = pool.pk_cur;
359 v.clear();
360 v
361 },
362 nnz_dbr: refill(pool.nnz_dbr, (mb_w * 4) * (mb_h * 4), 0),
363 bak_y: refill(pool.bak_y, cw, 0),
364 bak_u: refill(pool.bak_u, ccw, 0),
365 bak_v: refill(pool.bak_v, ccw, 0),
366 edc_jobs: Vec::new(),
367 edc_active: false,
368 db_ena: false,
369 db_oa: 0,
370 db_ob: 0,
371 mb_kind: refill(
372 pool.mb_kind,
373 mb_w * mb_h,
374 rusty_h264_common::deblock::MB_KIND_UNSET,
375 ),
376 weights: None,
377 cur_poc: 0,
378 weighted_bipred_idc: 0,
379 direct_8x8_inference: false,
380 }
381 }
382
383 pub fn set_weights(&mut self, weights: WeightTable) {
385 self.weights = Some(weights);
386 }
387
388 fn weight_partition(
392 &self,
393 pred_y: &mut [u8; 256],
394 c_pred: &mut [[u8; 64]; 2],
395 list: usize,
396 refi: usize,
397 rx: usize,
398 ry: usize,
399 rw: usize,
400 rh: usize,
401 ) {
402 let Some(wt) = &self.weights else { return };
403 for dy in 0..rh {
404 for dx in 0..rw {
405 let i = (ry + dy) * 16 + (rx + dx);
406 pred_y[i] = wt.apply_luma(pred_y[i], list, refi);
407 }
408 }
409 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
410 for cc in 0..2 {
411 for dy in 0..crh {
412 for dx in 0..crw {
413 let i = (cry + dy) * 8 + (crx + dx);
414 c_pred[cc][i] = wt.apply_chroma(c_pred[cc][i], list, refi, cc);
415 }
416 }
417 }
418 }
419
420 pub fn set_scaling(&mut self, scaling: [[i32; 16]; 6], scaling8: [[i32; 64]; 2]) {
423 self.scaling = Some(scaling);
424 self.scaling8 = Some(scaling8);
425 }
426
427 fn dequant(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
429 match &self.scaling {
430 Some(s) => dequantize_weighted(levels, qp, &s[list]),
431 None => dequantize(levels, qp),
432 }
433 }
434
435 fn dequant_dc4(&self, level: i32, qp: u8, list: usize) -> i32 {
437 rusty_h264_common::transform::dequantize_dc4(
438 level,
439 qp,
440 self.scaling.as_ref().map(|s| s[list][0]),
441 )
442 }
443
444 fn dequant_luma_dc(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
446 match &self.scaling {
447 Some(s) => inverse_quant_luma_dc_weighted(levels, qp, s[list][0]),
448 None => inverse_quant_luma_dc(levels, qp),
449 }
450 }
451
452 fn dequant_chroma_dc(&self, levels: &[i32; 4], qp: u8, list: usize) -> [i32; 4] {
454 match &self.scaling {
455 Some(s) => inverse_quant_chroma_dc_weighted(levels, qp, s[list][0]),
456 None => inverse_quant_chroma_dc(levels, qp),
457 }
458 }
459
460 #[allow(clippy::too_many_arguments)]
463 pub fn set_b_context(
464 &mut self,
465 refs1: Vec<crate::Ref>,
466 num_ref_active1: usize,
467 direct_spatial: bool,
468 cur_poc: i32,
469 weighted_bipred_idc: u8,
470 direct_8x8_inference: bool,
471 ) {
472 self.is_b = true;
473 self.refs1 = refs1;
474 self.num_ref_active1 = num_ref_active1;
475 self.direct_spatial = direct_spatial;
476 self.cur_poc = cur_poc;
477 self.weighted_bipred_idc = weighted_bipred_idc;
478 self.direct_8x8_inference = direct_8x8_inference;
479 }
480
481 fn step_qp(&mut self, delta: i32) {
484 self.cur_qp = (self.cur_qp as i32 + delta + 52).rem_euclid(52) as u8;
485 }
486
487 fn chroma_qp_for(&self, qp_y: u8) -> u8 {
490 let qpi = (qp_y as i32 + self.chroma_qp_offset).clamp(0, 51) as u8;
491 chroma_qp(qpi)
492 }
493
494 pub fn begin_slice(&mut self, slice_qp: u8, refs: Vec<crate::Ref>, num_ref_active: usize) {
498 self.cur_qp = slice_qp;
499 self.qp = slice_qp;
500 self.refs = refs;
501 self.num_ref_active = num_ref_active;
502 self.weights = None; }
504
505 #[inline]
509 fn nbr_in_slice(&self, nbx: usize, nby: usize) -> bool {
510 nby * self.mb_w + nbx >= self.slice_first_mb
511 }
512
513 #[inline]
517 fn intra_nbr_ok(&self, nbx: usize, nby: usize) -> bool {
518 !self.constrained_intra || !self.inter_y[nby * (self.mb_w * 4) + nbx]
519 }
520
521 fn mv_neighbors(&self, mb_x: usize, mb_y: usize) -> [MvNeighbor; 3] {
522 let w4 = self.mb_w * 4;
523 let get = |avail: bool, bx: isize, by: isize| {
524 if avail {
525 let idx = by as usize * w4 + bx as usize;
526 MvNeighbor {
527 available: true,
528 mv: self.mv_y[idx],
529 ref_idx: self.ref_idx_y[idx],
530 }
531 } else {
532 MvNeighbor::NONE
533 }
534 };
535 let (bx, by) = (mb_x as isize * 4, mb_y as isize * 4);
536 let a = get(mb_x > 0 && self.nbr_in_slice(mb_x - 1, mb_y), bx - 1, by);
537 let b = get(mb_y > 0 && self.nbr_in_slice(mb_x, mb_y - 1), bx, by - 1);
538 let c = if mb_y > 0 && mb_x + 1 < self.mb_w && self.nbr_in_slice(mb_x + 1, mb_y - 1) {
539 get(true, bx + 4, by - 1)
540 } else {
541 get(mb_x > 0 && mb_y > 0 && self.nbr_in_slice(mb_x - 1, mb_y - 1), bx - 1, by - 1)
542 };
543 [a, b, c]
544 }
545
546 fn mv_neighbors_block(&self, pbx: isize, pby: isize, pwb: isize) -> [MvNeighbor; 3] {
547 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Neighbors);
548 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
549 let get = |bx: isize, by: isize| -> MvNeighbor {
550 if bx < 0
552 || by < 0
553 || bx >= w4
554 || by >= h4
555 || !self.coded_y[(by * w4 + bx) as usize]
556 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
557 {
558 MvNeighbor::NONE
559 } else {
560 let idx = (by * w4 + bx) as usize;
561 MvNeighbor { available: true, mv: self.mv_y[idx], ref_idx: self.ref_idx_y[idx] }
562 }
563 };
564 let a = get(pbx - 1, pby);
565 let b = get(pbx, pby - 1);
566 let mut c = get(pbx + pwb, pby - 1);
567 if !c.available {
568 c = get(pbx - 1, pby - 1);
569 }
570 [a, b, c]
571 }
572
573 fn skip_mv(&self, mb_x: usize, mb_y: usize) -> (i32, i32) {
574 let [a, b, c] = self.mv_neighbors(mb_x, mb_y);
575 if !a.available
576 || !b.available
577 || (a.ref_idx == 0 && a.mv == (0, 0))
578 || (b.ref_idx == 0 && b.mv == (0, 0))
579 {
580 (0, 0)
581 } else {
582 predict_mv(a, b, c, 0)
583 }
584 }
585
586 fn set_mb_mv(&mut self, mb_x: usize, mb_y: usize, mv: (i32, i32), inter: bool, refi: i32) {
587 let w4 = self.mb_w * 4;
588 for dy in 0..4 {
589 for dx in 0..4 {
590 let idx = (mb_y * 4 + dy) * w4 + (mb_x * 4 + dx);
591 self.mv_y[idx] = mv;
592 self.inter_y[idx] = inter;
593 self.ref_idx_y[idx] = if inter { refi } else { -1 };
594 }
595 }
596 }
597
598 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) {
602 let w4 = self.mb_w * 4;
603 for by in ry / 4..ry / 4 + rh / 4 {
604 for bx in rx / 4..rx / 4 + rw / 4 {
605 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
606 self.mv_y[idx] = mv;
607 self.inter_y[idx] = true;
608 self.ref_idx_y[idx] = refi as i32;
609 self.coded_y[idx] = true;
610 }
611 }
612 }
613
614 pub fn set_deblock_params(&mut self, ena: bool, oa: i32, ob: i32) {
617 self.db_ena = ena && (self.flt_rows == 0 || self.db_ena);
621 self.db_oa = oa;
622 self.db_ob = ob;
623 }
624
625 fn derive_bs_row(&mut self, r: usize) {
629 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DebDerive);
632 use rusty_h264_common::deblock::{derive_mb_records, pack_mb, BlockInfo, MbBs};
633 let (mb_w, w4) = (self.mb_w, self.mb_w * 4);
634 for br in r * 4..r * 4 + 4 {
637 let a = br * w4;
638 self.nnz_dbr[a..a + w4].copy_from_slice(&self.nnz_y[a..a + w4]);
639 }
640 for mb_x in 0..mb_w {
641 if !self.mb_t8x8[r * mb_w + mb_x] {
642 continue;
643 }
644 for b8 in 0..4usize {
645 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, r * 4 + (b8 / 2) * 2);
646 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + bx + sx] > 0));
647 for sy in 0..2 {
648 for sx in 0..2 {
649 self.nnz_dbr[(by + sy) * w4 + bx + sx] = any as u8;
650 }
651 }
652 }
653 }
654 let poc0: Vec<i32> = self.refs.iter().map(|f| f.poc).collect();
655 let poc1: Vec<i32> = self.refs1.iter().map(|f| f.poc).collect();
656 let info = BlockInfo {
657 inter: &self.inter_y,
658 nnz: &self.nnz_dbr,
659 mv: &self.mv_y,
660 ref_id: &self.ref_idx_y,
661 mv1: &self.mv1,
662 ref_id1: if poc1.is_empty() { &[] } else { &self.ref_idx1 },
663 w4,
664 t8x8: &self.mb_t8x8,
665 bs: &[],
666 poc0: &poc0,
667 poc1: &poc1,
668 kind: &[],
669 };
670 let has1 = !info.ref_id1.is_empty();
671 std::mem::swap(&mut self.pk_prev, &mut self.pk_cur);
672 self.pk_cur.clear();
673 for mb_x in 0..mb_w {
674 self.pk_cur.push(pack_mb(&info, has1, mb_x, r));
675 let cur = &self.pk_cur[mb_x];
676 let left = if mb_x > 0 { Some(&self.pk_cur[mb_x - 1]) } else { None };
677 let top = if r > 0 { Some(&self.pk_prev[mb_x]) } else { None };
678 let mb_t8 = self.mb_t8x8[r * mb_w + mb_x];
679 let (mut bv, mut bh) = ([[0i32; 4]; 4], [[0i32; 4]; 4]);
680 derive_mb_records(cur, left, top, mb_t8, &mut bv, &mut bh);
681 let mut m = MbBs::default();
682 for e in 0..4 {
683 for sg in 0..4 {
684 m.v[e][sg] = bv[e][sg] as u8;
685 m.h[e][sg] = bh[e][sg] as u8;
686 }
687 }
688 self.bs_frame[r * mb_w + mb_x] = m;
689 }
690 }
691
692 #[inline]
698 fn row_hook(&mut self, addr: usize) {
699 if !rowdb_on() {
700 self.edc_flush();
704 return;
705 }
706 let done = addr / self.mb_w;
707 if self.bs_rows < done {
708 self.edc_flush();
709 }
710 while self.bs_rows < done {
711 let r = self.bs_rows;
712 self.derive_bs_row(r);
713 self.bs_rows += 1;
714 if self.db_ena {
719 self.save_bak(r);
720 self.filter_row(r);
721 self.flt_rows = r + 1;
722 }
723 }
724 }
725
726 fn save_bak(&mut self, r: usize) {
732 let y0 = (r * 16 + 15) * self.cw;
733 self.bak_y.copy_from_slice(&self.rec_y[y0..y0 + self.cw]);
734 let c0 = (r * 8 + 7) * self.ccw;
735 self.bak_u.copy_from_slice(&self.rec_u[c0..c0 + self.ccw]);
736 self.bak_v.copy_from_slice(&self.rec_v[c0..c0 + self.ccw]);
737 }
738
739 fn filter_row(&mut self, r: usize) {
744 let info = rusty_h264_common::deblock::BlockInfo {
745 inter: &self.inter_y,
746 nnz: &self.nnz_dbr,
747 mv: &self.mv_y,
748 ref_id: &self.ref_idx_y,
749 mv1: &self.mv1,
750 ref_id1: &self.ref_idx1,
751 w4: self.mb_w * 4,
752 t8x8: &self.mb_t8x8,
753 bs: &self.bs_frame,
754 poc0: &[],
755 poc1: &[],
756 kind: &self.mb_kind,
757 };
758 rusty_h264_common::deblock::filter_frame_rows(
759 &mut self.rec_y,
760 &mut self.rec_u,
761 &mut self.rec_v,
762 self.mb_w,
763 self.mb_h,
764 r..r + 1,
765 &self.mb_qp,
766 self.chroma_qp_offset,
767 self.db_oa,
768 self.db_ob,
769 &info,
770 );
771 }
772
773 #[inline]
778 fn top_y_px(&self, py: usize, x: usize) -> u8 {
779 if py % 16 == 0 && self.flt_rows * 16 >= py {
780 self.bak_y[x]
781 } else {
782 self.rec_y[(py - 1) * self.cw + x]
783 }
784 }
785
786 #[inline]
788 fn top_y_row(&self, py: usize, x: usize, n: usize) -> &[u8] {
789 if py % 16 == 0 && self.flt_rows * 16 >= py {
790 &self.bak_y[x..x + n]
791 } else {
792 &self.rec_y[(py - 1) * self.cw + x..][..n]
793 }
794 }
795
796 #[inline]
798 fn top_c_px(&self, c: usize, cy: usize, x: usize) -> u8 {
799 if cy % 8 == 0 && self.flt_rows * 8 >= cy {
800 if c == 0 { self.bak_u[x] } else { self.bak_v[x] }
801 } else {
802 let rec = if c == 0 { &self.rec_u } else { &self.rec_v };
803 rec[(cy - 1) * self.ccw + x]
804 }
805 }
806
807 #[inline]
809 fn top_c_row(&self, c: usize, cy: usize, x: usize, n: usize) -> &[u8] {
810 if cy % 8 == 0 && self.flt_rows * 8 >= cy {
811 if c == 0 { &self.bak_u[x..x + n] } else { &self.bak_v[x..x + n] }
812 } else {
813 let rec = if c == 0 { &self.rec_u } else { &self.rec_v };
814 &rec[(cy - 1) * self.ccw + x..][..n]
815 }
816 }
817
818 pub fn as_reference(&self) -> crate::RefFrame {
820 self.as_reference_pooled(&mut Vec::new())
821 }
822
823 pub fn as_reference_pooled(&self, pool: &mut Vec<Vec<u8>>) -> crate::RefFrame {
828 if mv_dump_on() {
832 MV_DUMP.lock().unwrap().push(MvField {
833 mb_w: self.mb_w,
834 mb_h: self.mb_h,
835 mv: self.mv_y.clone(),
836 ref_idx: self.ref_idx_y.clone(),
837 inter: self.inter_y.clone(),
838 });
839 }
840
841 let (mv, ref_idx, mv1, ref_idx1, ref_poc, w4) = if self.b_possible {
847 (
848 self.mv_y.clone(),
849 self.ref_idx_y.clone(),
850 self.mv1.clone(),
851 self.ref_idx1.clone(),
852 self.ref_idx_y
855 .iter()
856 .map(|&r| {
857 if r >= 0 {
858 self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc)
859 } else {
860 i32::MIN
861 }
862 })
863 .collect(),
864 self.mb_w * 4,
865 )
866 } else {
867 (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), 0)
868 };
869 let mut take = |len: usize| -> Vec<u8> {
872 match pool.iter().position(|v| v.len() == len) {
873 Some(i) => pool.swap_remove(i),
874 None => Vec::new(),
875 }
876 };
877 let (lpw, lph) = (self.cw + 2 * crate::LPAD, self.ch + 2 * crate::LPAD);
878 let (cpw, cph) = (self.ccw + 2 * crate::CPAD, self.ch / 2 + 2 * crate::CPAD);
879 crate::RefFrame {
880 py: rusty_h264_common::inter::pad_plane_into(take(lpw * lph), &self.rec_y, self.cw, self.ch, crate::LPAD),
883 pu: rusty_h264_common::inter::pad_plane_into(take(cpw * cph), &self.rec_u, self.ccw, self.ch / 2, crate::CPAD),
884 pv: rusty_h264_common::inter::pad_plane_into(take(cpw * cph), &self.rec_v, self.ccw, self.ch / 2, crate::CPAD),
885 cw: self.cw,
886 ch: self.ch,
887 frame_num: 0, poc: 0, mv,
890 ref_idx,
891 mv1,
892 ref_idx1,
893 ref_poc,
894 w4,
895 long_term: false,
896 long_term_idx: 0,
897 }
898 }
899
900 fn nnz_cache_load(&mut self, mb_x: usize, mb_y: usize) {
901 let w4 = self.mb_w * 4;
902 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
903 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
904 for lbx in 0..4 {
905 self.nnz_l_cache[1 + lbx] =
906 if top_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 - 1) * w4 + (mb_x * 4 + lbx)] };
907 }
908 for lby in 0..4 {
909 self.nnz_l_cache[(lby + 1) * 5] =
910 if left_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 - 1)] };
911 }
912 }
913 #[inline]
914 fn nc_pred(&self, lbx: usize, lby: usize) -> i32 {
915 let left = self.nnz_l_cache[(lby + 1) * 5 + lbx] as i32;
916 let top = self.nnz_l_cache[lby * 5 + (lbx + 1)] as i32;
917 let r = left + top;
918 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
919 }
920 #[inline]
921 fn nnz_cache_set(&mut self, lbx: usize, lby: usize, total: u8) {
922 self.nnz_l_cache[(lby + 1) * 5 + (lbx + 1)] = total;
923 }
924 fn chroma_cache_load(&mut self, mb_x: usize, mb_y: usize) {
925 let w2 = self.mb_w * 2;
926 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
927 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
928 for c in 0..2 {
929 for bx in 0..2 {
930 self.nnz_c_cache[c][1 + bx] =
931 if top_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 - 1) * w2 + (mb_x * 2 + bx)] };
932 }
933 for by in 0..2 {
934 self.nnz_c_cache[c][(by + 1) * 3] =
935 if left_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 - 1)] };
936 }
937 }
938 }
939 #[inline]
940 fn chroma_nc_pred(&self, c: usize, bx: usize, by: usize) -> i32 {
941 let left = self.nnz_c_cache[c][(by + 1) * 3 + bx] as i32;
942 let top = self.nnz_c_cache[c][by * 3 + (bx + 1)] as i32;
943 let r = left + top;
944 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
945 }
946 #[inline]
947 fn chroma_nnz_cache_set(&mut self, c: usize, bx: usize, by: usize, total: u8) {
948 self.nnz_c_cache[c][(by + 1) * 3 + (bx + 1)] = total;
949 }
950
951 #[allow(clippy::too_many_arguments)]
959 pub fn decode_slice_data_cabac(
960 &mut self,
961 rbsp: &[u8],
962 start_byte: usize,
963 slice_qp: u8,
964 cabac_init_idc: u32,
965 is_i: bool,
966 is_p: bool,
967 first_mb: usize,
968 ) -> Result<usize, MbError> {
969 self.edc_active = edc_on();
970 let mut cab = crate::cabac::Cabac::new(rbsp, start_byte, slice_qp as i32, cabac_init_idc, is_i);
971 let (range, _offset) = cab.dbg_state();
972 let trace = std::env::var_os("RH_CABAC_TRACE").is_some();
973 debug_assert_eq!(range, 510, "CABAC init range must be 510");
974
975 const I16_CBP: [u32; 6] = [0, 16, 32, 15, 31, 47];
976 let mbw = self.mb_w;
977 let total = self.mb_w * self.mb_h;
978 let mut cat = vec![255u8; total]; let mut mb_cbp = vec![0u8; total];
981 let mut cmode = vec![-1i32; total]; let mut mb_nzc = vec![[0u8; 24]; total]; let mut cbf_dc = vec![0u16; total];
984 let mut mb_skip = vec![false; total];
985 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;
991 let mut addr = first_mb;
992
993 loop {
994 if addr >= total {
1001 return Err(MbError::Truncated);
1002 }
1003 self.row_hook(addr);
1004 let (mbx, mby) = (addr % mbw, addr / mbw);
1005 let left = (mbx > 0).then(|| addr - 1);
1006 let top = (mby > 0).then(|| addr - mbw);
1007
1008 let mb_type;
1011 if is_p {
1012 let sctx = 11
1013 + left.map_or(0, |a| (!mb_skip[a]) as usize)
1014 + top.map_or(0, |a| (!mb_skip[a]) as usize);
1015 if parse_mb_skip_cabac(&mut cab, sctx) {
1016 mb_skip[addr] = true;
1017 cat[addr] = 100; last_delta_qp = 0; self.decode_p_skip(mbx, mby)?;
1023 self.mb_qp[addr] = self.cur_qp; let eos = cab.decode_terminate();
1025 addr += 1;
1026 if eos || addr >= total {
1027 break;
1028 }
1029 continue;
1030 }
1031 let mbt = parse_mb_type_p_cabac(&mut cab);
1032 if mbt == 30 {
1033 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1034 }
1035 if mbt <= 3 {
1036 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbP);
1037 let mut allow8 = true;
1040 let mut mvdc = [[0i16; 2]; 30];
1043 let mut refc = [-1i8; 30];
1044 if let Some(l) = left {
1045 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
1046 refc[ci] = mb_ref[l][bi];
1047 mvdc[ci] = mb_mvd[l][bi];
1048 }
1049 }
1050 if let Some(t) = top {
1051 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
1052 refc[ci] = mb_ref[t][bi];
1053 mvdc[ci] = mb_mvd[t][bi];
1054 }
1055 }
1056 if mbx > 0 && mby > 0 {
1057 let a = addr - mbw - 1;
1058 (refc[0], mvdc[0]) = (mb_ref[a][15], mb_mvd[a][15]);
1059 }
1060 if mby > 0 && mbx + 1 < mbw {
1061 let a = addr - mbw + 1;
1062 (refc[5], mvdc[5]) = (mb_ref[a][12], mb_mvd[a][12]);
1063 }
1064 let mut mmvd = [[0i16; 2]; 16];
1065 let mut mref = [0i8; 16];
1066 macro_rules! refidx {
1072 ($pi:expr, $zb:expr) => {{
1073 if self.num_ref_active > 1 {
1074 let s = CACHE30[$pi];
1075 let c0 = (refc[s - 1] > 0) as usize + 2 * (refc[s - 6] > 0) as usize;
1076 let r = parse_ref_idx_cabac(&mut cab, c0);
1077 for &zb in $zb.iter() {
1078 refc[CACHE30[zb]] = r;
1079 }
1080 r
1081 } else {
1082 0i8
1083 }
1084 }};
1085 }
1086 macro_rules! part {
1087 ($pi:expr, $zb:expr, $pred:expr, $rx:expr, $ry:expr, $rw:expr, $rh:expr, $refi:expr) => {{
1088 let (mvx, mvy) = parse_mvd_partition(&mut cab, $pi, $zb, &mut mvdc, &mut refc, &mut mmvd, &mut mref, $refi);
1089 let [na, nb, nc] = self.mv_neighbors_block(
1090 (mbx * 4 + $rx / 4) as isize,
1091 (mby * 4 + $ry / 4) as isize,
1092 ($rw / 4) as isize,
1093 );
1094 let pmv = $pred(na, nb, nc);
1095 self.commit_inter_grid(mbx, mby, $rx, $ry, $rw, $rh, (pmv.0 + mvx, pmv.1 + mvy), $refi);
1096 }};
1097 }
1098 match mbt {
1099 0 => {
1100 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
1101 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);
1102 }
1103 1 => {
1104 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7]);
1105 let r1 = refidx!(8, &[8, 9, 10, 11, 12, 13, 14, 15]);
1106 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);
1107 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);
1108 }
1109 2 => {
1110 let r0 = refidx!(0, &[0, 1, 2, 3, 8, 9, 10, 11]);
1111 let r1 = refidx!(4, &[4, 5, 6, 7, 12, 13, 14, 15]);
1112 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);
1113 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);
1114 }
1115 _ => {
1116 let mut subt = [0u32; 4];
1118 for st in &mut subt {
1119 *st = parse_sub_mb_type_p_cabac(&mut cab);
1120 }
1121 allow8 = subt.iter().all(|&t| t == 0);
1122 let mut pr = [0i8; 4];
1123 for (i, r) in pr.iter_mut().enumerate() {
1124 let b = i * 4;
1125 *r = refidx!(b, &[b, b + 1, b + 2, b + 3]);
1126 }
1127 for i in 0..4usize {
1128 let b = i * 4;
1129 let (ox, oy) = ((i % 2) * 8, (i / 2) * 8); let ri = pr[i];
1131 match subt[i] {
1132 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),
1133 1 => {
1134 part!(b, &[b, b + 1], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 8, 4, ri);
1135 part!(b + 2, &[b + 2, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy + 4, 8, 4, ri);
1136 }
1137 2 => {
1138 part!(b, &[b, b + 2], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 4, 8, ri);
1139 part!(b + 1, &[b + 1, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox + 4, oy, 4, 8, ri);
1140 }
1141 _ => {
1142 for j in 0..4usize {
1143 let (sx, sy) = ((j % 2) * 4, (j / 2) * 4);
1144 part!(b + j, &[b + j], |a, b, c| predict_mv(a, b, c, ri as i32), ox + sx, oy + sy, 4, 4, ri);
1145 }
1146 }
1147 }
1148 }
1149 }
1150 }
1151 mb_ref[addr] = mref;
1152 mb_mvd[addr] = mmvd;
1153 cat[addr] = 100;
1154
1155 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1157 mb_cbp[addr] = cbp as u8;
1158 let t8 = self.transform_8x8_mode && (cbp & 15) != 0 && allow8 && {
1162 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1163 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1164 cab.decode_decision(399 + a + b) != 0
1165 };
1166 self.mb_t8x8[addr] = t8;
1167 let mut luma8 = [[0i32; 64]; 4]; let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1169 let mut nzc = [0xffu8; 48];
1170 if let Some(t) = top {
1171 let tnz = mb_nzc[t];
1172 nzc[1..5].copy_from_slice(&tnz[12..16]);
1173 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1174 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
1175 }
1176 if let Some(l) = left {
1177 let lnz = mb_nzc[l];
1178 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
1179 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
1180 }
1181 let mut cbfdc = 0u16;
1182 let mut nnzs = [0u8; 24]; let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
1188 last_delta_qp = 0;
1189 }
1190 if cbp != 0 {
1191 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1192 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1193 self.step_qp(qpd);
1194 for id8 in 0..4usize {
1195 if cbp_luma & (1 << id8) != 0 {
1196 if t8 {
1197 nnzs[id8 * 4] = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, false, ndc, &mut luma8[id8]) as u8;
1198 } else {
1199 for id4 in 0..4usize {
1200 let iz = id8 * 4 + id4;
1201 nnzs[iz] = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]) as u8;
1202 }
1203 }
1204 } else {
1205 for k in 0..4 {
1206 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1207 }
1208 }
1209 }
1210 if cbp_chroma >= 1 {
1211 for i in 0..2usize {
1212 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
1213 }
1214 }
1215 if cbp_chroma == 2 {
1216 for i in 0..2usize {
1217 for id4 in 0..4usize {
1218 nnzs[16 + i * 4 + id4] = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]) as u8;
1219 }
1220 }
1221 }
1222 }
1223 self.mb_qp[addr] = self.cur_qp;
1224 cbf_dc[addr] = cbfdc;
1225 let _sc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecStateCache);
1226 let mut mn = [0u8; 24];
1227 for k in 0..4 {
1228 mn[k] = nzc[9 + k];
1229 mn[4 + k] = nzc[17 + k];
1230 mn[8 + k] = nzc[25 + k];
1231 mn[12 + k] = nzc[33 + k];
1232 }
1233 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1234 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1235 for v in mn.iter_mut() {
1239 if *v == 0xff {
1240 *v = 0;
1241 }
1242 }
1243 mb_nzc[addr] = mn;
1244 drop(_sc);
1245
1246 if self.refs.is_empty() {
1247 return Err(MbError::Unsupported("inter without reference"));
1248 }
1249 let job = PInterJob {
1250 mbx,
1251 mby,
1252 t8,
1253 qp: self.cur_qp,
1254 cbp_chroma,
1255 luma_scan,
1256 luma8,
1257 cdc,
1258 cac,
1259 nnzs,
1260 };
1261 if self.edc_active {
1262 self.edc_jobs.push(EdcJob::Inter(Box::new(job)));
1263 } else {
1264 self.recon_p_inter(&job);
1265 }
1266
1267 let eos = cab.decode_terminate();
1268 addr += 1;
1269 if eos || addr >= total {
1270 break;
1271 }
1272 continue;
1273 }
1274 mb_type = mbt - 5; } else if self.is_b {
1276 self.edc_flush(); let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbB);
1278 let mut allow8 = true;
1281 let sctx = 24
1283 + left.map_or(0, |a| (!mb_skip[a]) as usize)
1284 + top.map_or(0, |a| (!mb_skip[a]) as usize);
1285 if parse_mb_skip_cabac(&mut cab, sctx) {
1286 mb_skip[addr] = true;
1287 cat[addr] = 100;
1288 mb_direct[addr] = true;
1289 last_delta_qp = 0; self.decode_b_skip(mbx, mby)?;
1293 self.mb_qp[addr] = self.cur_qp;
1294 mb_ref[addr] = [0i8; 16];
1297 mb_ref1[addr] = [0i8; 16];
1298 let eos = cab.decode_terminate();
1299 addr += 1;
1300 if eos || addr >= total {
1301 break;
1302 }
1303 continue;
1304 }
1305 let bci = left.map_or(0, |a| (!mb_direct[a]) as usize)
1306 + top.map_or(0, |a| (!mb_direct[a]) as usize);
1307 let bmt = parse_mb_type_b_cabac(&mut cab, bci);
1308 if bmt < 23 {
1309 let mut mvdc0 = [[0i16; 2]; 30];
1312 let mut refc0 = [-1i8; 30];
1313 let mut mvdc1 = [[0i16; 2]; 30];
1314 let mut refc1 = [-1i8; 30];
1315 macro_rules! fill {
1317 ($mrf:expr, $mmv:expr, $rc:expr, $mc:expr) => {{
1318 if let Some(l) = left {
1319 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
1320 $rc[ci] = $mrf[l][bi];
1321 $mc[ci] = $mmv[l][bi];
1322 }
1323 }
1324 if let Some(t) = top {
1325 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
1326 $rc[ci] = $mrf[t][bi];
1327 $mc[ci] = $mmv[t][bi];
1328 }
1329 }
1330 if mbx > 0 && mby > 0 {
1331 let a = addr - mbw - 1;
1332 ($rc[0], $mc[0]) = ($mrf[a][15], $mmv[a][15]);
1333 }
1334 if mby > 0 && mbx + 1 < mbw {
1335 let a = addr - mbw + 1;
1336 ($rc[5], $mc[5]) = ($mrf[a][12], $mmv[a][12]);
1337 }
1338 }};
1339 }
1340 fill!(mb_ref, mb_mvd, refc0, mvdc0);
1341 fill!(mb_ref1, mb_mvd1, refc1, mvdc1);
1342 let mut mmvd0 = [[0i16; 2]; 16];
1343 let mut mref0 = [-1i8; 16];
1344 let mut mmvd1 = [[0i16; 2]; 16];
1345 let mut mref1 = [-1i8; 16];
1346 if self.refs.is_empty() || self.refs1.is_empty() {
1347 return Err(MbError::Unsupported("B without references"));
1348 }
1349 let mut pred_y = [0u8; 256];
1354 let mut c_pred = [[0u8; 64]; 2];
1355
1356 if bmt == 0 {
1357 mb_direct[addr] = true;
1360 allow8 = self.direct_8x8_inference;
1361 (mref0, mref1) = ([0i8; 16], [0i8; 16]);
1362 self.decode_b_direct(mbx, mby, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
1363 } else if bmt == 22 {
1364 let mut subt = [0u32; 4];
1367 for s in &mut subt {
1368 *s = parse_sub_mb_type_b_cabac(&mut cab);
1369 }
1370 allow8 = subt.iter().all(|&t| if t == 0 { self.direct_8x8_inference } else { (1..=3).contains(&t) });
1371 for i in 0..4usize {
1375 if subt[i] == 0 {
1376 let b = i * 4;
1377 for &zb in &[b, b + 1, b + 2, b + 3] {
1378 (mref0[G_SCAN4[zb]], mref1[G_SCAN4[zb]]) = (0, 0);
1379 (refc0[CACHE30[zb]], refc1[CACHE30[zb]]) = (0, 0);
1380 }
1381 }
1382 }
1383 let mut sref = [[0i8; 2]; 4]; for list in 0..2usize {
1388 let active = if list == 0 { self.num_ref_active } else { self.num_ref_active1 };
1389 if active <= 1 {
1390 continue;
1391 }
1392 let rc = if list == 0 { &mut refc0 } else { &mut refc1 };
1393 for i in 0..4usize {
1394 let st = subt[i];
1395 if st == 0 || !b_sub_uses(st, list) {
1396 continue;
1397 }
1398 let b = i * 4;
1399 let s = CACHE30[b];
1400 let c0 = (rc[s - 1] > 0) as usize + 2 * (rc[s - 6] > 0) as usize;
1401 let r = parse_ref_idx_cabac(&mut cab, c0);
1402 for &zb in &[b, b + 1, b + 2, b + 3] {
1403 rc[CACHE30[zb]] = r;
1404 }
1405 sref[i][list] = r;
1406 }
1407 }
1408 for list in 0..2usize {
1409 let (mmv, mrf, mc, rc) = if list == 0 {
1410 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1411 } else {
1412 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1413 };
1414 for i in 0..4usize {
1415 let st = subt[i];
1416 if st == 0 || !b_sub_uses(st, list) {
1417 continue;
1418 }
1419 let b = i * 4;
1420 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1421 let mut zb = [0usize; 4];
1422 let mut n = 0;
1423 for ly in sy / 4..sy / 4 + sh / 4 {
1424 for lx in sx / 4..sx / 4 + sw / 4 {
1425 zb[n] = b + ly * 2 + lx;
1426 n += 1;
1427 }
1428 }
1429 parse_mvd_partition(&mut cab, zb[0], &zb[..n], mc, rc, mmv, mrf, sref[i][list]);
1430 }
1431 }
1432 }
1433 for (p, &st) in subt.iter().enumerate() {
1436 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
1437 if st == 0 {
1438 self.decode_b_direct(mbx, mby, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
1439 continue;
1440 }
1441 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1442 let (px, py) = (b8x + sx, b8y + sy);
1443 let mut mv = [(0i32, 0i32); 2];
1444 for list in 0..2usize {
1445 if b_sub_uses(st, list) {
1446 let d = if list == 0 { mmvd0 } else { mmvd1 }[(py / 4) * 4 + px / 4];
1447 let n = self.mv_neighbors_list((mbx * 4 + px / 4) as isize, (mby * 4 + py / 4) as isize, (sw / 4) as isize, list);
1448 let pmv = predict_mv(n[0], n[1], n[2], sref[p][list] as i32);
1449 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1450 }
1451 }
1452 let refi0 = if b_sub_uses(st, 0) { sref[p][0] as i32 } else { -1 };
1453 let refi1 = if b_sub_uses(st, 1) { sref[p][1] as i32 } else { -1 };
1454 self.b_set_motion(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1]);
1455 self.b_mc(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1456 }
1457 }
1458 } else {
1459 let (layout, mvmode, preds) = b_inter_layout(bmt);
1460 let parts: &[(usize, &[usize])] = match mvmode {
1461 0 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])],
1462 1 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7]), (8, &[8, 9, 10, 11, 12, 13, 14, 15])],
1463 _ => &[(0, &[0, 1, 2, 3, 8, 9, 10, 11]), (4, &[4, 5, 6, 7, 12, 13, 14, 15])],
1464 };
1465 let mut pref = [[0i8; 2]; 2]; for list in 0..2usize {
1473 let active = if list == 0 { self.num_ref_active } else { self.num_ref_active1 };
1474 if active <= 1 {
1475 continue;
1476 }
1477 let rc = if list == 0 { &mut refc0 } else { &mut refc1 };
1478 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1479 if !preds[p].uses(list) {
1480 continue;
1481 }
1482 let s = CACHE30[pidx];
1483 let c0 = (rc[s - 1] > 0) as usize + 2 * (rc[s - 6] > 0) as usize;
1484 let r = parse_ref_idx_cabac(&mut cab, c0);
1485 for &zbi in zb.iter() {
1487 rc[CACHE30[zbi]] = r;
1488 }
1489 pref[p][list] = r;
1490 }
1491 }
1492 for list in 0..2usize {
1495 let (mmv, mrf, mc, rc) = if list == 0 {
1496 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1497 } else {
1498 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1499 };
1500 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1501 if preds[p].uses(list) {
1502 parse_mvd_partition(&mut cab, pidx, zb, mc, rc, mmv, mrf, pref[p][list]);
1503 }
1504 }
1505 }
1506 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1508 let mut mv = [(0i32, 0i32); 2];
1509 for list in 0..2usize {
1510 if preds[p].uses(list) {
1511 let d = if list == 0 { mmvd0 } else { mmvd1 }[(ry / 4) * 4 + rx / 4];
1512 let n = self.mv_neighbors_list((mbx * 4 + rx / 4) as isize, (mby * 4 + ry / 4) as isize, (rw / 4) as isize, list);
1513 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], pref[p][list] as i32);
1514 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1515 }
1516 }
1517 let refi0 = if preds[p].uses(0) { pref[p][0] as i32 } else { -1 };
1518 let refi1 = if preds[p].uses(1) { pref[p][1] as i32 } else { -1 };
1519 self.b_set_motion(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1]);
1520 self.b_mc(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1524 }
1525 }
1526 mb_ref[addr] = mref0;
1527 mb_mvd[addr] = mmvd0;
1528 mb_ref1[addr] = mref1;
1529 mb_mvd1[addr] = mmvd1;
1530 cat[addr] = 100;
1531
1532 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1534 mb_cbp[addr] = cbp as u8;
1535 let t8 = self.transform_8x8_mode && (cbp & 15) != 0 && allow8 && {
1539 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1540 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1541 cab.decode_decision(399 + a + b) != 0
1542 };
1543 self.mb_t8x8[addr] = t8;
1544 let mut luma8 = [[0i32; 64]; 4]; let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1546 let mut nzc = [0xffu8; 48];
1547 if let Some(t) = top {
1548 let tnz = mb_nzc[t];
1549 nzc[1..5].copy_from_slice(&tnz[12..16]);
1550 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1551 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
1552 }
1553 if let Some(l) = left {
1554 let lnz = mb_nzc[l];
1555 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
1556 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
1557 }
1558 let mut cbfdc = 0u16;
1559 let mut nnzs = [0u8; 24]; let mut luma_scan = [[0i32; 16]; 16];
1561 let mut cdc = [[0i32; 4]; 2];
1562 let mut cac = [[[0i32; 16]; 4]; 2];
1563 if cbp == 0 {
1564 last_delta_qp = 0;
1565 }
1566 if cbp != 0 {
1567 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1568 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1569 self.step_qp(qpd);
1570 for id8 in 0..4usize {
1571 if cbp_luma & (1 << id8) != 0 {
1572 if t8 {
1573 nnzs[id8 * 4] = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, false, ndc, &mut luma8[id8]) as u8;
1574 } else {
1575 for id4 in 0..4usize {
1576 let iz = id8 * 4 + id4;
1577 nnzs[iz] = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]) as u8;
1578 }
1579 }
1580 } else {
1581 for k in 0..4 {
1582 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1583 }
1584 }
1585 }
1586 if cbp_chroma >= 1 {
1587 for i in 0..2usize {
1588 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
1589 }
1590 }
1591 if cbp_chroma == 2 {
1592 for i in 0..2usize {
1593 for id4 in 0..4usize {
1594 nnzs[16 + i * 4 + id4] = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]) as u8;
1595 }
1596 }
1597 }
1598 }
1599 self.mb_qp[addr] = self.cur_qp;
1600 cbf_dc[addr] = cbfdc;
1601 let _sc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecStateCache);
1602 let mut mn = [0u8; 24];
1603 for k in 0..4 {
1604 mn[k] = nzc[9 + k];
1605 mn[4 + k] = nzc[17 + k];
1606 mn[8 + k] = nzc[25 + k];
1607 mn[12 + k] = nzc[33 + k];
1608 }
1609 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1610 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1611 for v in mn.iter_mut() {
1615 if *v == 0xff {
1616 *v = 0;
1617 }
1618 }
1619 mb_nzc[addr] = mn;
1620 drop(_sc);
1621 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, if t8 { Some(&luma8) } else { None }, &cdc, &cac, cbp_chroma, &nnzs);
1622
1623 let eos = cab.decode_terminate();
1624 addr += 1;
1625 if eos || addr >= total {
1626 break;
1627 }
1628 continue;
1629 }
1630 mb_type = bmt - 23; if mb_type == 25 {
1632 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1633 }
1634 } else {
1635 let li = left.map_or(0, |a| (cat[a] >= 2) as usize);
1636 let ti = top.map_or(0, |a| (cat[a] >= 2) as usize);
1637 mb_type = parse_mb_type_i_cabac(&mut cab, li + ti);
1638 if mb_type == 25 {
1639 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1640 }
1641 }
1642 self.edc_flush(); let _gi = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbI);
1649 let cci = left.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize)
1651 + top.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize);
1652
1653 if mb_type != 0 {
1654 let mt = mb_type - 1;
1659 let pred_mode = I16Mode::from_id(mt % 4);
1660 let cbp_chroma = (mt % 12) / 4;
1661 let cbp_luma_15 = mt / 12 == 1;
1662 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1663 cmode[addr] = chroma_mode as i32;
1664 cat[addr] = 2;
1665 mb_cbp[addr] = ((cbp_chroma as u8) << 4) | if cbp_luma_15 { 15 } else { 0 };
1666 let w4 = self.mb_w * 4;
1667
1668 let mut nzc = [0xffu8; 48];
1669 if let Some(t) = top {
1670 let tn = mb_nzc[t];
1671 nzc[1..5].copy_from_slice(&tn[12..16]);
1672 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1673 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1674 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1675 }
1676 if let Some(l) = left {
1677 let ln = mb_nzc[l];
1678 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1679 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1680 }
1681
1682 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1683 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1684 self.step_qp(qpd);
1685 let qp = self.cur_qp;
1686 let mut cbfdc = 0u16;
1687
1688 let mut dc_scan = [0i32; 16];
1690 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 0, RP_I16_DC, true, ndc, &mut dc_scan);
1691 let recon_dc = self.dequant_luma_dc(&un_scan_4x4_dcac(&dc_scan), qp, 0);
1692
1693 let mut q_blocks = [[0i32; 16]; 16];
1695 for (iz, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1696 let total = if cbp_luma_15 {
1697 let mut ac = [0i32; 16];
1698 let t = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_I16_AC, true, ndc, &mut ac);
1699 un_scan_4x4_ac_into(&ac, &mut q_blocks[lby * 4 + lbx]);
1700 t as u8
1701 } else {
1702 nzc[NZC_CACHE[iz]] = 0;
1703 0
1704 };
1705 self.nnz_y[(mby * 4 + lby) * w4 + (mbx * 4 + lbx)] = total;
1706 }
1707
1708 let mut cdc = [[0i32; 4]; 2];
1709 let mut cac = [[[0i32; 16]; 4]; 2];
1710 if cbp_chroma >= 1 {
1711 for i in 0..2usize {
1712 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1713 }
1714 }
1715 if cbp_chroma == 2 {
1716 for i in 0..2usize {
1717 for id4 in 0..4usize {
1718 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1719 }
1720 }
1721 }
1722
1723 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1725 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1726 let (lx, ly) = (mbx * 16, mby * 16);
1727 let mut t16 = [0u8; 16];
1728 let mut l16 = [0u8; 16];
1729 if top_ok {
1730 t16.copy_from_slice(self.top_y_row(ly, lx, 16));
1731 }
1732 if left_ok {
1733 for i in 0..16 {
1734 l16[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
1735 }
1736 }
1737 let corner = if top_ok && left_ok { self.top_y_px(ly, lx - 1) } else { 0 };
1738 let pred_l = luma16x16_pred(pred_mode, top_ok, left_ok, &t16, &l16, corner);
1739 for by in 0..4 {
1740 for bx in 0..4 {
1741 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
1742 deq[0] = recon_dc[by * 4 + bx];
1743 let predb: [i32; 16] = std::array::from_fn(|i| pred_l[(by * 4 + i / 4) * 16 + (bx * 4 + i % 4)] as i32);
1744 let s = reconstruct_4x4(&deq, &predb);
1745 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
1746 self.modes_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = 2;
1750 self.coded_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = true;
1751 }
1752 }
1753 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1754
1755 self.mb_qp[addr] = self.cur_qp;
1756 cbf_dc[addr] = cbfdc;
1757 let mut mn = [0u8; 24];
1758 for k in 0..4 {
1759 mn[k] = nzc[9 + k];
1760 mn[4 + k] = nzc[17 + k];
1761 mn[8 + k] = nzc[25 + k];
1762 mn[12 + k] = nzc[33 + k];
1763 }
1764 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1765 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1766 for v in mn.iter_mut() {
1767 if *v == 0xff {
1768 *v = 0;
1769 }
1770 }
1771 mb_nzc[addr] = mn;
1772
1773 let eos = cab.decode_terminate();
1774 addr += 1;
1775 if eos || addr >= total {
1776 break;
1777 }
1778 continue;
1779 }
1780 cat[addr] = 0;
1781 let w4 = self.mb_w * 4;
1782 let t8 = self.transform_8x8_mode && {
1787 let a = left.map_or(0, |x| self.mb_t8x8[x] as usize);
1788 let b = top.map_or(0, |x| self.mb_t8x8[x] as usize);
1789 cab.decode_decision(399 + a + b) != 0
1790 };
1791 self.mb_t8x8[addr] = t8;
1792 let mut modes = [2u8; 16]; let mut modes8 = [2u8; 4]; if t8 {
1797 for b8 in 0..4usize {
1800 let (b8x, b8y) = (b8 % 2, b8 / 2);
1801 let (bx, by) = (mbx * 4 + b8x * 2, mby * 4 + b8y * 2);
1802 let predicted = self.predict_i4_mode(bx, by);
1803 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1804 let actual = if rr < 0 {
1805 predicted
1806 } else {
1807 let rem = rr as u8;
1808 if rem < predicted { rem } else { rem + 1 }
1809 };
1810 modes8[b8] = actual;
1811 for dy in 0..2 {
1812 for dx in 0..2 {
1813 self.modes_y[(by + dy) * w4 + (bx + dx)] = actual;
1814 modes[(b8y * 2 + dy) * 4 + (b8x * 2 + dx)] = actual;
1815 }
1816 }
1817 }
1818 } else {
1819 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1820 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1821 let predicted = self.predict_i4_mode(bx, by);
1822 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1823 let actual = if rr < 0 {
1824 predicted
1825 } else {
1826 let rem = rr as u8;
1827 if rem < predicted { rem } else { rem + 1 }
1828 };
1829 self.modes_y[by * w4 + bx] = actual;
1830 modes[lby * 4 + lbx] = actual;
1831 }
1832 }
1833 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1834 cmode[addr] = chroma_mode as i32;
1835 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1836 mb_cbp[addr] = cbp as u8;
1837 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1838
1839 let mut nzc = [0xffu8; 48];
1841 if let Some(t) = top {
1842 let tn = mb_nzc[t];
1843 nzc[1..5].copy_from_slice(&tn[12..16]);
1844 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1845 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1846 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1847 }
1848 if let Some(l) = left {
1849 let ln = mb_nzc[l];
1850 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1851 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1852 }
1853
1854 let mut cbfdc = 0u16;
1857 let mut luma_scan = [[0i32; 16]; 16]; let mut luma8 = [[0i32; 64]; 4]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
1862 last_delta_qp = 0;
1863 }
1864 if cbp != 0 {
1865 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1866 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1867 self.step_qp(qpd);
1868 for id8 in 0..4usize {
1869 if cbp_luma & (1 << id8) != 0 {
1870 if t8 {
1871 let n = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, id8 * 4, RP_LUMA_8X8, true, ndc, &mut luma8[id8]);
1874 let (b8x, b8y) = (id8 % 2, id8 / 2);
1875 for sy in 0..2 {
1876 for sx in 0..2 {
1877 self.nnz_y[(mby * 4 + b8y * 2 + sy) * w4 + (mbx * 4 + b8x * 2 + sx)] = n as u8;
1878 }
1879 }
1880 } else {
1881 for id4 in 0..4usize {
1882 let iz = id8 * 4 + id4;
1883 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, true, ndc, &mut luma_scan[iz]);
1884 }
1885 }
1886 } else {
1887 for k in 0..4 {
1888 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1889 }
1890 if t8 {
1891 let (b8x, b8y) = (id8 % 2, id8 / 2);
1892 for sy in 0..2 {
1893 for sx in 0..2 {
1894 self.nnz_y[(mby * 4 + b8y * 2 + sy) * w4 + (mbx * 4 + b8x * 2 + sx)] = 0;
1895 }
1896 }
1897 }
1898 }
1899 }
1900 if cbp_chroma >= 1 {
1901 for i in 0..2usize {
1902 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1903 }
1904 }
1905 if cbp_chroma == 2 {
1906 for i in 0..2usize {
1907 for id4 in 0..4usize {
1908 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1909 }
1910 }
1911 }
1912 }
1913 self.mb_qp[addr] = self.cur_qp;
1914 cbf_dc[addr] = cbfdc;
1915 let mut mn = [0u8; 24];
1917 for k in 0..4 {
1918 mn[k] = nzc[9 + k];
1919 mn[4 + k] = nzc[17 + k];
1920 mn[8 + k] = nzc[25 + k];
1921 mn[12 + k] = nzc[33 + k];
1922 }
1923 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1924 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1925 for v in mn.iter_mut() {
1926 if *v == 0xff {
1927 *v = 0;
1928 }
1929 }
1930 mb_nzc[addr] = mn;
1931
1932 let qp = self.cur_qp;
1934 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1935 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1936 if t8 {
1937 for b8 in 0..4usize {
1941 let (b8x, b8y) = (b8 % 2, b8 / 2);
1942 let (bx, by) = (mbx * 4 + b8x * 2, mby * 4 + b8y * 2);
1943 let (px, py) = (bx * 4, by * 4);
1944 let res8 = if cbp_luma & (1 << b8) != 0 {
1945 let raster = un_scan_8x8(&luma8[b8]);
1946 self.inv_quant8(&raster, qp, 0)
1947 } else {
1948 [0i32; 64]
1949 };
1950 let avail_top = b8y > 0 || top_ok;
1951 let avail_left = b8x > 0 || left_ok;
1952 let (t, l, corner, avail_corner) =
1953 self.gather_i8(px, py, avail_top, avail_left, bx, by);
1954 let pred =
1955 intra8x8_pred(modes8[b8], avail_top, avail_left, avail_corner, &t, &l, corner);
1956 let mut predb = [0i32; 64];
1957 for i in 0..64 {
1958 predb[i] = pred[i] as i32;
1959 }
1960 let recon = add_residual_8x8(&res8, &predb);
1961 for dy in 0..8 {
1962 for dx in 0..8 {
1963 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
1964 }
1965 }
1966 for sy in 0..2 {
1967 for sx in 0..2 {
1968 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
1969 }
1970 }
1971 }
1972 }
1973 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1974 if t8 {
1975 break;
1976 }
1977 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1978 let (px, py) = (bx * 4, by * 4);
1979 let at = lby > 0 || top_ok;
1980 let al = lbx > 0 || left_ok;
1981 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1982 self.nnz_y[by * w4 + bx] = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1983 let (t, l, corner) = self.gather_i4(px, py, at, al, bx, by);
1984 let pred = intra4x4_pred(modes[lby * 4 + lbx], at, al, &t, &l, corner);
1985 let predb = std::array::from_fn(|i| pred[i] as i32);
1986 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
1987 store(&mut self.rec_y, self.cw, px, py, &s);
1988 self.coded_y[by * w4 + bx] = true;
1989 }
1990 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1991
1992 let eos = cab.decode_terminate();
1994 addr += 1;
1995 if eos || addr >= total {
1996 break;
1997 }
1998 }
1999 if trace {
2000 eprintln!("# CABAC decoded {} MBs (of {total})", addr - first_mb);
2001 }
2002 self.edc_flush(); Ok(addr)
2004 }
2005
2006 #[allow(clippy::too_many_arguments)]
2010 #[allow(clippy::too_many_arguments)]
2016 fn add_inter_residual(
2017 &mut self,
2018 mb_x: usize,
2019 mb_y: usize,
2020 pred_y: &[u8; 256],
2021 c_pred: &[[u8; 64]; 2],
2022 luma_scan: &[[i32; 16]; 16],
2023 luma8: Option<&[[i32; 64]; 4]>,
2026 cdc: &[[i32; 4]; 2],
2027 cac: &[[[i32; 16]; 4]; 2],
2028 cbp_chroma: u32,
2029 nnzs: &[u8; 24],
2036 ) {
2037 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecResidAdd);
2038 let qp = self.cur_qp;
2039 let qpc = self.chroma_qp_for(qp);
2040 let (w4r, w2r) = (self.mb_w * 4, self.mb_w * 2);
2041 if let Some(l8) = luma8 {
2042 for b8 in 0..4usize {
2044 let (b8x, b8y) = (b8 % 2, b8 / 2);
2045 let nnz = nnzs[b8 * 4];
2046 for sy in 0..2 {
2047 for sx in 0..2 {
2048 self.nnz_y[(mb_y * 4 + b8y * 2 + sy) * w4r + (mb_x * 4 + b8x * 2 + sx)] = nnz;
2049 }
2050 }
2051 let res8 = if nnz == 0 {
2052 [0i32; 64]
2053 } else {
2054 let raster = un_scan_8x8(&l8[b8]);
2055 self.inv_quant8(&raster, qp, 1)
2057 };
2058 for sy in 0..2 {
2061 for sx in 0..2 {
2062 self.coded_y[(mb_y * 4 + b8y * 2 + sy) * w4r + (mb_x * 4 + b8x * 2 + sx)] = true;
2063 }
2064 }
2065 let predb: [i32; 64] =
2066 std::array::from_fn(|i| pred_y[(b8y * 8 + i / 8) * 16 + (b8x * 8 + i % 8)] as i32);
2067 let recon = add_residual_8x8(&res8, &predb);
2068 let (px, py) = (mb_x * 16 + b8x * 8, mb_y * 16 + b8y * 8);
2069 for dy in 0..8 {
2070 for dx in 0..8 {
2071 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
2072 }
2073 }
2074 }
2075 }
2076 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2077 if luma8.is_some() {
2078 break;
2079 }
2080 let nnz = nnzs[blk];
2081 self.nnz_y[(mb_y * 4 + lby) * w4r + (mb_x * 4 + lbx)] = nnz;
2082 let cw = self.cw;
2083 let p_off = (lby * 4) * 16 + lbx * 4;
2084 let r_off = (mb_y * 4 + lby) * 4 * cw + (mb_x * 4 + lbx) * 4;
2085 if nnz == 0 {
2086 for r in 0..4 {
2091 self.rec_y[r_off + r * cw..r_off + r * cw + 4]
2092 .copy_from_slice(&pred_y[p_off + r * 16..p_off + r * 16 + 4]);
2093 }
2094 continue;
2095 }
2096 if nnz == 1 && luma_scan[blk][0] != 0 {
2100 let f = self.dequant_dc4(luma_scan[blk][0], qp, 3);
2101 reconstruct_4x4_dc_into((f + 32) >> 6, pred_y, p_off, 16, &mut self.rec_y, r_off, cw);
2102 } else {
2103 let deq = if nnz <= 6 {
2113 dequant_scatter_4x4(&luma_scan[blk], nnz, 0, qp, self.scaling.as_ref().map(|sc| &sc[3]))
2114 } else {
2115 self.dequant(&un_scan_4x4_dcac(&luma_scan[blk]), qp, 3)
2116 };
2117 reconstruct_4x4_into(&deq, pred_y, p_off, 16, &mut self.rec_y, r_off, cw);
2118 }
2119 }
2120 let mut c_dc = [[0i32; 4]; 2];
2121 if cbp_chroma != 0 {
2122 for c in 0..2 {
2123 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 4 + c);
2124 }
2125 }
2126 let ccw = self.ccw;
2127 for c in 0..2 {
2128 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2129 let mut ac_nz = false;
2130 if cbp_chroma == 2 {
2131 let n = nnzs[16 + c * 4 + by * 2 + bx];
2132 self.nnz_c[c][(mb_y * 2 + by) * w2r + (mb_x * 2 + bx)] = n;
2133 ac_nz = n != 0;
2134 }
2135 let dc = c_dc[c][by * 2 + bx];
2136 let p_off = (by * 4) * 8 + bx * 4;
2137 let r_off = (mb_y * 2 + by) * 4 * ccw + (mb_x * 2 + bx) * 4;
2138 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2139 if dc == 0 && !ac_nz {
2140 for r in 0..4 {
2142 plane[r_off + r * ccw..r_off + r * ccw + 4]
2143 .copy_from_slice(&c_pred[c][p_off + r * 8..p_off + r * 8 + 4]);
2144 }
2145 continue;
2146 }
2147 if !ac_nz {
2151 reconstruct_4x4_dc_into((dc + 32) >> 6, &c_pred[c], p_off, 8, plane, r_off, ccw);
2152 continue;
2153 }
2154 let n = nnzs[16 + c * 4 + by * 2 + bx];
2157 let mut deq = if n <= 6 {
2158 dequant_scatter_4x4(&cac[c][by * 2 + bx], n, 1, qpc, self.scaling.as_ref().map(|sc| &sc[4 + c]))
2159 } else {
2160 let mut ac = [0i32; 16];
2161 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
2162 match &self.scaling {
2165 Some(sc) => dequantize_weighted(&ac, qpc, &sc[4 + c]),
2166 None => dequantize(&ac, qpc),
2167 }
2168 };
2169 deq[0] = dc;
2170 reconstruct_4x4_into(&deq, &c_pred[c], p_off, 8, plane, r_off, ccw);
2171 }
2172 }
2173 }
2174
2175 fn recon_chroma_cabac(
2176 &mut self,
2177 mb_x: usize,
2178 mb_y: usize,
2179 chroma_mode: u8,
2180 cdc: &[[i32; 4]; 2],
2181 cac: &[[[i32; 16]; 4]; 2],
2182 cbp_chroma: u32,
2183 avail_top: bool,
2184 avail_left: bool,
2185 ) {
2186 let qpc = self.chroma_qp_for(self.cur_qp);
2187 let (cx, cy) = (mb_x * 8, mb_y * 8);
2188 let mut c_dc = [[0i32; 4]; 2];
2189 if cbp_chroma != 0 {
2190 for c in 0..2 {
2191 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 1 + c);
2192 }
2193 }
2194 let w2 = self.mb_w * 2;
2195 for c in 0..2 {
2196 let mut ctop = [0u8; 8];
2197 let mut cleft = [0u8; 8];
2198 let mut ccorner = 0u8;
2199 {
2200 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
2201 if avail_top {
2202 ctop.copy_from_slice(self.top_c_row(c, cy, cx, 8));
2203 }
2204 if avail_left {
2205 for i in 0..8 {
2206 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
2207 }
2208 }
2209 if avail_top && avail_left {
2210 ccorner = self.top_c_px(c, cy, cx - 1);
2211 }
2212 }
2213 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
2214 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2215 let mut ac = [0i32; 16];
2216 if cbp_chroma == 2 {
2217 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
2218 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] =
2219 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
2220 }
2221 let mut deq = self.dequant(&ac, qpc, 1 + c);
2222 deq[0] = c_dc[c][by * 2 + bx];
2223 let predb: [i32; 16] =
2224 std::array::from_fn(|i| pred8[(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
2225 let s = reconstruct_4x4(&deq, &predb);
2226 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2227 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
2228 }
2229 }
2230 }
2231
2232 pub fn decode_slice_data(
2233 &mut self,
2234 r: &mut BitReader,
2235 is_p: bool,
2236 first_mb: usize,
2237 ) -> Result<usize, MbError> {
2238 let total = self.mb_w * self.mb_h;
2239 self.slice_first_mb = first_mb;
2240 self.edc_active = false; let mut addr = first_mb;
2242 while addr < total {
2243 self.row_hook(addr);
2244 if is_p || self.is_b {
2245 let skip_run = {
2246 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
2247 r.read_ue()?
2248 } as usize;
2249 for _ in 0..skip_run {
2250 if addr >= total {
2251 break;
2252 }
2253 if self.is_b {
2254 self.decode_b_skip(addr % self.mb_w, addr / self.mb_w)?;
2255 } else {
2256 self.decode_p_skip(addr % self.mb_w, addr / self.mb_w)?;
2257 }
2258 self.mb_qp[addr] = self.cur_qp; addr += 1;
2260 }
2261 if addr >= total {
2262 break;
2263 }
2264 if skip_run > 0 && !r.more_rbsp_data() {
2266 break;
2267 }
2268 }
2269 if self.is_b {
2270 self.decode_b_mb(r, addr % self.mb_w, addr / self.mb_w)?;
2271 } else {
2272 self.decode_mb(r, addr % self.mb_w, addr / self.mb_w, is_p)?;
2273 }
2274 self.mb_qp[addr] = self.cur_qp;
2275 addr += 1;
2276 if !r.more_rbsp_data() {
2278 break;
2279 }
2280 }
2281 self.edc_flush(); Ok(addr)
2283 }
2284
2285 fn decode_mb(
2286 &mut self,
2287 r: &mut BitReader,
2288 mb_x: usize,
2289 mb_y: usize,
2290 is_p: bool,
2291 ) -> Result<(), MbError> {
2292 let mut mb_type = {
2293 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
2294 r.read_ue()?
2295 };
2296 if is_p {
2297 if mb_type <= 2 {
2300 return self.decode_inter(r, mb_x, mb_y, mb_type as u8);
2301 }
2302 if mb_type == 3 || mb_type == 4 {
2303 return self.decode_p8x8(r, mb_x, mb_y, mb_type == 4);
2304 }
2305 mb_type -= 5;
2306 }
2307 self.decode_intra_mb(r, mb_x, mb_y, mb_type)
2308 }
2309
2310 fn decode_intra_mb(
2313 &mut self,
2314 r: &mut BitReader,
2315 mb_x: usize,
2316 mb_y: usize,
2317 mb_type: u32,
2318 ) -> Result<(), MbError> {
2319 let _gi = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMbI);
2323 if mb_type == 0 {
2324 if self.transform_8x8_mode && r.read_bit()? {
2326 self.decode_i8x8(r, mb_x, mb_y)?;
2327 } else {
2328 self.decode_i4x4(r, mb_x, mb_y)?;
2329 }
2330 } else if (1..=24).contains(&mb_type) {
2331 self.decode_i16(r, mb_x, mb_y, mb_type - 1)?;
2332 } else if mb_type == 25 {
2333 self.decode_ipcm(r, mb_x, mb_y)?;
2334 } else {
2335 return Err(MbError::Unsupported("only I_4x4 / I_16x16 / I_PCM macroblocks"));
2336 }
2337 let w4 = self.mb_w * 4;
2339 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2340 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
2341 }
2342 Ok(())
2343 }
2344
2345 fn decode_inter(
2349 &mut self,
2350 r: &mut BitReader,
2351 mb_x: usize,
2352 mb_y: usize,
2353 mode: u8,
2354 ) -> Result<(), MbError> {
2355 if self.refs.is_empty() {
2356 return Err(MbError::Unsupported("inter without reference"));
2357 }
2358 if mode == 0 {
2365 self.mb_kind[mb_y * self.mb_w + mb_x] =
2366 rusty_h264_common::deblock::MB_KIND_INTER_UNIFORM;
2367 }
2368 let w4 = self.mb_w * 4;
2370 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2371 let num_refs = self.refs.len();
2372 let layout = inter_partitions(mode);
2373
2374 let nparts = layout.len();
2377 let mut ref_idxs = [0i32; 4];
2378 if self.num_ref_active > 1 {
2379 for ri in ref_idxs[..nparts].iter_mut() {
2380 *ri = read_ref_idx(r, self.num_ref_active)?;
2381 if *ri as usize >= num_refs {
2382 return Err(MbError::Truncated); }
2384 }
2385 }
2386
2387 let mut part_mv = [(0i32, (0i32, 0i32)); 4];
2390 {
2391 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::MvGrid);
2392 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2393 let refi = ref_idxs[part];
2394 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2395 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (rw / 4) as isize);
2396 let pmv = predict_partition_mv(mode, part, a, b, c, refi);
2397 let mvd_x = r.read_se()?;
2398 let mvd_y = r.read_se()?;
2399 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2400 part_mv[part] = (refi, mv);
2401 for by in ry / 4..ry / 4 + rh / 4 {
2402 for bx in rx / 4..rx / 4 + rw / 4 {
2403 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2404 self.mv_y[idx] = mv;
2405 self.inter_y[idx] = true;
2406 self.ref_idx_y[idx] = refi;
2407 self.coded_y[idx] = true;
2408 }
2409 }
2410 }
2411 }
2412
2413 let mut pred_y = [0u8; 256];
2415 let mut c_pred = [[0u8; 64]; 2];
2416 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2417 let (refi, mv) = part_mv[part];
2418 let reference = &self.refs[refi as usize];
2419 let mut tmp = [0u8; 256];
2420 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);
2421 {
2422 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
2423 restride(&mut pred_y, 16, rx, ry, &tmp, rw, rh);
2424 }
2425 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
2426 for cc in 0..2 {
2427 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
2428 let mut tc = [0u8; 64];
2429 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);
2430 {
2431 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
2432 restride(&mut c_pred[cc], 8, crx, cry, &tc, crw, crh);
2433 }
2434 }
2435 self.weight_partition(&mut pred_y, &mut c_pred, 0, refi as usize, rx, ry, rw, rh);
2436 }
2437
2438 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2440 }
2441
2442 fn inter_finish(
2446 &mut self,
2447 r: &mut BitReader,
2448 mb_x: usize,
2449 mb_y: usize,
2450 pred_y: &[u8; 256],
2451 c_pred: &[[u8; 64]; 2],
2452 allow_8x8: bool,
2453 ) -> Result<(), MbError> {
2454 let w4 = self.mb_w * 4;
2455 let cbp = {
2456 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
2457 read_cbp_inter(r)?
2458 };
2459 let cbp_luma = cbp & 15;
2460 let cbp_chroma = cbp >> 4;
2461 let t8x8 = cbp_luma > 0 && self.transform_8x8_mode && allow_8x8 && r.read_bit()?;
2464 if t8x8 {
2465 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
2466 }
2467 if cbp != 0 {
2468 self.step_qp(r.read_se()?);
2469 }
2470 let (qp, qpc) = (self.cur_qp, self.chroma_qp_for(self.cur_qp));
2471
2472 self.nnz_cache_load(mb_x, mb_y);
2474 let mut q_blocks = [[0i32; 16]; 16];
2475 let mut luma8 = [[0i32; 64]; 4]; if t8x8 {
2477 for b8 in 0..4 {
2478 let (b8x, b8y) = (b8 % 2, b8 / 2);
2479 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2480 if cbp_luma & (1 << b8) != 0 {
2481 let mut scan8 = [0i32; 64];
2482 for sub in 0..4 {
2483 let (sx, sy) = (sub % 2, sub / 2);
2484 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
2485 let nc = self.nc_pred(cx, cy);
2486 let blk = decode_residual_block(r, 16, nc)?;
2487 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
2488 self.nnz_cache_set(cx, cy, total);
2489 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
2490 for k in 0..16 {
2491 scan8[4 * k + sub] = blk[k];
2492 }
2493 }
2494 luma8[b8] = self.inv_quant8(&un_scan_8x8(&scan8), qp, 1);
2495 } else {
2496 for sub in 0..4 {
2497 let (sx, sy) = (sub % 2, sub / 2);
2498 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
2499 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
2500 }
2501 }
2502 }
2503 } else {
2504 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2505 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2506 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
2507 let nc = self.nc_pred(lbx, lby);
2508 let scan16 = decode_residual_block(r, 16, nc)?;
2509 q_blocks[lby * 4 + lbx] = un_scan_4x4_dcac(&scan16);
2510 scan16.iter().filter(|&&v| v != 0).count() as u8
2511 } else {
2512 0
2513 };
2514 self.nnz_cache_set(lbx, lby, total);
2515 self.nnz_y[by * w4 + bx] = total;
2516 }
2517 }
2518
2519 let mut c_recon_dc = [[0i32; 4]; 2];
2521 if cbp_chroma != 0 {
2522 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
2523 let dc = decode_residual_block(r, 4, -1)?;
2524 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 4 + c);
2525 }
2526 }
2527 let mut c_q = [[[0i32; 16]; 4]; 2];
2528 if cbp_chroma == 2 {
2529 self.chroma_cache_load(mb_x, mb_y);
2530 let w2 = self.mb_w * 2;
2531 for c in 0..2 {
2532 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2533 let nc = self.chroma_nc_pred(c, bx, by);
2534 let ac = decode_residual_block(r, 15, nc)?;
2535 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
2536 self.chroma_nnz_cache_set(c, bx, by, total);
2537 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
2538 un_scan_4x4_ac_into(&ac, &mut c_q[c][by * 2 + bx]);
2539 }
2540 }
2541 }
2542
2543 if t8x8 {
2545 for b8 in 0..4 {
2546 let (b8x, b8y) = (b8 % 2, b8 / 2);
2547 let (px, py) = (b8x * 8, b8y * 8);
2548 for dy in 0..8 {
2549 for dx in 0..8 {
2550 let p = pred_y[(py + dy) * 16 + (px + dx)] as i32;
2551 let v = (p + luma8[b8][dy * 8 + dx]).clamp(0, 255) as u8;
2552 self.rec_y[(mb_y * 16 + py + dy) * self.cw + (mb_x * 16 + px + dx)] = v;
2553 }
2554 }
2555 }
2556 } else {
2557 for b8 in 0..4 {
2564 let (b8x, b8y) = (b8 % 2, b8 / 2);
2565 let pred_off = (b8y * 8) * 16 + b8x * 8;
2566 let rec_off = (mb_y * 16 + b8y * 8) * self.cw + (mb_x * 16 + b8x * 8);
2567 if cbp_luma & (1 << b8) == 0 {
2568 for r in 0..8 {
2569 let (s, d) = (pred_off + r * 16, rec_off + r * self.cw);
2570 self.rec_y[d..d + 8].copy_from_slice(&pred_y[s..s + 8]);
2571 }
2572 continue;
2573 }
2574 #[cfg(accel)]
2575 {
2576 let mut dct = [0i16; 64];
2577 for (i, (sx, sy)) in [(0, 0), (1, 0), (0, 1), (1, 1)].into_iter().enumerate() {
2578 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2579 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2580 for k in 0..16 {
2581 dct[i * 16 + k] = deq[k] as i16;
2582 }
2583 }
2584 rusty_h264_accel::idct_four_t4_rec(
2585 &mut self.rec_y[rec_off..],
2586 self.cw,
2587 &pred_y[pred_off..],
2588 16,
2589 &dct,
2590 );
2591 }
2592 #[cfg(not(accel))]
2593 for (sx, sy) in [(0, 0), (1, 0), (0, 1), (1, 1)] {
2594 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
2595 let mut predb = [0i32; 16];
2596 for dy in 0..4 {
2597 for dx in 0..4 {
2598 predb[dy * 4 + dx] = pred_y[(lby * 4 + dy) * 16 + (lbx * 4 + dx)] as i32;
2599 }
2600 }
2601 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
2602 let s = reconstruct_4x4(&deq, &predb);
2603 store(&mut self.rec_y, self.cw, mb_x * 16 + lbx * 4, mb_y * 16 + lby * 4, &s);
2604 }
2605 }
2606 }
2607 if cbp_chroma == 0 {
2610 for c in 0..2 {
2611 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2612 for dy in 0..8 {
2613 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2614 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2615 }
2616 }
2617 } else {
2618 for c in 0..2 {
2619 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2620 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
2621 let mut predb = [0i32; 16];
2622 for dy in 0..4 {
2623 for dx in 0..4 {
2624 predb[dy * 4 + dx] = c_pred[c][(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
2625 }
2626 }
2627 let mut deq = match &self.scaling {
2628 Some(s) => dequantize_weighted(&c_q[c][by * 2 + bx], qpc, &s[4 + c]),
2629 None => dequantize(&c_q[c][by * 2 + bx], qpc),
2630 };
2631 deq[0] = c_recon_dc[c][by * 2 + bx];
2632 let s = reconstruct_4x4(&deq, &predb);
2633 store(plane, self.ccw, mb_x * 8 + bx * 4, mb_y * 8 + by * 4, &s);
2634 }
2635 }
2636 }
2637
2638 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2640 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2641 }
2642 Ok(())
2643 }
2644
2645 fn mv_neighbors_list(&self, pbx: isize, pby: isize, pwb: isize, list: usize) -> [MvNeighbor; 3] {
2653 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
2654 let (mvg, refg) = if list == 0 {
2655 (&self.mv_y, &self.ref_idx_y)
2656 } else {
2657 (&self.mv1, &self.ref_idx1)
2658 };
2659 let get = |bx: isize, by: isize| -> MvNeighbor {
2660 if bx < 0
2661 || by < 0
2662 || bx >= w4
2663 || by >= h4
2664 || !self.coded_y[(by * w4 + bx) as usize]
2665 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
2666 {
2667 MvNeighbor::NONE
2668 } else {
2669 let idx = (by * w4 + bx) as usize;
2670 MvNeighbor { available: true, mv: mvg[idx], ref_idx: refg[idx] }
2671 }
2672 };
2673 let a = get(pbx - 1, pby);
2674 let b = get(pbx, pby - 1);
2675 let mut c = get(pbx + pwb, pby - 1);
2676 if !c.available {
2677 c = get(pbx - 1, pby - 1);
2678 }
2679 [a, b, c]
2680 }
2681
2682 #[inline]
2696 fn col_block(&self, bx4: usize, by4: usize) -> (usize, usize) {
2697 if self.direct_8x8_inference {
2698 ((bx4 / 2) * 3, (by4 / 2) * 3)
2699 } else {
2700 (bx4, by4)
2701 }
2702 }
2703
2704 fn col_zero(&self, bx: usize, by: usize) -> bool {
2705 let Some(col) = self.refs1.first() else { return false };
2706 if col.long_term || col.w4 == 0 {
2707 return false;
2708 }
2709 let idx = by * col.w4 + bx;
2710 if idx >= col.ref_idx.len() {
2711 return false;
2712 }
2713 let (cref, cmv) = if col.ref_idx[idx] >= 0 {
2721 (col.ref_idx[idx], col.mv[idx])
2722 } else if idx < col.ref_idx1.len() && col.ref_idx1[idx] >= 0 {
2723 (col.ref_idx1[idx], col.mv1[idx])
2724 } else {
2725 return false;
2726 };
2727 cref == 0 && cmv.0.abs() <= 1 && cmv.1.abs() <= 1
2728 }
2729
2730 fn implicit_weights(&self, refi0: i32, refi1: i32) -> Option<(i32, i32)> {
2734 if self.weighted_bipred_idc != 2 || refi0 < 0 || refi1 < 0 {
2735 return None;
2736 }
2737 let r0 = &self.refs[refi0 as usize];
2738 let r1 = &self.refs1[refi1 as usize];
2739 let td = (r1.poc - r0.poc).clamp(-128, 127);
2740 let tb = (self.cur_poc - r0.poc).clamp(-128, 127);
2741 if td == 0 || r0.long_term || r1.long_term {
2742 return None; }
2744 let tx = (16384 + td.abs() / 2) / td;
2745 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2746 let w1 = dsf >> 2;
2747 if !(-64..=128).contains(&w1) {
2748 return None; }
2750 Some((64 - w1, w1))
2751 }
2752
2753 #[allow(clippy::too_many_arguments)]
2757 fn b_mc(
2758 &self,
2759 mb_x: usize,
2760 mb_y: usize,
2761 px: usize,
2762 py: usize,
2763 rw: usize,
2764 rh: usize,
2765 refi0: i32,
2766 mv0: (i32, i32),
2767 refi1: i32,
2768 mv1: (i32, i32),
2769 pred_y: &mut [u8; 256],
2770 c_pred: &mut [[u8; 64]; 2],
2771 ) {
2772 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBMc);
2773 let refi0 = if refi0 >= 0 { (refi0 as usize).min(self.refs.len().saturating_sub(1)) as i32 } else { -1 };
2779 let refi1 = if refi1 >= 0 { (refi1 as usize).min(self.refs1.len().saturating_sub(1)) as i32 } else { -1 };
2780 if (refi0 >= 0 && self.refs.is_empty()) || (refi1 >= 0 && self.refs1.is_empty()) {
2781 return;
2782 }
2783 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2784 let weights = {
2785 let _gw = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBWeights);
2786 self.implicit_weights(refi0, refi1)
2787 };
2788 let full = px == 0 && rw == 16;
2800 let _gl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBLuma);
2801 let chroma_done = rusty_h264_common::inter::with_mc_scratch(|scr| match (refi0 >= 0, refi1 >= 0, full) {
2806 (true, false, true) => {
2807 let rf = &self.refs[refi0 as usize];
2808 rusty_h264_common::inter::mc_luma_padded_pre(scr, &rf.py, rf.lstride(), crate::LPAD, self.cw, ch, mb_x * 16, mb_y * 16 + py, rw, rh, mv0.0, mv0.1, &mut pred_y[py * 16..py * 16 + rw * rh]);
2809 false
2810 }
2811 (false, true, true) => {
2812 let rf = &self.refs1[refi1 as usize];
2813 rusty_h264_common::inter::mc_luma_padded_pre(scr, &rf.py, rf.lstride(), crate::LPAD, self.cw, ch, mb_x * 16, mb_y * 16 + py, rw, rh, mv1.0, mv1.1, &mut pred_y[py * 16..py * 16 + rw * rh]);
2814 false
2815 }
2816 (true, true, true) => {
2817 let rf = &self.refs[refi0 as usize];
2818 rusty_h264_common::inter::mc_luma_padded_pre(scr, &rf.py, rf.lstride(), crate::LPAD, self.cw, ch, mb_x * 16, mb_y * 16 + py, rw, rh, mv0.0, mv0.1, &mut pred_y[py * 16..py * 16 + rw * rh]);
2819 let mut b = [0u8; 256];
2820 let rf = &self.refs1[refi1 as usize];
2821 rusty_h264_common::inter::mc_luma_padded_pre(scr, &rf.py, rf.lstride(), crate::LPAD, self.cw, ch, mb_x * 16, mb_y * 16 + py, rw, rh, mv1.0, mv1.1, &mut b[..rw * rh]);
2822 drop(_gl);
2823 let _gbl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBBlend);
2824 let dst = &mut pred_y[py * 16..py * 16 + rw * rh];
2830 match weights {
2831 None => {
2832 for (d, s) in dst.iter_mut().zip(&b[..rw * rh]) {
2833 *d = ((*d as u16 + *s as u16 + 1) >> 1) as u8;
2834 }
2835 }
2836 Some((w0, w1)) => {
2837 for (d, s) in dst.iter_mut().zip(&b[..rw * rh]) {
2838 *d = ((*d as i32 * w0 + *s as i32 * w1 + 32) >> 6).clamp(0, 255) as u8;
2839 }
2840 }
2841 }
2842 let _gc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBChroma);
2843 self.b_mc_chroma(mb_x, mb_y, px, py, rw, rh, refi0, mv0, refi1, mv1, c_pred, weights, cch);
2844 true
2845 }
2846 _ => {
2847 let (mut a, mut b) = ([0u8; 256], [0u8; 256]);
2849 if refi0 >= 0 {
2850 let rf = &self.refs[refi0 as usize];
2851 rusty_h264_common::inter::mc_luma_padded_pre(scr, &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[..rw * rh]);
2852 }
2853 if refi1 >= 0 {
2854 let rf = &self.refs1[refi1 as usize];
2855 rusty_h264_common::inter::mc_luma_padded_pre(scr, &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[..rw * rh]);
2856 }
2857 drop(_gl);
2858 let _gbl = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBBlend);
2859 match (refi0 >= 0, refi1 >= 0) {
2860 (true, true) => {
2861 for dy in 0..rh {
2862 let (ar, br) = (&a[dy * rw..dy * rw + rw], &b[dy * rw..dy * rw + rw]);
2863 let base = (py + dy) * 16 + px;
2864 let dst = &mut pred_y[base..base + rw];
2865 match weights {
2866 None => {
2867 for ((d, p), q) in dst.iter_mut().zip(ar).zip(br) {
2868 *d = ((*p as u16 + *q as u16 + 1) >> 1) as u8;
2869 }
2870 }
2871 Some((w0, w1)) => {
2872 for ((d, p), q) in dst.iter_mut().zip(ar).zip(br) {
2873 *d = ((*p as i32 * w0 + *q as i32 * w1 + 32) >> 6).clamp(0, 255) as u8;
2874 }
2875 }
2876 }
2877 }
2878 }
2879 (true, false) => {
2880 for dy in 0..rh {
2881 let d = (py + dy) * 16 + px;
2882 pred_y[d..d + rw].copy_from_slice(&a[dy * rw..dy * rw + rw]);
2883 }
2884 }
2885 _ => {
2886 for dy in 0..rh {
2887 let d = (py + dy) * 16 + px;
2888 pred_y[d..d + rw].copy_from_slice(&b[dy * rw..dy * rw + rw]);
2889 }
2890 }
2891 }
2892 false
2893 }
2894 });
2895 if chroma_done {
2896 return;
2897 }
2898 let _gc = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBChroma);
2899 self.b_mc_chroma(mb_x, mb_y, px, py, rw, rh, refi0, mv0, refi1, mv1, c_pred, weights, cch);
2900 }
2901
2902 #[allow(clippy::too_many_arguments)]
2905 fn b_mc_chroma(
2906 &self,
2907 mb_x: usize,
2908 mb_y: usize,
2909 px: usize,
2910 py: usize,
2911 rw: usize,
2912 rh: usize,
2913 refi0: i32,
2914 mv0: (i32, i32),
2915 refi1: i32,
2916 mv1: (i32, i32),
2917 c_pred: &mut [[u8; 64]; 2],
2918 weights: Option<(i32, i32)>,
2919 cch: usize,
2920 ) {
2921 let (crx, cry, crw, crh) = (px / 2, py / 2, rw / 2, rh / 2);
2922 let full = crx == 0 && crw == 8;
2923 for c in 0..2 {
2924 match (refi0 >= 0, refi1 >= 0, full) {
2925 (true, false, true) => {
2926 let rf = &self.refs[refi0 as usize];
2927 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2928 mc_chroma_padded(pl, rf.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8, mb_y * 8 + cry, crw, crh, mv0.0, mv0.1, &mut c_pred[c][cry * 8..cry * 8 + crw * crh]);
2929 }
2930 (false, true, true) => {
2931 let rf = &self.refs1[refi1 as usize];
2932 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2933 mc_chroma_padded(pl, rf.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8, mb_y * 8 + cry, crw, crh, mv1.0, mv1.1, &mut c_pred[c][cry * 8..cry * 8 + crw * crh]);
2934 }
2935 (true, true, true) => {
2936 let rf = &self.refs[refi0 as usize];
2937 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2938 mc_chroma_padded(pl, rf.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8, mb_y * 8 + cry, crw, crh, mv0.0, mv0.1, &mut c_pred[c][cry * 8..cry * 8 + crw * crh]);
2939 let mut cb = [0u8; 64];
2940 let rf = &self.refs1[refi1 as usize];
2941 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2942 mc_chroma_padded(pl, rf.cstride(), crate::CPAD, self.ccw, cch, mb_x * 8, mb_y * 8 + cry, crw, crh, mv1.0, mv1.1, &mut cb[..crw * crh]);
2943 let dst = &mut c_pred[c][cry * 8..cry * 8 + crw * crh];
2944 match weights {
2945 None => {
2946 for (d, s) in dst.iter_mut().zip(&cb[..crw * crh]) {
2947 *d = ((*d as u16 + *s as u16 + 1) >> 1) as u8;
2948 }
2949 }
2950 Some((w0, w1)) => {
2951 for (d, s) in dst.iter_mut().zip(&cb[..crw * crh]) {
2952 *d = ((*d as i32 * w0 + *s as i32 * w1 + 32) >> 6).clamp(0, 255) as u8;
2953 }
2954 }
2955 }
2956 }
2957 _ => {
2958 let (mut ca, mut cb) = ([0u8; 64], [0u8; 64]);
2959 if refi0 >= 0 {
2960 let rf = &self.refs[refi0 as usize];
2961 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2962 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[..crw * crh]);
2963 }
2964 if refi1 >= 0 {
2965 let rf = &self.refs1[refi1 as usize];
2966 let pl = if c == 0 { &rf.pu } else { &rf.pv };
2967 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[..crw * crh]);
2968 }
2969 match (refi0 >= 0, refi1 >= 0) {
2970 (true, true) => {
2971 for dy in 0..crh {
2972 let (pr, qr) = (&ca[dy * crw..dy * crw + crw], &cb[dy * crw..dy * crw + crw]);
2973 let base = (cry + dy) * 8 + crx;
2974 let dst = &mut c_pred[c][base..base + crw];
2975 match weights {
2976 None => {
2977 for ((d, p), q) in dst.iter_mut().zip(pr).zip(qr) {
2978 *d = ((*p as u16 + *q as u16 + 1) >> 1) as u8;
2979 }
2980 }
2981 Some((w0, w1)) => {
2982 for ((d, p), q) in dst.iter_mut().zip(pr).zip(qr) {
2983 *d = ((*p as i32 * w0 + *q as i32 * w1 + 32) >> 6).clamp(0, 255) as u8;
2984 }
2985 }
2986 }
2987 }
2988 }
2989 (true, false) => {
2990 for dy in 0..crh {
2991 let d = (cry + dy) * 8 + crx;
2992 c_pred[c][d..d + crw].copy_from_slice(&ca[dy * crw..dy * crw + crw]);
2993 }
2994 }
2995 _ => {
2996 for dy in 0..crh {
2997 let d = (cry + dy) * 8 + crx;
2998 c_pred[c][d..d + crw].copy_from_slice(&cb[dy * crw..dy * crw + crw]);
2999 }
3000 }
3001 }
3002 }
3003 }
3004 }
3005 }
3006
3007 #[allow(clippy::too_many_arguments)]
3009 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)) {
3010 let _gs = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBSet);
3011 let w4 = self.mb_w * 4;
3012 for by in py / 4..(py + rh) / 4 {
3013 for bx in px / 4..(px + rw) / 4 {
3014 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
3015 self.ref_idx_y[idx] = refi0;
3016 self.mv_y[idx] = if refi0 >= 0 { mv0 } else { (0, 0) };
3017 self.ref_idx1[idx] = refi1;
3018 self.mv1[idx] = if refi1 >= 0 { mv1 } else { (0, 0) };
3019 self.inter_y[idx] = true;
3020 self.coded_y[idx] = true;
3021 self.modes_y[idx] = 2;
3022 }
3023 }
3024 }
3025
3026 #[allow(clippy::too_many_arguments)]
3030 fn coalesce_region(
3035 x: usize,
3036 y: usize,
3037 w: usize,
3038 h: usize,
3039 uniform: &dyn Fn(usize, usize, usize, usize) -> bool,
3040 emit: &mut dyn FnMut(usize, usize, usize, usize),
3041 ) {
3042 if uniform(x, y, w, h) {
3043 emit(x, y, w, h);
3044 return;
3045 }
3046 if h > 1 && uniform(x, y, w, h / 2) && uniform(x, y + h / 2, w, h / 2) {
3047 emit(x, y, w, h / 2);
3048 emit(x, y + h / 2, w, h / 2);
3049 return;
3050 }
3051 if w > 1 && uniform(x, y, w / 2, h) && uniform(x + w / 2, y, w / 2, h) {
3052 emit(x, y, w / 2, h);
3053 emit(x + w / 2, y, w / 2, h);
3054 return;
3055 }
3056 match (w > 1, h > 1) {
3057 (true, true) => {
3058 for q in 0..4usize {
3059 Self::coalesce_region(x + (q % 2) * (w / 2), y + (q / 2) * (h / 2), w / 2, h / 2, uniform, emit);
3060 }
3061 }
3062 (true, false) => {
3063 Self::coalesce_region(x, y, w / 2, h, uniform, emit);
3064 Self::coalesce_region(x + w / 2, y, w / 2, h, uniform, emit);
3065 }
3066 (false, true) => {
3067 Self::coalesce_region(x, y, w, h / 2, uniform, emit);
3068 Self::coalesce_region(x, y + h / 2, w, h / 2, uniform, emit);
3069 }
3070 (false, false) => emit(x, y, 1, 1),
3071 }
3072 }
3073
3074 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]) {
3075 let _gb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDirect);
3076 if !self.direct_spatial {
3077 return self.decode_b_direct_temporal(mb_x, mb_y, px, py, rw, rh, pred_y, c_pred);
3078 }
3079 let gd = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecBDeriv);
3084 let (nbx, nby) = ((mb_x * 4) as isize, (mb_y * 4) as isize);
3086 let n0 = self.mv_neighbors_list(nbx, nby, 4, 0);
3087 let n1 = self.mv_neighbors_list(nbx, nby, 4, 1);
3088 let min_pos = |a: i32, b: i32| if a < 0 { b } else if b < 0 { a } else { a.min(b) };
3089 let rid = |n: &[MvNeighbor; 3]| min_pos(min_pos(n[0].ref_idx, n[1].ref_idx), n[2].ref_idx);
3090 let (mut refi0, mut refi1) = (rid(&n0), rid(&n1));
3091 let direct_zero = refi0 < 0 && refi1 < 0;
3092 if direct_zero {
3093 refi0 = 0;
3094 refi1 = 0;
3095 }
3096 let mv0 = if refi0 >= 0 && !direct_zero { predict_mv(n0[0], n0[1], n0[2], refi0) } else { (0, 0) };
3097 let mv1 = if refi1 >= 0 && !direct_zero { predict_mv(n1[0], n1[1], n1[2], refi1) } else { (0, 0) };
3098 let (bx0, by0, bw, bh) = (px / 4, py / 4, rw / 4, rh / 4);
3104 let mut czg = [[false; 4]; 4]; for dy in 0..bh {
3106 for dx in 0..bw {
3107 let (colx, coly) = self.col_block(bx0 + dx, by0 + dy);
3108 czg[dy][dx] = !direct_zero && self.col_zero(mb_x * 4 + colx, mb_y * 4 + coly);
3109 }
3110 }
3111 let uniform = |x: usize, y: usize, w: usize, h: usize| -> bool {
3112 let t = czg[y][x];
3113 (y..y + h).all(|dy| (x..x + w).all(|dx| czg[dy][dx] == t))
3114 };
3115 let mut rects: [(usize, usize, usize, usize); 16] = [(0, 0, 0, 0); 16];
3116 let mut n = 0usize;
3117 Self::coalesce_region(0, 0, bw, bh, &uniform, &mut |x, y, w, h| {
3118 rects[n] = (x, y, w, h);
3119 n += 1;
3120 });
3121 drop(gd); for &(x, y, w, h) in &rects[..n] {
3123 let cz = czg[y][x];
3124 let m0 = if refi0 == 0 && cz { (0, 0) } else { mv0 };
3125 let m1 = if refi1 == 0 && cz { (0, 0) } else { mv1 };
3126 let (lx, ly, lw, lh) = ((bx0 + x) * 4, (by0 + y) * 4, w * 4, h * 4);
3127 self.b_mc(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1, pred_y, c_pred);
3128 self.b_set_motion(mb_x, mb_y, lx, ly, lw, lh, refi0, m0, refi1, m1);
3129 }
3130 }
3131
3132 #[allow(clippy::too_many_arguments)]
3137 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]) {
3138 let poc1 = self.refs1.first().map_or(0, |f| f.poc);
3139 let infer = self.direct_8x8_inference;
3140 let step = if infer { 8 } else { 4 };
3146 let mut sy = py;
3147 while sy < py + rh {
3148 let mut sx = px;
3149 while sx < px + rw {
3150 let (colx, coly) = self.col_block(sx / 4, sy / 4);
3153 let (mvcol, refpoc) = {
3154 let col = &self.refs1[0];
3155 let idx = (mb_y * 4 + coly) * col.w4 + (mb_x * 4 + colx);
3156 if col.w4 != 0 && idx < col.mv.len() && col.ref_poc[idx] != i32::MIN {
3157 (col.mv[idx], col.ref_poc[idx])
3158 } else {
3159 ((0, 0), i32::MIN) }
3161 };
3162 let (refi0, mvc) = if refpoc == i32::MIN {
3164 (0, (0, 0))
3165 } else {
3166 let r = self.refs.iter().position(|f| f.poc == refpoc).unwrap_or(0) as i32;
3167 (r, mvcol)
3168 };
3169 let poc0 = self.refs[refi0 as usize].poc;
3170 let td = (poc1 - poc0).clamp(-128, 127);
3171 let tb = (self.cur_poc - poc0).clamp(-128, 127);
3172 let (mv0, mv1) = if td == 0 || self.refs[refi0 as usize].long_term {
3173 (mvc, (0, 0))
3174 } else {
3175 let tx = (16384 + td.abs() / 2) / td;
3176 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
3177 let m0 = ((dsf * mvc.0 + 128) >> 8, (dsf * mvc.1 + 128) >> 8);
3178 (m0, (m0.0 - mvc.0, m0.1 - mvc.1))
3179 };
3180 self.b_mc(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1, pred_y, c_pred);
3181 self.b_set_motion(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1);
3182 sx += step;
3183 }
3184 sy += step;
3185 }
3186 }
3187
3188 fn read_b_ref(&self, r: &mut BitReader, list: usize) -> Result<i32, MbError> {
3191 let (active, avail) = if list == 0 {
3192 (self.num_ref_active, self.refs.len())
3193 } else {
3194 (self.num_ref_active1, self.refs1.len())
3195 };
3196 let v = if active > 1 { read_ref_idx(r, active)? } else { 0 };
3197 if v as usize >= avail {
3198 return Err(MbError::Truncated);
3199 }
3200 Ok(v)
3201 }
3202
3203 fn decode_b_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3205 if self.refs.is_empty() || self.refs1.is_empty() {
3206 return Err(MbError::Unsupported("B without references"));
3207 }
3208 let mut pred_y = [0u8; 256];
3209 let mut c_pred = [[0u8; 64]; 2];
3210 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
3211 for dy in 0..16 {
3213 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
3214 self.rec_y[d..d + 16].copy_from_slice(&pred_y[dy * 16..dy * 16 + 16]);
3215 }
3216 for c in 0..2 {
3217 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3218 for dy in 0..8 {
3219 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
3220 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
3221 }
3222 }
3223 let w4 = self.mb_w * 4;
3225 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3226 self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 0;
3227 }
3228 Ok(())
3229 }
3230
3231 fn decode_b_mb(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3234 let mb_type = r.read_ue()?;
3235 if mb_type >= 23 {
3236 return self.decode_intra_mb(r, mb_x, mb_y, mb_type - 23);
3237 }
3238 if self.refs.is_empty() || self.refs1.is_empty() {
3239 return Err(MbError::Unsupported("B without references"));
3240 }
3241 let mut pred_y = [0u8; 256];
3242 let mut c_pred = [[0u8; 64]; 2];
3243
3244 if mb_type == 0 {
3245 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
3247 return self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, self.direct_8x8_inference);
3248 }
3249 if mb_type == 22 {
3250 return self.decode_b_8x8(r, mb_x, mb_y);
3251 }
3252
3253 let (layout, mvmode, preds) = b_inter_layout(mb_type);
3255 let mut refi = [[-1i32; 2]; 2]; for (p, &(_, _, _, _)) in layout.iter().enumerate() {
3258 if preds[p].uses(0) {
3259 refi[p][0] = self.read_b_ref(r, 0)?;
3260 }
3261 }
3262 for (p, _) in layout.iter().enumerate() {
3263 if preds[p].uses(1) {
3264 refi[p][1] = self.read_b_ref(r, 1)?;
3265 }
3266 }
3267 let mut mvd = [[(0i32, 0i32); 2]; 2];
3268 for (p, _) in layout.iter().enumerate() {
3269 if preds[p].uses(0) {
3270 mvd[p][0] = (r.read_se()?, r.read_se()?);
3271 }
3272 }
3273 for (p, _) in layout.iter().enumerate() {
3274 if preds[p].uses(1) {
3275 mvd[p][1] = (r.read_se()?, r.read_se()?);
3276 }
3277 }
3278 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
3280 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
3281 let pwb = (rw / 4) as isize;
3282 let mut mv = [(0i32, 0i32); 2];
3283 for list in 0..2 {
3284 if refi[p][list] >= 0 {
3285 let n = self.mv_neighbors_list(pbx, pby, pwb, list);
3286 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], refi[p][list]);
3287 mv[list] = (pmv.0 + mvd[p][list].0, pmv.1 + mvd[p][list].1);
3288 }
3289 }
3290 self.b_set_motion(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1]);
3291 self.b_mc(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1], &mut pred_y, &mut c_pred);
3301 }
3302 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
3303 }
3304
3305 fn decode_b_8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3308 let mut sub = [0u32; 4];
3309 for s in sub.iter_mut() {
3310 let v = r.read_ue()?;
3311 if v > 12 {
3312 return Err(MbError::Unsupported("invalid B sub_mb_type"));
3313 }
3314 *s = v;
3315 }
3316 let mut pred_y = [0u8; 256];
3317 let mut c_pred = [[0u8; 64]; 2];
3318 let mut refi = [[-1i32; 2]; 4];
3321 for (p, &st) in sub.iter().enumerate() {
3322 if st != 0 && b_sub_uses(st, 0) {
3323 refi[p][0] = self.read_b_ref(r, 0)?;
3324 }
3325 }
3326 for (p, &st) in sub.iter().enumerate() {
3327 if st != 0 && b_sub_uses(st, 1) {
3328 refi[p][1] = self.read_b_ref(r, 1)?;
3329 }
3330 }
3331 let mut mvd0: Vec<(i32, i32)> = Vec::new();
3333 let mut mvd1: Vec<(i32, i32)> = Vec::new();
3334 for &st in &sub {
3335 if st != 0 && b_sub_uses(st, 0) {
3336 for _ in b_sub_parts(st) {
3337 mvd0.push((r.read_se()?, r.read_se()?));
3338 }
3339 }
3340 }
3341 for &st in &sub {
3342 if st != 0 && b_sub_uses(st, 1) {
3343 for _ in b_sub_parts(st) {
3344 mvd1.push((r.read_se()?, r.read_se()?));
3345 }
3346 }
3347 }
3348 let (mut i0, mut i1) = (0usize, 0usize);
3350 for (p, &st) in sub.iter().enumerate() {
3351 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
3352 if st == 0 {
3353 self.decode_b_direct(mb_x, mb_y, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
3354 continue;
3355 }
3356 for &(sx, sy, sw, sh) in b_sub_parts(st) {
3357 let (px, py) = (b8x + sx, b8y + sy);
3358 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
3359 let pwb = (sw / 4) as isize;
3360 let mut mv = [(0i32, 0i32); 2];
3361 if b_sub_uses(st, 0) {
3362 let n = self.mv_neighbors_list(pbx, pby, pwb, 0);
3363 let pmv = predict_mv(n[0], n[1], n[2], refi[p][0]);
3364 let d = mvd0[i0];
3365 i0 += 1;
3366 mv[0] = (pmv.0 + d.0, pmv.1 + d.1);
3367 }
3368 if b_sub_uses(st, 1) {
3369 let n = self.mv_neighbors_list(pbx, pby, pwb, 1);
3370 let pmv = predict_mv(n[0], n[1], n[2], refi[p][1]);
3371 let d = mvd1[i1];
3372 i1 += 1;
3373 mv[1] = (pmv.0 + d.0, pmv.1 + d.1);
3374 }
3375 self.b_set_motion(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1]);
3376 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);
3377 }
3378 }
3379 let allow_8x8 = sub
3382 .iter()
3383 .all(|&st| if st == 0 { self.direct_8x8_inference } else { st <= 3 });
3384 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
3385 }
3386
3387 fn decode_p8x8(
3391 &mut self,
3392 r: &mut BitReader,
3393 mb_x: usize,
3394 mb_y: usize,
3395 ref0: bool,
3396 ) -> Result<(), MbError> {
3397 if self.refs.is_empty() {
3398 return Err(MbError::Unsupported("inter without reference"));
3399 }
3400 let w4 = self.mb_w * 4;
3401 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
3402 let num_refs = self.refs.len();
3403
3404 let mut sub_types = [0u32; 4];
3407 for st in sub_types.iter_mut() {
3408 let v = r.read_ue()?;
3409 if v > 3 {
3410 return Err(MbError::Unsupported("B-slice / invalid sub_mb_type"));
3411 }
3412 *st = v;
3413 }
3414 let mut ref_idxs = [0i32; 4];
3415 if self.num_ref_active > 1 && !ref0 {
3416 for ri in ref_idxs.iter_mut() {
3417 *ri = read_ref_idx(r, self.num_ref_active)?;
3418 if *ri as usize >= num_refs {
3419 return Err(MbError::Truncated); }
3421 }
3422 }
3423
3424 let mut pred_y = [0u8; 256];
3428 let mut c_pred = [[0u8; 64]; 2];
3429 for part in 0..4usize {
3430 let refi = ref_idxs[part];
3431 let (b8x, b8y) = ((part % 2) * 8, (part / 2) * 8);
3432 for &(srx, sry, srw, srh) in sub_mb_partitions(sub_types[part]) {
3433 let (px, py) = (b8x + srx, b8y + sry);
3434 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
3435 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (srw / 4) as isize);
3436 let pmv = predict_mv(a, b, c, refi);
3437 let mvd_x = r.read_se()?;
3438 let mvd_y = r.read_se()?;
3439 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
3440 for by in py / 4..py / 4 + srh / 4 {
3441 for bx in px / 4..px / 4 + srw / 4 {
3442 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
3443 self.mv_y[idx] = mv;
3444 self.inter_y[idx] = true;
3445 self.ref_idx_y[idx] = refi;
3446 self.coded_y[idx] = true;
3447 }
3448 }
3449 let reference = &self.refs[refi as usize];
3450 let mut tmp = [0u8; 256];
3451 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);
3452 restride(&mut pred_y, 16, px, py, &tmp, srw, srh);
3453 let (crx, cry, crw, crh) = (px / 2, py / 2, srw / 2, srh / 2);
3454 for cc in 0..2 {
3455 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
3456 let mut tc = [0u8; 64];
3457 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);
3458 restride(&mut c_pred[cc], 8, crx, cry, &tc, crw, crh);
3459 }
3460 self.weight_partition(
3461 &mut pred_y, &mut c_pred, 0, refi as usize, px, py, srw, srh,
3462 );
3463 }
3464 }
3465
3466 let allow_8x8 = sub_types.iter().all(|&t| t == 0);
3468 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
3469 }
3470
3471 fn edc_flush(&mut self) {
3478 if self.edc_jobs.is_empty() {
3479 return;
3480 }
3481 let jobs = std::mem::take(&mut self.edc_jobs);
3482 for j in &jobs {
3483 match j {
3484 EdcJob::Skip { mbx, mby, mv } => self.recon_p_skip(*mbx, *mby, *mv),
3485 EdcJob::Inter(job) => self.recon_p_inter(job),
3486 }
3487 }
3488 self.edc_jobs = jobs;
3490 self.edc_jobs.clear();
3491 }
3492
3493 fn recon_p_inter(&mut self, j: &PInterJob) {
3503 let mbw = self.mb_w;
3504 let saved_qp = self.cur_qp;
3509 self.cur_qp = j.qp;
3510 let qp = j.qp;
3515 let qpc = self.chroma_qp_for(qp);
3516 let (w4r, w2r) = (mbw * 4, mbw * 2);
3517 let mut pred_y = [0u8; 256];
3518 let mut c_pred = [[0u8; 64]; 2];
3519 {
3520 let _ms = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::DecMcStage);
3528 let (rh16, cch) = (self.mb_h * 16, self.mb_h * 8);
3529 let mut gmv = [(0i32, 0i32); 16];
3530 let mut gref = [0usize; 16];
3531 let _gg = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::MvGrid);
3532 for by in 0..4usize {
3533 for bx in 0..4usize {
3534 let bidx = (j.mby * 4 + by) * w4r + (j.mbx * 4 + bx);
3535 gmv[by * 4 + bx] = self.mv_y[bidx];
3536 gref[by * 4 + bx] =
3539 (self.ref_idx_y[bidx].max(0) as usize).min(self.refs.len() - 1);
3540 }
3541 }
3542 drop(_gg);
3543 let rect_eq = |x4: usize, y4: usize, w4: usize, h4: usize| -> bool {
3545 let t = y4 * 4 + x4;
3546 (0..h4).all(|dy| {
3547 (0..w4).all(|dx| {
3548 let b = (y4 + dy) * 4 + (x4 + dx);
3549 gmv[b] == gmv[t] && gref[b] == gref[t]
3550 })
3551 })
3552 };
3553 let refs = &self.refs;
3554 let (cw, ccw) = (self.cw, self.ccw);
3555 let mut mc_rect = |x4: usize,
3556 y4: usize,
3557 w4: usize,
3558 h4: usize,
3559 pred_y: &mut [u8; 256],
3560 c_pred: &mut [[u8; 64]; 2]| {
3561 let b = y4 * 4 + x4;
3562 let (mv, reference) = (gmv[b], &refs[gref[b]]);
3563 let (w, h) = (w4 * 4, h4 * 4);
3564 if w == 16 {
3573 rusty_h264_common::inter::with_mc_scratch(|scr| rusty_h264_common::inter::mc_luma_padded_pre(scr, &reference.py, reference.lstride(), crate::LPAD, cw, rh16, j.mbx * 16, j.mby * 16 + y4 * 4, w, h, mv.0, mv.1, &mut pred_y[y4 * 64..y4 * 64 + w * h]));
3574 } else {
3575 let mut t = [0u8; 256];
3576 rusty_h264_common::inter::with_mc_scratch(|scr| rusty_h264_common::inter::mc_luma_padded_pre(scr, &reference.py, reference.lstride(), crate::LPAD, cw, rh16, j.mbx * 16 + x4 * 4, j.mby * 16 + y4 * 4, w, h, mv.0, mv.1, &mut t[..w * h]));
3577 let _pb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
3578 for dy in 0..h {
3579 pred_y[(y4 * 4 + dy) * 16 + x4 * 4..][..w]
3580 .copy_from_slice(&t[dy * w..dy * w + w]);
3581 }
3582 }
3583 let (cw4, ch4) = (w4 * 2, h4 * 2);
3584 for cc in 0..2 {
3585 let rc = if cc == 0 { &reference.pu } else { &reference.pv };
3586 if cw4 == 8 {
3589 mc_chroma_padded(rc, reference.cstride(), crate::CPAD, ccw, cch, j.mbx * 8, j.mby * 8 + y4 * 2, cw4, ch4, mv.0, mv.1, &mut c_pred[cc][y4 * 16..y4 * 16 + cw4 * ch4]);
3590 continue;
3591 }
3592 let mut tc = [0u8; 64];
3593 mc_chroma_padded(rc, reference.cstride(), crate::CPAD, ccw, cch, j.mbx * 8 + x4 * 2, j.mby * 8 + y4 * 2, cw4, ch4, mv.0, mv.1, &mut tc[..cw4 * ch4]);
3594 let _pb = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
3595 for dy in 0..ch4 {
3596 c_pred[cc][(y4 * 2 + dy) * 8 + x4 * 2..][..cw4]
3597 .copy_from_slice(&tc[dy * cw4..dy * cw4 + cw4]);
3598 }
3599 }
3600 };
3601 if rect_eq(0, 0, 4, 4) {
3602 mc_rect(0, 0, 4, 4, &mut pred_y, &mut c_pred);
3603 } else if rect_eq(0, 0, 4, 2) && rect_eq(0, 2, 4, 2) {
3604 mc_rect(0, 0, 4, 2, &mut pred_y, &mut c_pred);
3605 mc_rect(0, 2, 4, 2, &mut pred_y, &mut c_pred);
3606 } else if rect_eq(0, 0, 2, 4) && rect_eq(2, 0, 2, 4) {
3607 mc_rect(0, 0, 2, 4, &mut pred_y, &mut c_pred);
3608 mc_rect(2, 0, 2, 4, &mut pred_y, &mut c_pred);
3609 } else {
3610 for q in 0..4usize {
3611 let (qx, qy) = ((q % 2) * 2, (q / 2) * 2);
3612 if rect_eq(qx, qy, 2, 2) {
3613 mc_rect(qx, qy, 2, 2, &mut pred_y, &mut c_pred);
3614 } else if rect_eq(qx, qy, 2, 1) && rect_eq(qx, qy + 1, 2, 1) {
3615 mc_rect(qx, qy, 2, 1, &mut pred_y, &mut c_pred);
3616 mc_rect(qx, qy + 1, 2, 1, &mut pred_y, &mut c_pred);
3617 } else if rect_eq(qx, qy, 1, 2) && rect_eq(qx + 1, qy, 1, 2) {
3618 mc_rect(qx, qy, 1, 2, &mut pred_y, &mut c_pred);
3619 mc_rect(qx + 1, qy, 1, 2, &mut pred_y, &mut c_pred);
3620 } else {
3621 for j in 0..4usize {
3622 mc_rect(qx + (j % 2), qy + (j / 2), 1, 1, &mut pred_y, &mut c_pred);
3623 }
3624 }
3625 }
3626 }
3627 if self.weights.is_some() {
3641 for by in 0..4usize {
3642 for bx in 0..4usize {
3643 let refi = gref[by * 4 + bx];
3644 self.weight_partition(
3645 &mut pred_y, &mut c_pred, 0, refi, bx * 4, by * 4, 4, 4,
3646 );
3647 }
3648 }
3649 }
3650 }
3651 self.add_inter_residual(j.mbx, j.mby, &pred_y, &c_pred, &j.luma_scan, if j.t8 { Some(&j.luma8) } else { None }, &j.cdc, &j.cac, j.cbp_chroma, &j.nnzs);
3655 self.cur_qp = saved_qp;
3656 }
3657
3658 fn decode_p_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3659 self.mb_kind[mb_y * self.mb_w + mb_x] = rusty_h264_common::deblock::MB_KIND_SKIP;
3671 if self.refs.is_empty() {
3675 return Err(MbError::Unsupported("P_Skip without reference"));
3676 }
3677 let mv = self.skip_mv(mb_x, mb_y);
3678 {
3682 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
3683 self.set_mb_mv(mb_x, mb_y, mv, true, 0);
3684 let w4 = self.mb_w * 4;
3685 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3686 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
3687 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3688 }
3689 }
3690 if self.edc_active {
3691 self.edc_jobs.push(EdcJob::Skip { mbx: mb_x, mby: mb_y, mv });
3692 return Ok(());
3693 }
3694 self.recon_p_skip(mb_x, mb_y, mv);
3695 Ok(())
3696 }
3697
3698 fn recon_p_skip(&mut self, mb_x: usize, mb_y: usize, mv: (i32, i32)) {
3700 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
3701
3702 let mut pred = [0u8; 256];
3703 let rf0 = &self.refs[0];
3704 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);
3705 if let Some(wt) = &self.weights {
3706 for p in pred.iter_mut() {
3707 *p = wt.apply_luma(*p, 0, 0);
3708 }
3709 }
3710 {
3711 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
3712 for dy in 0..16 {
3713 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
3714 self.rec_y[d..d + 16].copy_from_slice(&pred[dy * 16..dy * 16 + 16]);
3715 }
3716 }
3717 for c in 0..2 {
3718 let mut pc = [0u8; 64];
3719 let rf0 = &self.refs[0];
3720 let rc = if c == 0 { &rf0.pu } else { &rf0.pv };
3721 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);
3722 if let Some(wt) = &self.weights {
3723 for p in pc.iter_mut() {
3724 *p = wt.apply_chroma(*p, 0, 0, c);
3725 }
3726 }
3727 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3728 for dy in 0..8 {
3729 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
3730 plane[d..d + 8].copy_from_slice(&pc[dy * 8..dy * 8 + 8]);
3731 }
3732 }
3733 }
3734
3735 fn predict_i4_mode(&self, bx: usize, by: usize) -> u8 {
3739 if bx == 0 || by == 0 {
3740 return 2;
3741 }
3742 if !self.nbr_in_slice((bx - 1) / 4, by / 4)
3746 || !self.nbr_in_slice(bx / 4, (by - 1) / 4)
3747 || !self.intra_nbr_ok(bx - 1, by)
3748 || !self.intra_nbr_ok(bx, by - 1)
3749 {
3750 return 2;
3751 }
3752 let w4 = self.mb_w * 4;
3753 self.modes_y[by * w4 + (bx - 1)].min(self.modes_y[(by - 1) * w4 + bx])
3754 }
3755
3756 fn gather_i4(
3758 &self,
3759 px: usize,
3760 py: usize,
3761 avail_top: bool,
3762 avail_left: bool,
3763 bx: usize,
3764 by: usize,
3765 ) -> ([u8; 8], [u8; 4], u8) {
3766 let (cw, w4) = (self.cw, self.mb_w * 4);
3767 let mut top = [0u8; 8];
3768 let mut left = [0u8; 4];
3769 let mut corner = 0;
3770 if avail_top {
3771 for i in 0..4 {
3772 top[i] = self.top_y_px(py, px + i);
3773 }
3774 let tr_avail = bx + 1 < w4
3775 && self.coded_y[(by - 1) * w4 + (bx + 1)]
3776 && self.nbr_in_slice((bx + 1) / 4, (by - 1) / 4)
3777 && self.intra_nbr_ok(bx + 1, by - 1);
3778 for i in 0..4 {
3779 top[4 + i] = if tr_avail {
3780 self.top_y_px(py, px + 4 + i)
3781 } else {
3782 top[3]
3783 };
3784 }
3785 }
3786 if avail_left {
3787 for i in 0..4 {
3788 left[i] = self.rec_y[(py + i) * cw + px - 1];
3789 }
3790 }
3791 if avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1) {
3794 corner = self.top_y_px(py, px - 1);
3795 }
3796 (top, left, corner)
3797 }
3798
3799 fn decode_ipcm(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3802 r.align_to_byte()?;
3803 let (lx, ly) = (mb_x * 16, mb_y * 16);
3804 for dy in 0..16 {
3805 for dx in 0..16 {
3806 self.rec_y[(ly + dy) * self.cw + (lx + dx)] = r.read_bits(8)? as u8;
3807 }
3808 }
3809 let (cx, cy) = (mb_x * 8, mb_y * 8);
3810 for plane in [&mut self.rec_u, &mut self.rec_v] {
3811 for dy in 0..8 {
3812 for dx in 0..8 {
3813 plane[(cy + dy) * self.ccw + (cx + dx)] = r.read_bits(8)? as u8;
3814 }
3815 }
3816 }
3817 let (w4, w2) = (self.mb_w * 4, self.mb_w * 2);
3820 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3821 let idx = (mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx);
3822 self.nnz_y[idx] = 16;
3823 self.modes_y[idx] = 2;
3824 self.inter_y[idx] = false;
3825 self.ref_idx_y[idx] = -1;
3826 self.mv_y[idx] = (0, 0);
3827 }
3828 for c in 0..2 {
3829 for by in 0..2 {
3830 for bx in 0..2 {
3831 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = 16;
3832 }
3833 }
3834 }
3835 Ok(())
3836 }
3837
3838 fn decode_i4x4(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3839 let w4 = self.mb_w * 4;
3840
3841 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3844 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
3845 let predicted = self.predict_i4_mode(bx, by);
3846 let actual = if r.read_bit()? {
3847 predicted
3848 } else {
3849 let rem = r.read_bits(3)? as u8;
3850 if rem < predicted {
3851 rem
3852 } else {
3853 rem + 1
3854 }
3855 };
3856 self.modes_y[by * w4 + bx] = actual;
3857 modes[lby * 4 + lbx] = actual;
3858 }
3859
3860 let chroma_mode = r.read_ue()? as u8;
3861 let cbp = read_cbp_intra(r)?;
3862 let cbp_luma = cbp & 15;
3863 let cbp_chroma = cbp >> 4;
3864 if cbp != 0 {
3865 self.step_qp(r.read_se()?);
3866 }
3867 let qp = self.cur_qp;
3868
3869 let top_mb_avail = mb_y > 0
3873 && self.nbr_in_slice(mb_x, mb_y - 1)
3874 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3875 let left_mb_avail = mb_x > 0
3876 && self.nbr_in_slice(mb_x - 1, mb_y)
3877 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3878 self.nnz_cache_load(mb_x, mb_y);
3879 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
3880 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
3881 let (px, py) = (bx * 4, by * 4);
3882 let avail_top = lby > 0 || top_mb_avail;
3883 let avail_left = lbx > 0 || left_mb_avail;
3884 let mut qb = [0i32; 16];
3885 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
3886 let nc = self.nc_pred(lbx, lby);
3887 let scan16 = decode_residual_block(r, 16, nc)?;
3888 qb = un_scan_4x4_dcac(&scan16);
3889 scan16.iter().filter(|&&v| v != 0).count() as u8
3890 } else {
3891 0
3892 };
3893 self.nnz_cache_set(lbx, lby, total);
3894 self.nnz_y[by * w4 + bx] = total;
3895 let (top, left, corner) = self.gather_i4(px, py, avail_top, avail_left, bx, by);
3896 let pred = intra4x4_pred(modes[lby * 4 + lbx], avail_top, avail_left, &top, &left, corner);
3897 let mut predb = [0i32; 16];
3898 for i in 0..16 {
3899 predb[i] = pred[i] as i32;
3900 }
3901 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
3902 store(&mut self.rec_y, self.cw, px, py, &s);
3903 self.coded_y[by * w4 + bx] = true;
3904 }
3905
3906 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3907 }
3908
3909 fn decode_i8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
3913 let w4 = self.mb_w * 4;
3914 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
3915
3916 let mut modes8 = [2u8; 4];
3919 for (b8, mode) in modes8.iter_mut().enumerate() {
3920 let (b8x, b8y) = (b8 % 2, b8 / 2);
3921 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
3922 let predicted = self.predict_i4_mode(bx, by);
3923 let actual = if r.read_bit()? {
3924 predicted
3925 } else {
3926 let rem = r.read_bits(3)? as u8;
3927 if rem < predicted { rem } else { rem + 1 }
3928 };
3929 *mode = actual;
3930 for sy in 0..2 {
3931 for sx in 0..2 {
3932 self.modes_y[(by + sy) * w4 + (bx + sx)] = actual;
3933 }
3934 }
3935 }
3936
3937 let chroma_mode = r.read_ue()? as u8;
3938 let cbp = read_cbp_intra(r)?;
3939 let cbp_luma = cbp & 15;
3940 let cbp_chroma = cbp >> 4;
3941 if cbp != 0 {
3942 self.step_qp(r.read_se()?);
3943 }
3944 let qp = self.cur_qp;
3945
3946 let top_mb_avail = mb_y > 0
3947 && self.nbr_in_slice(mb_x, mb_y - 1)
3948 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3949 let left_mb_avail = mb_x > 0
3950 && self.nbr_in_slice(mb_x - 1, mb_y)
3951 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3952 self.nnz_cache_load(mb_x, mb_y);
3953
3954 for b8 in 0..4 {
3955 let (b8x, b8y) = (b8 % 2, b8 / 2);
3956 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
3957 let (px, py) = (bx * 4, by * 4);
3958
3959 let mut res8 = [0i32; 64];
3962 if cbp_luma & (1 << b8) != 0 {
3963 let mut scan8 = [0i32; 64];
3964 for sub in 0..4 {
3965 let (sx, sy) = (sub % 2, sub / 2);
3966 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
3967 let nc = self.nc_pred(cx, cy);
3968 let blk = decode_residual_block(r, 16, nc)?;
3969 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
3970 self.nnz_cache_set(cx, cy, total);
3971 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
3972 for k in 0..16 {
3973 scan8[4 * k + sub] = blk[k];
3974 }
3975 }
3976 let raster = un_scan_8x8(&scan8);
3977 res8 = self.inv_quant8(&raster, qp, 0);
3978 } else {
3979 for sub in 0..4 {
3980 let (sx, sy) = (sub % 2, sub / 2);
3981 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
3982 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
3983 }
3984 }
3985
3986 let avail_top = b8y > 0 || top_mb_avail;
3987 let avail_left = b8x > 0 || left_mb_avail;
3988 let (top, left, corner, avail_corner) =
3989 self.gather_i8(px, py, avail_top, avail_left, bx, by);
3990 let pred = intra8x8_pred(
3991 modes8[b8], avail_top, avail_left, avail_corner, &top, &left, corner,
3992 );
3993 let mut predb = [0i32; 64];
3994 for i in 0..64 {
3995 predb[i] = pred[i] as i32;
3996 }
3997 let recon = add_residual_8x8(&res8, &predb);
3998 for dy in 0..8 {
3999 for dx in 0..8 {
4000 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
4001 }
4002 }
4003 for sy in 0..2 {
4004 for sx in 0..2 {
4005 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
4006 }
4007 }
4008 }
4009
4010 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
4011 }
4012
4013 fn inv_quant8(&self, raster: &[i32; 64], qp: u8, list: usize) -> [i32; 64] {
4016 match &self.scaling8 {
4017 Some(s) => inverse_quant_8x8(raster, qp, &s[list]),
4018 None => inverse_quant_8x8(raster, qp, &[16i32; 64]),
4019 }
4020 }
4021
4022 #[allow(clippy::too_many_arguments)]
4026 fn gather_i8(
4027 &self,
4028 px: usize,
4029 py: usize,
4030 avail_top: bool,
4031 avail_left: bool,
4032 bx: usize,
4033 by: usize,
4034 ) -> ([u8; 16], [u8; 8], u8, bool) {
4035 let (cw, w4) = (self.cw, self.mb_w * 4);
4036 let mut top = [0u8; 16];
4037 let mut left = [0u8; 8];
4038 let mut corner = 0;
4039 if avail_top {
4040 for i in 0..8 {
4041 top[i] = self.top_y_px(py, px + i);
4042 }
4043 let tr_avail = bx + 2 < w4
4044 && self.coded_y[(by - 1) * w4 + (bx + 2)]
4045 && self.nbr_in_slice((bx + 2) / 4, (by - 1) / 4)
4046 && self.intra_nbr_ok(bx + 2, by - 1);
4047 for i in 0..8 {
4048 top[8 + i] = if tr_avail {
4049 self.top_y_px(py, px + 8 + i)
4050 } else {
4051 top[7]
4052 };
4053 }
4054 }
4055 if avail_left {
4056 for i in 0..8 {
4057 left[i] = self.rec_y[(py + i) * cw + px - 1];
4058 }
4059 }
4060 let avail_corner = avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1);
4061 if avail_corner {
4062 corner = self.top_y_px(py, px - 1);
4063 }
4064 (top, left, corner, avail_corner)
4065 }
4066
4067 fn decode_i16(
4068 &mut self,
4069 r: &mut BitReader,
4070 mb_x: usize,
4071 mb_y: usize,
4072 mt: u32,
4073 ) -> Result<(), MbError> {
4074 let pred_mode = I16Mode::from_id(mt % 4);
4075 let cbp_chroma = (mt % 12) / 4;
4076 let cbp_luma_15 = mt / 12 == 1;
4077 let chroma_mode = r.read_ue()? as u8;
4078 self.step_qp(r.read_se()?);
4079 let qp = self.cur_qp;
4080 let w4 = self.mb_w * 4;
4081
4082 self.nnz_cache_load(mb_x, mb_y);
4084 let nc_dc = self.nc_pred(0, 0);
4085 let dc_scan = decode_residual_block(r, 16, nc_dc)?;
4086 let dc_levels = un_scan_4x4_dcac(&dc_scan);
4087 let recon_dc = self.dequant_luma_dc(&dc_levels, qp, 0);
4088
4089 let mut q_blocks = [[0i32; 16]; 16];
4091 for &(bx, by) in &LUMA_4X4_SCAN_XY {
4092 let total = if cbp_luma_15 {
4093 let nc = self.nc_pred(bx, by);
4094 let ac = decode_residual_block(r, 15, nc)?;
4095 un_scan_4x4_ac_into(&ac, &mut q_blocks[by * 4 + bx]);
4096 ac.iter().filter(|&&v| v != 0).count() as u8
4097 } else {
4098 0
4099 };
4100 self.nnz_cache_set(bx, by, total);
4101 self.nnz_y[(mb_y * 4 + by) * w4 + (mb_x * 4 + bx)] = total;
4102 }
4103
4104 let avail_top = mb_y > 0
4106 && self.nbr_in_slice(mb_x, mb_y - 1)
4107 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
4108 let avail_left = mb_x > 0
4109 && self.nbr_in_slice(mb_x - 1, mb_y)
4110 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
4111 let (lx, ly) = (mb_x * 16, mb_y * 16);
4112 let mut top = [0u8; 16];
4113 let mut left = [0u8; 16];
4114 if avail_top {
4115 for i in 0..16 {
4116 top[i] = self.top_y_px(ly, lx + i);
4117 }
4118 }
4119 if avail_left {
4120 for i in 0..16 {
4121 left[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
4122 }
4123 }
4124 let corner = if avail_top && avail_left {
4125 self.top_y_px(ly, lx - 1)
4126 } else {
4127 0
4128 };
4129 let pred_l = luma16x16_pred(pred_mode, avail_top, avail_left, &top, &left, corner);
4130 for by in 0..4 {
4131 for bx in 0..4 {
4132 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
4133 deq[0] = recon_dc[by * 4 + bx];
4134 let mut predb = [0i32; 16];
4135 for dy in 0..4 {
4136 for dx in 0..4 {
4137 predb[dy * 4 + dx] = pred_l[(by * 4 + dy) * 16 + (bx * 4 + dx)] as i32;
4138 }
4139 }
4140 let s = reconstruct_4x4(&deq, &predb);
4141 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
4142 }
4143 }
4144 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
4146 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
4147 }
4148
4149 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
4150 }
4151
4152 fn decode_chroma(
4154 &mut self,
4155 r: &mut BitReader,
4156 mb_x: usize,
4157 mb_y: usize,
4158 cbp_chroma: u32,
4159 chroma_mode: u8,
4160 ) -> Result<(), MbError> {
4161 let qpc = self.chroma_qp_for(self.cur_qp);
4162 let (cx, cy) = (mb_x * 8, mb_y * 8);
4163 let avail_top = mb_y > 0
4164 && self.nbr_in_slice(mb_x, mb_y - 1)
4165 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
4166 let avail_left = mb_x > 0
4167 && self.nbr_in_slice(mb_x - 1, mb_y)
4168 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
4169
4170 let mut c_recon_dc = [[0i32; 4]; 2];
4171 if cbp_chroma != 0 {
4172 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
4173 let dc = decode_residual_block(r, 4, -1)?;
4174 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 1 + c);
4175 }
4176 }
4177 let mut c_q_blocks = [[[0i32; 16]; 4]; 2];
4178 if cbp_chroma == 2 {
4179 self.chroma_cache_load(mb_x, mb_y);
4180 let w2 = self.mb_w * 2;
4181 for c in 0..2 {
4182 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
4183 let nc = self.chroma_nc_pred(c, bx, by);
4184 let ac = decode_residual_block(r, 15, nc)?;
4185 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
4186 self.chroma_nnz_cache_set(c, bx, by, total);
4187 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
4188 un_scan_4x4_ac_into(&ac, &mut c_q_blocks[c][by * 2 + bx]);
4189 }
4190 }
4191 }
4192 for c in 0..2 {
4193 let mut ctop = [0u8; 8];
4194 let mut cleft = [0u8; 8];
4195 let mut ccorner = 0u8;
4196 {
4197 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
4198 if avail_top {
4199 for i in 0..8 {
4200 ctop[i] = self.top_c_px(c, cy, cx + i);
4201 }
4202 }
4203 if avail_left {
4204 for i in 0..8 {
4205 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
4206 }
4207 }
4208 if avail_top && avail_left {
4209 ccorner = self.top_c_px(c, cy, cx - 1);
4210 }
4211 }
4212 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
4213 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
4214 let mut predb = [0i32; 16];
4215 for dy in 0..4 {
4216 for dx in 0..4 {
4217 predb[dy * 4 + dx] = pred8[(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
4218 }
4219 }
4220 let mut deq = self.dequant(&c_q_blocks[c][by * 2 + bx], qpc, 1 + c);
4221 deq[0] = c_recon_dc[c][by * 2 + bx];
4222 let s = reconstruct_4x4(&deq, &predb);
4223 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
4224 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
4225 }
4226 }
4227 Ok(())
4228 }
4229
4230 fn dump_mb_map(&self) {
4239 if std::env::var_os("RH264_DUMP_MB").is_none() {
4240 return;
4241 }
4242 let w4 = self.mb_w * 4;
4243 let mut hist = [0usize; 4];
4244 eprintln!("--- frame poc {} ---", self.cur_poc);
4245 for mb_y in 0..self.mb_h {
4246 let mut row = String::new();
4247 for mb_x in 0..self.mb_w {
4248 let b = (mb_y * 4) * w4 + mb_x * 4;
4249 let r = self.ref_idx_y[b];
4250 if r < 0 {
4251 row.push('i');
4252 } else {
4253 if (r as usize) < 4 {
4254 hist[r as usize] += 1;
4255 }
4256 row.push((b'0' + (r as u8).min(9)) as char);
4257 }
4258 }
4259 eprintln!("{row}");
4260 }
4261 eprintln!(
4262 "ref histogram: {hist:?} num_ref_active={} refs.len()={} OUT-OF-RANGE={}",
4263 self.num_ref_active,
4264 self.refs.len(),
4265 hist.iter().skip(self.refs.len()).sum::<usize>()
4266 );
4267 let list: Vec<String> = self
4268 .refs
4269 .iter()
4270 .enumerate()
4271 .map(|(i, f)| {
4272 let synth = if f.w4 == 0 { " SYNTH-GREY" } else { "" };
4275 format!("[{i}] poc={} fn={}{synth}", f.poc, f.frame_num)
4276 })
4277 .collect();
4278 eprintln!(" RefPicList0: {}", list.join(" "));
4279 }
4280
4281 pub fn deblock(&mut self, offset_a: i32, offset_b: i32) {
4282 self.edc_flush(); self.dump_mb_map();
4284 if rowdb_on() {
4287 while self.bs_rows < self.mb_h {
4288 let r = self.bs_rows;
4289 self.derive_bs_row(r);
4290 self.bs_rows += 1;
4291 }
4292 }
4293 let nnz_db_storage;
4300 let nnz_db: &[u8] = if self.mb_t8x8.iter().any(|&t| t) {
4301 let mut n = self.nnz_y.clone();
4302 let w4 = self.mb_w * 4;
4303 for mb_y in 0..self.mb_h {
4304 for mb_x in 0..self.mb_w {
4305 if !self.mb_t8x8[mb_y * self.mb_w + mb_x] {
4306 continue;
4307 }
4308 for b8 in 0..4 {
4309 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, mb_y * 4 + (b8 / 2) * 2);
4310 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + (bx + sx)] > 0));
4311 for sy in 0..2 {
4312 for sx in 0..2 {
4313 n[(by + sy) * w4 + (bx + sx)] = u8::from(any);
4314 }
4315 }
4316 }
4317 }
4318 }
4319 nnz_db_storage = n;
4320 &nnz_db_storage
4321 } else {
4322 &self.nnz_y
4323 };
4324 let poc0: Vec<i32> = self.refs.iter().map(|f| f.poc).collect();
4330 let poc1: Vec<i32> = self.refs1.iter().map(|f| f.poc).collect();
4331 let mut info = rusty_h264_common::deblock::BlockInfo {
4332 inter: &self.inter_y,
4333 nnz: nnz_db,
4334 mv: &self.mv_y,
4335 ref_id: &self.ref_idx_y,
4336 mv1: &self.mv1,
4337 ref_id1: if poc1.is_empty() { &[] } else { &self.ref_idx1 },
4338 w4: self.mb_w * 4,
4339 t8x8: &self.mb_t8x8,
4340 bs: &[],
4341 poc0: &poc0,
4342 poc1: &poc1,
4343 kind: &self.mb_kind,
4344 };
4345 let bs_store;
4350 if rowdb_on() {
4351 bs_store = std::mem::take(&mut self.bs_frame);
4352 info.bs = &bs_store;
4353 } else if !std::env::var_os("RS_H264_BS_PRE").is_some_and(|v| v == "0") {
4354 let mut buf = Vec::new();
4355 rusty_h264_common::deblock::precompute_bs_frame(&info, self.mb_w, self.mb_h, &mut buf);
4356 bs_store = buf;
4357 info.bs = &bs_store;
4358 } else {
4359 bs_store = Vec::new();
4360 }
4361 let first_row = if rowdb_on() { self.flt_rows } else { 0 };
4362 rusty_h264_common::deblock::filter_frame_rows(
4363 &mut self.rec_y,
4364 &mut self.rec_u,
4365 &mut self.rec_v,
4366 self.mb_w,
4367 self.mb_h,
4368 first_row..self.mb_h,
4369 &self.mb_qp,
4370 self.chroma_qp_offset,
4371 offset_a,
4372 offset_b,
4373 &info,
4374 );
4375 drop(info);
4376 if rowdb_on() {
4377 self.bs_frame = bs_store;
4378 }
4379 }
4380
4381 pub fn into_frame_recycle(mut self, crop_r: usize, crop_b: usize) -> (YuvFrame, GridPool) {
4385 let [c0, c1] = std::mem::take(&mut self.nnz_c);
4386 let pool = GridPool {
4387 mb_qp: std::mem::take(&mut self.mb_qp),
4388 bs_frame: std::mem::take(&mut self.bs_frame),
4389 pk_prev: std::mem::take(&mut self.pk_prev),
4390 pk_cur: std::mem::take(&mut self.pk_cur),
4391 nnz_dbr: std::mem::take(&mut self.nnz_dbr),
4392 bak_y: std::mem::take(&mut self.bak_y),
4393 bak_u: std::mem::take(&mut self.bak_u),
4394 bak_v: std::mem::take(&mut self.bak_v),
4395 nnz_y: std::mem::take(&mut self.nnz_y),
4396 nnz_c0: c0,
4397 nnz_c1: c1,
4398 modes_y: std::mem::take(&mut self.modes_y),
4399 coded_y: std::mem::take(&mut self.coded_y),
4400 mv_y: std::mem::take(&mut self.mv_y),
4401 inter_y: std::mem::take(&mut self.inter_y),
4402 ref_idx_y: std::mem::take(&mut self.ref_idx_y),
4403 mv1: std::mem::take(&mut self.mv1),
4404 ref_idx1: std::mem::take(&mut self.ref_idx1),
4405 mb_t8x8: std::mem::take(&mut self.mb_t8x8),
4406 mb_kind: std::mem::take(&mut self.mb_kind),
4407 };
4408 (self.into_frame(crop_r, crop_b), pool)
4409 }
4410
4411 pub fn into_frame(self, crop_r: usize, crop_b: usize) -> YuvFrame {
4412 if crop_r == 0 && crop_b == 0 {
4415 return YuvFrame {
4416 width: self.cw,
4417 height: self.ch,
4418 y: self.rec_y,
4419 u: self.rec_u,
4420 v: self.rec_v,
4421 };
4422 }
4423 let dw = self.cw - 2 * crop_r;
4424 let dh = self.ch - 2 * crop_b;
4425 let mut y = vec![0u8; dw * dh];
4426 for row in 0..dh {
4427 y[row * dw..row * dw + dw].copy_from_slice(&self.rec_y[row * self.cw..row * self.cw + dw]);
4428 }
4429 let (cdw, cdh) = (dw / 2, dh / 2);
4430 let mut u = vec![0u8; cdw * cdh];
4431 let mut v = vec![0u8; cdw * cdh];
4432 for row in 0..cdh {
4433 u[row * cdw..row * cdw + cdw]
4434 .copy_from_slice(&self.rec_u[row * self.ccw..row * self.ccw + cdw]);
4435 v[row * cdw..row * cdw + cdw]
4436 .copy_from_slice(&self.rec_v[row * self.ccw..row * self.ccw + cdw]);
4437 }
4438 let _ = self.cch;
4439 YuvFrame {
4440 width: dw,
4441 height: dh,
4442 y,
4443 u,
4444 v,
4445 }
4446 }
4447}
4448
4449fn cabac_unary(cab: &mut crate::cabac::Cabac, ctx: usize, off: usize) -> u32 {
4456 if cab.decode_decision(ctx) == 0 {
4457 return 0;
4458 }
4459 let mut sym = 0;
4460 loop {
4461 let bin = cab.decode_decision(ctx + off);
4462 sym += 1;
4463 if bin == 0 || sym >= 512 {
4468 break;
4469 }
4470 }
4471 sym
4472}
4473
4474fn cabac_exp_bypass(cab: &mut crate::cabac::Cabac, mut count: i32) -> u32 {
4476 let mut sym = 0u32;
4477 loop {
4478 let c = cab.decode_bypass();
4479 if c == 1 {
4480 sym += 1 << count;
4481 count += 1;
4482 }
4483 if c == 0 || count == 16 {
4484 break;
4485 }
4486 }
4487 let mut sym2 = 0u32;
4488 while count > 0 {
4489 count -= 1;
4490 if cab.decode_bypass() != 0 {
4491 sym2 |= 1 << count;
4492 }
4493 }
4494 sym + sym2
4495}
4496
4497fn cabac_ueg_level(cab: &mut crate::cabac::Cabac, ctx: usize) -> u32 {
4500 if cab.decode_decision(ctx) == 0 {
4501 return 0;
4502 }
4503 let mut code = 0u32;
4504 let mut count = 1;
4505 let mut tmp;
4506 loop {
4507 tmp = cab.decode_decision(ctx);
4508 code += 1;
4509 count += 1;
4510 if tmp == 0 || count == 13 {
4511 break;
4512 }
4513 }
4514 if tmp != 0 {
4515 code += cabac_exp_bypass(cab, 0) + 1;
4516 }
4517 code
4518}
4519
4520fn parse_mb_qp_delta_cabac(cab: &mut crate::cabac::Cabac, last_delta_qp: &mut i32) -> i32 {
4522 const O: usize = 60;
4523 let ctx_inc = (*last_delta_qp != 0) as usize;
4524 let mut qp_delta = 0;
4525 if cab.decode_decision(O + ctx_inc) != 0 {
4526 let code = cabac_unary(cab, O + 2, 1) + 1;
4527 qp_delta = ((code + 1) >> 1) as i32;
4528 if code & 1 == 0 {
4529 qp_delta = -qp_delta;
4530 }
4531 }
4532 *last_delta_qp = qp_delta;
4533 qp_delta
4534}
4535
4536const NZC_CACHE: [usize; 24] = [
4539 9, 10, 17, 18, 11, 12, 19, 20, 25, 26, 33, 34, 27, 28, 35, 36, 14, 15, 22, 23, 38, 39, 46, 47, ];
4543
4544const RES_MAXPOS: [i32; 11] = [0, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14];
4546const RES_MAXC2: [i32; 11] = [0, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4];
4547const RES_CBF: [usize; 11] = [0, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16];
4548const RES_MAP: [usize; 11] = [0, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47];
4549const RES_ONE: [usize; 11] = [0, 0, 10, 20, 30, 39, 199, 30, 30, 39, 39];
4552const RP_I16_DC: usize = 1;
4554const RP_I16_AC: usize = 2;
4555const RP_LUMA_4X4: usize = 3;
4556const RP_CHROMA_DC: usize = 7; const RP_CHROMA_AC: usize = 9; const RP_LUMA_8X8: usize = 6;
4565
4566const SIG8X8: [u8; 64] = [
4570 0, 1, 2, 3, 4, 5, 5, 4, 4, 3, 3, 4, 4, 4, 5, 5, 4, 4, 4, 4, 3, 3, 6, 7, 7, 7, 8, 9, 10, 9, 8, 7, 7, 6, 11, 12, 13, 11, 6, 7, 8, 9, 14, 10, 9, 8, 6, 11, 12, 13, 11, 6, 9, 14, 10, 9, 11, 12, 13, 11, 14, 10, 12, 14,
4574];
4575const LAST8X8: [u8; 64] = [
4578 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
4582];
4583
4584#[allow(clippy::too_many_arguments)]
4589fn parse_residual_cabac(
4590 cab: &mut crate::cabac::Cabac,
4591 nzc: &mut [u8; 48],
4592 cbf_dc: &mut u16,
4593 iz: usize,
4594 rp: usize,
4595 is_intra: bool,
4596 ndc: (Option<u16>, Option<u16>), out: &mut [i32], ) -> u32 {
4599 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Entropy);
4602 let is8 = rp == RP_LUMA_8X8;
4606 let is_dc = rp == RP_I16_DC || rp == RP_CHROMA_DC || rp == RP_CHROMA_DC + 1;
4607 let (mut na, mut nb) = (is_intra as u8, is_intra as u8);
4608 let scan = NZC_CACHE[iz.min(23)];
4609 if is_dc {
4610 if let Some(t) = ndc.0 {
4611 nb = ((t >> rp) & 1) as u8;
4612 }
4613 if let Some(l) = ndc.1 {
4614 na = ((l >> rp) & 1) as u8;
4615 }
4616 } else {
4617 if nzc[scan - 8] != 0xff {
4618 nb = (nzc[scan - 8] != 0) as u8;
4619 }
4620 if nzc[scan - 1] != 0xff {
4621 na = (nzc[scan - 1] != 0) as u8;
4622 }
4623 }
4624 if !is8 {
4625 let _sg = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::EntCbf);
4626 let cbf = cab.decode_decision(85 + RES_CBF[rp] + (na + (nb << 1)) as usize);
4627 if cbf == 0 {
4628 if !is_dc {
4629 nzc[scan] = 0;
4630 }
4631 return 0;
4632 }
4633 if is_dc {
4634 *cbf_dc |= 1 << rp;
4635 }
4636 }
4637 let maxpos = RES_MAXPOS[rp] as usize;
4639 let (map, last) = if is8 { (402, 417) } else { (105 + RES_MAP[rp], 166 + RES_MAP[rp]) };
4641 let mut pos = [0u8; 64];
4653 let mut n = 0usize;
4654 let mut last_hit = false;
4655 let _sg = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::EntSig);
4656 for i in 0..maxpos {
4657 let (mi, li) = if is8 { (SIG8X8[i] as usize, LAST8X8[i] as usize) } else { (i, i) };
4659 if cab.decode_decision(map + mi) != 0 {
4660 pos[n] = i as u8;
4661 n += 1;
4662 if cab.decode_decision(last + li) != 0 {
4663 last_hit = true;
4664 break;
4665 }
4666 }
4667 }
4668 if !last_hit {
4669 pos[n] = maxpos as u8;
4670 n += 1;
4671 }
4672 let coeff_num = n as u32;
4673 let one = 227 + RES_ONE[rp];
4675 let abs = 232 + RES_ONE[rp];
4676 let maxc2 = RES_MAXC2[rp];
4677 let (mut c1, mut c2) = (1i32, 0i32);
4678 drop(_sg);
4679 let _lg = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::EntLvl);
4680 for k in (0..n).rev() {
4681 let mut level = 1 + cab.decode_decision(one + c1 as usize) as i32;
4682 if level == 2 {
4683 level += cabac_ueg_level(cab, abs + c2 as usize) as i32;
4684 c2 = (c2 + 1).min(maxc2);
4685 c1 = 0;
4686 } else if c1 != 0 {
4687 c1 = (c1 + 1).min(4);
4688 }
4689 if cab.decode_bypass() != 0 {
4690 level = -level;
4691 }
4692 out[pos[k] as usize] = level;
4693 }
4694 if is8 {
4695 for k in 0..4 {
4699 nzc[NZC_CACHE[(iz + k).min(23)]] = coeff_num as u8;
4700 }
4701 } else if !is_dc {
4702 nzc[scan] = coeff_num as u8;
4703 }
4704 coeff_num
4705}
4706
4707enum EdcJob {
4709 Skip { mbx: usize, mby: usize, mv: (i32, i32) },
4710 Inter(Box<PInterJob>),
4711}
4712
4713struct PInterJob {
4715 mbx: usize,
4716 mby: usize,
4717 t8: bool,
4718 qp: u8,
4719 cbp_chroma: u32,
4720 luma_scan: [[i32; 16]; 16],
4721 luma8: [[i32; 64]; 4],
4722 cdc: [[i32; 4]; 2],
4723 cac: [[[i32; 16]; 4]; 2],
4724 nnzs: [u8; 24],
4725}
4726
4727fn edc_on() -> bool {
4734 use std::sync::atomic::{AtomicU8, Ordering};
4735 static ON: AtomicU8 = AtomicU8::new(0);
4736 match ON.load(Ordering::Relaxed) {
4737 0 => {
4738 let v = !std::env::var_os("RS_H264_EDC").is_some_and(|v| v == "0");
4739 ON.store(if v { 1 } else { 2 }, Ordering::Relaxed);
4740 v
4741 }
4742 n => n == 1,
4743 }
4744}
4745
4746fn rowdb_on() -> bool {
4749 use std::sync::atomic::{AtomicU8, Ordering};
4750 static ON: AtomicU8 = AtomicU8::new(0);
4751 match ON.load(Ordering::Relaxed) {
4752 0 => {
4753 let v = !std::env::var_os("RS_H264_ROWDB").is_some_and(|v| v == "0");
4754 ON.store(if v { 1 } else { 2 }, Ordering::Relaxed);
4755 v
4756 }
4757 n => n == 1,
4758 }
4759}
4760
4761const CACHE30: [usize; 16] = [7, 8, 13, 14, 9, 10, 15, 16, 19, 20, 25, 26, 21, 22, 27, 28];
4764
4765const G_SCAN4: [usize; 16] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15];
4768
4769fn parse_sub_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4771 const S: usize = 21;
4772 if cab.decode_decision(S) != 0 {
4773 return 0;
4774 }
4775 if cab.decode_decision(S + 1) != 0 {
4776 3 - cab.decode_decision(S + 2)
4777 } else {
4778 1
4779 }
4780}
4781
4782fn parse_intra_mb_type_cabac(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
4785 if cab.decode_decision(base) == 0 {
4786 return 0; }
4788 if cab.decode_terminate() {
4789 return 25; }
4791 let mut t = 1 + 12 * cab.decode_decision(base + 1) as u32; if cab.decode_decision(base + 2) != 0 {
4793 t += 4 + 4 * cab.decode_decision(base + 2) as u32;
4794 }
4795 t += 2 * cab.decode_decision(base + 3) as u32;
4796 t += cab.decode_decision(base + 3) as u32;
4797 t
4798}
4799
4800#[doc(hidden)]
4806pub fn parse_mb_type_b(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4807 parse_mb_type_b_cabac(cab, ctx_inc)
4808}
4809
4810fn parse_mb_type_b_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
4811 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4812 const B: usize = 27;
4813 if cab.decode_decision(B + ctx_inc) == 0 {
4814 return 0; }
4816 if cab.decode_decision(B + 3) == 0 {
4817 return 1 + cab.decode_decision(B + 5) as u32; }
4819 let mut m = (cab.decode_decision(B + 4) as u32) << 3;
4820 m |= (cab.decode_decision(B + 5) as u32) << 2;
4821 m |= (cab.decode_decision(B + 5) as u32) << 1;
4822 m |= cab.decode_decision(B + 5) as u32;
4823 if m < 8 {
4824 return m + 3;
4825 }
4826 if m == 13 {
4827 return parse_intra_mb_type_cabac(cab, 32) + 23;
4828 }
4829 if m == 14 {
4830 return 11; }
4832 if m == 15 {
4833 return 22; }
4835 m = (m << 1) | cab.decode_decision(B + 5) as u32;
4836 m - 4
4837}
4838
4839fn parse_sub_mb_type_b_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4842 const B: usize = 36;
4843 if cab.decode_decision(B) == 0 {
4844 return 0; }
4846 if cab.decode_decision(B + 1) == 0 {
4847 return 1 + cab.decode_decision(B + 3) as u32; }
4849 let mut st = 3u32;
4850 if cab.decode_decision(B + 2) != 0 {
4851 if cab.decode_decision(B + 3) != 0 {
4852 return 11 + cab.decode_decision(B + 3) as u32; }
4854 st += 4;
4855 }
4856 st += 2 * cab.decode_decision(B + 3) as u32;
4857 st += cab.decode_decision(B + 3) as u32;
4858 st
4859}
4860
4861fn parse_mvd_partition(
4865 cab: &mut crate::cabac::Cabac,
4866 part_idx: usize,
4867 zblocks: &[usize],
4868 mvdc: &mut [[i16; 2]; 30],
4869 refc: &mut [i8; 30],
4870 mmvd: &mut [[i16; 2]; 16],
4871 mref: &mut [i8; 16],
4872 ref_idx: i8,
4873) -> (i32, i32) {
4874 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4875 let s = CACHE30[part_idx];
4876 let ctx = |comp: usize| -> usize {
4877 let mut a = 0i32;
4878 if refc[s - 6] >= 0 {
4879 a += mvdc[s - 6][comp].unsigned_abs() as i32;
4880 }
4881 if refc[s - 1] >= 0 {
4882 a += mvdc[s - 1][comp].unsigned_abs() as i32;
4883 }
4884 if a >= 3 {
4885 1 + (a > 32) as usize
4886 } else {
4887 0
4888 }
4889 };
4890 let (cx, cy) = (ctx(0), ctx(1));
4891 let mvx = parse_mvd_cabac(cab, 0, cx);
4892 let mvy = parse_mvd_cabac(cab, 1, cy);
4893 for &zb in zblocks {
4894 mvdc[CACHE30[zb]] = [mvx, mvy];
4895 refc[CACHE30[zb]] = ref_idx;
4896 mmvd[G_SCAN4[zb]] = [mvx, mvy];
4897 mref[G_SCAN4[zb]] = ref_idx;
4898 }
4899 (mvx as i32, mvy as i32)
4900}
4901
4902fn parse_ref_idx_cabac(cab: &mut crate::cabac::Cabac, ctx0: usize) -> i8 {
4905 const B: usize = 54;
4906 let mut r = 0i8;
4907 let mut bin_idx = 0u32;
4908 while bin_idx < 32 {
4912 let ctx = match bin_idx {
4913 0 => ctx0,
4914 1 => 4,
4915 _ => 5,
4916 };
4917 if cab.decode_decision(B + ctx) == 0 {
4918 break;
4919 }
4920 r += 1;
4921 bin_idx += 1;
4922 }
4923 r
4924}
4925
4926fn decode_ueg_mv(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
4929 const P2C: [usize; 8] = [0, 1, 2, 3, 3, 3, 3, 3];
4930 if cab.decode_decision(base) == 0 {
4931 return 0;
4932 }
4933 let mut code = 0u32;
4934 let mut count = 1usize;
4935 let mut tmp;
4936 loop {
4937 tmp = cab.decode_decision(base + P2C[count]);
4938 code += 1;
4939 count += 1;
4940 if tmp == 0 || count == 8 {
4941 break;
4942 }
4943 }
4944 if tmp != 0 {
4945 code += cabac_exp_bypass(cab, 3) + 1;
4946 }
4947 code
4948}
4949
4950fn parse_mvd_cabac(cab: &mut crate::cabac::Cabac, comp: usize, ctx_inc: usize) -> i16 {
4953 let base = 40 + comp * 7; if cab.decode_decision(base + ctx_inc) == 0 {
4955 return 0;
4956 }
4957 let mag = (decode_ueg_mv(cab, base + 3) + 1) as i16;
4958 if cab.decode_bypass() != 0 {
4959 -mag
4960 } else {
4961 mag
4962 }
4963}
4964
4965fn parse_mb_skip_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> bool {
4968 cab.decode_decision(ctx_inc) != 0
4969}
4970
4971fn parse_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
4974 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
4975 const S: usize = 11; if cab.decode_decision(S + 3) == 0 {
4977 return if cab.decode_decision(S + 4) != 0 {
4979 if cab.decode_decision(S + 6) != 0 { 1 } else { 2 }
4980 } else if cab.decode_decision(S + 5) != 0 {
4981 3
4982 } else {
4983 0
4984 };
4985 }
4986 if cab.decode_decision(S + 6) == 0 {
4988 return 5; }
4990 if cab.decode_terminate() {
4991 return 30; }
4993 let mut t = 6 + cab.decode_decision(S + 7) * 12;
4994 if cab.decode_decision(S + 8) != 0 {
4995 t += 4;
4996 if cab.decode_decision(S + 8) != 0 {
4997 t += 4;
4998 }
4999 }
5000 t += cab.decode_decision(S + 9) << 1;
5001 t += cab.decode_decision(S + 9);
5002 t
5003}
5004
5005fn parse_mb_type_i_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
5010 const O: usize = 3; if cab.decode_decision(O + ctx_inc) == 0 {
5012 return 0; }
5014 if cab.decode_terminate() {
5015 return 25; }
5017 let mut t = 1 + cab.decode_decision(O + 3) * 12; if cab.decode_decision(O + 4) != 0 {
5019 t += 4; if cab.decode_decision(O + 5) != 0 {
5021 t += 4;
5022 }
5023 }
5024 t += cab.decode_decision(O + 6) << 1; t += cab.decode_decision(O + 7);
5026 t
5027}
5028
5029fn parse_intra4x4_pred_mode_cabac(cab: &mut crate::cabac::Cabac) -> i32 {
5033 const IPR: usize = 68;
5034 if cab.decode_decision(IPR) == 1 {
5035 return -1; }
5037 let mut m = cab.decode_decision(IPR + 1) as i32;
5038 m |= (cab.decode_decision(IPR + 1) as i32) << 1;
5039 m |= (cab.decode_decision(IPR + 1) as i32) << 2;
5040 m
5041}
5042
5043fn parse_intra_chroma_pred_mode_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
5047 const CIPR: usize = 64;
5048 if cab.decode_decision(CIPR + ctx_inc) == 0 {
5049 return 0;
5050 }
5051 if cab.decode_decision(CIPR + 3) == 0 {
5052 return 1;
5053 }
5054 if cab.decode_decision(CIPR + 3) == 0 {
5055 return 2;
5056 }
5057 3
5058}
5059
5060fn parse_cbp_cabac(cab: &mut crate::cabac::Cabac, top: Option<u8>, left: Option<u8>) -> u32 {
5065 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
5066 const CBP: usize = 73;
5067 let t = |m: u32| top.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
5068 let l = |m: u32| left.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
5069 let nb = |x: u32| (x == 0) as u32; let b0 = cab.decode_decision(CBP + (l(1 << 1) + (t(1 << 2) << 1)) as usize);
5072 let b1 = cab.decode_decision(CBP + (nb(b0) + (t(1 << 3) << 1)) as usize);
5073 let b2 = cab.decode_decision(CBP + (l(1 << 3) + (nb(b0) << 1)) as usize);
5074 let b3 = cab.decode_decision(CBP + (nb(b2) + (nb(b1) << 1)) as usize);
5075 let mut cbp = b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
5076 let ct = top.map_or(0u32, |c| ((c >> 4) != 0) as u32);
5078 let cl = left.map_or(0u32, |c| ((c >> 4) != 0) as u32);
5079 if cab.decode_decision(CBP + 4 + (cl + (ct << 1)) as usize) != 0 {
5080 let ct2 = top.map_or(0u32, |c| ((c >> 4) == 2) as u32);
5081 let cl2 = left.map_or(0u32, |c| ((c >> 4) == 2) as u32);
5082 let c1 = cab.decode_decision(CBP + 8 + (cl2 + (ct2 << 1)) as usize);
5083 cbp |= 1 << (4 + c1);
5084 }
5085 cbp
5086}
5087
5088fn read_ref_idx(r: &mut BitReader, num_ref_active: usize) -> Result<i32, OutOfData> {
5089 if num_ref_active == 2 {
5090 Ok(if r.read_bit()? { 0 } else { 1 }) } else {
5092 Ok(r.read_ue()? as i32)
5093 }
5094}
5095
5096#[derive(Clone, Copy, PartialEq)]
5098enum BPred {
5099 L0,
5100 L1,
5101 Bi,
5102}
5103impl BPred {
5104 fn uses(self, list: usize) -> bool {
5106 matches!(
5107 (self, list),
5108 (BPred::L0, 0) | (BPred::L1, 1) | (BPred::Bi, 0) | (BPred::Bi, 1)
5109 )
5110 }
5111}
5112
5113const B16X16: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 16)];
5114const B16X8: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 8), (0, 8, 16, 8)];
5115const B8X16: &[(usize, usize, usize, usize)] = &[(0, 0, 8, 16), (8, 0, 8, 16)];
5116
5117type Region = (usize, usize, usize, usize);
5119
5120pub fn b_inter_shape(mb_type: u32) -> (u8, u8, u8) {
5126 let (_, mvmode, preds) = b_inter_layout(mb_type);
5127 let code = |p: BPred| match (p.uses(0), p.uses(1)) {
5128 (true, true) => 3,
5129 (true, false) => 1,
5130 _ => 2,
5131 };
5132 (mvmode, code(preds[0]), code(preds[1]))
5133}
5134
5135fn b_inter_layout(mb_type: u32) -> (&'static [Region], u8, [BPred; 2]) {
5136 use BPred::*;
5137 match mb_type {
5138 1 => (B16X16, 0, [L0, L0]),
5139 2 => (B16X16, 0, [L1, L1]),
5140 3 => (B16X16, 0, [Bi, Bi]),
5141 4 => (B16X8, 1, [L0, L0]),
5142 5 => (B8X16, 2, [L0, L0]),
5143 6 => (B16X8, 1, [L1, L1]),
5144 7 => (B8X16, 2, [L1, L1]),
5145 8 => (B16X8, 1, [L0, L1]),
5146 9 => (B8X16, 2, [L0, L1]),
5147 10 => (B16X8, 1, [L1, L0]),
5148 11 => (B8X16, 2, [L1, L0]),
5149 12 => (B16X8, 1, [L0, Bi]),
5150 13 => (B8X16, 2, [L0, Bi]),
5151 14 => (B16X8, 1, [L1, Bi]),
5152 15 => (B8X16, 2, [L1, Bi]),
5153 16 => (B16X8, 1, [Bi, L0]),
5154 17 => (B8X16, 2, [Bi, L0]),
5155 18 => (B16X8, 1, [Bi, L1]),
5156 19 => (B8X16, 2, [Bi, L1]),
5157 20 => (B16X8, 1, [Bi, Bi]),
5158 _ => (B8X16, 2, [Bi, Bi]), }
5160}
5161
5162fn b_sub_uses(st: u32, list: usize) -> bool {
5164 let pred = match st {
5165 1 | 4 | 5 | 10 => 0, 2 | 6 | 7 | 11 => 1, _ => 2, };
5169 (list == 0 && pred != 1) || (list == 1 && pred != 0)
5170}
5171
5172fn b_sub_parts(st: u32) -> &'static [(usize, usize, usize, usize)] {
5174 match st {
5175 1..=3 => &[(0, 0, 8, 8)],
5176 4 | 6 | 8 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
5177 5 | 7 | 9 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
5178 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)], }
5180}
5181
5182fn sub_mb_partitions(sub_type: u32) -> &'static [(usize, usize, usize, usize)] {
5185 match sub_type {
5186 0 => &[(0, 0, 8, 8)],
5187 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
5188 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
5189 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
5190 }
5191}
5192
5193#[inline]
5203fn restride(dst: &mut [u8], dst_stride: usize, x0: usize, y0: usize, src: &[u8], w: usize, h: usize) {
5204 macro_rules! rows {
5205 ($n:expr) => {{
5206 for dy in 0..h {
5207 dst[(y0 + dy) * dst_stride + x0..][..$n].copy_from_slice(&src[dy * $n..][..$n]);
5208 }
5209 }};
5210 }
5211 match w {
5212 16 => rows!(16),
5213 8 => rows!(8),
5214 4 => rows!(4),
5215 2 => rows!(2),
5216 _ => {
5217 for dy in 0..h {
5218 dst[(y0 + dy) * dst_stride + x0..][..w].copy_from_slice(&src[dy * w..][..w]);
5219 }
5220 }
5221 }
5222}
5223
5224fn store(plane: &mut [u8], stride: usize, x0: usize, y0: usize, s: &[u8; 16]) {
5225 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Scatter);
5226 for dy in 0..4 {
5227 for dx in 0..4 {
5228 plane[(y0 + dy) * stride + (x0 + dx)] = s[dy * 4 + dx];
5229 }
5230 }
5231}
5232
5233fn un_scan_8x8(scan: &[i32; 64]) -> [i32; 64] {
5235 const ZZ8: [usize; 64] = [
5236 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,
5237 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
5238 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
5239 ];
5240 let mut out = [0i32; 64];
5241 for k in 0..64 {
5242 out[ZZ8[k]] = scan[k];
5243 }
5244 out
5245}
5246
5247#[cfg(test)]
5248mod tests {
5249 use super::*;
5250
5251 fn fd(qp: u8, offset: i32) -> FrameDecoder {
5252 FrameDecoder::new(1, 1, qp, offset, Vec::new(), 1, false, false, true)
5253 }
5254
5255 #[test]
5256 fn mb_qp_delta_accumulates_mod_52() {
5257 let mut d = fd(26, 0);
5258 assert_eq!(d.cur_qp, 26, "QPy starts at the slice QP");
5259 d.step_qp(4);
5260 assert_eq!(d.cur_qp, 30); d.step_qp(-10);
5262 assert_eq!(d.cur_qp, 20); d.step_qp(40);
5265 assert_eq!(d.cur_qp, 8);
5266 d.step_qp(-20);
5268 assert_eq!(d.cur_qp, 40);
5269 }
5270
5271 #[test]
5272 fn chroma_qp_index_offset_applied_and_clamped() {
5273 assert_eq!(fd(0, 0).chroma_qp_for(30), 29);
5275 assert_eq!(fd(0, 2).chroma_qp_for(30), 31);
5277 assert_eq!(fd(0, -12).chroma_qp_for(5), chroma_qp(0));
5279 assert_eq!(fd(0, 99).chroma_qp_for(40), chroma_qp(51));
5280 }
5281}