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, mc_luma, predict_mv, predict_partition_mv, MvNeighbor,
14};
15use rusty_h264_common::predict::{
16 add_residual_8x8, chroma8x8_pred, chroma_qp, intra4x4_pred, intra8x8_pred, luma16x16_pred,
17 reconstruct_4x4, I16Mode, CHROMA_4X4_SCAN_XY, LUMA_4X4_SCAN_XY,
18};
19use rusty_h264_common::transform::{
20 dequantize, dequantize_weighted, inverse_quant_8x8, inverse_quant_chroma_dc,
21 inverse_quant_chroma_dc_weighted, inverse_quant_luma_dc, inverse_quant_luma_dc_weighted,
22};
23use rusty_h264_common::{BitReader, YuvFrame};
24
25pub struct MvField {
31 pub mb_w: usize,
32 pub mb_h: usize,
33 pub mv: Vec<(i32, i32)>,
34 pub ref_idx: Vec<i32>,
35 pub inter: Vec<bool>,
36}
37
38pub static MV_DUMP: std::sync::Mutex<Vec<MvField>> = std::sync::Mutex::new(Vec::new());
40
41pub fn mv_dump_on() -> bool {
42 static ON: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
43 *ON.get_or_init(|| std::env::var("RFF_MV_DUMP").map_or(false, |v| v != "0"))
44}
45
46pub struct FrameDecoder {
48 mb_w: usize,
49 mb_h: usize,
50 qp: u8,
52 cur_qp: u8,
55 chroma_qp_offset: i32,
57 cw: usize,
58 ch: usize,
59 ccw: usize,
60 cch: usize,
61 rec_y: Vec<u8>,
62 rec_u: Vec<u8>,
63 rec_v: Vec<u8>,
64 mb_qp: Vec<u8>,
66 slice_first_mb: usize,
71 nnz_y: Vec<u8>,
72 nnz_c: [Vec<u8>; 2],
73 modes_y: Vec<u8>,
74 coded_y: Vec<bool>,
75 mv_y: Vec<(i32, i32)>,
78 inter_y: Vec<bool>,
79 ref_idx_y: Vec<i32>,
80 mv1: Vec<(i32, i32)>,
82 ref_idx1: Vec<i32>,
83 refs1: Vec<crate::RefFrame>,
85 num_ref_active1: usize,
86 is_b: bool,
87 b_possible: bool,
91 direct_spatial: bool,
92 nnz_l_cache: [u8; 25],
93 nnz_c_cache: [[u8; 9]; 2],
94 refs: Vec<crate::RefFrame>,
97 num_ref_active: usize,
101 constrained_intra: bool,
104 scaling: Option<[[i32; 16]; 6]>,
107 scaling8: Option<[[i32; 64]; 2]>,
110 transform_8x8_mode: bool,
112 mb_t8x8: Vec<bool>,
115 weights: Option<WeightTable>,
117 cur_poc: i32,
119 weighted_bipred_idc: u8,
121 direct_8x8_inference: bool,
123}
124
125#[derive(Clone, Default)]
129pub struct WeightTable {
130 pub luma_log2_denom: i32,
131 pub chroma_log2_denom: i32,
132 pub luma: [Vec<(i32, i32)>; 2],
134 pub chroma: [Vec<[(i32, i32); 2]>; 2],
136}
137
138impl WeightTable {
139 fn apply_luma(&self, sample: u8, list: usize, refi: usize) -> u8 {
141 let (w, o) = self.luma[list][refi];
142 let lwd = self.luma_log2_denom;
143 let v = if lwd >= 1 {
144 ((sample as i32 * w + (1 << (lwd - 1))) >> lwd) + o
145 } else {
146 sample as i32 * w + o
147 };
148 v.clamp(0, 255) as u8
149 }
150
151 fn apply_chroma(&self, sample: u8, list: usize, refi: usize, cc: usize) -> u8 {
153 let (w, o) = self.chroma[list][refi][cc];
154 let cwd = self.chroma_log2_denom;
155 let v = if cwd >= 1 {
156 ((sample as i32 * w + (1 << (cwd - 1))) >> cwd) + o
157 } else {
158 sample as i32 * w + o
159 };
160 v.clamp(0, 255) as u8
161 }
162}
163
164#[derive(Debug, Clone, PartialEq, Eq)]
166pub enum MbError {
167 Truncated,
168 Unsupported(&'static str),
169}
170
171impl From<OutOfData> for MbError {
172 fn from(_: OutOfData) -> Self {
173 MbError::Truncated
174 }
175}
176
177impl FrameDecoder {
178 pub fn new(
179 mb_w: usize,
180 mb_h: usize,
181 qp: u8,
182 chroma_qp_offset: i32,
183 refs: Vec<crate::RefFrame>,
184 num_ref_active: usize,
185 constrained_intra: bool,
186 transform_8x8_mode: bool,
187 b_possible: bool,
188 ) -> Self {
189 let (cw, ch) = (mb_w * 16, mb_h * 16);
190 let (ccw, cch) = (cw / 2, ch / 2);
191 Self {
192 mb_w,
193 mb_h,
194 qp,
195 cur_qp: qp,
196 chroma_qp_offset,
197 cw,
198 ch,
199 ccw,
200 cch,
201 rec_y: vec![0; cw * ch],
202 rec_u: vec![0; ccw * cch],
203 rec_v: vec![0; ccw * cch],
204 mb_qp: vec![qp; mb_w * mb_h],
205 slice_first_mb: 0,
206 nnz_y: vec![0; (mb_w * 4) * (mb_h * 4)],
207 nnz_c: [vec![0; (mb_w * 2) * (mb_h * 2)], vec![0; (mb_w * 2) * (mb_h * 2)]],
208 modes_y: vec![2; (mb_w * 4) * (mb_h * 4)],
209 coded_y: vec![false; (mb_w * 4) * (mb_h * 4)],
210 mv_y: vec![(0, 0); (mb_w * 4) * (mb_h * 4)],
211 inter_y: vec![false; (mb_w * 4) * (mb_h * 4)],
212 ref_idx_y: vec![-1; (mb_w * 4) * (mb_h * 4)],
213 mv1: vec![(0, 0); (mb_w * 4) * (mb_h * 4)],
214 ref_idx1: vec![-1; (mb_w * 4) * (mb_h * 4)],
215 refs1: Vec::new(),
216 num_ref_active1: 0,
217 is_b: false,
218 b_possible,
219 direct_spatial: true,
220 nnz_l_cache: [0x80; 25],
221 nnz_c_cache: [[0x80; 9]; 2],
222 refs,
223 num_ref_active,
224 constrained_intra,
225 scaling: None,
226 scaling8: None,
227 transform_8x8_mode,
228 mb_t8x8: vec![false; mb_w * mb_h],
229 weights: None,
230 cur_poc: 0,
231 weighted_bipred_idc: 0,
232 direct_8x8_inference: false,
233 }
234 }
235
236 pub fn set_weights(&mut self, weights: WeightTable) {
238 self.weights = Some(weights);
239 }
240
241 fn weight_partition(
245 &self,
246 pred_y: &mut [u8; 256],
247 c_pred: &mut [[u8; 64]; 2],
248 list: usize,
249 refi: usize,
250 rx: usize,
251 ry: usize,
252 rw: usize,
253 rh: usize,
254 ) {
255 let Some(wt) = &self.weights else { return };
256 for dy in 0..rh {
257 for dx in 0..rw {
258 let i = (ry + dy) * 16 + (rx + dx);
259 pred_y[i] = wt.apply_luma(pred_y[i], list, refi);
260 }
261 }
262 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
263 for cc in 0..2 {
264 for dy in 0..crh {
265 for dx in 0..crw {
266 let i = (cry + dy) * 8 + (crx + dx);
267 c_pred[cc][i] = wt.apply_chroma(c_pred[cc][i], list, refi, cc);
268 }
269 }
270 }
271 }
272
273 pub fn set_scaling(&mut self, scaling: [[i32; 16]; 6], scaling8: [[i32; 64]; 2]) {
276 self.scaling = Some(scaling);
277 self.scaling8 = Some(scaling8);
278 }
279
280 fn dequant(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
282 match &self.scaling {
283 Some(s) => dequantize_weighted(levels, qp, &s[list]),
284 None => dequantize(levels, qp),
285 }
286 }
287
288 fn dequant_luma_dc(&self, levels: &[i32; 16], qp: u8, list: usize) -> [i32; 16] {
290 match &self.scaling {
291 Some(s) => inverse_quant_luma_dc_weighted(levels, qp, s[list][0]),
292 None => inverse_quant_luma_dc(levels, qp),
293 }
294 }
295
296 fn dequant_chroma_dc(&self, levels: &[i32; 4], qp: u8, list: usize) -> [i32; 4] {
298 match &self.scaling {
299 Some(s) => inverse_quant_chroma_dc_weighted(levels, qp, s[list][0]),
300 None => inverse_quant_chroma_dc(levels, qp),
301 }
302 }
303
304 #[allow(clippy::too_many_arguments)]
307 pub fn set_b_context(
308 &mut self,
309 refs1: Vec<crate::RefFrame>,
310 num_ref_active1: usize,
311 direct_spatial: bool,
312 cur_poc: i32,
313 weighted_bipred_idc: u8,
314 direct_8x8_inference: bool,
315 ) {
316 self.is_b = true;
317 self.refs1 = refs1;
318 self.num_ref_active1 = num_ref_active1;
319 self.direct_spatial = direct_spatial;
320 self.cur_poc = cur_poc;
321 self.weighted_bipred_idc = weighted_bipred_idc;
322 self.direct_8x8_inference = direct_8x8_inference;
323 }
324
325 fn step_qp(&mut self, delta: i32) {
328 self.cur_qp = (self.cur_qp as i32 + delta + 52).rem_euclid(52) as u8;
329 }
330
331 fn chroma_qp_for(&self, qp_y: u8) -> u8 {
334 let qpi = (qp_y as i32 + self.chroma_qp_offset).clamp(0, 51) as u8;
335 chroma_qp(qpi)
336 }
337
338 pub fn begin_slice(&mut self, slice_qp: u8, refs: Vec<crate::RefFrame>, num_ref_active: usize) {
342 self.cur_qp = slice_qp;
343 self.qp = slice_qp;
344 self.refs = refs;
345 self.num_ref_active = num_ref_active;
346 self.weights = None; }
348
349 #[inline]
353 fn nbr_in_slice(&self, nbx: usize, nby: usize) -> bool {
354 nby * self.mb_w + nbx >= self.slice_first_mb
355 }
356
357 #[inline]
361 fn intra_nbr_ok(&self, nbx: usize, nby: usize) -> bool {
362 !self.constrained_intra || !self.inter_y[nby * (self.mb_w * 4) + nbx]
363 }
364
365 fn mv_neighbors(&self, mb_x: usize, mb_y: usize) -> [MvNeighbor; 3] {
366 let w4 = self.mb_w * 4;
367 let get = |avail: bool, bx: isize, by: isize| {
368 if avail {
369 let idx = by as usize * w4 + bx as usize;
370 MvNeighbor {
371 available: true,
372 mv: self.mv_y[idx],
373 ref_idx: self.ref_idx_y[idx],
374 }
375 } else {
376 MvNeighbor::NONE
377 }
378 };
379 let (bx, by) = (mb_x as isize * 4, mb_y as isize * 4);
380 let a = get(mb_x > 0 && self.nbr_in_slice(mb_x - 1, mb_y), bx - 1, by);
381 let b = get(mb_y > 0 && self.nbr_in_slice(mb_x, mb_y - 1), bx, by - 1);
382 let c = if mb_y > 0 && mb_x + 1 < self.mb_w && self.nbr_in_slice(mb_x + 1, mb_y - 1) {
383 get(true, bx + 4, by - 1)
384 } else {
385 get(mb_x > 0 && mb_y > 0 && self.nbr_in_slice(mb_x - 1, mb_y - 1), bx - 1, by - 1)
386 };
387 [a, b, c]
388 }
389
390 fn mv_neighbors_block(&self, pbx: isize, pby: isize, pwb: isize) -> [MvNeighbor; 3] {
391 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Neighbors);
392 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
393 let get = |bx: isize, by: isize| -> MvNeighbor {
394 if bx < 0
396 || by < 0
397 || bx >= w4
398 || by >= h4
399 || !self.coded_y[(by * w4 + bx) as usize]
400 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
401 {
402 MvNeighbor::NONE
403 } else {
404 let idx = (by * w4 + bx) as usize;
405 MvNeighbor { available: true, mv: self.mv_y[idx], ref_idx: self.ref_idx_y[idx] }
406 }
407 };
408 let a = get(pbx - 1, pby);
409 let b = get(pbx, pby - 1);
410 let mut c = get(pbx + pwb, pby - 1);
411 if !c.available {
412 c = get(pbx - 1, pby - 1);
413 }
414 [a, b, c]
415 }
416
417 fn skip_mv(&self, mb_x: usize, mb_y: usize) -> (i32, i32) {
418 let [a, b, c] = self.mv_neighbors(mb_x, mb_y);
419 if !a.available
420 || !b.available
421 || (a.ref_idx == 0 && a.mv == (0, 0))
422 || (b.ref_idx == 0 && b.mv == (0, 0))
423 {
424 (0, 0)
425 } else {
426 predict_mv(a, b, c, 0)
427 }
428 }
429
430 fn set_mb_mv(&mut self, mb_x: usize, mb_y: usize, mv: (i32, i32), inter: bool, refi: i32) {
431 let w4 = self.mb_w * 4;
432 for dy in 0..4 {
433 for dx in 0..4 {
434 let idx = (mb_y * 4 + dy) * w4 + (mb_x * 4 + dx);
435 self.mv_y[idx] = mv;
436 self.inter_y[idx] = inter;
437 self.ref_idx_y[idx] = if inter { refi } else { -1 };
438 }
439 }
440 }
441
442 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) {
446 let w4 = self.mb_w * 4;
447 for by in ry / 4..ry / 4 + rh / 4 {
448 for bx in rx / 4..rx / 4 + rw / 4 {
449 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
450 self.mv_y[idx] = mv;
451 self.inter_y[idx] = true;
452 self.ref_idx_y[idx] = refi as i32;
453 self.coded_y[idx] = true;
454 }
455 }
456 }
457
458 pub fn as_reference(&self) -> crate::RefFrame {
460 if mv_dump_on() {
464 MV_DUMP.lock().unwrap().push(MvField {
465 mb_w: self.mb_w,
466 mb_h: self.mb_h,
467 mv: self.mv_y.clone(),
468 ref_idx: self.ref_idx_y.clone(),
469 inter: self.inter_y.clone(),
470 });
471 }
472
473 let (mv, ref_idx, ref_poc, w4) = if self.b_possible {
479 (
480 self.mv_y.clone(),
481 self.ref_idx_y.clone(),
482 self.ref_idx_y
485 .iter()
486 .map(|&r| {
487 if r >= 0 {
488 self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc)
489 } else {
490 i32::MIN
491 }
492 })
493 .collect(),
494 self.mb_w * 4,
495 )
496 } else {
497 (Vec::new(), Vec::new(), Vec::new(), 0)
498 };
499 crate::RefFrame {
500 y: self.rec_y.clone(),
501 u: self.rec_u.clone(),
502 v: self.rec_v.clone(),
503 cw: self.cw,
504 ch: self.ch,
505 frame_num: 0, poc: 0, mv,
508 ref_idx,
509 ref_poc,
510 w4,
511 long_term: false,
512 long_term_idx: 0,
513 }
514 }
515
516 fn nnz_cache_load(&mut self, mb_x: usize, mb_y: usize) {
517 let w4 = self.mb_w * 4;
518 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
519 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
520 for lbx in 0..4 {
521 self.nnz_l_cache[1 + lbx] =
522 if top_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 - 1) * w4 + (mb_x * 4 + lbx)] };
523 }
524 for lby in 0..4 {
525 self.nnz_l_cache[(lby + 1) * 5] =
526 if left_unavail { 0x80 } else { self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 - 1)] };
527 }
528 }
529 #[inline]
530 fn nc_pred(&self, lbx: usize, lby: usize) -> i32 {
531 let left = self.nnz_l_cache[(lby + 1) * 5 + lbx] as i32;
532 let top = self.nnz_l_cache[lby * 5 + (lbx + 1)] as i32;
533 let r = left + top;
534 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
535 }
536 #[inline]
537 fn nnz_cache_set(&mut self, lbx: usize, lby: usize, total: u8) {
538 self.nnz_l_cache[(lby + 1) * 5 + (lbx + 1)] = total;
539 }
540 fn chroma_cache_load(&mut self, mb_x: usize, mb_y: usize) {
541 let w2 = self.mb_w * 2;
542 let top_unavail = mb_y == 0 || !self.nbr_in_slice(mb_x, mb_y - 1);
543 let left_unavail = mb_x == 0 || !self.nbr_in_slice(mb_x - 1, mb_y);
544 for c in 0..2 {
545 for bx in 0..2 {
546 self.nnz_c_cache[c][1 + bx] =
547 if top_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 - 1) * w2 + (mb_x * 2 + bx)] };
548 }
549 for by in 0..2 {
550 self.nnz_c_cache[c][(by + 1) * 3] =
551 if left_unavail { 0x80 } else { self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 - 1)] };
552 }
553 }
554 }
555 #[inline]
556 fn chroma_nc_pred(&self, c: usize, bx: usize, by: usize) -> i32 {
557 let left = self.nnz_c_cache[c][(by + 1) * 3 + bx] as i32;
558 let top = self.nnz_c_cache[c][by * 3 + (bx + 1)] as i32;
559 let r = left + top;
560 if r < 0x80 { (r + 1) >> 1 } else { r & 0x7f }
561 }
562 #[inline]
563 fn chroma_nnz_cache_set(&mut self, c: usize, bx: usize, by: usize, total: u8) {
564 self.nnz_c_cache[c][(by + 1) * 3 + (bx + 1)] = total;
565 }
566
567 #[allow(clippy::too_many_arguments)]
575 pub fn decode_slice_data_cabac(
576 &mut self,
577 rbsp: &[u8],
578 start_byte: usize,
579 slice_qp: u8,
580 cabac_init_idc: u32,
581 is_i: bool,
582 is_p: bool,
583 first_mb: usize,
584 ) -> Result<usize, MbError> {
585 let mut cab = crate::cabac::Cabac::new(rbsp, start_byte, slice_qp as i32, cabac_init_idc, is_i);
586 let (range, _offset) = cab.dbg_state();
587 let trace = std::env::var_os("RH_CABAC_TRACE").is_some();
588 debug_assert_eq!(range, 510, "CABAC init range must be 510");
589
590 const I16_CBP: [u32; 6] = [0, 16, 32, 15, 31, 47];
591 let mbw = self.mb_w;
592 let total = self.mb_w * self.mb_h;
593 let mut cat = vec![255u8; total]; let mut mb_cbp = vec![0u8; total];
596 let mut cmode = vec![-1i32; total]; let mut mb_nzc = vec![[0u8; 24]; total]; let mut cbf_dc = vec![0u16; total];
599 let mut mb_skip = vec![false; total];
600 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;
606 let mut addr = first_mb;
607
608 loop {
609 if addr >= total {
616 return Err(MbError::Truncated);
617 }
618 let (mbx, mby) = (addr % mbw, addr / mbw);
619 let left = (mbx > 0).then(|| addr - 1);
620 let top = (mby > 0).then(|| addr - mbw);
621
622 let mb_type;
625 if is_p {
626 let sctx = 11
627 + left.map_or(0, |a| (!mb_skip[a]) as usize)
628 + top.map_or(0, |a| (!mb_skip[a]) as usize);
629 if parse_mb_skip_cabac(&mut cab, sctx) {
630 mb_skip[addr] = true;
631 cat[addr] = 100; last_delta_qp = 0; self.decode_p_skip(mbx, mby)?;
637 self.mb_qp[addr] = self.cur_qp; let eos = cab.decode_terminate();
639 addr += 1;
640 if eos || addr >= total {
641 break;
642 }
643 continue;
644 }
645 let mbt = parse_mb_type_p_cabac(&mut cab);
646 if mbt == 30 {
647 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
648 }
649 if mbt <= 3 {
650 let mut mvdc = [[0i16; 2]; 30];
653 let mut refc = [-1i8; 30];
654 if let Some(l) = left {
655 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
656 refc[ci] = mb_ref[l][bi];
657 mvdc[ci] = mb_mvd[l][bi];
658 }
659 }
660 if let Some(t) = top {
661 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
662 refc[ci] = mb_ref[t][bi];
663 mvdc[ci] = mb_mvd[t][bi];
664 }
665 }
666 if mbx > 0 && mby > 0 {
667 let a = addr - mbw - 1;
668 (refc[0], mvdc[0]) = (mb_ref[a][15], mb_mvd[a][15]);
669 }
670 if mby > 0 && mbx + 1 < mbw {
671 let a = addr - mbw + 1;
672 (refc[5], mvdc[5]) = (mb_ref[a][12], mb_mvd[a][12]);
673 }
674 let mut mmvd = [[0i16; 2]; 16];
675 let mut mref = [0i8; 16];
676 macro_rules! refidx {
682 ($pi:expr, $zb:expr) => {{
683 if self.num_ref_active > 1 {
684 let s = CACHE30[$pi];
685 let c0 = (refc[s - 1] > 0) as usize + 2 * (refc[s - 6] > 0) as usize;
686 let r = parse_ref_idx_cabac(&mut cab, c0);
687 for &zb in $zb.iter() {
688 refc[CACHE30[zb]] = r;
689 }
690 r
691 } else {
692 0i8
693 }
694 }};
695 }
696 macro_rules! part {
697 ($pi:expr, $zb:expr, $pred:expr, $rx:expr, $ry:expr, $rw:expr, $rh:expr, $refi:expr) => {{
698 let (mvx, mvy) = parse_mvd_partition(&mut cab, $pi, $zb, &mut mvdc, &mut refc, &mut mmvd, &mut mref, $refi);
699 let [na, nb, nc] = self.mv_neighbors_block(
700 (mbx * 4 + $rx / 4) as isize,
701 (mby * 4 + $ry / 4) as isize,
702 ($rw / 4) as isize,
703 );
704 let pmv = $pred(na, nb, nc);
705 self.commit_inter_grid(mbx, mby, $rx, $ry, $rw, $rh, (pmv.0 + mvx, pmv.1 + mvy), $refi);
706 }};
707 }
708 match mbt {
709 0 => {
710 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
711 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);
712 }
713 1 => {
714 let r0 = refidx!(0, &[0, 1, 2, 3, 4, 5, 6, 7]);
715 let r1 = refidx!(8, &[8, 9, 10, 11, 12, 13, 14, 15]);
716 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);
717 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);
718 }
719 2 => {
720 let r0 = refidx!(0, &[0, 1, 2, 3, 8, 9, 10, 11]);
721 let r1 = refidx!(4, &[4, 5, 6, 7, 12, 13, 14, 15]);
722 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);
723 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);
724 }
725 _ => {
726 let mut subt = [0u32; 4];
728 for st in &mut subt {
729 *st = parse_sub_mb_type_p_cabac(&mut cab);
730 }
731 let mut pr = [0i8; 4];
732 for (i, r) in pr.iter_mut().enumerate() {
733 let b = i * 4;
734 *r = refidx!(b, &[b, b + 1, b + 2, b + 3]);
735 }
736 for i in 0..4usize {
737 let b = i * 4;
738 let (ox, oy) = ((i % 2) * 8, (i / 2) * 8); let ri = pr[i];
740 match subt[i] {
741 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),
742 1 => {
743 part!(b, &[b, b + 1], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 8, 4, ri);
744 part!(b + 2, &[b + 2, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy + 4, 8, 4, ri);
745 }
746 2 => {
747 part!(b, &[b, b + 2], |a, b, c| predict_mv(a, b, c, ri as i32), ox, oy, 4, 8, ri);
748 part!(b + 1, &[b + 1, b + 3], |a, b, c| predict_mv(a, b, c, ri as i32), ox + 4, oy, 4, 8, ri);
749 }
750 _ => {
751 for j in 0..4usize {
752 let (sx, sy) = ((j % 2) * 4, (j / 2) * 4);
753 part!(b + j, &[b + j], |a, b, c| predict_mv(a, b, c, ri as i32), ox + sx, oy + sy, 4, 4, ri);
754 }
755 }
756 }
757 }
758 }
759 }
760 mb_ref[addr] = mref;
761 mb_mvd[addr] = mmvd;
762 cat[addr] = 100;
763
764 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
766 mb_cbp[addr] = cbp as u8;
767 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
768 let mut nzc = [0xffu8; 48];
769 if let Some(t) = top {
770 let tnz = mb_nzc[t];
771 nzc[1..5].copy_from_slice(&tnz[12..16]);
772 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
773 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
774 }
775 if let Some(l) = left {
776 let lnz = mb_nzc[l];
777 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
778 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
779 }
780 let mut cbfdc = 0u16;
781 let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
786 last_delta_qp = 0;
787 }
788 if cbp != 0 {
789 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
790 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
791 self.step_qp(qpd);
792 for id8 in 0..4usize {
793 if cbp_luma & (1 << id8) != 0 {
794 for id4 in 0..4usize {
795 let iz = id8 * 4 + id4;
796 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
797 }
798 } else {
799 for k in 0..4 {
800 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
801 }
802 }
803 }
804 if cbp_chroma >= 1 {
805 for i in 0..2usize {
806 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
807 }
808 }
809 if cbp_chroma == 2 {
810 for i in 0..2usize {
811 for id4 in 0..4usize {
812 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
813 }
814 }
815 }
816 }
817 self.mb_qp[addr] = self.cur_qp;
818 cbf_dc[addr] = cbfdc;
819 let mut mn = [0u8; 24];
820 for k in 0..4 {
821 mn[k] = nzc[9 + k];
822 mn[4 + k] = nzc[17 + k];
823 mn[8 + k] = nzc[25 + k];
824 mn[12 + k] = nzc[33 + k];
825 }
826 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
827 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
828 for v in mn.iter_mut() {
832 if *v == 0xff {
833 *v = 0;
834 }
835 }
836 mb_nzc[addr] = mn;
837
838 if self.refs.is_empty() {
843 return Err(MbError::Unsupported("inter without reference"));
844 }
845 let qp = self.cur_qp;
846 let qpc = self.chroma_qp_for(qp);
847 let (w4r, w2r) = (mbw * 4, mbw * 2);
848 let mut pred_y = [0u8; 256];
849 let mut c_pred = [[0u8; 64]; 2];
850 {
851 let (rh16, cch) = (self.mb_h * 16, self.mb_h * 8);
852 for by in 0..4usize {
853 for bx in 0..4usize {
854 let bidx = (mby * 4 + by) * w4r + (mbx * 4 + bx);
855 let mv = self.mv_y[bidx];
856 let refi = (self.ref_idx_y[bidx].max(0) as usize).min(self.refs.len() - 1);
859 let reference = &self.refs[refi];
860 let mut t = [0u8; 16];
861 mc_luma(&reference.y, self.cw, rh16, mbx * 16 + bx * 4, mby * 16 + by * 4, 4, 4, mv.0, mv.1, &mut t);
862 for dy in 0..4 {
863 for dx in 0..4 {
864 pred_y[(by * 4 + dy) * 16 + (bx * 4 + dx)] = t[dy * 4 + dx];
865 }
866 }
867 for cc in 0..2 {
868 let rc = if cc == 0 { &reference.u } else { &reference.v };
869 let mut tc = [0u8; 4];
870 mc_chroma(rc, self.ccw, cch, mbx * 8 + bx * 2, mby * 8 + by * 2, 2, 2, mv.0, mv.1, &mut tc);
871 for dy in 0..2 {
872 for dx in 0..2 {
873 c_pred[cc][(by * 2 + dy) * 8 + (bx * 2 + dx)] = tc[dy * 2 + dx];
874 }
875 }
876 }
877 }
878 }
879 }
880 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
882 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
883 let deq = self.dequant(&qb, qp, 3);
884 let predb: [i32; 16] = std::array::from_fn(|i| pred_y[(lby * 4 + i / 4) * 16 + (lbx * 4 + i % 4)] as i32);
885 let s = reconstruct_4x4(&deq, &predb);
886 store(&mut self.rec_y, self.cw, (mbx * 4 + lbx) * 4, (mby * 4 + lby) * 4, &s);
887 self.nnz_y[(mby * 4 + lby) * w4r + (mbx * 4 + lbx)] = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
888 }
889 let mut c_dc = [[0i32; 4]; 2];
891 if cbp_chroma != 0 {
892 for c in 0..2 {
893 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 4 + c);
894 }
895 }
896 for c in 0..2 {
897 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
898 let mut ac = [0i32; 16];
899 if cbp_chroma == 2 {
900 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
901 self.nnz_c[c][(mby * 2 + by) * w2r + (mbx * 2 + bx)] =
902 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
903 }
904 let mut deq = self.dequant(&ac, qpc, 4 + c);
905 deq[0] = c_dc[c][by * 2 + bx];
906 let predb: [i32; 16] =
907 std::array::from_fn(|i| c_pred[c][(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
908 let s = reconstruct_4x4(&deq, &predb);
909 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
910 store(plane, self.ccw, (mbx * 2 + bx) * 4, (mby * 2 + by) * 4, &s);
911 }
912 }
913
914 let eos = cab.decode_terminate();
915 addr += 1;
916 if eos || addr >= total {
917 break;
918 }
919 continue;
920 }
921 mb_type = mbt - 5; } else if self.is_b {
923 let sctx = 24
925 + left.map_or(0, |a| (!mb_skip[a]) as usize)
926 + top.map_or(0, |a| (!mb_skip[a]) as usize);
927 if parse_mb_skip_cabac(&mut cab, sctx) {
928 mb_skip[addr] = true;
929 cat[addr] = 100;
930 mb_direct[addr] = true;
931 last_delta_qp = 0; self.decode_b_skip(mbx, mby)?;
935 self.mb_qp[addr] = self.cur_qp;
936 mb_ref[addr] = [0i8; 16];
939 mb_ref1[addr] = [0i8; 16];
940 let eos = cab.decode_terminate();
941 addr += 1;
942 if eos || addr >= total {
943 break;
944 }
945 continue;
946 }
947 let bci = left.map_or(0, |a| (!mb_direct[a]) as usize)
948 + top.map_or(0, |a| (!mb_direct[a]) as usize);
949 let bmt = parse_mb_type_b_cabac(&mut cab, bci);
950 if bmt < 23 {
951 let mut mvdc0 = [[0i16; 2]; 30];
954 let mut refc0 = [-1i8; 30];
955 let mut mvdc1 = [[0i16; 2]; 30];
956 let mut refc1 = [-1i8; 30];
957 macro_rules! fill {
959 ($mrf:expr, $mmv:expr, $rc:expr, $mc:expr) => {{
960 if let Some(l) = left {
961 for (ci, bi) in [(6usize, 3usize), (12, 7), (18, 11), (24, 15)] {
962 $rc[ci] = $mrf[l][bi];
963 $mc[ci] = $mmv[l][bi];
964 }
965 }
966 if let Some(t) = top {
967 for (ci, bi) in [(1usize, 12usize), (2, 13), (3, 14), (4, 15)] {
968 $rc[ci] = $mrf[t][bi];
969 $mc[ci] = $mmv[t][bi];
970 }
971 }
972 if mbx > 0 && mby > 0 {
973 let a = addr - mbw - 1;
974 ($rc[0], $mc[0]) = ($mrf[a][15], $mmv[a][15]);
975 }
976 if mby > 0 && mbx + 1 < mbw {
977 let a = addr - mbw + 1;
978 ($rc[5], $mc[5]) = ($mrf[a][12], $mmv[a][12]);
979 }
980 }};
981 }
982 fill!(mb_ref, mb_mvd, refc0, mvdc0);
983 fill!(mb_ref1, mb_mvd1, refc1, mvdc1);
984 let mut mmvd0 = [[0i16; 2]; 16];
985 let mut mref0 = [-1i8; 16];
986 let mut mmvd1 = [[0i16; 2]; 16];
987 let mut mref1 = [-1i8; 16];
988 if self.refs.is_empty() || self.refs1.is_empty() {
989 return Err(MbError::Unsupported("B without references"));
990 }
991 let mut pred_y = [0u8; 256];
996 let mut c_pred = [[0u8; 64]; 2];
997
998 if bmt == 0 {
999 mb_direct[addr] = true;
1002 (mref0, mref1) = ([0i8; 16], [0i8; 16]);
1003 self.decode_b_direct(mbx, mby, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
1004 } else if bmt == 22 {
1005 let mut subt = [0u32; 4];
1008 for s in &mut subt {
1009 *s = parse_sub_mb_type_b_cabac(&mut cab);
1010 }
1011 for i in 0..4usize {
1015 if subt[i] == 0 {
1016 let b = i * 4;
1017 for &zb in &[b, b + 1, b + 2, b + 3] {
1018 (mref0[G_SCAN4[zb]], mref1[G_SCAN4[zb]]) = (0, 0);
1019 (refc0[CACHE30[zb]], refc1[CACHE30[zb]]) = (0, 0);
1020 }
1021 }
1022 }
1023 for list in 0..2usize {
1024 let (mmv, mrf, mc, rc) = if list == 0 {
1025 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1026 } else {
1027 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1028 };
1029 for i in 0..4usize {
1030 let st = subt[i];
1031 if st == 0 || !b_sub_uses(st, list) {
1032 continue;
1033 }
1034 let b = i * 4;
1035 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1036 let mut zb = [0usize; 4];
1037 let mut n = 0;
1038 for ly in sy / 4..sy / 4 + sh / 4 {
1039 for lx in sx / 4..sx / 4 + sw / 4 {
1040 zb[n] = b + ly * 2 + lx;
1041 n += 1;
1042 }
1043 }
1044 parse_mvd_partition(&mut cab, zb[0], &zb[..n], mc, rc, mmv, mrf, 0);
1045 }
1046 }
1047 }
1048 for (p, &st) in subt.iter().enumerate() {
1051 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
1052 if st == 0 {
1053 self.decode_b_direct(mbx, mby, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
1054 continue;
1055 }
1056 for &(sx, sy, sw, sh) in b_sub_parts(st) {
1057 let (px, py) = (b8x + sx, b8y + sy);
1058 let mut mv = [(0i32, 0i32); 2];
1059 for list in 0..2usize {
1060 if b_sub_uses(st, list) {
1061 let d = if list == 0 { mmvd0 } else { mmvd1 }[(py / 4) * 4 + px / 4];
1062 let n = self.mv_neighbors_list((mbx * 4 + px / 4) as isize, (mby * 4 + py / 4) as isize, (sw / 4) as isize, list);
1063 let pmv = predict_mv(n[0], n[1], n[2], 0);
1064 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1065 }
1066 }
1067 let refi0 = if b_sub_uses(st, 0) { 0 } else { -1 };
1068 let refi1 = if b_sub_uses(st, 1) { 0 } else { -1 };
1069 self.b_set_motion(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1]);
1070 self.b_mc(mbx, mby, px, py, sw, sh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1071 }
1072 }
1073 } else {
1074 let (layout, mvmode, preds) = b_inter_layout(bmt);
1075 let parts: &[(usize, &[usize])] = match mvmode {
1076 0 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])],
1077 1 => &[(0, &[0, 1, 2, 3, 4, 5, 6, 7]), (8, &[8, 9, 10, 11, 12, 13, 14, 15])],
1078 _ => &[(0, &[0, 1, 2, 3, 8, 9, 10, 11]), (4, &[4, 5, 6, 7, 12, 13, 14, 15])],
1079 };
1080 for list in 0..2usize {
1083 let (mmv, mrf, mc, rc) = if list == 0 {
1084 (&mut mmvd0, &mut mref0, &mut mvdc0, &mut refc0)
1085 } else {
1086 (&mut mmvd1, &mut mref1, &mut mvdc1, &mut refc1)
1087 };
1088 for (p, &(pidx, zb)) in parts.iter().enumerate() {
1089 if preds[p].uses(list) {
1090 parse_mvd_partition(&mut cab, pidx, zb, mc, rc, mmv, mrf, 0);
1091 }
1092 }
1093 }
1094 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1096 let mut mv = [(0i32, 0i32); 2];
1097 for list in 0..2usize {
1098 if preds[p].uses(list) {
1099 let d = if list == 0 { mmvd0 } else { mmvd1 }[(ry / 4) * 4 + rx / 4];
1100 let n = self.mv_neighbors_list((mbx * 4 + rx / 4) as isize, (mby * 4 + ry / 4) as isize, (rw / 4) as isize, list);
1101 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], 0);
1102 mv[list] = (pmv.0 + d[0] as i32, pmv.1 + d[1] as i32);
1103 }
1104 }
1105 let refi0 = if preds[p].uses(0) { 0 } else { -1 };
1106 let refi1 = if preds[p].uses(1) { 0 } else { -1 };
1107 self.b_set_motion(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1]);
1108 self.b_mc(mbx, mby, rx, ry, rw, rh, refi0, mv[0], refi1, mv[1], &mut pred_y, &mut c_pred);
1112 }
1113 }
1114 mb_ref[addr] = mref0;
1115 mb_mvd[addr] = mmvd0;
1116 mb_ref1[addr] = mref1;
1117 mb_mvd1[addr] = mmvd1;
1118 cat[addr] = 100;
1119
1120 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1122 mb_cbp[addr] = cbp as u8;
1123 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1124 let mut nzc = [0xffu8; 48];
1125 if let Some(t) = top {
1126 let tnz = mb_nzc[t];
1127 nzc[1..5].copy_from_slice(&tnz[12..16]);
1128 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1129 (nzc[6], nzc[7], nzc[30], nzc[31]) = (tnz[20], tnz[21], tnz[22], tnz[23]);
1130 }
1131 if let Some(l) = left {
1132 let lnz = mb_nzc[l];
1133 (nzc[8], nzc[16], nzc[24], nzc[32]) = (lnz[3], lnz[7], lnz[11], lnz[15]);
1134 (nzc[13], nzc[21], nzc[37], nzc[45]) = (lnz[17], lnz[21], lnz[19], lnz[23]);
1135 }
1136 let mut cbfdc = 0u16;
1137 let mut luma_scan = [[0i32; 16]; 16];
1138 let mut cdc = [[0i32; 4]; 2];
1139 let mut cac = [[[0i32; 16]; 4]; 2];
1140 if cbp == 0 {
1141 last_delta_qp = 0;
1142 }
1143 if cbp != 0 {
1144 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1145 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1146 self.step_qp(qpd);
1147 for id8 in 0..4usize {
1148 if cbp_luma & (1 << id8) != 0 {
1149 for id4 in 0..4usize {
1150 let iz = id8 * 4 + id4;
1151 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, false, ndc, &mut luma_scan[iz]);
1152 }
1153 } else {
1154 for k in 0..4 {
1155 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1156 }
1157 }
1158 }
1159 if cbp_chroma >= 1 {
1160 for i in 0..2usize {
1161 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, false, ndc, &mut cdc[i]);
1162 }
1163 }
1164 if cbp_chroma == 2 {
1165 for i in 0..2usize {
1166 for id4 in 0..4usize {
1167 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, false, ndc, &mut cac[i][id4]);
1168 }
1169 }
1170 }
1171 }
1172 self.mb_qp[addr] = self.cur_qp;
1173 cbf_dc[addr] = cbfdc;
1174 let mut mn = [0u8; 24];
1175 for k in 0..4 {
1176 mn[k] = nzc[9 + k];
1177 mn[4 + k] = nzc[17 + k];
1178 mn[8 + k] = nzc[25 + k];
1179 mn[12 + k] = nzc[33 + k];
1180 }
1181 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1182 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1183 for v in mn.iter_mut() {
1187 if *v == 0xff {
1188 *v = 0;
1189 }
1190 }
1191 mb_nzc[addr] = mn;
1192 self.add_inter_residual(mbx, mby, &pred_y, &c_pred, &luma_scan, &cdc, &cac, cbp_chroma);
1193
1194 let eos = cab.decode_terminate();
1195 addr += 1;
1196 if eos || addr >= total {
1197 break;
1198 }
1199 continue;
1200 }
1201 mb_type = bmt - 23; if mb_type == 25 {
1203 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1204 }
1205 } else {
1206 let li = left.map_or(0, |a| (cat[a] >= 2) as usize);
1207 let ti = top.map_or(0, |a| (cat[a] >= 2) as usize);
1208 mb_type = parse_mb_type_i_cabac(&mut cab, li + ti);
1209 if mb_type == 25 {
1210 return Err(MbError::Unsupported("CABAC I_PCM (WIP)"));
1211 }
1212 }
1213 let cci = left.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize)
1215 + top.map_or(0, |a| (1..=3).contains(&cmode[a]) as usize);
1216
1217 if mb_type != 0 {
1218 let mt = mb_type - 1;
1223 let pred_mode = I16Mode::from_id(mt % 4);
1224 let cbp_chroma = (mt % 12) / 4;
1225 let cbp_luma_15 = mt / 12 == 1;
1226 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1227 cmode[addr] = chroma_mode as i32;
1228 cat[addr] = 2;
1229 mb_cbp[addr] = ((cbp_chroma as u8) << 4) | if cbp_luma_15 { 15 } else { 0 };
1230 let w4 = self.mb_w * 4;
1231
1232 let mut nzc = [0xffu8; 48];
1233 if let Some(t) = top {
1234 let tn = mb_nzc[t];
1235 nzc[1..5].copy_from_slice(&tn[12..16]);
1236 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1237 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1238 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1239 }
1240 if let Some(l) = left {
1241 let ln = mb_nzc[l];
1242 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1243 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1244 }
1245
1246 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1247 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1248 self.step_qp(qpd);
1249 let qp = self.cur_qp;
1250 let mut cbfdc = 0u16;
1251
1252 let mut dc_scan = [0i32; 16];
1254 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 0, RP_I16_DC, true, ndc, &mut dc_scan);
1255 let recon_dc = self.dequant_luma_dc(&un_scan_4x4_dcac(&dc_scan), qp, 0);
1256
1257 let mut q_blocks = [[0i32; 16]; 16];
1259 for (iz, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1260 let total = if cbp_luma_15 {
1261 let mut ac = [0i32; 16];
1262 let t = parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_I16_AC, true, ndc, &mut ac);
1263 un_scan_4x4_ac_into(&ac, &mut q_blocks[lby * 4 + lbx]);
1264 t as u8
1265 } else {
1266 nzc[NZC_CACHE[iz]] = 0;
1267 0
1268 };
1269 self.nnz_y[(mby * 4 + lby) * w4 + (mbx * 4 + lbx)] = total;
1270 }
1271
1272 let mut cdc = [[0i32; 4]; 2];
1273 let mut cac = [[[0i32; 16]; 4]; 2];
1274 if cbp_chroma >= 1 {
1275 for i in 0..2usize {
1276 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1277 }
1278 }
1279 if cbp_chroma == 2 {
1280 for i in 0..2usize {
1281 for id4 in 0..4usize {
1282 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1283 }
1284 }
1285 }
1286
1287 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1289 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1290 let (lx, ly) = (mbx * 16, mby * 16);
1291 let mut t16 = [0u8; 16];
1292 let mut l16 = [0u8; 16];
1293 if top_ok {
1294 t16.copy_from_slice(&self.rec_y[(ly - 1) * self.cw + lx..][..16]);
1295 }
1296 if left_ok {
1297 for i in 0..16 {
1298 l16[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
1299 }
1300 }
1301 let corner = if top_ok && left_ok { self.rec_y[(ly - 1) * self.cw + lx - 1] } else { 0 };
1302 let pred_l = luma16x16_pred(pred_mode, top_ok, left_ok, &t16, &l16, corner);
1303 for by in 0..4 {
1304 for bx in 0..4 {
1305 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
1306 deq[0] = recon_dc[by * 4 + bx];
1307 let predb: [i32; 16] = std::array::from_fn(|i| pred_l[(by * 4 + i / 4) * 16 + (bx * 4 + i % 4)] as i32);
1308 let s = reconstruct_4x4(&deq, &predb);
1309 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
1310 self.modes_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = 2;
1314 self.coded_y[(mby * 4 + by) * w4 + (mbx * 4 + bx)] = true;
1315 }
1316 }
1317 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1318
1319 self.mb_qp[addr] = self.cur_qp;
1320 cbf_dc[addr] = cbfdc;
1321 let mut mn = [0u8; 24];
1322 for k in 0..4 {
1323 mn[k] = nzc[9 + k];
1324 mn[4 + k] = nzc[17 + k];
1325 mn[8 + k] = nzc[25 + k];
1326 mn[12 + k] = nzc[33 + k];
1327 }
1328 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1329 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1330 for v in mn.iter_mut() {
1331 if *v == 0xff {
1332 *v = 0;
1333 }
1334 }
1335 mb_nzc[addr] = mn;
1336
1337 let eos = cab.decode_terminate();
1338 addr += 1;
1339 if eos || addr >= total {
1340 break;
1341 }
1342 continue;
1343 }
1344 cat[addr] = 0;
1345 let w4 = self.mb_w * 4;
1346 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1350 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1351 let predicted = self.predict_i4_mode(bx, by);
1352 let rr = parse_intra4x4_pred_mode_cabac(&mut cab);
1353 let actual = if rr < 0 {
1354 predicted
1355 } else {
1356 let rem = rr as u8;
1357 if rem < predicted { rem } else { rem + 1 }
1358 };
1359 self.modes_y[by * w4 + bx] = actual;
1360 modes[lby * 4 + lbx] = actual;
1361 }
1362 let chroma_mode = parse_intra_chroma_pred_mode_cabac(&mut cab, cci) as u8;
1363 cmode[addr] = chroma_mode as i32;
1364 let cbp = parse_cbp_cabac(&mut cab, top.map(|a| mb_cbp[a]), left.map(|a| mb_cbp[a]));
1365 mb_cbp[addr] = cbp as u8;
1366 let (cbp_luma, cbp_chroma) = (cbp & 15, cbp >> 4);
1367
1368 let mut nzc = [0xffu8; 48];
1370 if let Some(t) = top {
1371 let tn = mb_nzc[t];
1372 nzc[1..5].copy_from_slice(&tn[12..16]);
1373 (nzc[0], nzc[5], nzc[29]) = (0, 0, 0);
1374 (nzc[6], nzc[7]) = (tn[20], tn[21]);
1375 (nzc[30], nzc[31]) = (tn[22], tn[23]);
1376 }
1377 if let Some(l) = left {
1378 let ln = mb_nzc[l];
1379 (nzc[8], nzc[16], nzc[24], nzc[32]) = (ln[3], ln[7], ln[11], ln[15]);
1380 (nzc[13], nzc[21], nzc[37], nzc[45]) = (ln[17], ln[21], ln[19], ln[23]);
1381 }
1382
1383 let mut cbfdc = 0u16;
1386 let mut luma_scan = [[0i32; 16]; 16]; let mut cdc = [[0i32; 4]; 2]; let mut cac = [[[0i32; 16]; 4]; 2]; if cbp == 0 {
1390 last_delta_qp = 0;
1391 }
1392 if cbp != 0 {
1393 let ndc = (top.map(|a| cbf_dc[a]), left.map(|a| cbf_dc[a]));
1394 let qpd = parse_mb_qp_delta_cabac(&mut cab, &mut last_delta_qp);
1395 self.step_qp(qpd);
1396 for id8 in 0..4usize {
1397 if cbp_luma & (1 << id8) != 0 {
1398 for id4 in 0..4usize {
1399 let iz = id8 * 4 + id4;
1400 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, iz, RP_LUMA_4X4, true, ndc, &mut luma_scan[iz]);
1401 }
1402 } else {
1403 for k in 0..4 {
1404 nzc[NZC_CACHE[id8 * 4 + k]] = 0;
1405 }
1406 }
1407 }
1408 if cbp_chroma >= 1 {
1409 for i in 0..2usize {
1410 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4, RP_CHROMA_DC + i, true, ndc, &mut cdc[i]);
1411 }
1412 }
1413 if cbp_chroma == 2 {
1414 for i in 0..2usize {
1415 for id4 in 0..4usize {
1416 parse_residual_cabac(&mut cab, &mut nzc, &mut cbfdc, 16 + i * 4 + id4, RP_CHROMA_AC + i, true, ndc, &mut cac[i][id4]);
1417 }
1418 }
1419 }
1420 }
1421 self.mb_qp[addr] = self.cur_qp;
1422 cbf_dc[addr] = cbfdc;
1423 let mut mn = [0u8; 24];
1425 for k in 0..4 {
1426 mn[k] = nzc[9 + k];
1427 mn[4 + k] = nzc[17 + k];
1428 mn[8 + k] = nzc[25 + k];
1429 mn[12 + k] = nzc[33 + k];
1430 }
1431 (mn[16], mn[17], mn[20], mn[21]) = (nzc[14], nzc[15], nzc[22], nzc[23]);
1432 (mn[18], mn[19], mn[22], mn[23]) = (nzc[38], nzc[39], nzc[46], nzc[47]);
1433 for v in mn.iter_mut() {
1434 if *v == 0xff {
1435 *v = 0;
1436 }
1437 }
1438 mb_nzc[addr] = mn;
1439
1440 let qp = self.cur_qp;
1442 let top_ok = mby > 0 && self.nbr_in_slice(mbx, mby - 1) && self.intra_nbr_ok(mbx * 4, mby * 4 - 1);
1443 let left_ok = mbx > 0 && self.nbr_in_slice(mbx - 1, mby) && self.intra_nbr_ok(mbx * 4 - 1, mby * 4);
1444 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1445 let (bx, by) = (mbx * 4 + lbx, mby * 4 + lby);
1446 let (px, py) = (bx * 4, by * 4);
1447 let at = lby > 0 || top_ok;
1448 let al = lbx > 0 || left_ok;
1449 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1450 self.nnz_y[by * w4 + bx] = luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1451 let (t, l, corner) = self.gather_i4(px, py, at, al, bx, by);
1452 let pred = intra4x4_pred(modes[lby * 4 + lbx], at, al, &t, &l, corner);
1453 let predb = std::array::from_fn(|i| pred[i] as i32);
1454 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
1455 store(&mut self.rec_y, self.cw, px, py, &s);
1456 self.coded_y[by * w4 + bx] = true;
1457 }
1458 self.recon_chroma_cabac(mbx, mby, chroma_mode, &cdc, &cac, cbp_chroma, top_ok, left_ok);
1459
1460 let eos = cab.decode_terminate();
1462 addr += 1;
1463 if eos || addr >= total {
1464 break;
1465 }
1466 }
1467 if trace {
1468 eprintln!("# CABAC decoded {} MBs (of {total})", addr - first_mb);
1469 }
1470 Ok(addr)
1471 }
1472
1473 #[allow(clippy::too_many_arguments)]
1477 #[allow(clippy::too_many_arguments)]
1483 fn add_inter_residual(
1484 &mut self,
1485 mb_x: usize,
1486 mb_y: usize,
1487 pred_y: &[u8; 256],
1488 c_pred: &[[u8; 64]; 2],
1489 luma_scan: &[[i32; 16]; 16],
1490 cdc: &[[i32; 4]; 2],
1491 cac: &[[[i32; 16]; 4]; 2],
1492 cbp_chroma: u32,
1493 ) {
1494 let qp = self.cur_qp;
1495 let qpc = self.chroma_qp_for(qp);
1496 let (w4r, w2r) = (self.mb_w * 4, self.mb_w * 2);
1497 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1498 let qb = un_scan_4x4_dcac(&luma_scan[blk]);
1499 let deq = self.dequant(&qb, qp, 3);
1500 let predb: [i32; 16] = std::array::from_fn(|i| pred_y[(lby * 4 + i / 4) * 16 + (lbx * 4 + i % 4)] as i32);
1501 let s = reconstruct_4x4(&deq, &predb);
1502 store(&mut self.rec_y, self.cw, (mb_x * 4 + lbx) * 4, (mb_y * 4 + lby) * 4, &s);
1503 self.nnz_y[(mb_y * 4 + lby) * w4r + (mb_x * 4 + lbx)] =
1504 luma_scan[blk].iter().filter(|&&v| v != 0).count() as u8;
1505 }
1506 let mut c_dc = [[0i32; 4]; 2];
1507 if cbp_chroma != 0 {
1508 for c in 0..2 {
1509 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 4 + c);
1510 }
1511 }
1512 for c in 0..2 {
1513 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1514 let mut ac = [0i32; 16];
1515 if cbp_chroma == 2 {
1516 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1517 self.nnz_c[c][(mb_y * 2 + by) * w2r + (mb_x * 2 + bx)] =
1518 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1519 }
1520 let mut deq = self.dequant(&ac, qpc, 4 + c);
1521 deq[0] = c_dc[c][by * 2 + bx];
1522 let predb: [i32; 16] =
1523 std::array::from_fn(|i| c_pred[c][(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1524 let s = reconstruct_4x4(&deq, &predb);
1525 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1526 store(plane, self.ccw, (mb_x * 2 + bx) * 4, (mb_y * 2 + by) * 4, &s);
1527 }
1528 }
1529 }
1530
1531 fn recon_chroma_cabac(
1532 &mut self,
1533 mb_x: usize,
1534 mb_y: usize,
1535 chroma_mode: u8,
1536 cdc: &[[i32; 4]; 2],
1537 cac: &[[[i32; 16]; 4]; 2],
1538 cbp_chroma: u32,
1539 avail_top: bool,
1540 avail_left: bool,
1541 ) {
1542 let qpc = self.chroma_qp_for(self.cur_qp);
1543 let (cx, cy) = (mb_x * 8, mb_y * 8);
1544 let mut c_dc = [[0i32; 4]; 2];
1545 if cbp_chroma != 0 {
1546 for c in 0..2 {
1547 c_dc[c] = self.dequant_chroma_dc(&cdc[c], qpc, 1 + c);
1548 }
1549 }
1550 let w2 = self.mb_w * 2;
1551 for c in 0..2 {
1552 let mut ctop = [0u8; 8];
1553 let mut cleft = [0u8; 8];
1554 let mut ccorner = 0u8;
1555 {
1556 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
1557 if avail_top {
1558 ctop.copy_from_slice(&rec_c[(cy - 1) * self.ccw + cx..][..8]);
1559 }
1560 if avail_left {
1561 for i in 0..8 {
1562 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
1563 }
1564 }
1565 if avail_top && avail_left {
1566 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
1567 }
1568 }
1569 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
1570 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1571 let mut ac = [0i32; 16];
1572 if cbp_chroma == 2 {
1573 un_scan_4x4_ac_into(&cac[c][by * 2 + bx], &mut ac);
1574 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] =
1575 cac[c][by * 2 + bx].iter().filter(|&&v| v != 0).count() as u8;
1576 }
1577 let mut deq = self.dequant(&ac, qpc, 1 + c);
1578 deq[0] = c_dc[c][by * 2 + bx];
1579 let predb: [i32; 16] =
1580 std::array::from_fn(|i| pred8[(by * 4 + i / 4) * 8 + (bx * 4 + i % 4)] as i32);
1581 let s = reconstruct_4x4(&deq, &predb);
1582 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1583 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
1584 }
1585 }
1586 }
1587
1588 pub fn decode_slice_data(
1589 &mut self,
1590 r: &mut BitReader,
1591 is_p: bool,
1592 first_mb: usize,
1593 ) -> Result<usize, MbError> {
1594 let total = self.mb_w * self.mb_h;
1595 self.slice_first_mb = first_mb;
1596 let mut addr = first_mb;
1597 while addr < total {
1598 if is_p || self.is_b {
1599 let skip_run = {
1600 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1601 r.read_ue()?
1602 } as usize;
1603 for _ in 0..skip_run {
1604 if addr >= total {
1605 break;
1606 }
1607 if self.is_b {
1608 self.decode_b_skip(addr % self.mb_w, addr / self.mb_w)?;
1609 } else {
1610 self.decode_p_skip(addr % self.mb_w, addr / self.mb_w)?;
1611 }
1612 self.mb_qp[addr] = self.cur_qp; addr += 1;
1614 }
1615 if addr >= total {
1616 break;
1617 }
1618 if skip_run > 0 && !r.more_rbsp_data() {
1620 break;
1621 }
1622 }
1623 if self.is_b {
1624 self.decode_b_mb(r, addr % self.mb_w, addr / self.mb_w)?;
1625 } else {
1626 self.decode_mb(r, addr % self.mb_w, addr / self.mb_w, is_p)?;
1627 }
1628 self.mb_qp[addr] = self.cur_qp;
1629 addr += 1;
1630 if !r.more_rbsp_data() {
1632 break;
1633 }
1634 }
1635 Ok(addr)
1636 }
1637
1638 fn decode_mb(
1639 &mut self,
1640 r: &mut BitReader,
1641 mb_x: usize,
1642 mb_y: usize,
1643 is_p: bool,
1644 ) -> Result<(), MbError> {
1645 let mut mb_type = {
1646 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1647 r.read_ue()?
1648 };
1649 if is_p {
1650 if mb_type <= 2 {
1653 return self.decode_inter(r, mb_x, mb_y, mb_type as u8);
1654 }
1655 if mb_type == 3 || mb_type == 4 {
1656 return self.decode_p8x8(r, mb_x, mb_y, mb_type == 4);
1657 }
1658 mb_type -= 5;
1659 }
1660 self.decode_intra_mb(r, mb_x, mb_y, mb_type)
1661 }
1662
1663 fn decode_intra_mb(
1666 &mut self,
1667 r: &mut BitReader,
1668 mb_x: usize,
1669 mb_y: usize,
1670 mb_type: u32,
1671 ) -> Result<(), MbError> {
1672 if mb_type == 0 {
1673 if self.transform_8x8_mode && r.read_bit()? {
1675 self.decode_i8x8(r, mb_x, mb_y)?;
1676 } else {
1677 self.decode_i4x4(r, mb_x, mb_y)?;
1678 }
1679 } else if (1..=24).contains(&mb_type) {
1680 self.decode_i16(r, mb_x, mb_y, mb_type - 1)?;
1681 } else if mb_type == 25 {
1682 self.decode_ipcm(r, mb_x, mb_y)?;
1683 } else {
1684 return Err(MbError::Unsupported("only I_4x4 / I_16x16 / I_PCM macroblocks"));
1685 }
1686 let w4 = self.mb_w * 4;
1688 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1689 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
1690 }
1691 Ok(())
1692 }
1693
1694 fn decode_inter(
1698 &mut self,
1699 r: &mut BitReader,
1700 mb_x: usize,
1701 mb_y: usize,
1702 mode: u8,
1703 ) -> Result<(), MbError> {
1704 if self.refs.is_empty() {
1705 return Err(MbError::Unsupported("inter without reference"));
1706 }
1707 let w4 = self.mb_w * 4;
1709 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
1710 let num_refs = self.refs.len();
1711 let layout = inter_partitions(mode);
1712
1713 let nparts = layout.len();
1716 let mut ref_idxs = [0i32; 4];
1717 if self.num_ref_active > 1 {
1718 for ri in ref_idxs[..nparts].iter_mut() {
1719 *ri = read_ref_idx(r, self.num_ref_active)?;
1720 if *ri as usize >= num_refs {
1721 return Err(MbError::Truncated); }
1723 }
1724 }
1725
1726 let mut part_mv = [(0i32, (0i32, 0i32)); 4];
1729 {
1730 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::MvGrid);
1731 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1732 let refi = ref_idxs[part];
1733 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
1734 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (rw / 4) as isize);
1735 let pmv = predict_partition_mv(mode, part, a, b, c, refi);
1736 let mvd_x = r.read_se()?;
1737 let mvd_y = r.read_se()?;
1738 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
1739 part_mv[part] = (refi, mv);
1740 for by in ry / 4..ry / 4 + rh / 4 {
1741 for bx in rx / 4..rx / 4 + rw / 4 {
1742 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
1743 self.mv_y[idx] = mv;
1744 self.inter_y[idx] = true;
1745 self.ref_idx_y[idx] = refi;
1746 self.coded_y[idx] = true;
1747 }
1748 }
1749 }
1750 }
1751
1752 let mut pred_y = [0u8; 256];
1754 let mut c_pred = [[0u8; 64]; 2];
1755 for (part, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
1756 let (refi, mv) = part_mv[part];
1757 let reference = &self.refs[refi as usize];
1758 let mut tmp = [0u8; 256];
1759 mc_luma(&reference.y, self.cw, ch, mb_x * 16 + rx, mb_y * 16 + ry, rw, rh, mv.0, mv.1, &mut tmp);
1760 {
1761 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
1762 for dy in 0..rh {
1763 for dx in 0..rw {
1764 pred_y[(ry + dy) * 16 + (rx + dx)] = tmp[dy * rw + dx];
1765 }
1766 }
1767 }
1768 let (crx, cry, crw, crh) = (rx / 2, ry / 2, rw / 2, rh / 2);
1769 for cc in 0..2 {
1770 let rc = if cc == 0 { &reference.u } else { &reference.v };
1771 let mut tc = [0u8; 64];
1772 mc_chroma(rc, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv.0, mv.1, &mut tc);
1773 {
1774 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::PredBuf);
1775 for dy in 0..crh {
1776 for dx in 0..crw {
1777 c_pred[cc][(cry + dy) * 8 + (crx + dx)] = tc[dy * crw + dx];
1778 }
1779 }
1780 }
1781 }
1782 self.weight_partition(&mut pred_y, &mut c_pred, 0, refi as usize, rx, ry, rw, rh);
1783 }
1784
1785 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
1787 }
1788
1789 fn inter_finish(
1793 &mut self,
1794 r: &mut BitReader,
1795 mb_x: usize,
1796 mb_y: usize,
1797 pred_y: &[u8; 256],
1798 c_pred: &[[u8; 64]; 2],
1799 allow_8x8: bool,
1800 ) -> Result<(), MbError> {
1801 let w4 = self.mb_w * 4;
1802 let cbp = {
1803 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Syntax);
1804 read_cbp_inter(r)?
1805 };
1806 let cbp_luma = cbp & 15;
1807 let cbp_chroma = cbp >> 4;
1808 let t8x8 = cbp_luma > 0 && self.transform_8x8_mode && allow_8x8 && r.read_bit()?;
1811 if t8x8 {
1812 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
1813 }
1814 if cbp != 0 {
1815 self.step_qp(r.read_se()?);
1816 }
1817 let (qp, qpc) = (self.cur_qp, self.chroma_qp_for(self.cur_qp));
1818
1819 self.nnz_cache_load(mb_x, mb_y);
1821 let mut q_blocks = [[0i32; 16]; 16];
1822 let mut luma8 = [[0i32; 64]; 4]; if t8x8 {
1824 for b8 in 0..4 {
1825 let (b8x, b8y) = (b8 % 2, b8 / 2);
1826 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
1827 if cbp_luma & (1 << b8) != 0 {
1828 let mut scan8 = [0i32; 64];
1829 for sub in 0..4 {
1830 let (sx, sy) = (sub % 2, sub / 2);
1831 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
1832 let nc = self.nc_pred(cx, cy);
1833 let blk = decode_residual_block(r, 16, nc)?;
1834 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
1835 self.nnz_cache_set(cx, cy, total);
1836 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
1837 for k in 0..16 {
1838 scan8[4 * k + sub] = blk[k];
1839 }
1840 }
1841 luma8[b8] = self.inv_quant8(&un_scan_8x8(&scan8), qp, 1);
1842 } else {
1843 for sub in 0..4 {
1844 let (sx, sy) = (sub % 2, sub / 2);
1845 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
1846 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
1847 }
1848 }
1849 }
1850 } else {
1851 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
1852 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
1853 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
1854 let nc = self.nc_pred(lbx, lby);
1855 let scan16 = decode_residual_block(r, 16, nc)?;
1856 q_blocks[lby * 4 + lbx] = un_scan_4x4_dcac(&scan16);
1857 scan16.iter().filter(|&&v| v != 0).count() as u8
1858 } else {
1859 0
1860 };
1861 self.nnz_cache_set(lbx, lby, total);
1862 self.nnz_y[by * w4 + bx] = total;
1863 }
1864 }
1865
1866 let mut c_recon_dc = [[0i32; 4]; 2];
1868 if cbp_chroma != 0 {
1869 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
1870 let dc = decode_residual_block(r, 4, -1)?;
1871 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 4 + c);
1872 }
1873 }
1874 let mut c_q = [[[0i32; 16]; 4]; 2];
1875 if cbp_chroma == 2 {
1876 self.chroma_cache_load(mb_x, mb_y);
1877 let w2 = self.mb_w * 2;
1878 for c in 0..2 {
1879 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1880 let nc = self.chroma_nc_pred(c, bx, by);
1881 let ac = decode_residual_block(r, 15, nc)?;
1882 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
1883 self.chroma_nnz_cache_set(c, bx, by, total);
1884 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
1885 un_scan_4x4_ac_into(&ac, &mut c_q[c][by * 2 + bx]);
1886 }
1887 }
1888 }
1889
1890 if t8x8 {
1892 for b8 in 0..4 {
1893 let (b8x, b8y) = (b8 % 2, b8 / 2);
1894 let (px, py) = (b8x * 8, b8y * 8);
1895 for dy in 0..8 {
1896 for dx in 0..8 {
1897 let p = pred_y[(py + dy) * 16 + (px + dx)] as i32;
1898 let v = (p + luma8[b8][dy * 8 + dx]).clamp(0, 255) as u8;
1899 self.rec_y[(mb_y * 16 + py + dy) * self.cw + (mb_x * 16 + px + dx)] = v;
1900 }
1901 }
1902 }
1903 } else {
1904 for b8 in 0..4 {
1911 let (b8x, b8y) = (b8 % 2, b8 / 2);
1912 let pred_off = (b8y * 8) * 16 + b8x * 8;
1913 let rec_off = (mb_y * 16 + b8y * 8) * self.cw + (mb_x * 16 + b8x * 8);
1914 if cbp_luma & (1 << b8) == 0 {
1915 for r in 0..8 {
1916 let (s, d) = (pred_off + r * 16, rec_off + r * self.cw);
1917 self.rec_y[d..d + 8].copy_from_slice(&pred_y[s..s + 8]);
1918 }
1919 continue;
1920 }
1921 #[cfg(accel)]
1922 {
1923 let mut dct = [0i16; 64];
1924 for (i, (sx, sy)) in [(0, 0), (1, 0), (0, 1), (1, 1)].into_iter().enumerate() {
1925 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
1926 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
1927 for k in 0..16 {
1928 dct[i * 16 + k] = deq[k] as i16;
1929 }
1930 }
1931 rusty_h264_accel::idct_four_t4_rec(
1932 &mut self.rec_y[rec_off..],
1933 self.cw,
1934 &pred_y[pred_off..],
1935 16,
1936 &dct,
1937 );
1938 }
1939 #[cfg(not(accel))]
1940 for (sx, sy) in [(0, 0), (1, 0), (0, 1), (1, 1)] {
1941 let (lbx, lby) = (2 * b8x + sx, 2 * b8y + sy);
1942 let mut predb = [0i32; 16];
1943 for dy in 0..4 {
1944 for dx in 0..4 {
1945 predb[dy * 4 + dx] = pred_y[(lby * 4 + dy) * 16 + (lbx * 4 + dx)] as i32;
1946 }
1947 }
1948 let deq = self.dequant(&q_blocks[lby * 4 + lbx], qp, 3);
1949 let s = reconstruct_4x4(&deq, &predb);
1950 store(&mut self.rec_y, self.cw, mb_x * 16 + lbx * 4, mb_y * 16 + lby * 4, &s);
1951 }
1952 }
1953 }
1954 if cbp_chroma == 0 {
1957 for c in 0..2 {
1958 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1959 for dy in 0..8 {
1960 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
1961 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
1962 }
1963 }
1964 } else {
1965 for c in 0..2 {
1966 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
1967 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
1968 let mut predb = [0i32; 16];
1969 for dy in 0..4 {
1970 for dx in 0..4 {
1971 predb[dy * 4 + dx] = c_pred[c][(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
1972 }
1973 }
1974 let mut deq = match &self.scaling {
1975 Some(s) => dequantize_weighted(&c_q[c][by * 2 + bx], qpc, &s[4 + c]),
1976 None => dequantize(&c_q[c][by * 2 + bx], qpc),
1977 };
1978 deq[0] = c_recon_dc[c][by * 2 + bx];
1979 let s = reconstruct_4x4(&deq, &predb);
1980 store(plane, self.ccw, mb_x * 8 + bx * 4, mb_y * 8 + by * 4, &s);
1981 }
1982 }
1983 }
1984
1985 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
1987 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
1988 }
1989 Ok(())
1990 }
1991
1992 fn mv_neighbors_list(&self, pbx: isize, pby: isize, pwb: isize, list: usize) -> [MvNeighbor; 3] {
2000 let (w4, h4) = ((self.mb_w * 4) as isize, (self.mb_h * 4) as isize);
2001 let (mvg, refg) = if list == 0 {
2002 (&self.mv_y, &self.ref_idx_y)
2003 } else {
2004 (&self.mv1, &self.ref_idx1)
2005 };
2006 let get = |bx: isize, by: isize| -> MvNeighbor {
2007 if bx < 0
2008 || by < 0
2009 || bx >= w4
2010 || by >= h4
2011 || !self.coded_y[(by * w4 + bx) as usize]
2012 || !self.nbr_in_slice(bx as usize / 4, by as usize / 4)
2013 {
2014 MvNeighbor::NONE
2015 } else {
2016 let idx = (by * w4 + bx) as usize;
2017 MvNeighbor { available: true, mv: mvg[idx], ref_idx: refg[idx] }
2018 }
2019 };
2020 let a = get(pbx - 1, pby);
2021 let b = get(pbx, pby - 1);
2022 let mut c = get(pbx + pwb, pby - 1);
2023 if !c.available {
2024 c = get(pbx - 1, pby - 1);
2025 }
2026 [a, b, c]
2027 }
2028
2029 fn col_zero(&self, bx: usize, by: usize) -> bool {
2033 let Some(col) = self.refs1.first() else { return false };
2034 if col.long_term || col.w4 == 0 {
2035 return false;
2036 }
2037 let idx = by * col.w4 + bx;
2038 if idx >= col.ref_idx.len() {
2039 return false;
2040 }
2041 col.ref_idx[idx] == 0 && col.mv[idx].0.abs() <= 1 && col.mv[idx].1.abs() <= 1
2042 }
2043
2044 fn implicit_weights(&self, refi0: i32, refi1: i32) -> Option<(i32, i32)> {
2048 if self.weighted_bipred_idc != 2 || refi0 < 0 || refi1 < 0 {
2049 return None;
2050 }
2051 let r0 = &self.refs[refi0 as usize];
2052 let r1 = &self.refs1[refi1 as usize];
2053 let td = (r1.poc - r0.poc).clamp(-128, 127);
2054 let tb = (self.cur_poc - r0.poc).clamp(-128, 127);
2055 if td == 0 || r0.long_term || r1.long_term {
2056 return None; }
2058 let tx = (16384 + td.abs() / 2) / td;
2059 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2060 let w1 = dsf >> 2;
2061 if !(-64..=128).contains(&w1) {
2062 return None; }
2064 Some((64 - w1, w1))
2065 }
2066
2067 #[allow(clippy::too_many_arguments)]
2071 fn b_mc(
2072 &self,
2073 mb_x: usize,
2074 mb_y: usize,
2075 px: usize,
2076 py: usize,
2077 rw: usize,
2078 rh: usize,
2079 refi0: i32,
2080 mv0: (i32, i32),
2081 refi1: i32,
2082 mv1: (i32, i32),
2083 pred_y: &mut [u8; 256],
2084 c_pred: &mut [[u8; 64]; 2],
2085 ) {
2086 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2087 let weights = self.implicit_weights(refi0, refi1);
2088 let blend = |p: i32, q: i32| -> u8 {
2090 match weights {
2091 Some((w0, w1)) => (((p * w0 + q * w1 + 32) >> 6).clamp(0, 255)) as u8,
2092 None => ((p + q + 1) >> 1) as u8,
2093 }
2094 };
2095 let (mut a, mut b) = ([0u8; 256], [0u8; 256]);
2096 if refi0 >= 0 {
2097 mc_luma(&self.refs[refi0 as usize].y, self.cw, ch, mb_x * 16 + px, mb_y * 16 + py, rw, rh, mv0.0, mv0.1, &mut a);
2098 }
2099 if refi1 >= 0 {
2100 mc_luma(&self.refs1[refi1 as usize].y, self.cw, ch, mb_x * 16 + px, mb_y * 16 + py, rw, rh, mv1.0, mv1.1, &mut b);
2101 }
2102 match (refi0 >= 0, refi1 >= 0) {
2105 (true, true) => {
2106 for dy in 0..rh {
2107 for dx in 0..rw {
2108 let (p, q) = (a[dy * rw + dx] as i32, b[dy * rw + dx] as i32);
2109 pred_y[(py + dy) * 16 + (px + dx)] = blend(p, q);
2110 }
2111 }
2112 }
2113 (true, false) => {
2114 for dy in 0..rh {
2115 let d = (py + dy) * 16 + px;
2116 pred_y[d..d + rw].copy_from_slice(&a[dy * rw..dy * rw + rw]);
2117 }
2118 }
2119 _ => {
2120 for dy in 0..rh {
2121 let d = (py + dy) * 16 + px;
2122 pred_y[d..d + rw].copy_from_slice(&b[dy * rw..dy * rw + rw]);
2123 }
2124 }
2125 }
2126 let (crx, cry, crw, crh) = (px / 2, py / 2, rw / 2, rh / 2);
2127 for c in 0..2 {
2128 let (mut ca, mut cb) = ([0u8; 64], [0u8; 64]);
2129 if refi0 >= 0 {
2130 let rf = &self.refs[refi0 as usize];
2131 let pl = if c == 0 { &rf.u } else { &rf.v };
2132 mc_chroma(pl, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv0.0, mv0.1, &mut ca);
2133 }
2134 if refi1 >= 0 {
2135 let rf = &self.refs1[refi1 as usize];
2136 let pl = if c == 0 { &rf.u } else { &rf.v };
2137 mc_chroma(pl, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv1.0, mv1.1, &mut cb);
2138 }
2139 match (refi0 >= 0, refi1 >= 0) {
2140 (true, true) => {
2141 for dy in 0..crh {
2142 for dx in 0..crw {
2143 let (p, q) = (ca[dy * crw + dx] as i32, cb[dy * crw + dx] as i32);
2144 c_pred[c][(cry + dy) * 8 + (crx + dx)] = blend(p, q);
2145 }
2146 }
2147 }
2148 (true, false) => {
2149 for dy in 0..crh {
2150 let d = (cry + dy) * 8 + crx;
2151 c_pred[c][d..d + crw].copy_from_slice(&ca[dy * crw..dy * crw + crw]);
2152 }
2153 }
2154 _ => {
2155 for dy in 0..crh {
2156 let d = (cry + dy) * 8 + crx;
2157 c_pred[c][d..d + crw].copy_from_slice(&cb[dy * crw..dy * crw + crw]);
2158 }
2159 }
2160 }
2161 }
2162 }
2163
2164 #[allow(clippy::too_many_arguments)]
2166 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)) {
2167 let w4 = self.mb_w * 4;
2168 for by in py / 4..(py + rh) / 4 {
2169 for bx in px / 4..(px + rw) / 4 {
2170 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2171 self.ref_idx_y[idx] = refi0;
2172 self.mv_y[idx] = if refi0 >= 0 { mv0 } else { (0, 0) };
2173 self.ref_idx1[idx] = refi1;
2174 self.mv1[idx] = if refi1 >= 0 { mv1 } else { (0, 0) };
2175 self.inter_y[idx] = true;
2176 self.coded_y[idx] = true;
2177 self.modes_y[idx] = 2;
2178 }
2179 }
2180 }
2181
2182 #[allow(clippy::too_many_arguments)]
2186 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]) {
2187 if !self.direct_spatial {
2188 return self.decode_b_direct_temporal(mb_x, mb_y, px, py, rw, rh, pred_y, c_pred);
2189 }
2190 let (nbx, nby) = ((mb_x * 4) as isize, (mb_y * 4) as isize);
2192 let n0 = self.mv_neighbors_list(nbx, nby, 4, 0);
2193 let n1 = self.mv_neighbors_list(nbx, nby, 4, 1);
2194 let min_pos = |a: i32, b: i32| if a < 0 { b } else if b < 0 { a } else { a.min(b) };
2195 let rid = |n: &[MvNeighbor; 3]| min_pos(min_pos(n[0].ref_idx, n[1].ref_idx), n[2].ref_idx);
2196 let (mut refi0, mut refi1) = (rid(&n0), rid(&n1));
2197 let direct_zero = refi0 < 0 && refi1 < 0;
2198 if direct_zero {
2199 refi0 = 0;
2200 refi1 = 0;
2201 }
2202 let mv0 = if refi0 >= 0 && !direct_zero { predict_mv(n0[0], n0[1], n0[2], refi0) } else { (0, 0) };
2203 let mv1 = if refi1 >= 0 && !direct_zero { predict_mv(n1[0], n1[1], n1[2], refi1) } else { (0, 0) };
2204 for sby in py / 4..(py + rh) / 4 {
2206 for sbx in px / 4..(px + rw) / 4 {
2207 let cz = !direct_zero && self.col_zero(mb_x * 4 + sbx, mb_y * 4 + sby);
2208 let m0 = if refi0 == 0 && cz { (0, 0) } else { mv0 };
2209 let m1 = if refi1 == 0 && cz { (0, 0) } else { mv1 };
2210 self.b_mc(mb_x, mb_y, sbx * 4, sby * 4, 4, 4, refi0, m0, refi1, m1, pred_y, c_pred);
2211 self.b_set_motion(mb_x, mb_y, sbx * 4, sby * 4, 4, 4, refi0, m0, refi1, m1);
2212 }
2213 }
2214 }
2215
2216 #[allow(clippy::too_many_arguments)]
2221 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]) {
2222 let poc1 = self.refs1.first().map_or(0, |f| f.poc);
2223 let infer = self.direct_8x8_inference;
2224 let step = if infer { 8 } else { 4 };
2230 let mut sy = py;
2231 while sy < py + rh {
2232 let mut sx = px;
2233 while sx < px + rw {
2234 let (cx4, cy4) = (sx / 4, sy / 4);
2235 let (colx, coly) = if infer {
2237 ((cx4 / 2) * 3, (cy4 / 2) * 3)
2238 } else {
2239 (cx4, cy4)
2240 };
2241 let (mvcol, refpoc) = {
2242 let col = &self.refs1[0];
2243 let idx = (mb_y * 4 + coly) * col.w4 + (mb_x * 4 + colx);
2244 if col.w4 != 0 && idx < col.mv.len() && col.ref_poc[idx] != i32::MIN {
2245 (col.mv[idx], col.ref_poc[idx])
2246 } else {
2247 ((0, 0), i32::MIN) }
2249 };
2250 let (refi0, mvc) = if refpoc == i32::MIN {
2252 (0, (0, 0))
2253 } else {
2254 let r = self.refs.iter().position(|f| f.poc == refpoc).unwrap_or(0) as i32;
2255 (r, mvcol)
2256 };
2257 let poc0 = self.refs[refi0 as usize].poc;
2258 let td = (poc1 - poc0).clamp(-128, 127);
2259 let tb = (self.cur_poc - poc0).clamp(-128, 127);
2260 let (mv0, mv1) = if td == 0 || self.refs[refi0 as usize].long_term {
2261 (mvc, (0, 0))
2262 } else {
2263 let tx = (16384 + td.abs() / 2) / td;
2264 let dsf = ((tb * tx + 32) >> 6).clamp(-1024, 1023);
2265 let m0 = ((dsf * mvc.0 + 128) >> 8, (dsf * mvc.1 + 128) >> 8);
2266 (m0, (m0.0 - mvc.0, m0.1 - mvc.1))
2267 };
2268 self.b_mc(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1, pred_y, c_pred);
2269 self.b_set_motion(mb_x, mb_y, sx, sy, step, step, refi0, mv0, 0, mv1);
2270 sx += step;
2271 }
2272 sy += step;
2273 }
2274 }
2275
2276 fn read_b_ref(&self, r: &mut BitReader, list: usize) -> Result<i32, MbError> {
2279 let (active, avail) = if list == 0 {
2280 (self.num_ref_active, self.refs.len())
2281 } else {
2282 (self.num_ref_active1, self.refs1.len())
2283 };
2284 let v = if active > 1 { read_ref_idx(r, active)? } else { 0 };
2285 if v as usize >= avail {
2286 return Err(MbError::Truncated);
2287 }
2288 Ok(v)
2289 }
2290
2291 fn decode_b_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2293 if self.refs.is_empty() || self.refs1.is_empty() {
2294 return Err(MbError::Unsupported("B without references"));
2295 }
2296 let mut pred_y = [0u8; 256];
2297 let mut c_pred = [[0u8; 64]; 2];
2298 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2299 for dy in 0..16 {
2301 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2302 self.rec_y[d..d + 16].copy_from_slice(&pred_y[dy * 16..dy * 16 + 16]);
2303 }
2304 for c in 0..2 {
2305 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2306 for dy in 0..8 {
2307 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2308 plane[d..d + 8].copy_from_slice(&c_pred[c][dy * 8..dy * 8 + 8]);
2309 }
2310 }
2311 let w4 = self.mb_w * 4;
2313 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2314 self.nnz_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 0;
2315 }
2316 Ok(())
2317 }
2318
2319 fn decode_b_mb(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2322 let mb_type = r.read_ue()?;
2323 if mb_type >= 23 {
2324 return self.decode_intra_mb(r, mb_x, mb_y, mb_type - 23);
2325 }
2326 if self.refs.is_empty() || self.refs1.is_empty() {
2327 return Err(MbError::Unsupported("B without references"));
2328 }
2329 let mut pred_y = [0u8; 256];
2330 let mut c_pred = [[0u8; 64]; 2];
2331
2332 if mb_type == 0 {
2333 self.decode_b_direct(mb_x, mb_y, 0, 0, 16, 16, &mut pred_y, &mut c_pred);
2335 return self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, self.direct_8x8_inference);
2336 }
2337 if mb_type == 22 {
2338 return self.decode_b_8x8(r, mb_x, mb_y);
2339 }
2340
2341 let (layout, mvmode, preds) = b_inter_layout(mb_type);
2343 let mut refi = [[-1i32; 2]; 2]; for (p, &(_, _, _, _)) in layout.iter().enumerate() {
2346 if preds[p].uses(0) {
2347 refi[p][0] = self.read_b_ref(r, 0)?;
2348 }
2349 }
2350 for (p, _) in layout.iter().enumerate() {
2351 if preds[p].uses(1) {
2352 refi[p][1] = self.read_b_ref(r, 1)?;
2353 }
2354 }
2355 let mut mvd = [[(0i32, 0i32); 2]; 2];
2356 for (p, _) in layout.iter().enumerate() {
2357 if preds[p].uses(0) {
2358 mvd[p][0] = (r.read_se()?, r.read_se()?);
2359 }
2360 }
2361 for (p, _) in layout.iter().enumerate() {
2362 if preds[p].uses(1) {
2363 mvd[p][1] = (r.read_se()?, r.read_se()?);
2364 }
2365 }
2366 for (p, &(rx, ry, rw, rh)) in layout.iter().enumerate() {
2368 let (pbx, pby) = ((mb_x * 4 + rx / 4) as isize, (mb_y * 4 + ry / 4) as isize);
2369 let pwb = (rw / 4) as isize;
2370 let mut mv = [(0i32, 0i32); 2];
2371 for list in 0..2 {
2372 if refi[p][list] >= 0 {
2373 let n = self.mv_neighbors_list(pbx, pby, pwb, list);
2374 let pmv = predict_partition_mv(mvmode, p, n[0], n[1], n[2], refi[p][list]);
2375 mv[list] = (pmv.0 + mvd[p][list].0, pmv.1 + mvd[p][list].1);
2376 }
2377 }
2378 self.b_set_motion(mb_x, mb_y, rx, ry, rw, rh, refi[p][0], mv[0], refi[p][1], mv[1]);
2379 let (mc_r0, mc_r1) = if mvmode != 0 && refi[p][0] >= 0 && refi[p][1] >= 0 {
2386 if p == 0 {
2387 (-1, refi[p][1])
2388 } else {
2389 (refi[p][0], -1)
2390 }
2391 } else {
2392 (refi[p][0], refi[p][1])
2393 };
2394 self.b_mc(mb_x, mb_y, rx, ry, rw, rh, mc_r0, mv[0], mc_r1, mv[1], &mut pred_y, &mut c_pred);
2395 }
2396 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, true)
2397 }
2398
2399 fn decode_b_8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2402 let mut sub = [0u32; 4];
2403 for s in sub.iter_mut() {
2404 let v = r.read_ue()?;
2405 if v > 12 {
2406 return Err(MbError::Unsupported("invalid B sub_mb_type"));
2407 }
2408 *s = v;
2409 }
2410 let mut pred_y = [0u8; 256];
2411 let mut c_pred = [[0u8; 64]; 2];
2412 let mut refi = [[-1i32; 2]; 4];
2415 for (p, &st) in sub.iter().enumerate() {
2416 if st != 0 && b_sub_uses(st, 0) {
2417 refi[p][0] = self.read_b_ref(r, 0)?;
2418 }
2419 }
2420 for (p, &st) in sub.iter().enumerate() {
2421 if st != 0 && b_sub_uses(st, 1) {
2422 refi[p][1] = self.read_b_ref(r, 1)?;
2423 }
2424 }
2425 let mut mvd0: Vec<(i32, i32)> = Vec::new();
2427 let mut mvd1: Vec<(i32, i32)> = Vec::new();
2428 for &st in &sub {
2429 if st != 0 && b_sub_uses(st, 0) {
2430 for _ in b_sub_parts(st) {
2431 mvd0.push((r.read_se()?, r.read_se()?));
2432 }
2433 }
2434 }
2435 for &st in &sub {
2436 if st != 0 && b_sub_uses(st, 1) {
2437 for _ in b_sub_parts(st) {
2438 mvd1.push((r.read_se()?, r.read_se()?));
2439 }
2440 }
2441 }
2442 let (mut i0, mut i1) = (0usize, 0usize);
2444 for (p, &st) in sub.iter().enumerate() {
2445 let (b8x, b8y) = ((p % 2) * 8, (p / 2) * 8);
2446 if st == 0 {
2447 self.decode_b_direct(mb_x, mb_y, b8x, b8y, 8, 8, &mut pred_y, &mut c_pred);
2448 continue;
2449 }
2450 for &(sx, sy, sw, sh) in b_sub_parts(st) {
2451 let (px, py) = (b8x + sx, b8y + sy);
2452 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2453 let pwb = (sw / 4) as isize;
2454 let mut mv = [(0i32, 0i32); 2];
2455 if b_sub_uses(st, 0) {
2456 let n = self.mv_neighbors_list(pbx, pby, pwb, 0);
2457 let pmv = predict_mv(n[0], n[1], n[2], refi[p][0]);
2458 let d = mvd0[i0];
2459 i0 += 1;
2460 mv[0] = (pmv.0 + d.0, pmv.1 + d.1);
2461 }
2462 if b_sub_uses(st, 1) {
2463 let n = self.mv_neighbors_list(pbx, pby, pwb, 1);
2464 let pmv = predict_mv(n[0], n[1], n[2], refi[p][1]);
2465 let d = mvd1[i1];
2466 i1 += 1;
2467 mv[1] = (pmv.0 + d.0, pmv.1 + d.1);
2468 }
2469 self.b_set_motion(mb_x, mb_y, px, py, sw, sh, refi[p][0], mv[0], refi[p][1], mv[1]);
2470 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);
2471 }
2472 }
2473 let allow_8x8 = sub
2476 .iter()
2477 .all(|&st| if st == 0 { self.direct_8x8_inference } else { st <= 3 });
2478 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2479 }
2480
2481 fn decode_p8x8(
2485 &mut self,
2486 r: &mut BitReader,
2487 mb_x: usize,
2488 mb_y: usize,
2489 ref0: bool,
2490 ) -> Result<(), MbError> {
2491 if self.refs.is_empty() {
2492 return Err(MbError::Unsupported("inter without reference"));
2493 }
2494 let w4 = self.mb_w * 4;
2495 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2496 let num_refs = self.refs.len();
2497
2498 let mut sub_types = [0u32; 4];
2501 for st in sub_types.iter_mut() {
2502 let v = r.read_ue()?;
2503 if v > 3 {
2504 return Err(MbError::Unsupported("B-slice / invalid sub_mb_type"));
2505 }
2506 *st = v;
2507 }
2508 let mut ref_idxs = [0i32; 4];
2509 if self.num_ref_active > 1 && !ref0 {
2510 for ri in ref_idxs.iter_mut() {
2511 *ri = read_ref_idx(r, self.num_ref_active)?;
2512 if *ri as usize >= num_refs {
2513 return Err(MbError::Truncated); }
2515 }
2516 }
2517
2518 let mut pred_y = [0u8; 256];
2522 let mut c_pred = [[0u8; 64]; 2];
2523 for part in 0..4usize {
2524 let refi = ref_idxs[part];
2525 let (b8x, b8y) = ((part % 2) * 8, (part / 2) * 8);
2526 for &(srx, sry, srw, srh) in sub_mb_partitions(sub_types[part]) {
2527 let (px, py) = (b8x + srx, b8y + sry);
2528 let (pbx, pby) = ((mb_x * 4 + px / 4) as isize, (mb_y * 4 + py / 4) as isize);
2529 let [a, b, c] = self.mv_neighbors_block(pbx, pby, (srw / 4) as isize);
2530 let pmv = predict_mv(a, b, c, refi);
2531 let mvd_x = r.read_se()?;
2532 let mvd_y = r.read_se()?;
2533 let mv = (pmv.0 + mvd_x, pmv.1 + mvd_y);
2534 for by in py / 4..py / 4 + srh / 4 {
2535 for bx in px / 4..px / 4 + srw / 4 {
2536 let idx = (mb_y * 4 + by) * w4 + (mb_x * 4 + bx);
2537 self.mv_y[idx] = mv;
2538 self.inter_y[idx] = true;
2539 self.ref_idx_y[idx] = refi;
2540 self.coded_y[idx] = true;
2541 }
2542 }
2543 let reference = &self.refs[refi as usize];
2544 let mut tmp = [0u8; 256];
2545 mc_luma(&reference.y, self.cw, ch, mb_x * 16 + px, mb_y * 16 + py, srw, srh, mv.0, mv.1, &mut tmp);
2546 for dy in 0..srh {
2547 for dx in 0..srw {
2548 pred_y[(py + dy) * 16 + (px + dx)] = tmp[dy * srw + dx];
2549 }
2550 }
2551 let (crx, cry, crw, crh) = (px / 2, py / 2, srw / 2, srh / 2);
2552 for cc in 0..2 {
2553 let rc = if cc == 0 { &reference.u } else { &reference.v };
2554 let mut tc = [0u8; 64];
2555 mc_chroma(rc, self.ccw, cch, mb_x * 8 + crx, mb_y * 8 + cry, crw, crh, mv.0, mv.1, &mut tc);
2556 for dy in 0..crh {
2557 for dx in 0..crw {
2558 c_pred[cc][(cry + dy) * 8 + (crx + dx)] = tc[dy * crw + dx];
2559 }
2560 }
2561 }
2562 self.weight_partition(
2563 &mut pred_y, &mut c_pred, 0, refi as usize, px, py, srw, srh,
2564 );
2565 }
2566 }
2567
2568 let allow_8x8 = sub_types.iter().all(|&t| t == 0);
2570 self.inter_finish(r, mb_x, mb_y, &pred_y, &c_pred, allow_8x8)
2571 }
2572
2573 fn decode_p_skip(&mut self, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2576 if self.refs.is_empty() {
2580 return Err(MbError::Unsupported("P_Skip without reference"));
2581 }
2582 let mv = self.skip_mv(mb_x, mb_y);
2583 let (ch, cch) = (self.mb_h * 16, self.mb_h * 8);
2584
2585 let mut pred = [0u8; 256];
2586 mc_luma(&self.refs[0].y, self.cw, ch, mb_x * 16, mb_y * 16, 16, 16, mv.0, mv.1, &mut pred);
2587 if let Some(wt) = &self.weights {
2588 for p in pred.iter_mut() {
2589 *p = wt.apply_luma(*p, 0, 0);
2590 }
2591 }
2592 {
2593 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
2594 for dy in 0..16 {
2595 let d = (mb_y * 16 + dy) * self.cw + mb_x * 16;
2596 self.rec_y[d..d + 16].copy_from_slice(&pred[dy * 16..dy * 16 + 16]);
2597 }
2598 }
2599 for c in 0..2 {
2600 let mut pc = [0u8; 64];
2601 let rc = if c == 0 { &self.refs[0].u } else { &self.refs[0].v };
2602 mc_chroma(rc, self.ccw, cch, mb_x * 8, mb_y * 8, 8, 8, mv.0, mv.1, &mut pc);
2603 if let Some(wt) = &self.weights {
2604 for p in pc.iter_mut() {
2605 *p = wt.apply_chroma(*p, 0, 0, c);
2606 }
2607 }
2608 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
2609 for dy in 0..8 {
2610 let d = (mb_y * 8 + dy) * self.ccw + mb_x * 8;
2611 plane[d..d + 8].copy_from_slice(&pc[dy * 8..dy * 8 + 8]);
2612 }
2613 }
2614 {
2615 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::SkipRecon);
2616 self.set_mb_mv(mb_x, mb_y, mv, true, 0);
2617 let w4 = self.mb_w * 4;
2619 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2620 self.coded_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = true;
2621 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
2622 }
2623 }
2624 Ok(())
2625 }
2626
2627 fn predict_i4_mode(&self, bx: usize, by: usize) -> u8 {
2631 if bx == 0 || by == 0 {
2632 return 2;
2633 }
2634 if !self.nbr_in_slice((bx - 1) / 4, by / 4)
2638 || !self.nbr_in_slice(bx / 4, (by - 1) / 4)
2639 || !self.intra_nbr_ok(bx - 1, by)
2640 || !self.intra_nbr_ok(bx, by - 1)
2641 {
2642 return 2;
2643 }
2644 let w4 = self.mb_w * 4;
2645 self.modes_y[by * w4 + (bx - 1)].min(self.modes_y[(by - 1) * w4 + bx])
2646 }
2647
2648 fn gather_i4(
2650 &self,
2651 px: usize,
2652 py: usize,
2653 avail_top: bool,
2654 avail_left: bool,
2655 bx: usize,
2656 by: usize,
2657 ) -> ([u8; 8], [u8; 4], u8) {
2658 let (cw, w4) = (self.cw, self.mb_w * 4);
2659 let mut top = [0u8; 8];
2660 let mut left = [0u8; 4];
2661 let mut corner = 0;
2662 if avail_top {
2663 for i in 0..4 {
2664 top[i] = self.rec_y[(py - 1) * cw + px + i];
2665 }
2666 let tr_avail = bx + 1 < w4
2667 && self.coded_y[(by - 1) * w4 + (bx + 1)]
2668 && self.nbr_in_slice((bx + 1) / 4, (by - 1) / 4)
2669 && self.intra_nbr_ok(bx + 1, by - 1);
2670 for i in 0..4 {
2671 top[4 + i] = if tr_avail {
2672 self.rec_y[(py - 1) * cw + px + 4 + i]
2673 } else {
2674 top[3]
2675 };
2676 }
2677 }
2678 if avail_left {
2679 for i in 0..4 {
2680 left[i] = self.rec_y[(py + i) * cw + px - 1];
2681 }
2682 }
2683 if avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1) {
2686 corner = self.rec_y[(py - 1) * cw + px - 1];
2687 }
2688 (top, left, corner)
2689 }
2690
2691 fn decode_ipcm(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2694 r.align_to_byte()?;
2695 let (lx, ly) = (mb_x * 16, mb_y * 16);
2696 for dy in 0..16 {
2697 for dx in 0..16 {
2698 self.rec_y[(ly + dy) * self.cw + (lx + dx)] = r.read_bits(8)? as u8;
2699 }
2700 }
2701 let (cx, cy) = (mb_x * 8, mb_y * 8);
2702 for plane in [&mut self.rec_u, &mut self.rec_v] {
2703 for dy in 0..8 {
2704 for dx in 0..8 {
2705 plane[(cy + dy) * self.ccw + (cx + dx)] = r.read_bits(8)? as u8;
2706 }
2707 }
2708 }
2709 let (w4, w2) = (self.mb_w * 4, self.mb_w * 2);
2712 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2713 let idx = (mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx);
2714 self.nnz_y[idx] = 16;
2715 self.modes_y[idx] = 2;
2716 self.inter_y[idx] = false;
2717 self.ref_idx_y[idx] = -1;
2718 self.mv_y[idx] = (0, 0);
2719 }
2720 for c in 0..2 {
2721 for by in 0..2 {
2722 for bx in 0..2 {
2723 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = 16;
2724 }
2725 }
2726 }
2727 Ok(())
2728 }
2729
2730 fn decode_i4x4(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2731 let w4 = self.mb_w * 4;
2732
2733 let mut modes = [2u8; 16]; for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
2736 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2737 let predicted = self.predict_i4_mode(bx, by);
2738 let actual = if r.read_bit()? {
2739 predicted
2740 } else {
2741 let rem = r.read_bits(3)? as u8;
2742 if rem < predicted {
2743 rem
2744 } else {
2745 rem + 1
2746 }
2747 };
2748 self.modes_y[by * w4 + bx] = actual;
2749 modes[lby * 4 + lbx] = actual;
2750 }
2751
2752 let chroma_mode = r.read_ue()? as u8;
2753 let cbp = read_cbp_intra(r)?;
2754 let cbp_luma = cbp & 15;
2755 let cbp_chroma = cbp >> 4;
2756 if cbp != 0 {
2757 self.step_qp(r.read_se()?);
2758 }
2759 let qp = self.cur_qp;
2760
2761 let top_mb_avail = mb_y > 0
2765 && self.nbr_in_slice(mb_x, mb_y - 1)
2766 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
2767 let left_mb_avail = mb_x > 0
2768 && self.nbr_in_slice(mb_x - 1, mb_y)
2769 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
2770 self.nnz_cache_load(mb_x, mb_y);
2771 for (blk, &(lbx, lby)) in LUMA_4X4_SCAN_XY.iter().enumerate() {
2772 let (bx, by) = (mb_x * 4 + lbx, mb_y * 4 + lby);
2773 let (px, py) = (bx * 4, by * 4);
2774 let avail_top = lby > 0 || top_mb_avail;
2775 let avail_left = lbx > 0 || left_mb_avail;
2776 let mut qb = [0i32; 16];
2777 let total = if cbp_luma & (1 << (blk / 4)) != 0 {
2778 let nc = self.nc_pred(lbx, lby);
2779 let scan16 = decode_residual_block(r, 16, nc)?;
2780 qb = un_scan_4x4_dcac(&scan16);
2781 scan16.iter().filter(|&&v| v != 0).count() as u8
2782 } else {
2783 0
2784 };
2785 self.nnz_cache_set(lbx, lby, total);
2786 self.nnz_y[by * w4 + bx] = total;
2787 let (top, left, corner) = self.gather_i4(px, py, avail_top, avail_left, bx, by);
2788 let pred = intra4x4_pred(modes[lby * 4 + lbx], avail_top, avail_left, &top, &left, corner);
2789 let mut predb = [0i32; 16];
2790 for i in 0..16 {
2791 predb[i] = pred[i] as i32;
2792 }
2793 let s = reconstruct_4x4(&self.dequant(&qb, qp, 0), &predb);
2794 store(&mut self.rec_y, self.cw, px, py, &s);
2795 self.coded_y[by * w4 + bx] = true;
2796 }
2797
2798 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
2799 }
2800
2801 fn decode_i8x8(&mut self, r: &mut BitReader, mb_x: usize, mb_y: usize) -> Result<(), MbError> {
2805 let w4 = self.mb_w * 4;
2806 self.mb_t8x8[mb_y * self.mb_w + mb_x] = true;
2807
2808 let mut modes8 = [2u8; 4];
2811 for (b8, mode) in modes8.iter_mut().enumerate() {
2812 let (b8x, b8y) = (b8 % 2, b8 / 2);
2813 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2814 let predicted = self.predict_i4_mode(bx, by);
2815 let actual = if r.read_bit()? {
2816 predicted
2817 } else {
2818 let rem = r.read_bits(3)? as u8;
2819 if rem < predicted { rem } else { rem + 1 }
2820 };
2821 *mode = actual;
2822 for sy in 0..2 {
2823 for sx in 0..2 {
2824 self.modes_y[(by + sy) * w4 + (bx + sx)] = actual;
2825 }
2826 }
2827 }
2828
2829 let chroma_mode = r.read_ue()? as u8;
2830 let cbp = read_cbp_intra(r)?;
2831 let cbp_luma = cbp & 15;
2832 let cbp_chroma = cbp >> 4;
2833 if cbp != 0 {
2834 self.step_qp(r.read_se()?);
2835 }
2836 let qp = self.cur_qp;
2837
2838 let top_mb_avail = mb_y > 0
2839 && self.nbr_in_slice(mb_x, mb_y - 1)
2840 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
2841 let left_mb_avail = mb_x > 0
2842 && self.nbr_in_slice(mb_x - 1, mb_y)
2843 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
2844 self.nnz_cache_load(mb_x, mb_y);
2845
2846 for b8 in 0..4 {
2847 let (b8x, b8y) = (b8 % 2, b8 / 2);
2848 let (bx, by) = (mb_x * 4 + b8x * 2, mb_y * 4 + b8y * 2);
2849 let (px, py) = (bx * 4, by * 4);
2850
2851 let mut res8 = [0i32; 64];
2854 if cbp_luma & (1 << b8) != 0 {
2855 let mut scan8 = [0i32; 64];
2856 for sub in 0..4 {
2857 let (sx, sy) = (sub % 2, sub / 2);
2858 let (cx, cy) = (b8x * 2 + sx, b8y * 2 + sy);
2859 let nc = self.nc_pred(cx, cy);
2860 let blk = decode_residual_block(r, 16, nc)?;
2861 let total = blk.iter().filter(|&&v| v != 0).count() as u8;
2862 self.nnz_cache_set(cx, cy, total);
2863 self.nnz_y[(by + sy) * w4 + (bx + sx)] = total;
2864 for k in 0..16 {
2865 scan8[4 * k + sub] = blk[k];
2866 }
2867 }
2868 let raster = un_scan_8x8(&scan8);
2869 res8 = self.inv_quant8(&raster, qp, 0);
2870 } else {
2871 for sub in 0..4 {
2872 let (sx, sy) = (sub % 2, sub / 2);
2873 self.nnz_cache_set(b8x * 2 + sx, b8y * 2 + sy, 0);
2874 self.nnz_y[(by + sy) * w4 + (bx + sx)] = 0;
2875 }
2876 }
2877
2878 let avail_top = b8y > 0 || top_mb_avail;
2879 let avail_left = b8x > 0 || left_mb_avail;
2880 let (top, left, corner, avail_corner) =
2881 self.gather_i8(px, py, avail_top, avail_left, bx, by);
2882 let pred = intra8x8_pred(
2883 modes8[b8], avail_top, avail_left, avail_corner, &top, &left, corner,
2884 );
2885 let mut predb = [0i32; 64];
2886 for i in 0..64 {
2887 predb[i] = pred[i] as i32;
2888 }
2889 let recon = add_residual_8x8(&res8, &predb);
2890 for dy in 0..8 {
2891 for dx in 0..8 {
2892 self.rec_y[(py + dy) * self.cw + (px + dx)] = recon[dy * 8 + dx];
2893 }
2894 }
2895 for sy in 0..2 {
2896 for sx in 0..2 {
2897 self.coded_y[(by + sy) * w4 + (bx + sx)] = true;
2898 }
2899 }
2900 }
2901
2902 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
2903 }
2904
2905 fn inv_quant8(&self, raster: &[i32; 64], qp: u8, list: usize) -> [i32; 64] {
2908 match &self.scaling8 {
2909 Some(s) => inverse_quant_8x8(raster, qp, &s[list]),
2910 None => inverse_quant_8x8(raster, qp, &[16i32; 64]),
2911 }
2912 }
2913
2914 #[allow(clippy::too_many_arguments)]
2918 fn gather_i8(
2919 &self,
2920 px: usize,
2921 py: usize,
2922 avail_top: bool,
2923 avail_left: bool,
2924 bx: usize,
2925 by: usize,
2926 ) -> ([u8; 16], [u8; 8], u8, bool) {
2927 let (cw, w4) = (self.cw, self.mb_w * 4);
2928 let mut top = [0u8; 16];
2929 let mut left = [0u8; 8];
2930 let mut corner = 0;
2931 if avail_top {
2932 for i in 0..8 {
2933 top[i] = self.rec_y[(py - 1) * cw + px + i];
2934 }
2935 let tr_avail = bx + 2 < w4
2936 && self.coded_y[(by - 1) * w4 + (bx + 2)]
2937 && self.nbr_in_slice((bx + 2) / 4, (by - 1) / 4)
2938 && self.intra_nbr_ok(bx + 2, by - 1);
2939 for i in 0..8 {
2940 top[8 + i] = if tr_avail {
2941 self.rec_y[(py - 1) * cw + px + 8 + i]
2942 } else {
2943 top[7]
2944 };
2945 }
2946 }
2947 if avail_left {
2948 for i in 0..8 {
2949 left[i] = self.rec_y[(py + i) * cw + px - 1];
2950 }
2951 }
2952 let avail_corner = avail_top && avail_left && self.intra_nbr_ok(bx - 1, by - 1);
2953 if avail_corner {
2954 corner = self.rec_y[(py - 1) * cw + px - 1];
2955 }
2956 (top, left, corner, avail_corner)
2957 }
2958
2959 fn decode_i16(
2960 &mut self,
2961 r: &mut BitReader,
2962 mb_x: usize,
2963 mb_y: usize,
2964 mt: u32,
2965 ) -> Result<(), MbError> {
2966 let pred_mode = I16Mode::from_id(mt % 4);
2967 let cbp_chroma = (mt % 12) / 4;
2968 let cbp_luma_15 = mt / 12 == 1;
2969 let chroma_mode = r.read_ue()? as u8;
2970 self.step_qp(r.read_se()?);
2971 let qp = self.cur_qp;
2972 let w4 = self.mb_w * 4;
2973
2974 self.nnz_cache_load(mb_x, mb_y);
2976 let nc_dc = self.nc_pred(0, 0);
2977 let dc_scan = decode_residual_block(r, 16, nc_dc)?;
2978 let dc_levels = un_scan_4x4_dcac(&dc_scan);
2979 let recon_dc = self.dequant_luma_dc(&dc_levels, qp, 0);
2980
2981 let mut q_blocks = [[0i32; 16]; 16];
2983 for &(bx, by) in &LUMA_4X4_SCAN_XY {
2984 let total = if cbp_luma_15 {
2985 let nc = self.nc_pred(bx, by);
2986 let ac = decode_residual_block(r, 15, nc)?;
2987 un_scan_4x4_ac_into(&ac, &mut q_blocks[by * 4 + bx]);
2988 ac.iter().filter(|&&v| v != 0).count() as u8
2989 } else {
2990 0
2991 };
2992 self.nnz_cache_set(bx, by, total);
2993 self.nnz_y[(mb_y * 4 + by) * w4 + (mb_x * 4 + bx)] = total;
2994 }
2995
2996 let avail_top = mb_y > 0
2998 && self.nbr_in_slice(mb_x, mb_y - 1)
2999 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3000 let avail_left = mb_x > 0
3001 && self.nbr_in_slice(mb_x - 1, mb_y)
3002 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3003 let (lx, ly) = (mb_x * 16, mb_y * 16);
3004 let mut top = [0u8; 16];
3005 let mut left = [0u8; 16];
3006 if avail_top {
3007 for i in 0..16 {
3008 top[i] = self.rec_y[(ly - 1) * self.cw + lx + i];
3009 }
3010 }
3011 if avail_left {
3012 for i in 0..16 {
3013 left[i] = self.rec_y[(ly + i) * self.cw + lx - 1];
3014 }
3015 }
3016 let corner = if avail_top && avail_left {
3017 self.rec_y[(ly - 1) * self.cw + lx - 1]
3018 } else {
3019 0
3020 };
3021 let pred_l = luma16x16_pred(pred_mode, avail_top, avail_left, &top, &left, corner);
3022 for by in 0..4 {
3023 for bx in 0..4 {
3024 let mut deq = self.dequant(&q_blocks[by * 4 + bx], qp, 0);
3025 deq[0] = recon_dc[by * 4 + bx];
3026 let mut predb = [0i32; 16];
3027 for dy in 0..4 {
3028 for dx in 0..4 {
3029 predb[dy * 4 + dx] = pred_l[(by * 4 + dy) * 16 + (bx * 4 + dx)] as i32;
3030 }
3031 }
3032 let s = reconstruct_4x4(&deq, &predb);
3033 store(&mut self.rec_y, self.cw, lx + bx * 4, ly + by * 4, &s);
3034 }
3035 }
3036 for &(lbx, lby) in &LUMA_4X4_SCAN_XY {
3038 self.modes_y[(mb_y * 4 + lby) * w4 + (mb_x * 4 + lbx)] = 2;
3039 }
3040
3041 self.decode_chroma(r, mb_x, mb_y, cbp_chroma, chroma_mode)
3042 }
3043
3044 fn decode_chroma(
3046 &mut self,
3047 r: &mut BitReader,
3048 mb_x: usize,
3049 mb_y: usize,
3050 cbp_chroma: u32,
3051 chroma_mode: u8,
3052 ) -> Result<(), MbError> {
3053 let qpc = self.chroma_qp_for(self.cur_qp);
3054 let (cx, cy) = (mb_x * 8, mb_y * 8);
3055 let avail_top = mb_y > 0
3056 && self.nbr_in_slice(mb_x, mb_y - 1)
3057 && self.intra_nbr_ok(mb_x * 4, mb_y * 4 - 1);
3058 let avail_left = mb_x > 0
3059 && self.nbr_in_slice(mb_x - 1, mb_y)
3060 && self.intra_nbr_ok(mb_x * 4 - 1, mb_y * 4);
3061
3062 let mut c_recon_dc = [[0i32; 4]; 2];
3063 if cbp_chroma != 0 {
3064 for (c, slot) in c_recon_dc.iter_mut().enumerate() {
3065 let dc = decode_residual_block(r, 4, -1)?;
3066 *slot = self.dequant_chroma_dc(&[dc[0], dc[1], dc[2], dc[3]], qpc, 1 + c);
3067 }
3068 }
3069 let mut c_q_blocks = [[[0i32; 16]; 4]; 2];
3070 if cbp_chroma == 2 {
3071 self.chroma_cache_load(mb_x, mb_y);
3072 let w2 = self.mb_w * 2;
3073 for c in 0..2 {
3074 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3075 let nc = self.chroma_nc_pred(c, bx, by);
3076 let ac = decode_residual_block(r, 15, nc)?;
3077 let total = ac.iter().filter(|&&v| v != 0).count() as u8;
3078 self.chroma_nnz_cache_set(c, bx, by, total);
3079 self.nnz_c[c][(mb_y * 2 + by) * w2 + (mb_x * 2 + bx)] = total;
3080 un_scan_4x4_ac_into(&ac, &mut c_q_blocks[c][by * 2 + bx]);
3081 }
3082 }
3083 }
3084 for c in 0..2 {
3085 let mut ctop = [0u8; 8];
3086 let mut cleft = [0u8; 8];
3087 let mut ccorner = 0u8;
3088 {
3089 let rec_c = if c == 0 { &self.rec_u } else { &self.rec_v };
3090 if avail_top {
3091 for i in 0..8 {
3092 ctop[i] = rec_c[(cy - 1) * self.ccw + cx + i];
3093 }
3094 }
3095 if avail_left {
3096 for i in 0..8 {
3097 cleft[i] = rec_c[(cy + i) * self.ccw + cx - 1];
3098 }
3099 }
3100 if avail_top && avail_left {
3101 ccorner = rec_c[(cy - 1) * self.ccw + cx - 1];
3102 }
3103 }
3104 let pred8 = chroma8x8_pred(chroma_mode, avail_top, avail_left, &ctop, &cleft, ccorner);
3105 for &(bx, by) in &CHROMA_4X4_SCAN_XY {
3106 let mut predb = [0i32; 16];
3107 for dy in 0..4 {
3108 for dx in 0..4 {
3109 predb[dy * 4 + dx] = pred8[(by * 4 + dy) * 8 + (bx * 4 + dx)] as i32;
3110 }
3111 }
3112 let mut deq = self.dequant(&c_q_blocks[c][by * 2 + bx], qpc, 1 + c);
3113 deq[0] = c_recon_dc[c][by * 2 + bx];
3114 let s = reconstruct_4x4(&deq, &predb);
3115 let plane = if c == 0 { &mut self.rec_u } else { &mut self.rec_v };
3116 store(plane, self.ccw, cx + bx * 4, cy + by * 4, &s);
3117 }
3118 }
3119 Ok(())
3120 }
3121
3122 pub fn deblock(&mut self, offset_a: i32, offset_b: i32) {
3126 let nnz_db_storage;
3133 let nnz_db: &[u8] = if self.mb_t8x8.iter().any(|&t| t) {
3134 let mut n = self.nnz_y.clone();
3135 let w4 = self.mb_w * 4;
3136 for mb_y in 0..self.mb_h {
3137 for mb_x in 0..self.mb_w {
3138 if !self.mb_t8x8[mb_y * self.mb_w + mb_x] {
3139 continue;
3140 }
3141 for b8 in 0..4 {
3142 let (bx, by) = (mb_x * 4 + (b8 % 2) * 2, mb_y * 4 + (b8 / 2) * 2);
3143 let any = (0..2).any(|sy| (0..2).any(|sx| self.nnz_y[(by + sy) * w4 + (bx + sx)] > 0));
3144 for sy in 0..2 {
3145 for sx in 0..2 {
3146 n[(by + sy) * w4 + (bx + sx)] = u8::from(any);
3147 }
3148 }
3149 }
3150 }
3151 }
3152 nnz_db_storage = n;
3153 &nnz_db_storage
3154 } else {
3155 &self.nnz_y
3156 };
3157 let ref_id: Vec<i32> = self
3160 .ref_idx_y
3161 .iter()
3162 .map(|&r| if r >= 0 { self.refs.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3163 .collect();
3164 let ref_id1: Vec<i32> = if self.refs1.is_empty() {
3167 Vec::new()
3168 } else {
3169 self.ref_idx1
3170 .iter()
3171 .map(|&r| if r >= 0 { self.refs1.get(r as usize).map_or(i32::MIN, |f| f.poc) } else { i32::MIN })
3172 .collect()
3173 };
3174 let info = rusty_h264_common::deblock::BlockInfo {
3175 inter: &self.inter_y,
3176 nnz: nnz_db,
3177 mv: &self.mv_y,
3178 ref_id: &ref_id,
3179 mv1: &self.mv1,
3180 ref_id1: &ref_id1,
3181 w4: self.mb_w * 4,
3182 t8x8: &self.mb_t8x8,
3183 bs: &[],
3184 };
3185 rusty_h264_common::deblock::filter_frame(
3186 &mut self.rec_y,
3187 &mut self.rec_u,
3188 &mut self.rec_v,
3189 self.mb_w,
3190 self.mb_h,
3191 &self.mb_qp,
3192 self.chroma_qp_offset,
3193 offset_a,
3194 offset_b,
3195 &info,
3196 );
3197 }
3198
3199 pub fn into_frame(self, crop_r: usize, crop_b: usize) -> YuvFrame {
3201 if crop_r == 0 && crop_b == 0 {
3204 return YuvFrame {
3205 width: self.cw,
3206 height: self.ch,
3207 y: self.rec_y,
3208 u: self.rec_u,
3209 v: self.rec_v,
3210 };
3211 }
3212 let dw = self.cw - 2 * crop_r;
3213 let dh = self.ch - 2 * crop_b;
3214 let mut y = vec![0u8; dw * dh];
3215 for row in 0..dh {
3216 y[row * dw..row * dw + dw].copy_from_slice(&self.rec_y[row * self.cw..row * self.cw + dw]);
3217 }
3218 let (cdw, cdh) = (dw / 2, dh / 2);
3219 let mut u = vec![0u8; cdw * cdh];
3220 let mut v = vec![0u8; cdw * cdh];
3221 for row in 0..cdh {
3222 u[row * cdw..row * cdw + cdw]
3223 .copy_from_slice(&self.rec_u[row * self.ccw..row * self.ccw + cdw]);
3224 v[row * cdw..row * cdw + cdw]
3225 .copy_from_slice(&self.rec_v[row * self.ccw..row * self.ccw + cdw]);
3226 }
3227 let _ = self.cch;
3228 YuvFrame {
3229 width: dw,
3230 height: dh,
3231 y,
3232 u,
3233 v,
3234 }
3235 }
3236}
3237
3238fn cabac_unary(cab: &mut crate::cabac::Cabac, ctx: usize, off: usize) -> u32 {
3245 if cab.decode_decision(ctx) == 0 {
3246 return 0;
3247 }
3248 let mut sym = 0;
3249 loop {
3250 let bin = cab.decode_decision(ctx + off);
3251 sym += 1;
3252 if bin == 0 || sym >= 512 {
3257 break;
3258 }
3259 }
3260 sym
3261}
3262
3263fn cabac_exp_bypass(cab: &mut crate::cabac::Cabac, mut count: i32) -> u32 {
3265 let mut sym = 0u32;
3266 loop {
3267 let c = cab.decode_bypass();
3268 if c == 1 {
3269 sym += 1 << count;
3270 count += 1;
3271 }
3272 if c == 0 || count == 16 {
3273 break;
3274 }
3275 }
3276 let mut sym2 = 0u32;
3277 while count > 0 {
3278 count -= 1;
3279 if cab.decode_bypass() != 0 {
3280 sym2 |= 1 << count;
3281 }
3282 }
3283 sym + sym2
3284}
3285
3286fn cabac_ueg_level(cab: &mut crate::cabac::Cabac, ctx: usize) -> u32 {
3289 if cab.decode_decision(ctx) == 0 {
3290 return 0;
3291 }
3292 let mut code = 0u32;
3293 let mut count = 1;
3294 let mut tmp;
3295 loop {
3296 tmp = cab.decode_decision(ctx);
3297 code += 1;
3298 count += 1;
3299 if tmp == 0 || count == 13 {
3300 break;
3301 }
3302 }
3303 if tmp != 0 {
3304 code += cabac_exp_bypass(cab, 0) + 1;
3305 }
3306 code
3307}
3308
3309fn parse_mb_qp_delta_cabac(cab: &mut crate::cabac::Cabac, last_delta_qp: &mut i32) -> i32 {
3311 const O: usize = 60;
3312 let ctx_inc = (*last_delta_qp != 0) as usize;
3313 let mut qp_delta = 0;
3314 if cab.decode_decision(O + ctx_inc) != 0 {
3315 let code = cabac_unary(cab, O + 2, 1) + 1;
3316 qp_delta = ((code + 1) >> 1) as i32;
3317 if code & 1 == 0 {
3318 qp_delta = -qp_delta;
3319 }
3320 }
3321 *last_delta_qp = qp_delta;
3322 qp_delta
3323}
3324
3325const NZC_CACHE: [usize; 24] = [
3328 9, 10, 17, 18, 11, 12, 19, 20, 25, 26, 33, 34, 27, 28, 35, 36, 14, 15, 22, 23, 38, 39, 46, 47, ];
3332
3333const RES_MAXPOS: [i32; 11] = [0, 15, 14, 15, 3, 14, 63, 3, 3, 14, 14];
3335const RES_MAXC2: [i32; 11] = [0, 4, 4, 4, 3, 4, 4, 3, 3, 4, 4];
3336const RES_CBF: [usize; 11] = [0, 0, 4, 8, 12, 16, 0, 12, 12, 16, 16];
3337const RES_MAP: [usize; 11] = [0, 0, 15, 29, 44, 47, 0, 44, 44, 47, 47];
3338const RES_ONE: [usize; 11] = [0, 0, 10, 20, 30, 39, 0, 30, 30, 39, 39];
3339const RP_I16_DC: usize = 1;
3341const RP_I16_AC: usize = 2;
3342const RP_LUMA_4X4: usize = 3;
3343const RP_CHROMA_DC: usize = 7; const RP_CHROMA_AC: usize = 9; #[allow(clippy::too_many_arguments)]
3351fn parse_residual_cabac(
3352 cab: &mut crate::cabac::Cabac,
3353 nzc: &mut [u8; 48],
3354 cbf_dc: &mut u16,
3355 iz: usize,
3356 rp: usize,
3357 is_intra: bool,
3358 ndc: (Option<u16>, Option<u16>), out: &mut [i32], ) -> u32 {
3361 let is_dc = rp == RP_I16_DC || rp == RP_CHROMA_DC || rp == RP_CHROMA_DC + 1;
3363 let (mut na, mut nb) = (is_intra as u8, is_intra as u8);
3364 let scan = NZC_CACHE[iz.min(23)];
3365 if is_dc {
3366 if let Some(t) = ndc.0 {
3367 nb = ((t >> rp) & 1) as u8;
3368 }
3369 if let Some(l) = ndc.1 {
3370 na = ((l >> rp) & 1) as u8;
3371 }
3372 } else {
3373 if nzc[scan - 8] != 0xff {
3374 nb = (nzc[scan - 8] != 0) as u8;
3375 }
3376 if nzc[scan - 1] != 0xff {
3377 na = (nzc[scan - 1] != 0) as u8;
3378 }
3379 }
3380 let cbf = cab.decode_decision(85 + RES_CBF[rp] + (na + (nb << 1)) as usize);
3381 if cbf == 0 {
3382 if !is_dc {
3383 nzc[scan] = 0;
3384 }
3385 return 0;
3386 }
3387 if is_dc {
3388 *cbf_dc |= 1 << rp;
3389 }
3390 let maxpos = RES_MAXPOS[rp] as usize;
3392 let map = 105 + RES_MAP[rp];
3393 let last = 166 + RES_MAP[rp];
3394 let mut sig = [0i32; 64];
3395 let mut coeff_num = 0u32;
3396 let mut last_hit = false;
3397 for i in 0..maxpos {
3398 if cab.decode_decision(map + i) != 0 {
3399 sig[i] = 1;
3400 coeff_num += 1;
3401 if cab.decode_decision(last + i) != 0 {
3402 last_hit = true;
3403 break;
3404 }
3405 }
3406 }
3407 if !last_hit {
3408 sig[maxpos] = 1;
3409 coeff_num += 1;
3410 }
3411 let one = 227 + RES_ONE[rp];
3413 let abs = 232 + RES_ONE[rp];
3414 let maxc2 = RES_MAXC2[rp];
3415 let (mut c1, mut c2) = (1i32, 0i32);
3416 for i in (0..=maxpos).rev() {
3417 if sig[i] != 0 {
3418 let mut level = sig[i] + cab.decode_decision(one + c1 as usize) as i32;
3419 if level == 2 {
3420 level += cabac_ueg_level(cab, abs + c2 as usize) as i32;
3421 c2 = (c2 + 1).min(maxc2);
3422 c1 = 0;
3423 } else if c1 != 0 {
3424 c1 = (c1 + 1).min(4);
3425 }
3426 if cab.decode_bypass() != 0 {
3427 level = -level;
3428 }
3429 sig[i] = level;
3430 }
3431 }
3432 out[..=maxpos].copy_from_slice(&sig[..=maxpos]);
3433 if !is_dc {
3434 nzc[scan] = coeff_num as u8;
3435 }
3436 coeff_num
3437}
3438
3439const CACHE30: [usize; 16] = [7, 8, 13, 14, 9, 10, 15, 16, 19, 20, 25, 26, 21, 22, 27, 28];
3442
3443const G_SCAN4: [usize; 16] = [0, 1, 4, 5, 2, 3, 6, 7, 8, 9, 12, 13, 10, 11, 14, 15];
3446
3447fn parse_sub_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3449 const S: usize = 21;
3450 if cab.decode_decision(S) != 0 {
3451 return 0;
3452 }
3453 if cab.decode_decision(S + 1) != 0 {
3454 3 - cab.decode_decision(S + 2)
3455 } else {
3456 1
3457 }
3458}
3459
3460fn parse_intra_mb_type_cabac(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3463 if cab.decode_decision(base) == 0 {
3464 return 0; }
3466 if cab.decode_terminate() {
3467 return 25; }
3469 let mut t = 1 + 12 * cab.decode_decision(base + 1) as u32; if cab.decode_decision(base + 2) != 0 {
3471 t += 4 + 4 * cab.decode_decision(base + 2) as u32;
3472 }
3473 t += 2 * cab.decode_decision(base + 3) as u32;
3474 t += cab.decode_decision(base + 3) as u32;
3475 t
3476}
3477
3478fn parse_mb_type_b_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3482 const B: usize = 27;
3483 if cab.decode_decision(B + ctx_inc) == 0 {
3484 return 0; }
3486 if cab.decode_decision(B + 3) == 0 {
3487 return 1 + cab.decode_decision(B + 5) as u32; }
3489 let mut m = (cab.decode_decision(B + 4) as u32) << 3;
3490 m |= (cab.decode_decision(B + 5) as u32) << 2;
3491 m |= (cab.decode_decision(B + 5) as u32) << 1;
3492 m |= cab.decode_decision(B + 5) as u32;
3493 if m < 8 {
3494 return m + 3;
3495 }
3496 if m == 13 {
3497 return parse_intra_mb_type_cabac(cab, 32) + 23;
3498 }
3499 if m == 14 {
3500 return 11; }
3502 if m == 15 {
3503 return 22; }
3505 m = (m << 1) | cab.decode_decision(B + 5) as u32;
3506 m - 4
3507}
3508
3509fn parse_sub_mb_type_b_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3512 const B: usize = 36;
3513 if cab.decode_decision(B) == 0 {
3514 return 0; }
3516 if cab.decode_decision(B + 1) == 0 {
3517 return 1 + cab.decode_decision(B + 3) as u32; }
3519 let mut st = 3u32;
3520 if cab.decode_decision(B + 2) != 0 {
3521 if cab.decode_decision(B + 3) != 0 {
3522 return 11 + cab.decode_decision(B + 3) as u32; }
3524 st += 4;
3525 }
3526 st += 2 * cab.decode_decision(B + 3) as u32;
3527 st += cab.decode_decision(B + 3) as u32;
3528 st
3529}
3530
3531fn parse_mvd_partition(
3535 cab: &mut crate::cabac::Cabac,
3536 part_idx: usize,
3537 zblocks: &[usize],
3538 mvdc: &mut [[i16; 2]; 30],
3539 refc: &mut [i8; 30],
3540 mmvd: &mut [[i16; 2]; 16],
3541 mref: &mut [i8; 16],
3542 ref_idx: i8,
3543) -> (i32, i32) {
3544 let s = CACHE30[part_idx];
3545 let ctx = |comp: usize| -> usize {
3546 let mut a = 0i32;
3547 if refc[s - 6] >= 0 {
3548 a += mvdc[s - 6][comp].unsigned_abs() as i32;
3549 }
3550 if refc[s - 1] >= 0 {
3551 a += mvdc[s - 1][comp].unsigned_abs() as i32;
3552 }
3553 if a >= 3 {
3554 1 + (a > 32) as usize
3555 } else {
3556 0
3557 }
3558 };
3559 let (cx, cy) = (ctx(0), ctx(1));
3560 let mvx = parse_mvd_cabac(cab, 0, cx);
3561 let mvy = parse_mvd_cabac(cab, 1, cy);
3562 for &zb in zblocks {
3563 mvdc[CACHE30[zb]] = [mvx, mvy];
3564 refc[CACHE30[zb]] = ref_idx;
3565 mmvd[G_SCAN4[zb]] = [mvx, mvy];
3566 mref[G_SCAN4[zb]] = ref_idx;
3567 }
3568 (mvx as i32, mvy as i32)
3569}
3570
3571fn parse_ref_idx_cabac(cab: &mut crate::cabac::Cabac, ctx0: usize) -> i8 {
3574 const B: usize = 54;
3575 let mut r = 0i8;
3576 let mut bin_idx = 0u32;
3577 while bin_idx < 32 {
3581 let ctx = match bin_idx {
3582 0 => ctx0,
3583 1 => 4,
3584 _ => 5,
3585 };
3586 if cab.decode_decision(B + ctx) == 0 {
3587 break;
3588 }
3589 r += 1;
3590 bin_idx += 1;
3591 }
3592 r
3593}
3594
3595fn decode_ueg_mv(cab: &mut crate::cabac::Cabac, base: usize) -> u32 {
3598 const P2C: [usize; 8] = [0, 1, 2, 3, 3, 3, 3, 3];
3599 if cab.decode_decision(base) == 0 {
3600 return 0;
3601 }
3602 let mut code = 0u32;
3603 let mut count = 1usize;
3604 let mut tmp;
3605 loop {
3606 tmp = cab.decode_decision(base + P2C[count]);
3607 code += 1;
3608 count += 1;
3609 if tmp == 0 || count == 8 {
3610 break;
3611 }
3612 }
3613 if tmp != 0 {
3614 code += cabac_exp_bypass(cab, 3) + 1;
3615 }
3616 code
3617}
3618
3619fn parse_mvd_cabac(cab: &mut crate::cabac::Cabac, comp: usize, ctx_inc: usize) -> i16 {
3622 let base = 40 + comp * 7; if cab.decode_decision(base + ctx_inc) == 0 {
3624 return 0;
3625 }
3626 let mag = (decode_ueg_mv(cab, base + 3) + 1) as i16;
3627 if cab.decode_bypass() != 0 {
3628 -mag
3629 } else {
3630 mag
3631 }
3632}
3633
3634fn parse_mb_skip_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> bool {
3637 cab.decode_decision(ctx_inc) != 0
3638}
3639
3640fn parse_mb_type_p_cabac(cab: &mut crate::cabac::Cabac) -> u32 {
3643 const S: usize = 11; if cab.decode_decision(S + 3) == 0 {
3645 return if cab.decode_decision(S + 4) != 0 {
3647 if cab.decode_decision(S + 6) != 0 { 1 } else { 2 }
3648 } else if cab.decode_decision(S + 5) != 0 {
3649 3
3650 } else {
3651 0
3652 };
3653 }
3654 if cab.decode_decision(S + 6) == 0 {
3656 return 5; }
3658 if cab.decode_terminate() {
3659 return 30; }
3661 let mut t = 6 + cab.decode_decision(S + 7) * 12;
3662 if cab.decode_decision(S + 8) != 0 {
3663 t += 4;
3664 if cab.decode_decision(S + 8) != 0 {
3665 t += 4;
3666 }
3667 }
3668 t += cab.decode_decision(S + 9) << 1;
3669 t += cab.decode_decision(S + 9);
3670 t
3671}
3672
3673fn parse_mb_type_i_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3678 const O: usize = 3; if cab.decode_decision(O + ctx_inc) == 0 {
3680 return 0; }
3682 if cab.decode_terminate() {
3683 return 25; }
3685 let mut t = 1 + cab.decode_decision(O + 3) * 12; if cab.decode_decision(O + 4) != 0 {
3687 t += 4; if cab.decode_decision(O + 5) != 0 {
3689 t += 4;
3690 }
3691 }
3692 t += cab.decode_decision(O + 6) << 1; t += cab.decode_decision(O + 7);
3694 t
3695}
3696
3697fn parse_intra4x4_pred_mode_cabac(cab: &mut crate::cabac::Cabac) -> i32 {
3701 const IPR: usize = 68;
3702 if cab.decode_decision(IPR) == 1 {
3703 return -1; }
3705 let mut m = cab.decode_decision(IPR + 1) as i32;
3706 m |= (cab.decode_decision(IPR + 1) as i32) << 1;
3707 m |= (cab.decode_decision(IPR + 1) as i32) << 2;
3708 m
3709}
3710
3711fn parse_intra_chroma_pred_mode_cabac(cab: &mut crate::cabac::Cabac, ctx_inc: usize) -> u32 {
3715 const CIPR: usize = 64;
3716 if cab.decode_decision(CIPR + ctx_inc) == 0 {
3717 return 0;
3718 }
3719 if cab.decode_decision(CIPR + 3) == 0 {
3720 return 1;
3721 }
3722 if cab.decode_decision(CIPR + 3) == 0 {
3723 return 2;
3724 }
3725 3
3726}
3727
3728fn parse_cbp_cabac(cab: &mut crate::cabac::Cabac, top: Option<u8>, left: Option<u8>) -> u32 {
3733 const CBP: usize = 73;
3734 let t = |m: u32| top.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
3735 let l = |m: u32| left.map_or(0u32, |c| ((c as u32 & m) == 0) as u32);
3736 let nb = |x: u32| (x == 0) as u32; let b0 = cab.decode_decision(CBP + (l(1 << 1) + (t(1 << 2) << 1)) as usize);
3739 let b1 = cab.decode_decision(CBP + (nb(b0) + (t(1 << 3) << 1)) as usize);
3740 let b2 = cab.decode_decision(CBP + (l(1 << 3) + (nb(b0) << 1)) as usize);
3741 let b3 = cab.decode_decision(CBP + (nb(b2) + (nb(b1) << 1)) as usize);
3742 let mut cbp = b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
3743 let ct = top.map_or(0u32, |c| ((c >> 4) != 0) as u32);
3745 let cl = left.map_or(0u32, |c| ((c >> 4) != 0) as u32);
3746 if cab.decode_decision(CBP + 4 + (cl + (ct << 1)) as usize) != 0 {
3747 let ct2 = top.map_or(0u32, |c| ((c >> 4) == 2) as u32);
3748 let cl2 = left.map_or(0u32, |c| ((c >> 4) == 2) as u32);
3749 let c1 = cab.decode_decision(CBP + 8 + (cl2 + (ct2 << 1)) as usize);
3750 cbp |= 1 << (4 + c1);
3751 }
3752 cbp
3753}
3754
3755fn read_ref_idx(r: &mut BitReader, num_ref_active: usize) -> Result<i32, OutOfData> {
3756 if num_ref_active == 2 {
3757 Ok(if r.read_bit()? { 0 } else { 1 }) } else {
3759 Ok(r.read_ue()? as i32)
3760 }
3761}
3762
3763#[derive(Clone, Copy, PartialEq)]
3765enum BPred {
3766 L0,
3767 L1,
3768 Bi,
3769}
3770impl BPred {
3771 fn uses(self, list: usize) -> bool {
3773 matches!(
3774 (self, list),
3775 (BPred::L0, 0) | (BPred::L1, 1) | (BPred::Bi, 0) | (BPred::Bi, 1)
3776 )
3777 }
3778}
3779
3780const B16X16: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 16)];
3781const B16X8: &[(usize, usize, usize, usize)] = &[(0, 0, 16, 8), (0, 8, 16, 8)];
3782const B8X16: &[(usize, usize, usize, usize)] = &[(0, 0, 8, 16), (8, 0, 8, 16)];
3783
3784type Region = (usize, usize, usize, usize);
3786
3787fn b_inter_layout(mb_type: u32) -> (&'static [Region], u8, [BPred; 2]) {
3790 use BPred::*;
3791 match mb_type {
3792 1 => (B16X16, 0, [L0, L0]),
3793 2 => (B16X16, 0, [L1, L1]),
3794 3 => (B16X16, 0, [Bi, Bi]),
3795 4 => (B16X8, 1, [L0, L0]),
3796 5 => (B8X16, 2, [L0, L0]),
3797 6 => (B16X8, 1, [L1, L1]),
3798 7 => (B8X16, 2, [L1, L1]),
3799 8 => (B16X8, 1, [L0, L1]),
3800 9 => (B8X16, 2, [L0, L1]),
3801 10 => (B16X8, 1, [L1, L0]),
3802 11 => (B8X16, 2, [L1, L0]),
3803 12 => (B16X8, 1, [L0, Bi]),
3804 13 => (B8X16, 2, [L0, Bi]),
3805 14 => (B16X8, 1, [L1, Bi]),
3806 15 => (B8X16, 2, [L1, Bi]),
3807 16 => (B16X8, 1, [Bi, L0]),
3808 17 => (B8X16, 2, [Bi, L0]),
3809 18 => (B16X8, 1, [Bi, L1]),
3810 19 => (B8X16, 2, [Bi, L1]),
3811 20 => (B16X8, 1, [Bi, Bi]),
3812 _ => (B8X16, 2, [Bi, Bi]), }
3814}
3815
3816fn b_sub_uses(st: u32, list: usize) -> bool {
3818 let pred = match st {
3819 1 | 4 | 5 | 10 => 0, 2 | 6 | 7 | 11 => 1, _ => 2, };
3823 (list == 0 && pred != 1) || (list == 1 && pred != 0)
3824}
3825
3826fn b_sub_parts(st: u32) -> &'static [(usize, usize, usize, usize)] {
3828 match st {
3829 1..=3 => &[(0, 0, 8, 8)],
3830 4 | 6 | 8 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
3831 5 | 7 | 9 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
3832 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)], }
3834}
3835
3836fn sub_mb_partitions(sub_type: u32) -> &'static [(usize, usize, usize, usize)] {
3839 match sub_type {
3840 0 => &[(0, 0, 8, 8)],
3841 1 => &[(0, 0, 8, 4), (0, 4, 8, 4)],
3842 2 => &[(0, 0, 4, 8), (4, 0, 4, 8)],
3843 _ => &[(0, 0, 4, 4), (4, 0, 4, 4), (0, 4, 4, 4), (4, 4, 4, 4)],
3844 }
3845}
3846
3847fn store(plane: &mut [u8], stride: usize, x0: usize, y0: usize, s: &[u8; 16]) {
3848 let _g = rusty_h264_common::prof::scope(rusty_h264_common::prof::Stage::Scatter);
3849 for dy in 0..4 {
3850 for dx in 0..4 {
3851 plane[(y0 + dy) * stride + (x0 + dx)] = s[dy * 4 + dx];
3852 }
3853 }
3854}
3855
3856fn un_scan_8x8(scan: &[i32; 64]) -> [i32; 64] {
3858 const ZZ8: [usize; 64] = [
3859 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,
3860 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
3861 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63,
3862 ];
3863 let mut out = [0i32; 64];
3864 for k in 0..64 {
3865 out[ZZ8[k]] = scan[k];
3866 }
3867 out
3868}
3869
3870#[cfg(test)]
3871mod tests {
3872 use super::*;
3873
3874 fn fd(qp: u8, offset: i32) -> FrameDecoder {
3875 FrameDecoder::new(1, 1, qp, offset, Vec::new(), 1, false, false, true)
3876 }
3877
3878 #[test]
3879 fn mb_qp_delta_accumulates_mod_52() {
3880 let mut d = fd(26, 0);
3881 assert_eq!(d.cur_qp, 26, "QPy starts at the slice QP");
3882 d.step_qp(4);
3883 assert_eq!(d.cur_qp, 30); d.step_qp(-10);
3885 assert_eq!(d.cur_qp, 20); d.step_qp(40);
3888 assert_eq!(d.cur_qp, 8);
3889 d.step_qp(-20);
3891 assert_eq!(d.cur_qp, 40);
3892 }
3893
3894 #[test]
3895 fn chroma_qp_index_offset_applied_and_clamped() {
3896 assert_eq!(fd(0, 0).chroma_qp_for(30), 29);
3898 assert_eq!(fd(0, 2).chroma_qp_for(30), 31);
3900 assert_eq!(fd(0, -12).chroma_qp_for(5), chroma_qp(0));
3902 assert_eq!(fd(0, 99).chroma_qp_for(40), chroma_qp(51));
3903 }
3904}