h264_parser/
pps.rs

1use crate::bitreader::BitReader;
2use crate::eg::{read_se, read_ue};
3use crate::{Error, Result};
4
5#[derive(Debug, Clone)]
6pub struct Pps {
7    pub pic_parameter_set_id: u8,
8    pub seq_parameter_set_id: u8,
9    pub entropy_coding_mode_flag: bool,
10    pub bottom_field_pic_order_in_frame_present_flag: bool,
11    
12    pub num_slice_groups_minus1: u32,
13    pub slice_group_map_type: u32,
14    
15    pub num_ref_idx_l0_default_active_minus1: u8,
16    pub num_ref_idx_l1_default_active_minus1: u8,
17    pub weighted_pred_flag: bool,
18    pub weighted_bipred_idc: u8,
19    pub pic_init_qp_minus26: i8,
20    pub pic_init_qs_minus26: i8,
21    pub chroma_qp_index_offset: i8,
22    pub deblocking_filter_control_present_flag: bool,
23    pub constrained_intra_pred_flag: bool,
24    pub redundant_pic_cnt_present_flag: bool,
25    
26    pub transform_8x8_mode_flag: bool,
27    pub pic_scaling_matrix_present_flag: bool,
28    pub second_chroma_qp_index_offset: i8,
29}
30
31impl Pps {
32    pub fn parse(rbsp: &[u8]) -> Result<Self> {
33        let mut reader = BitReader::new(rbsp);
34        
35        let pic_parameter_set_id = read_ue(&mut reader)?;
36        if pic_parameter_set_id > 255 {
37            return Err(Error::MalformedPps("Invalid PPS ID".into()));
38        }
39        
40        let seq_parameter_set_id = read_ue(&mut reader)?;
41        if seq_parameter_set_id > 31 {
42            return Err(Error::MalformedPps("Invalid SPS ID reference".into()));
43        }
44        
45        let entropy_coding_mode_flag = reader.read_flag()?;
46        let bottom_field_pic_order_in_frame_present_flag = reader.read_flag()?;
47        
48        let num_slice_groups_minus1 = read_ue(&mut reader)?;
49        let mut slice_group_map_type = 0;
50        
51        if num_slice_groups_minus1 > 0 {
52            slice_group_map_type = read_ue(&mut reader)?;
53            
54            match slice_group_map_type {
55                0 => {
56                    for _ in 0..=num_slice_groups_minus1 {
57                        let _run_length_minus1 = read_ue(&mut reader)?;
58                    }
59                }
60                2 => {
61                    for _ in 0..num_slice_groups_minus1 {
62                        let _top_left = read_ue(&mut reader)?;
63                        let _bottom_right = read_ue(&mut reader)?;
64                    }
65                }
66                3 | 4 | 5 => {
67                    let _slice_group_change_direction_flag = reader.read_flag()?;
68                    let _slice_group_change_rate_minus1 = read_ue(&mut reader)?;
69                }
70                6 => {
71                    let pic_size_in_map_units_minus1 = read_ue(&mut reader)?;
72                    let num_bits = (num_slice_groups_minus1 + 1).ilog2() as u32;
73                    for _ in 0..=pic_size_in_map_units_minus1 {
74                        reader.read_bits(num_bits)?;
75                    }
76                }
77                _ => {}
78            }
79        }
80        
81        let num_ref_idx_l0_default_active_minus1 = read_ue(&mut reader)?;
82        if num_ref_idx_l0_default_active_minus1 > 31 {
83            return Err(Error::MalformedPps("Invalid num_ref_idx_l0".into()));
84        }
85        
86        let num_ref_idx_l1_default_active_minus1 = read_ue(&mut reader)?;
87        if num_ref_idx_l1_default_active_minus1 > 31 {
88            return Err(Error::MalformedPps("Invalid num_ref_idx_l1".into()));
89        }
90        
91        let weighted_pred_flag = reader.read_flag()?;
92        let weighted_bipred_idc = reader.read_bits(2)? as u8;
93        
94        let pic_init_qp_minus26 = read_se(&mut reader)?;
95        if pic_init_qp_minus26 < -26 || pic_init_qp_minus26 > 25 {
96            return Err(Error::MalformedPps("Invalid pic_init_qp".into()));
97        }
98        
99        let pic_init_qs_minus26 = read_se(&mut reader)?;
100        if pic_init_qs_minus26 < -26 || pic_init_qs_minus26 > 25 {
101            return Err(Error::MalformedPps("Invalid pic_init_qs".into()));
102        }
103        
104        let chroma_qp_index_offset = read_se(&mut reader)?;
105        if chroma_qp_index_offset < -12 || chroma_qp_index_offset > 12 {
106            return Err(Error::MalformedPps("Invalid chroma_qp_index_offset".into()));
107        }
108        
109        let deblocking_filter_control_present_flag = reader.read_flag()?;
110        let constrained_intra_pred_flag = reader.read_flag()?;
111        let redundant_pic_cnt_present_flag = reader.read_flag()?;
112        
113        let mut transform_8x8_mode_flag = false;
114        let mut pic_scaling_matrix_present_flag = false;
115        let mut second_chroma_qp_index_offset = chroma_qp_index_offset;
116        
117        if reader.more_rbsp_data() {
118            transform_8x8_mode_flag = reader.read_flag()?;
119            pic_scaling_matrix_present_flag = reader.read_flag()?;
120            
121            if pic_scaling_matrix_present_flag {
122                let num_lists = 6 + if transform_8x8_mode_flag { 2 } else { 0 };
123                for i in 0..num_lists {
124                    let pic_scaling_list_present_flag = reader.read_flag()?;
125                    if pic_scaling_list_present_flag {
126                        let size = if i < 6 { 16 } else { 64 };
127                        skip_scaling_list(&mut reader, size)?;
128                    }
129                }
130            }
131            
132            second_chroma_qp_index_offset = read_se(&mut reader)?;
133            if second_chroma_qp_index_offset < -12 || second_chroma_qp_index_offset > 12 {
134                return Err(Error::MalformedPps("Invalid second_chroma_qp_index_offset".into()));
135            }
136        }
137        
138        Ok(Pps {
139            pic_parameter_set_id: pic_parameter_set_id as u8,
140            seq_parameter_set_id: seq_parameter_set_id as u8,
141            entropy_coding_mode_flag,
142            bottom_field_pic_order_in_frame_present_flag,
143            num_slice_groups_minus1,
144            slice_group_map_type,
145            num_ref_idx_l0_default_active_minus1: num_ref_idx_l0_default_active_minus1 as u8,
146            num_ref_idx_l1_default_active_minus1: num_ref_idx_l1_default_active_minus1 as u8,
147            weighted_pred_flag,
148            weighted_bipred_idc,
149            pic_init_qp_minus26: pic_init_qp_minus26 as i8,
150            pic_init_qs_minus26: pic_init_qs_minus26 as i8,
151            chroma_qp_index_offset: chroma_qp_index_offset as i8,
152            deblocking_filter_control_present_flag,
153            constrained_intra_pred_flag,
154            redundant_pic_cnt_present_flag,
155            transform_8x8_mode_flag,
156            pic_scaling_matrix_present_flag,
157            second_chroma_qp_index_offset: second_chroma_qp_index_offset as i8,
158        })
159    }
160}
161
162fn skip_scaling_list(reader: &mut BitReader, size: usize) -> Result<()> {
163    let mut last_scale = 8;
164    let mut next_scale = 8;
165    
166    for _ in 0..size {
167        if next_scale != 0 {
168            let delta_scale = read_se(reader)?;
169            next_scale = (last_scale + delta_scale + 256) % 256;
170        }
171        last_scale = if next_scale == 0 { last_scale } else { next_scale };
172    }
173    
174    Ok(())
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use crate::nal::ebsp_to_rbsp;
181
182    #[test]
183    fn test_basic_pps_parse() {
184        let ebsp = vec![0xee, 0x3c, 0x80];
185        let rbsp = ebsp_to_rbsp(&ebsp);
186        let pps = Pps::parse(&rbsp).unwrap();
187        
188        assert_eq!(pps.pic_parameter_set_id, 0);
189        assert_eq!(pps.seq_parameter_set_id, 0);
190    }
191}