h264_parser/
sps.rs

1use crate::bitreader::BitReader;
2use crate::eg::{read_se, read_ue};
3use crate::{Error, Result};
4
5#[derive(Debug, Clone)]
6pub struct Sps {
7    pub profile_idc: u8,
8    pub constraint_set0_flag: bool,
9    pub constraint_set1_flag: bool,
10    pub constraint_set2_flag: bool,
11    pub constraint_set3_flag: bool,
12    pub constraint_set4_flag: bool,
13    pub constraint_set5_flag: bool,
14    pub level_idc: u8,
15    pub seq_parameter_set_id: u8,
16
17    pub chroma_format_idc: u8,
18    pub separate_colour_plane_flag: bool,
19    pub bit_depth_luma_minus8: u8,
20    pub bit_depth_chroma_minus8: u8,
21    pub qpprime_y_zero_transform_bypass_flag: bool,
22    pub seq_scaling_matrix_present_flag: bool,
23
24    pub log2_max_frame_num_minus4: u8,
25    pub pic_order_cnt_type: u8,
26    pub log2_max_pic_order_cnt_lsb_minus4: u8,
27    pub delta_pic_order_always_zero_flag: bool,
28    pub offset_for_non_ref_pic: i32,
29    pub offset_for_top_to_bottom_field: i32,
30    pub num_ref_frames_in_pic_order_cnt_cycle: u8,
31
32    pub max_num_ref_frames: u32,
33    pub gaps_in_frame_num_value_allowed_flag: bool,
34    pub pic_width_in_mbs_minus1: u32,
35    pub pic_height_in_map_units_minus1: u32,
36    pub frame_mbs_only_flag: bool,
37    pub mb_adaptive_frame_field_flag: bool,
38    pub direct_8x8_inference_flag: bool,
39
40    pub frame_cropping_flag: bool,
41    pub frame_crop_left_offset: u32,
42    pub frame_crop_right_offset: u32,
43    pub frame_crop_top_offset: u32,
44    pub frame_crop_bottom_offset: u32,
45
46    pub vui_parameters_present_flag: bool,
47
48    pub width: u32,
49    pub height: u32,
50}
51
52impl Sps {
53    pub fn parse(rbsp: &[u8]) -> Result<Self> {
54        let mut reader = BitReader::new(rbsp);
55
56        let profile_idc = reader.read_u8()?;
57        let constraint_set0_flag = reader.read_flag()?;
58        let constraint_set1_flag = reader.read_flag()?;
59        let constraint_set2_flag = reader.read_flag()?;
60        let constraint_set3_flag = reader.read_flag()?;
61        let constraint_set4_flag = reader.read_flag()?;
62        let constraint_set5_flag = reader.read_flag()?;
63        let _reserved_zero_2bits = reader.read_bits(2)?;
64        let level_idc = reader.read_u8()?;
65
66        let seq_parameter_set_id = read_ue(&mut reader)?;
67        if seq_parameter_set_id > 31 {
68            return Err(Error::MalformedSps("Invalid SPS ID".into()));
69        }
70
71        let mut chroma_format_idc = 1;
72        let mut separate_colour_plane_flag = false;
73        let mut bit_depth_luma_minus8 = 0;
74        let mut bit_depth_chroma_minus8 = 0;
75        let mut qpprime_y_zero_transform_bypass_flag = false;
76        let mut seq_scaling_matrix_present_flag = false;
77
78        if profile_idc == 100
79            || profile_idc == 110
80            || profile_idc == 122
81            || profile_idc == 244
82            || profile_idc == 44
83            || profile_idc == 83
84            || profile_idc == 86
85            || profile_idc == 118
86            || profile_idc == 128
87            || profile_idc == 138
88            || profile_idc == 139
89            || profile_idc == 134
90            || profile_idc == 135
91        {
92            chroma_format_idc = read_ue(&mut reader)? as u8;
93            if chroma_format_idc > 3 {
94                return Err(Error::MalformedSps("Invalid chroma format".into()));
95            }
96
97            if chroma_format_idc == 3 {
98                separate_colour_plane_flag = reader.read_flag()?;
99            }
100
101            bit_depth_luma_minus8 = read_ue(&mut reader)? as u8;
102            bit_depth_chroma_minus8 = read_ue(&mut reader)? as u8;
103            qpprime_y_zero_transform_bypass_flag = reader.read_flag()?;
104            seq_scaling_matrix_present_flag = reader.read_flag()?;
105
106            if seq_scaling_matrix_present_flag {
107                let num_lists = if chroma_format_idc != 3 { 8 } else { 12 };
108                for _ in 0..num_lists {
109                    let seq_scaling_list_present_flag = reader.read_flag()?;
110                    if seq_scaling_list_present_flag {
111                        skip_scaling_list(&mut reader)?;
112                    }
113                }
114            }
115        }
116
117        let log2_max_frame_num_minus4 = read_ue(&mut reader)? as u8;
118        if log2_max_frame_num_minus4 > 12 {
119            return Err(Error::MalformedSps("Invalid log2_max_frame_num".into()));
120        }
121
122        let pic_order_cnt_type = read_ue(&mut reader)? as u8;
123
124        let mut log2_max_pic_order_cnt_lsb_minus4 = 0;
125        let mut delta_pic_order_always_zero_flag = false;
126        let mut offset_for_non_ref_pic = 0;
127        let mut offset_for_top_to_bottom_field = 0;
128        let mut num_ref_frames_in_pic_order_cnt_cycle = 0;
129
130        match pic_order_cnt_type {
131            0 => {
132                log2_max_pic_order_cnt_lsb_minus4 = read_ue(&mut reader)? as u8;
133                if log2_max_pic_order_cnt_lsb_minus4 > 12 {
134                    return Err(Error::MalformedSps(
135                        "Invalid log2_max_pic_order_cnt_lsb".into(),
136                    ));
137                }
138            }
139            1 => {
140                delta_pic_order_always_zero_flag = reader.read_flag()?;
141                offset_for_non_ref_pic = read_se(&mut reader)?;
142                offset_for_top_to_bottom_field = read_se(&mut reader)?;
143                num_ref_frames_in_pic_order_cnt_cycle = read_ue(&mut reader)? as u8;
144
145                for _ in 0..num_ref_frames_in_pic_order_cnt_cycle {
146                    let _offset_for_ref_frame = read_se(&mut reader)?;
147                }
148            }
149            2 => {}
150            _ => return Err(Error::MalformedSps("Invalid pic_order_cnt_type".into())),
151        }
152
153        let max_num_ref_frames = read_ue(&mut reader)?;
154        let gaps_in_frame_num_value_allowed_flag = reader.read_flag()?;
155
156        let pic_width_in_mbs_minus1 = read_ue(&mut reader)?;
157        let pic_height_in_map_units_minus1 = read_ue(&mut reader)?;
158
159        let frame_mbs_only_flag = reader.read_flag()?;
160        let mut mb_adaptive_frame_field_flag = false;
161        if !frame_mbs_only_flag {
162            mb_adaptive_frame_field_flag = reader.read_flag()?;
163        }
164
165        let direct_8x8_inference_flag = reader.read_flag()?;
166
167        let frame_cropping_flag = reader.read_flag()?;
168        let mut frame_crop_left_offset = 0;
169        let mut frame_crop_right_offset = 0;
170        let mut frame_crop_top_offset = 0;
171        let mut frame_crop_bottom_offset = 0;
172
173        if frame_cropping_flag {
174            frame_crop_left_offset = read_ue(&mut reader)?;
175            frame_crop_right_offset = read_ue(&mut reader)?;
176            frame_crop_top_offset = read_ue(&mut reader)?;
177            frame_crop_bottom_offset = read_ue(&mut reader)?;
178        }
179
180        let vui_parameters_present_flag = reader.read_flag()?;
181
182        let width = (pic_width_in_mbs_minus1 + 1) * 16;
183        let height =
184            (pic_height_in_map_units_minus1 + 1) * 16 * if frame_mbs_only_flag { 1 } else { 2 };
185
186        let (sub_width_c, sub_height_c) = match chroma_format_idc {
187            0 => (0, 0),
188            1 => (2, 2),
189            2 => (2, 1),
190            3 => (1, 1),
191            _ => (0, 0),
192        };
193
194        let width = if frame_cropping_flag && sub_width_c > 0 {
195            width - sub_width_c * (frame_crop_left_offset + frame_crop_right_offset)
196        } else {
197            width
198        };
199
200        let height = if frame_cropping_flag && sub_height_c > 0 {
201            let mult = if frame_mbs_only_flag { 1 } else { 2 };
202            height - sub_height_c * mult * (frame_crop_top_offset + frame_crop_bottom_offset)
203        } else {
204            height
205        };
206
207        Ok(Sps {
208            profile_idc,
209            constraint_set0_flag,
210            constraint_set1_flag,
211            constraint_set2_flag,
212            constraint_set3_flag,
213            constraint_set4_flag,
214            constraint_set5_flag,
215            level_idc,
216            seq_parameter_set_id: seq_parameter_set_id as u8,
217            chroma_format_idc,
218            separate_colour_plane_flag,
219            bit_depth_luma_minus8,
220            bit_depth_chroma_minus8,
221            qpprime_y_zero_transform_bypass_flag,
222            seq_scaling_matrix_present_flag,
223            log2_max_frame_num_minus4,
224            pic_order_cnt_type,
225            log2_max_pic_order_cnt_lsb_minus4,
226            delta_pic_order_always_zero_flag,
227            offset_for_non_ref_pic,
228            offset_for_top_to_bottom_field,
229            num_ref_frames_in_pic_order_cnt_cycle,
230            max_num_ref_frames,
231            gaps_in_frame_num_value_allowed_flag,
232            pic_width_in_mbs_minus1,
233            pic_height_in_map_units_minus1,
234            frame_mbs_only_flag,
235            mb_adaptive_frame_field_flag,
236            direct_8x8_inference_flag,
237            frame_cropping_flag,
238            frame_crop_left_offset,
239            frame_crop_right_offset,
240            frame_crop_top_offset,
241            frame_crop_bottom_offset,
242            vui_parameters_present_flag,
243            width,
244            height,
245        })
246    }
247}
248
249fn skip_scaling_list(reader: &mut BitReader) -> Result<()> {
250    let mut last_scale = 8;
251    let mut next_scale = 8;
252
253    for _ in 0..16 {
254        if next_scale != 0 {
255            let delta_scale = read_se(reader)?;
256            next_scale = (last_scale + delta_scale + 256) % 256;
257        }
258        last_scale = if next_scale == 0 {
259            last_scale
260        } else {
261            next_scale
262        };
263    }
264
265    Ok(())
266}
267
268#[cfg(test)]
269mod tests {
270    use super::*;
271    use crate::nal::ebsp_to_rbsp;
272
273    #[test]
274    fn test_basic_sps_parse() {
275        let ebsp = vec![
276            0x42, 0x00, 0x1f, 0xac, 0x34, 0xc8, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00,
277            0x03, 0x00, 0xf0, 0x3c, 0x60, 0xc6, 0x58,
278        ];
279
280        let rbsp = ebsp_to_rbsp(&ebsp);
281        let sps = Sps::parse(&rbsp).unwrap();
282
283        assert_eq!(sps.profile_idc, 66);
284        assert_eq!(sps.level_idc, 31);
285        assert!(sps.width > 0);
286        assert!(sps.height > 0);
287    }
288}