Skip to content

Commit 49d5805

Browse files
committed
progress on parsing P macroblocks
1 parent 11bdeed commit 49d5805

File tree

4 files changed

+81
-14
lines changed

4 files changed

+81
-14
lines changed

src/h264/decoder.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,6 @@ impl Decoder {
107107
.map_err(parse_error_handler)?;
108108

109109
info!("non-IDR Slice: {:#?}", slice);
110-
if slice.header.slice_type != SliceType::I {
111-
todo!("implement P-slices")
112-
}
113-
114110
let frame = VideoFrame::new_with_padding(
115111
slice.sps.pic_width(),
116112
slice.sps.pic_hight(),

src/h264/macroblock.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ pub struct IMb {
378378
#[derive(Clone, Debug, Default)]
379379
pub struct PMb {
380380
pub mb_type: PMbType,
381+
pub coded_block_pattern: CodedBlockPattern,
382+
pub mb_qp_delta: i32,
383+
pub residual: Option<Box<Residual>>,
381384
}
382385

383386
#[derive(Clone, Debug)]
@@ -405,6 +408,20 @@ impl IMb {
405408
}
406409
}
407410

411+
#[allow(non_snake_case)]
412+
impl PMb {
413+
#[inline]
414+
pub fn MbPartPredMode(&self, partition: usize) -> MbPredictionMode {
415+
match self.mb_type {
416+
PMbType::P_Skip
417+
| PMbType::P_L0_16x16
418+
| PMbType::P_L0_L0_16x8
419+
| PMbType::P_L0_L0_8x16 => MbPredictionMode::Pred_L0,
420+
PMbType::P_8x8ref0 | PMbType::P_8x8 => MbPredictionMode::None,
421+
}
422+
}
423+
}
424+
408425
#[allow(non_snake_case)]
409426
impl Macroblock {
410427
#[inline]
@@ -433,10 +450,8 @@ impl Macroblock {
433450
pub fn get_coded_block_pattern(&self) -> CodedBlockPattern {
434451
match self {
435452
Macroblock::I(mb) => mb.coded_block_pattern,
453+
Macroblock::P(mb) => mb.coded_block_pattern,
436454
Macroblock::PCM(_) => CodedBlockPattern::default(),
437-
Macroblock::P(_) => {
438-
todo!("P blocks")
439-
}
440455
}
441456
}
442457

@@ -445,10 +460,10 @@ impl Macroblock {
445460
Macroblock::I(mb) => {
446461
mb.residual = r;
447462
}
448-
Macroblock::PCM(_) => {}
449-
Macroblock::P(_) => {
450-
todo!("P blocks")
463+
Macroblock::P(mb) => {
464+
mb.residual = r;
451465
}
466+
Macroblock::PCM(_) => {}
452467
}
453468
}
454469
}

src/h264/parser.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -744,9 +744,52 @@ fn calc_prev_intra4x4_pred_mode(
744744
}
745745

746746
pub fn parse_macroblock(input: &mut BitReader, slice: &Slice) -> ParseResult<Macroblock> {
747-
let mb_type: IMbType;
748-
read_value!(input, mb_type, ue);
747+
let mb_type_val: u32;
748+
read_value!(input, mb_type_val, ue);
749749

750+
if slice.header.slice_type == SliceType::I || slice.header.slice_type == SliceType::SI {
751+
let mb_type = IMbType::try_from(mb_type_val)?;
752+
parse_i_macroblock(input, slice, mb_type)
753+
} else {
754+
let mb_type = PMbType::try_from(mb_type_val)?;
755+
parse_p_macroblock(input, slice, mb_type)
756+
}
757+
}
758+
759+
pub fn parse_p_macroblock(
760+
input: &mut BitReader,
761+
slice: &Slice,
762+
mb_type: PMbType,
763+
) -> ParseResult<Macroblock> {
764+
let mut block = PMb { mb_type, ..PMb::default() };
765+
let this_mb_addr = slice.get_next_mb_addr();
766+
/*
767+
TODO: Parse motion vectors here
768+
*/
769+
770+
let coded_block_pattern_num: u8;
771+
read_value!(input, coded_block_pattern_num, ue, 8);
772+
block.coded_block_pattern =
773+
tables::code_num_to_inter_coded_block_pattern(coded_block_pattern_num)
774+
.ok_or("Invalid coded_block_pattern")?;
775+
776+
if !block.coded_block_pattern.is_zero() {
777+
read_value!(input, block.mb_qp_delta, se);
778+
let mut residual = Box::<Residual>::default();
779+
residual.coded_block_pattern = block.coded_block_pattern;
780+
residual.prediction_mode = block.MbPartPredMode(0);
781+
parse_residual(input, slice, &mut residual)?;
782+
block.residual = Some(residual);
783+
}
784+
785+
Ok(Macroblock::P(block))
786+
}
787+
788+
pub fn parse_i_macroblock(
789+
input: &mut BitReader,
790+
slice: &Slice,
791+
mb_type: IMbType,
792+
) -> ParseResult<Macroblock> {
750793
if mb_type == IMbType::I_PCM {
751794
let mut block = PcmMb::default();
752795
input.align();
@@ -865,7 +908,7 @@ pub fn parse_slice_data(input: &mut BitReader, slice: &mut Slice) -> ParseResult
865908
));
866909
}
867910
for i in 0..mb_skip_run {
868-
let block = Macroblock::P(PMb { mb_type: PMbType::P_Skip });
911+
let block = Macroblock::P(PMb { mb_type: PMbType::P_Skip, ..Default::default() });
869912
slice.append_mb(block);
870913
}
871914
if mb_skip_run > 0 {

src/h264/tables.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,24 @@ const CODE_NUM_TO_INTRA_CODED_BLOCK_PATTERN: [u8; 48] = [
2222
35, 37, 42, 44, 1, 2, 4, 8, 17, 18, 20, 24, 6, 9, 22, 25, 32, 33, 34, 36, 40, 38, 41,
2323
];
2424

25+
const CODE_NUM_TO_INTER_CODED_BLOCK_PATTERN: [u8; 48] = [
26+
0, 16, 1, 2, 4, 8, 32, 3, 5, 10, 12, 15, 47, 7, 11, 13, 14, 6, 9, 31, 35, 37, 42, 44, 33, 34,
27+
36, 40, 39, 43, 45, 46, 17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41,
28+
];
29+
2530
#[inline]
2631
pub fn code_num_to_intra_coded_block_pattern(x: u8) -> Option<CodedBlockPattern> {
2732
let result =
2833
CODE_NUM_TO_INTRA_CODED_BLOCK_PATTERN.get(x as usize).map(|x| CodedBlockPattern(*x));
29-
trace!("coded_block_pattern num: {} pattern: {:?}", x, result);
34+
trace!("intra coded_block_pattern num: {} pattern: {:?}", x, result);
35+
result
36+
}
37+
38+
#[inline]
39+
pub fn code_num_to_inter_coded_block_pattern(x: u8) -> Option<CodedBlockPattern> {
40+
let result =
41+
CODE_NUM_TO_INTER_CODED_BLOCK_PATTERN.get(x as usize).map(|x| CodedBlockPattern(*x));
42+
trace!("inter coded_block_pattern num: {} pattern: {:?}", x, result);
3043
result
3144
}
3245

0 commit comments

Comments
 (0)