1pub use crate::nal::slice::cavlc::{CavlcContext, CavlcError};
11use crate::nal::slice::macroblock::{
12 coded_block_pattern_from_me, i_mb_type_info, p_mb_type_info, p_sub_mb_type_info, IMbTypeInfo,
13 MbPartPredMode, MbTypeError, PMbTypeInfo, SubMbTypeInfo,
14};
15use crate::nal::slice::{cavlc, SliceFamily};
16use crate::rbsp::{BitRead, BitReaderError};
17use std::convert::TryFrom;
18use std::fmt;
19
20#[derive(Debug)]
21pub enum SliceDataError {
22 BitReaderError(BitReaderError),
23 InvalidMbType(MbTypeError),
24 InvalidSubMbType(MbTypeError),
25 InvalidCodedBlockPattern(u32),
26 InvalidParameter { field: &'static str, value: i64 },
27}
28
29impl fmt::Display for SliceDataError {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 match self {
32 SliceDataError::BitReaderError(e) => write!(f, "bitstream I/O: {e:?}"),
33 SliceDataError::InvalidMbType(e) => write!(f, "{e}"),
34 SliceDataError::InvalidSubMbType(e) => write!(f, "{e}"),
35 SliceDataError::InvalidCodedBlockPattern(v) => {
36 write!(f, "invalid coded_block_pattern code_num {v}")
37 }
38 SliceDataError::InvalidParameter { field, value } => {
39 write!(f, "{field} out of range: {value}")
40 }
41 }
42 }
43}
44
45impl std::error::Error for SliceDataError {}
46
47impl From<BitReaderError> for SliceDataError {
48 fn from(e: BitReaderError) -> Self {
49 SliceDataError::BitReaderError(e)
50 }
51}
52
53impl From<MbTypeError> for SliceDataError {
54 fn from(e: MbTypeError) -> Self {
55 match e {
56 MbTypeError::InvalidPSubMbType(_) => SliceDataError::InvalidSubMbType(e),
57 _ => SliceDataError::InvalidMbType(e),
58 }
59 }
60}
61
62#[derive(Debug)]
63pub struct InterPrediction {
64 pub num_parts: u8,
65 pub part_width: u8,
66 pub part_height: u8,
67 pub ref_idx_l0: [i8; 4],
68 pub mvd_l0: [[[i16; 2]; 4]; 4],
69 pub sub_mb_info: Option<SubMbInfo>,
70}
71
72#[derive(Debug)]
73pub struct SubMbInfo {
74 pub sub_mb_type: [u8; 4],
75 pub info: [SubMbTypeInfo; 4],
76 pub ref_idx_l0: [i8; 4],
77}
78
79#[derive(Debug)]
80pub enum MbPrediction {
81 Intra4x4 {
82 prev_intra4x4_pred_mode_flag: [bool; 16],
83 rem_intra4x4_pred_mode: [u8; 16],
84 intra_chroma_pred_mode: u8,
85 },
86 Intra16x16 {
87 intra_chroma_pred_mode: u8,
88 },
89 IntraPCM {
90 pcm_sample_luma: [u8; 256],
91 pcm_sample_chroma: [u8; 128],
92 },
93 Inter(InterPrediction),
94}
95
96#[derive(Debug)]
97pub enum MbTypeInfo {
98 I(IMbTypeInfo),
99 P(PMbTypeInfo),
100}
101
102#[derive(Debug)]
103pub struct MacroblockHeader {
104 pub mb_addr: u32,
105 pub mb_type: MbTypeInfo,
106 pub coded_block_pattern_luma: u8,
107 pub coded_block_pattern_chroma: u8,
108 pub mb_qp_delta: i32,
109 pub mb_pred: MbPrediction,
110}
111
112pub enum SliceEvent<'a, R: BitRead> {
113 End,
114 Skip {
115 mb_addr: u32,
116 next: SliceDataReader<'a, R>,
117 },
118 Macroblock(MacroblockResidual<'a, R>),
119}
120
121struct SliceDataCore<'a, R: BitRead> {
122 reader: &'a mut R,
123 slice_family: SliceFamily,
124 curr_mb_addr: u32,
125 pic_size_in_mbs: u32,
126 num_ref_idx_l0_active_minus1: u32,
127 pending_skips: u32,
128 after_skip_run: bool,
129 done: bool,
130}
131
132impl<R: BitRead> SliceDataCore<'_, R> {
133 fn next_mb_address(&self, addr: u32) -> u32 {
134 addr + 1
135 }
136
137 fn parse_macroblock_header(
138 &mut self,
139 mb_addr: u32,
140 ) -> Result<MacroblockHeader, SliceDataError> {
141 let raw_mb_type = self.reader.read_ue("mb_type")?;
142 log::trace!(
143 "MB {}: raw_mb_type={}, slice_family={:?}",
144 mb_addr,
145 raw_mb_type,
146 self.slice_family
147 );
148
149 match self.slice_family {
150 SliceFamily::I | SliceFamily::SI => {
151 let info = i_mb_type_info(raw_mb_type)?;
152 self.parse_i_macroblock(mb_addr, info)
153 }
154 SliceFamily::P | SliceFamily::SP => {
155 let info = p_mb_type_info(raw_mb_type)?;
156 self.parse_p_macroblock(mb_addr, info)
157 }
158 SliceFamily::B => {
159 Err(SliceDataError::InvalidParameter {
161 field: "slice_type",
162 value: 1,
163 })
164 }
165 }
166 }
167
168 fn parse_i_macroblock(
169 &mut self,
170 mb_addr: u32,
171 info: IMbTypeInfo,
172 ) -> Result<MacroblockHeader, SliceDataError> {
173 let (mb_pred, cbp_luma, cbp_chroma) = self.parse_i_mb_body(&info)?;
174
175 let mb_qp_delta =
176 if cbp_luma > 0 || cbp_chroma > 0 || matches!(info, IMbTypeInfo::I16x16 { .. }) {
177 self.read_mb_qp_delta()?
178 } else {
179 0
180 };
181
182 Ok(MacroblockHeader {
183 mb_addr,
184 mb_type: MbTypeInfo::I(info),
185 coded_block_pattern_luma: cbp_luma,
186 coded_block_pattern_chroma: cbp_chroma,
187 mb_qp_delta,
188 mb_pred,
189 })
190 }
191
192 fn parse_p_macroblock(
193 &mut self,
194 mb_addr: u32,
195 info: PMbTypeInfo,
196 ) -> Result<MacroblockHeader, SliceDataError> {
197 match info {
198 PMbTypeInfo::I(ref i_info) => {
199 let (mb_pred, cbp_luma, cbp_chroma) = self.parse_i_mb_body(i_info)?;
200
201 let mb_qp_delta = if cbp_luma > 0
202 || cbp_chroma > 0
203 || matches!(i_info, IMbTypeInfo::I16x16 { .. })
204 {
205 self.read_mb_qp_delta()?
206 } else {
207 0
208 };
209
210 Ok(MacroblockHeader {
211 mb_addr,
212 mb_type: MbTypeInfo::P(info),
213 coded_block_pattern_luma: cbp_luma,
214 coded_block_pattern_chroma: cbp_chroma,
215 mb_qp_delta,
216 mb_pred,
217 })
218 }
219 PMbTypeInfo::P {
220 num_parts,
221 part_width,
222 part_height,
223 ref_idx_forced_zero,
224 ..
225 } => {
226 let is_8x8 = num_parts == 4;
227
228 let mb_pred = if is_8x8 {
229 self.parse_sub_mb_pred(ref_idx_forced_zero)?
230 } else {
231 self.parse_inter_mb_pred(num_parts, part_width, part_height)?
232 };
233
234 let code_num = self.reader.read_ue("coded_block_pattern")?;
236 let (cbp_luma, cbp_chroma) = coded_block_pattern_from_me(code_num, false)
237 .ok_or(SliceDataError::InvalidCodedBlockPattern(code_num))?;
238
239 let mb_qp_delta = if cbp_luma > 0 || cbp_chroma > 0 {
240 self.read_mb_qp_delta()?
241 } else {
242 0
243 };
244
245 Ok(MacroblockHeader {
246 mb_addr,
247 mb_type: MbTypeInfo::P(info),
248 coded_block_pattern_luma: cbp_luma,
249 coded_block_pattern_chroma: cbp_chroma,
250 mb_qp_delta,
251 mb_pred,
252 })
253 }
254 }
255 }
256
257 fn parse_i_mb_body(
258 &mut self,
259 info: &IMbTypeInfo,
260 ) -> Result<(MbPrediction, u8, u8), SliceDataError> {
261 match info {
262 IMbTypeInfo::INxN => {
263 let mut prev_flags = [false; 16];
264 let mut rem_modes = [0u8; 16];
265 for i in 0..16 {
266 prev_flags[i] = self.reader.read_bit("prev_intra4x4_pred_mode_flag")?;
267 if !prev_flags[i] {
268 rem_modes[i] = self.reader.read::<3, u8>("rem_intra4x4_pred_mode")?;
269 }
270 }
271 let intra_chroma_pred_mode_val = self.reader.read_ue("intra_chroma_pred_mode")?;
272 if intra_chroma_pred_mode_val > 3 {
273 return Err(SliceDataError::InvalidParameter {
274 field: "intra_chroma_pred_mode",
275 value: intra_chroma_pred_mode_val as i64,
276 });
277 }
278 let intra_chroma_pred_mode = intra_chroma_pred_mode_val as u8;
279
280 let code_num = self.reader.read_ue("coded_block_pattern")?;
281 let (cbp_luma, cbp_chroma) = coded_block_pattern_from_me(code_num, true)
282 .ok_or(SliceDataError::InvalidCodedBlockPattern(code_num))?;
283
284 Ok((
285 MbPrediction::Intra4x4 {
286 prev_intra4x4_pred_mode_flag: prev_flags,
287 rem_intra4x4_pred_mode: rem_modes,
288 intra_chroma_pred_mode,
289 },
290 cbp_luma,
291 cbp_chroma,
292 ))
293 }
294 IMbTypeInfo::I16x16 {
295 coded_block_pattern_luma,
296 coded_block_pattern_chroma,
297 ..
298 } => {
299 let intra_chroma_pred_mode_val = self.reader.read_ue("intra_chroma_pred_mode")?;
300 if intra_chroma_pred_mode_val > 3 {
301 return Err(SliceDataError::InvalidParameter {
302 field: "intra_chroma_pred_mode",
303 value: intra_chroma_pred_mode_val as i64,
304 });
305 }
306 let intra_chroma_pred_mode = intra_chroma_pred_mode_val as u8;
307
308 Ok((
309 MbPrediction::Intra16x16 {
310 intra_chroma_pred_mode,
311 },
312 *coded_block_pattern_luma,
313 *coded_block_pattern_chroma,
314 ))
315 }
316 IMbTypeInfo::IPCM => {
317 while !self.reader.byte_aligned() {
318 if self.reader.read_bit("pcm_alignment_zero_bit")? {
319 return Err(SliceDataError::InvalidParameter {
320 field: "pcm_alignment_zero_bit",
321 value: 1,
322 });
323 }
324 }
325
326 let mut pcm_sample_luma = [0u8; 256];
327 for sample in &mut pcm_sample_luma {
328 *sample = self.reader.read::<8, u8>("pcm_sample_luma")?;
329 }
330 let mut pcm_sample_chroma = [0u8; 128];
331 for sample in &mut pcm_sample_chroma {
332 *sample = self.reader.read::<8, u8>("pcm_sample_chroma")?;
333 }
334
335 Ok((
336 MbPrediction::IntraPCM {
337 pcm_sample_luma,
338 pcm_sample_chroma,
339 },
340 0,
341 0,
342 ))
343 }
344 }
345 }
346
347 fn parse_inter_mb_pred(
348 &mut self,
349 num_parts: u8,
350 part_width: u8,
351 part_height: u8,
352 ) -> Result<MbPrediction, SliceDataError> {
353 let mut ref_idx_l0 = [0i8; 4];
354 let mut mvd_l0 = [[[0i16; 2]; 4]; 4];
355
356 for item in ref_idx_l0.iter_mut().take(num_parts as usize) {
357 *item = self.read_te("ref_idx_l0", self.num_ref_idx_l0_active_minus1)?;
358 }
359
360 for item in mvd_l0.iter_mut().take(num_parts as usize) {
361 let x = self.reader.read_se("mvd_l0_x")?;
362 item[0][0] = i16::try_from(x).map_err(|_| SliceDataError::InvalidParameter {
363 field: "mvd_l0_x",
364 value: x as i64,
365 })?;
366 let y = self.reader.read_se("mvd_l0_y")?;
367 item[0][1] = i16::try_from(y).map_err(|_| SliceDataError::InvalidParameter {
368 field: "mvd_l0_y",
369 value: y as i64,
370 })?;
371 }
372
373 Ok(MbPrediction::Inter(InterPrediction {
374 num_parts,
375 part_width,
376 part_height,
377 ref_idx_l0,
378 mvd_l0,
379 sub_mb_info: None,
380 }))
381 }
382
383 fn parse_sub_mb_pred(
384 &mut self,
385 ref_idx_forced_zero: bool,
386 ) -> Result<MbPrediction, SliceDataError> {
387 let mut sub_mb_type_raw = [0u8; 4];
388 let mut sub_info: [SubMbTypeInfo; 4] = [
389 SubMbTypeInfo {
390 num_sub_parts: 1,
391 sub_part_width: 8,
392 sub_part_height: 8,
393 pred_mode: MbPartPredMode::PredL0,
394 },
395 SubMbTypeInfo {
396 num_sub_parts: 1,
397 sub_part_width: 8,
398 sub_part_height: 8,
399 pred_mode: MbPartPredMode::PredL0,
400 },
401 SubMbTypeInfo {
402 num_sub_parts: 1,
403 sub_part_width: 8,
404 sub_part_height: 8,
405 pred_mode: MbPartPredMode::PredL0,
406 },
407 SubMbTypeInfo {
408 num_sub_parts: 1,
409 sub_part_width: 8,
410 sub_part_height: 8,
411 pred_mode: MbPartPredMode::PredL0,
412 },
413 ];
414 for i in 0..4 {
415 let raw = self.reader.read_ue("sub_mb_type")?;
416 sub_mb_type_raw[i] = raw as u8;
417 sub_info[i] = p_sub_mb_type_info(raw)?;
418 }
419
420 let mut sub_ref_idx_l0 = [0i8; 4];
421 if !ref_idx_forced_zero {
422 for item in &mut sub_ref_idx_l0 {
423 *item = self.read_te("ref_idx_l0", self.num_ref_idx_l0_active_minus1)?;
424 }
425 }
426
427 let mut mvd_l0 = [[[0i16; 2]; 4]; 4];
428 for mb_part in 0..4 {
429 for sub_part in 0..sub_info[mb_part].num_sub_parts as usize {
430 let x = self.reader.read_se("mvd_l0_x")?;
431 mvd_l0[mb_part][sub_part][0] =
432 i16::try_from(x).map_err(|_| SliceDataError::InvalidParameter {
433 field: "mvd_l0_x",
434 value: x as i64,
435 })?;
436 let y = self.reader.read_se("mvd_l0_y")?;
437 mvd_l0[mb_part][sub_part][1] =
438 i16::try_from(y).map_err(|_| SliceDataError::InvalidParameter {
439 field: "mvd_l0_y",
440 value: y as i64,
441 })?;
442 }
443 }
444
445 Ok(MbPrediction::Inter(InterPrediction {
446 num_parts: 4,
447 part_width: 8,
448 part_height: 8,
449 ref_idx_l0: [0; 4],
450 mvd_l0,
451 sub_mb_info: Some(SubMbInfo {
452 sub_mb_type: sub_mb_type_raw,
453 info: sub_info,
454 ref_idx_l0: sub_ref_idx_l0,
455 }),
456 }))
457 }
458
459 fn read_mb_qp_delta(&mut self) -> Result<i32, SliceDataError> {
460 let val = self.reader.read_se("mb_qp_delta")?;
461 if !(-26..=25).contains(&val) {
462 return Err(SliceDataError::InvalidParameter {
463 field: "mb_qp_delta",
464 value: val as i64,
465 });
466 }
467 Ok(val)
468 }
469
470 fn read_te(&mut self, name: &'static str, max: u32) -> Result<i8, SliceDataError> {
476 if max == 0 {
477 Ok(0)
478 } else if max == 1 {
479 let bit = self.reader.read_bit(name)?;
480 Ok(if bit { 0 } else { 1 })
481 } else {
482 let val = self.reader.read_ue(name)?;
483 if val > max {
484 return Err(SliceDataError::InvalidParameter {
485 field: name,
486 value: val as i64,
487 });
488 }
489 Ok(val as i8)
490 }
491 }
492}
493
494pub struct SliceDataReader<'a, R: BitRead> {
495 core: SliceDataCore<'a, R>,
496}
497
498impl<'a, R: BitRead> SliceDataReader<'a, R> {
499 pub fn new(
500 reader: &'a mut R,
501 slice_family: SliceFamily,
502 first_mb_in_slice: u32,
503 pic_size_in_mbs: u32,
504 num_ref_idx_l0_active_minus1: u32,
505 ) -> Self {
506 SliceDataReader {
507 core: SliceDataCore {
508 reader,
509 slice_family,
510 curr_mb_addr: first_mb_in_slice,
511 pic_size_in_mbs,
512 num_ref_idx_l0_active_minus1,
513 pending_skips: 0,
514 after_skip_run: false,
515 done: false,
516 },
517 }
518 }
519
520 pub fn next(mut self) -> Result<SliceEvent<'a, R>, SliceDataError> {
521 if self.core.done {
522 return Ok(SliceEvent::End);
523 }
524
525 if self.core.curr_mb_addr >= self.core.pic_size_in_mbs {
526 self.core.done = true;
527 return Ok(SliceEvent::End);
528 }
529
530 if self.core.pending_skips > 0 {
531 self.core.pending_skips -= 1;
532 let addr = self.core.curr_mb_addr;
533 self.core.curr_mb_addr = self.core.next_mb_address(addr);
534 if self.core.pending_skips == 0 {
535 if !self.core.reader.has_more_rbsp_data("slice_data")? {
536 self.core.done = true;
537 } else {
538 self.core.after_skip_run = true;
539 }
540 }
541 return Ok(SliceEvent::Skip {
542 mb_addr: addr,
543 next: self,
544 });
545 }
546
547 if self.core.after_skip_run {
548 self.core.after_skip_run = false;
549 } else if self.core.slice_family != SliceFamily::I
550 && self.core.slice_family != SliceFamily::SI
551 {
552 let mb_skip_run = self.core.reader.read_ue("mb_skip_run")?;
553 if mb_skip_run > 0 {
554 self.core.pending_skips = mb_skip_run;
555 self.core.pending_skips -= 1;
556 let addr = self.core.curr_mb_addr;
557 self.core.curr_mb_addr = self.core.next_mb_address(addr);
558 if self.core.pending_skips == 0 {
559 if !self.core.reader.has_more_rbsp_data("slice_data")? {
560 self.core.done = true;
561 } else {
562 self.core.after_skip_run = true;
563 }
564 }
565 return Ok(SliceEvent::Skip {
566 mb_addr: addr,
567 next: self,
568 });
569 }
570 if !self.core.reader.has_more_rbsp_data("slice_data")? {
571 self.core.done = true;
572 return Ok(SliceEvent::End);
573 }
574 }
575
576 let mb_addr = self.core.curr_mb_addr;
577 let header = self.core.parse_macroblock_header(mb_addr)?;
578 self.core.curr_mb_addr = self.core.next_mb_address(mb_addr);
579
580 Ok(SliceEvent::Macroblock(MacroblockResidual {
581 core: self.core,
582 header,
583 }))
584 }
585
586 pub fn curr_mb_addr(&self) -> u32 {
587 self.core.curr_mb_addr
588 }
589
590 pub fn pic_size_in_mbs(&self) -> u32 {
591 self.core.pic_size_in_mbs
592 }
593}
594
595pub struct MacroblockResidual<'a, R: BitRead> {
596 core: SliceDataCore<'a, R>,
597 header: MacroblockHeader,
598}
599
600impl<'a, R: BitRead> MacroblockResidual<'a, R> {
601 pub fn header(&self) -> &MacroblockHeader {
602 &self.header
603 }
604
605 pub fn residual_block_cavlc(
606 &mut self,
607 coeff_level: &mut [i32],
608 start_idx: usize,
609 end_idx: usize,
610 max_num_coeff: usize,
611 nc: CavlcContext,
612 ) -> Result<u8, CavlcError> {
613 cavlc::residual_block_cavlc(
614 self.core.reader,
615 coeff_level,
616 start_idx,
617 end_idx,
618 max_num_coeff,
619 nc,
620 )
621 }
622
623 pub fn curr_mb_addr(&self) -> u32 {
624 self.core.curr_mb_addr
625 }
626
627 pub fn finish(mut self) -> Result<SliceDataReader<'a, R>, SliceDataError> {
628 match self.core.reader.has_more_rbsp_data("slice_data") {
629 Ok(false) => {
630 self.core.done = true;
631 }
632 Ok(true) => {}
633 Err(_) => {
634 self.core.done = true;
635 }
636 }
637 Ok(SliceDataReader { core: self.core })
638 }
639}