]>
Commit | Line | Data |
---|---|---|
696e4e20 KS |
1 | use nihav_core::codecs::{DecoderResult, DecoderError}; |
2 | use nihav_core::io::bitreader::*; | |
3 | ||
4 | use super::ReadUE; | |
5 | ||
6 | #[derive(Clone)] | |
7 | pub struct SeqParameterSet { | |
8 | pub profile_idc: u8, | |
9 | pub high_profile: bool, | |
10 | pub constraint_set0: bool, | |
11 | pub constraint_set1: bool, | |
12 | pub constraint_set2: bool, | |
13 | pub level_idc: u8, | |
14 | pub seq_parameter_set_id: u32, | |
15 | pub chroma_format_idc: u8, | |
16 | pub separate_colour_plane: bool, | |
17 | pub bit_depth_luma: u8, | |
18 | pub bit_depth_chroma: u8, | |
19 | pub qpprime_y_zero_transform_bypass: bool, | |
20 | pub seq_scaling_matrix_present: bool, | |
21 | pub scaling_list_4x4: [[u8; 16]; 6], | |
22 | pub scaling_list_8x8: [[u8; 64]; 6], | |
23 | pub log2_max_frame_num: u8, | |
24 | pub pic_order_cnt_type: u8, | |
25 | pub log2_max_pic_order_cnt_lsb: u8, | |
26 | pub delta_pic_order_always_zero: bool, | |
27 | pub offset_for_non_ref_pic: i32, | |
28 | pub offset_for_top_to_bottom_field: i32, | |
29 | pub num_ref_frames_in_pic_order_cnt_cycle: usize, | |
30 | pub offset_for_ref_frame: [i32; 256], | |
31 | pub num_ref_frames: usize, | |
32 | pub gaps_in_frame_num_value_allowed: bool, | |
33 | pub pic_width_in_mbs: usize, | |
34 | pub pic_height_in_mbs: usize, | |
35 | pub frame_mbs_only: bool, | |
36 | pub mb_adaptive_frame_field: bool, | |
37 | pub direct_8x8_inference: bool, | |
38 | pub frame_cropping: bool, | |
39 | pub frame_crop_left_offset: usize, | |
40 | pub frame_crop_right_offset: usize, | |
41 | pub frame_crop_top_offset: usize, | |
42 | pub frame_crop_bottom_offset: usize, | |
43 | pub vui_parameters_present: bool, | |
44 | } | |
45 | ||
46 | pub fn is_high_profile(profile: u8) -> bool { | |
42005e25 | 47 | matches!(profile, 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 125) |
696e4e20 KS |
48 | } |
49 | ||
b7c882c1 | 50 | #[allow(clippy::cognitive_complexity)] |
696e4e20 KS |
51 | pub fn parse_sps(src: &[u8]) -> DecoderResult<SeqParameterSet> { |
52 | let mut br = BitReader::new(src, BitReaderMode::BE); | |
53 | let mut sps: SeqParameterSet = unsafe { std::mem::zeroed() }; | |
54 | ||
55 | sps.profile_idc = br.read(8)? as u8; | |
56 | sps.constraint_set0 = br.read_bool()?; | |
57 | sps.constraint_set1 = br.read_bool()?; | |
58 | sps.constraint_set2 = br.read_bool()?; | |
59 | let reserved = br.read(5)?; | |
60 | validate!(reserved == 0); | |
61 | sps.level_idc = br.read(8)? as u8; | |
62 | sps.seq_parameter_set_id = br.read_ue()?; | |
63 | sps.high_profile = is_high_profile(sps.profile_idc); | |
64 | if sps.high_profile { | |
65 | sps.chroma_format_idc = br.read_ue_lim(3)? as u8; | |
66 | if sps.chroma_format_idc == 3 { | |
67 | sps.separate_colour_plane = br.read_bool()?; | |
68 | } | |
69 | sps.bit_depth_luma = br.read_ue_lim(6)? as u8 + 8; | |
70 | sps.bit_depth_chroma = br.read_ue_lim(6)? as u8 + 8; | |
71 | sps.qpprime_y_zero_transform_bypass = br.read_bool()?; | |
72 | sps.seq_scaling_matrix_present = br.read_bool()?; | |
73 | if sps.seq_scaling_matrix_present { | |
74 | let mut slist_present = [false; 6]; | |
75 | for (i, slist) in sps.scaling_list_4x4.iter_mut().enumerate() { | |
76 | slist_present[i] = br.read_bool()?; | |
77 | if slist_present[i] { | |
78 | parse_scaling_list(&mut br, slist, i < 3)?; | |
79 | } | |
80 | } | |
81 | for i in 1..6 { | |
82 | if i == 3 { | |
83 | continue; | |
84 | } | |
85 | if !slist_present[i] { | |
86 | sps.scaling_list_4x4[i] = sps.scaling_list_4x4[i - 1]; | |
87 | } | |
88 | } | |
89 | ||
90 | let mut slist_present = [false; 6]; | |
91 | let num_8x8 = if sps.chroma_format_idc != 3 { 2 } else { 6 }; | |
92 | for (i, slist) in sps.scaling_list_8x8.iter_mut().take(num_8x8).enumerate() { | |
93 | slist_present[i] = br.read_bool()?; | |
94 | if slist_present[i] { | |
95 | parse_scaling_list(&mut br, slist, (i & 1) == 0)?; | |
96 | } | |
97 | } | |
98 | if num_8x8 > 2 { | |
99 | for i in 2..6 { | |
100 | if !slist_present[i] { | |
101 | sps.scaling_list_8x8[i] = sps.scaling_list_8x8[i - 2]; | |
102 | } | |
103 | } | |
104 | } | |
105 | } else { | |
106 | sps.scaling_list_4x4 = [[16; 16]; 6]; | |
107 | sps.scaling_list_8x8 = [[16; 64]; 6]; | |
108 | } | |
109 | } else { | |
110 | sps.chroma_format_idc = 1; | |
111 | sps.bit_depth_luma = 8; | |
112 | sps.bit_depth_chroma = 8; | |
113 | } | |
114 | sps.log2_max_frame_num = (br.read_ue_lim(12)? + 4) as u8; | |
115 | sps.pic_order_cnt_type = br.read_ue_lim(2)? as u8; | |
116 | match sps.pic_order_cnt_type { | |
117 | 0 => { | |
118 | sps.log2_max_pic_order_cnt_lsb = (br.read_ue_lim(12)? + 4) as u8; | |
119 | }, | |
120 | 1 => { | |
121 | sps.delta_pic_order_always_zero = br.read_bool()?; | |
122 | sps.offset_for_non_ref_pic = br.read_se()?; | |
123 | sps.offset_for_top_to_bottom_field = br.read_se()?; | |
124 | sps.num_ref_frames_in_pic_order_cnt_cycle = br.read_ue_lim(255)? as usize; | |
125 | for offset in sps.offset_for_ref_frame[..sps.num_ref_frames_in_pic_order_cnt_cycle].iter_mut() { | |
126 | *offset = br.read_se()?; | |
127 | } | |
128 | }, | |
129 | _ => {}, | |
130 | }; | |
131 | sps.num_ref_frames = br.read_ue()? as usize; | |
132 | validate!(sps.num_ref_frames <= super::slice::MAX_FRAMES); | |
133 | sps.gaps_in_frame_num_value_allowed = br.read_bool()?; | |
134 | sps.pic_width_in_mbs = (br.read_ue()? + 1) as usize; | |
135 | sps.pic_height_in_mbs = (br.read_ue()? + 1) as usize; | |
136 | validate!(sps.pic_width_in_mbs <= 1024 && sps.pic_height_in_mbs <= 1024); | |
137 | sps.frame_mbs_only = br.read_bool()?; | |
138 | if !sps.frame_mbs_only { | |
139 | sps.mb_adaptive_frame_field = br.read_bool()?; | |
140 | } | |
141 | sps.direct_8x8_inference = br.read_bool()?; | |
142 | sps.frame_cropping = br.read_bool()?; | |
143 | if sps.frame_cropping { | |
144 | sps.frame_crop_left_offset = br.read_ue()? as usize; | |
145 | sps.frame_crop_right_offset = br.read_ue()? as usize; | |
146 | sps.frame_crop_top_offset = br.read_ue()? as usize; | |
147 | sps.frame_crop_bottom_offset = br.read_ue()? as usize; | |
148 | let l = sps.frame_crop_left_offset * 2; | |
149 | let r = sps.pic_width_in_mbs * 16 - sps.frame_crop_right_offset * 2; | |
150 | let t = sps.frame_crop_top_offset * 2; | |
151 | let d = sps.pic_height_in_mbs * 16 - sps.frame_crop_bottom_offset * 2; | |
152 | validate!(l < r && t < d); | |
153 | } | |
154 | sps.vui_parameters_present = br.read_bool()?; | |
155 | if sps.vui_parameters_present { | |
156 | // xxx: vui is ignored for now | |
157 | if br.read_bool()? { | |
158 | let idc = br.read(8)?; | |
159 | if idc == 255 { | |
160 | br.read(16)?; | |
161 | br.read(16)?; | |
162 | } | |
163 | } | |
164 | if br.read_bool()? { | |
165 | br.read_bool()?; | |
166 | } | |
167 | if br.read_bool()? { | |
168 | br.read(3)?; | |
169 | br.read_bool()?; | |
170 | if br.read_bool()? { | |
171 | br.read(8)?; | |
172 | br.read(8)?; | |
173 | br.read(8)?; | |
174 | } | |
175 | } | |
176 | if br.read_bool()? { | |
177 | br.read_ue()?; | |
178 | br.read_ue()?; | |
179 | } | |
180 | if br.read_bool()? { | |
181 | br.read(32)?; | |
182 | br.read(32)?; | |
183 | br.read_bool()?; | |
184 | } | |
185 | let nal_hrd_parameters_present = br.read_bool()?; | |
186 | if nal_hrd_parameters_present { | |
187 | skip_hrd_parameters(&mut br)?; | |
188 | } | |
189 | let vcl_hrd_parameters_present = br.read_bool()?; | |
190 | if vcl_hrd_parameters_present { | |
191 | skip_hrd_parameters(&mut br)?; | |
192 | } | |
193 | if nal_hrd_parameters_present || vcl_hrd_parameters_present { | |
194 | br.read_bool()?; | |
195 | } | |
196 | br.read_bool()?; | |
197 | if br.read_bool()? { | |
198 | br.read_bool()?; | |
199 | br.read_ue()?; | |
200 | br.read_ue()?; | |
201 | br.read_ue()?; | |
202 | br.read_ue()?; | |
203 | br.read_ue()?; | |
204 | br.read_ue()?; | |
205 | } | |
206 | } | |
207 | ||
208 | Ok(sps) | |
209 | } | |
210 | ||
211 | fn parse_scaling_list(br: &mut BitReader, slist: &mut[u8], is_intra: bool) -> DecoderResult<()> { | |
212 | const DEFAULT_INTRA_4X4: [u8; 16] = [ | |
213 | 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 | |
214 | ]; | |
215 | const DEFAULT_INTER_4X4: [u8; 16] = [ | |
216 | 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34 | |
217 | ]; | |
218 | const DEFAULT_INTRA_8X8: [u8; 64] = [ | |
219 | 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, | |
220 | 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, | |
221 | 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, | |
222 | 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 | |
223 | ]; | |
224 | const DEFAULT_INTER_8X8: [u8; 64] = [ | |
225 | 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, | |
226 | 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, | |
227 | 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, | |
228 | 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 | |
229 | ]; | |
230 | let mut last_scale = 8u8; | |
231 | let mut next_scale = 8u8; | |
232 | let mut use_default = false; | |
233 | for (j, elem) in slist.iter_mut().enumerate() { | |
234 | if next_scale != 0 { | |
235 | let delta = br.read_se()?; | |
236 | next_scale = last_scale.wrapping_add(delta as u8); | |
237 | if (j == 0) && (next_scale == 0) { | |
238 | use_default = true; | |
239 | break; | |
240 | } | |
241 | } | |
242 | *elem = if next_scale == 0 { last_scale } else { next_scale }; | |
243 | last_scale = *elem; | |
244 | } | |
245 | if use_default { | |
246 | match (slist.len(), is_intra) { | |
247 | (16, true) => slist.copy_from_slice(&DEFAULT_INTRA_4X4), | |
248 | (16, false) => slist.copy_from_slice(&DEFAULT_INTER_4X4), | |
249 | (64, true) => slist.copy_from_slice(&DEFAULT_INTRA_8X8), | |
250 | (64, false) => slist.copy_from_slice(&DEFAULT_INTER_8X8), | |
251 | _ => unreachable!(), | |
252 | }; | |
253 | } | |
254 | Ok(()) | |
255 | } | |
256 | ||
257 | fn skip_hrd_parameters(br: &mut BitReader) -> DecoderResult<()> { | |
258 | let cpb_cnt = br.read_ue()? as usize + 1; | |
259 | br.read(4)?; | |
260 | br.read(4)?; | |
261 | for _ in 0..cpb_cnt { | |
262 | br.read_ue()?; | |
263 | br.read_ue()?; | |
264 | br.read_bool()?; | |
265 | } | |
266 | br.read(5)?; | |
267 | br.read(5)?; | |
268 | br.read(5)?; | |
269 | br.read(5)?; | |
270 | Ok(()) | |
271 | } | |
272 | ||
273 | const MAX_SLICE_GROUPS: usize = 8; | |
274 | ||
275 | #[derive(Clone)] | |
276 | pub struct PicParameterSet { | |
277 | pub pic_parameter_set_id: u32, | |
278 | pub seq_parameter_set_id: u32, | |
279 | pub entropy_coding_mode: bool, | |
280 | pub pic_order_present: bool, | |
281 | pub num_slice_groups: usize, | |
282 | pub slice_group_map_type: u8, | |
283 | pub run_length: [u32; MAX_SLICE_GROUPS], | |
284 | pub top_left: [u32; MAX_SLICE_GROUPS], | |
285 | pub bottom_right: [u32; MAX_SLICE_GROUPS], | |
286 | pub slice_group_change_direction: bool, | |
287 | pub slice_group_change_rate: u32, | |
288 | pub pic_size_in_map_units: u32, | |
289 | pub num_ref_idx_l0_active: usize, | |
290 | pub num_ref_idx_l1_active: usize, | |
291 | pub weighted_pred: bool, | |
292 | pub weighted_bipred_idc: u8, | |
293 | pub pic_init_qp: u8, | |
294 | pub pic_init_qs: u8, | |
295 | pub chroma_qp_index_offset: i8, | |
296 | pub deblocking_filter_control_present: bool, | |
297 | pub constrained_intra_pred: bool, | |
298 | pub redundant_pic_cnt_present: bool, | |
299 | pub transform_8x8_mode: bool, | |
300 | pub pic_scaling_matrix_present: bool, | |
301 | pub scaling_list_4x4: [[u8; 16]; 6], | |
302 | pub scaling_list_8x8: [[u8; 64]; 6], | |
303 | pub second_chroma_qp_index_offset: i8, | |
304 | } | |
305 | ||
306 | pub fn parse_pps(src: &[u8], sps_arr: &[SeqParameterSet], full_size: usize) -> DecoderResult<PicParameterSet> { | |
307 | let mut br = BitReader::new(src, BitReaderMode::BE); | |
308 | let mut pps: PicParameterSet = unsafe { std::mem::zeroed() }; | |
309 | ||
310 | pps.pic_parameter_set_id = br.read_ue()?; | |
311 | pps.seq_parameter_set_id = br.read_ue()?; | |
312 | let mut found = false; | |
313 | let mut cur_sps = None; | |
314 | for sps in sps_arr.iter() { | |
315 | if sps.seq_parameter_set_id == pps.seq_parameter_set_id { | |
316 | found = true; | |
317 | cur_sps = Some(sps); | |
318 | break; | |
319 | } | |
320 | } | |
321 | validate!(found); | |
322 | let sps = cur_sps.unwrap(); | |
323 | pps.entropy_coding_mode = br.read_bool()?; | |
324 | pps.pic_order_present = br.read_bool()?; | |
325 | pps.num_slice_groups = (br.read_ue()? + 1) as usize; | |
326 | validate!(pps.num_slice_groups <= MAX_SLICE_GROUPS); | |
327 | if pps.num_slice_groups > 1 { | |
328 | let smtype = br.read_ue()?; | |
329 | validate!(smtype <= 6); | |
330 | pps.slice_group_map_type = smtype as u8; | |
331 | match pps.slice_group_map_type { | |
332 | 0 => { | |
333 | for elem in pps.run_length[..pps.num_slice_groups].iter_mut() { | |
334 | *elem = br.read_ue()?; | |
335 | } | |
336 | }, | |
337 | 2 => { | |
338 | for i in 0..pps.num_slice_groups - 1 { | |
339 | pps.top_left[i] = br.read_ue()?; | |
340 | pps.bottom_right[i] = br.read_ue()?; | |
341 | } | |
342 | }, | |
343 | 3 | 4 | 5 => { | |
344 | pps.slice_group_change_direction = br.read_bool()?; | |
345 | pps.slice_group_change_rate = br.read_ue()?; | |
346 | }, | |
347 | 6 => { | |
348 | pps.pic_size_in_map_units = br.read_ue()? + 1; | |
349 | for _ in 0..pps.pic_size_in_map_units { | |
350 | let _slice_group_id = br.read_ue()?; | |
351 | } | |
352 | }, | |
353 | _ => {}, | |
354 | }; | |
355 | println!("slice mode!"); | |
356 | return Err(DecoderError::NotImplemented); | |
357 | } | |
358 | pps.num_ref_idx_l0_active = (br.read_ue()? + 1) as usize; | |
359 | pps.num_ref_idx_l1_active = (br.read_ue()? + 1) as usize; | |
360 | pps.weighted_pred = br.read_bool()?; | |
361 | pps.weighted_bipred_idc = br.read(2)? as u8; | |
362 | let qp = br.read_se()? + 26; | |
363 | validate!(qp > 0 && qp < 52); | |
364 | pps.pic_init_qp = qp as u8; | |
365 | let qs = br.read_se()? + 26; | |
366 | validate!(qs > 0 && qs < 52); | |
367 | pps.pic_init_qs = qs as u8; | |
368 | let off = br.read_se()?; | |
369 | validate!(off >= -12 && off <= 12); | |
370 | pps.chroma_qp_index_offset = off as i8; | |
371 | pps.deblocking_filter_control_present = br.read_bool()?; | |
372 | pps.constrained_intra_pred = br.read_bool()?; | |
373 | pps.redundant_pic_cnt_present = br.read_bool()?; | |
374 | if br.tell() < full_size { | |
375 | pps.transform_8x8_mode = br.read_bool()?; | |
376 | pps.pic_scaling_matrix_present = br.read_bool()?; | |
377 | if pps.pic_scaling_matrix_present { | |
378 | let mut slist_present = [false; 6]; | |
379 | for (i, slist) in pps.scaling_list_4x4.iter_mut().enumerate() { | |
380 | slist_present[i] = br.read_bool()?; | |
381 | if slist_present[i] { | |
382 | parse_scaling_list(&mut br, slist, i < 3)?; | |
383 | } | |
384 | } | |
385 | for i in 1..6 { | |
386 | if i == 3 { | |
387 | continue; | |
388 | } | |
389 | if !slist_present[i] { | |
390 | pps.scaling_list_4x4[i] = pps.scaling_list_4x4[i - 1]; | |
391 | } | |
392 | } | |
393 | ||
394 | let mut slist_present = [false; 6]; | |
395 | let num_8x8 = if !pps.transform_8x8_mode { 0 } else if sps.chroma_format_idc != 3 { 2 } else { 6 }; | |
396 | for (i, slist) in pps.scaling_list_8x8.iter_mut().take(num_8x8).enumerate() { | |
397 | slist_present[i] = br.read_bool()?; | |
398 | if slist_present[i] { | |
399 | parse_scaling_list(&mut br, slist, (i & 1) == 0)?; | |
400 | } | |
401 | } | |
402 | if num_8x8 > 2 { | |
403 | for i in 2..6 { | |
404 | if !slist_present[i] { | |
405 | pps.scaling_list_8x8[i] = pps.scaling_list_8x8[i - 2]; | |
406 | } | |
407 | } | |
408 | } | |
409 | } else { | |
410 | pps.scaling_list_4x4 = sps.scaling_list_4x4; | |
411 | pps.scaling_list_8x8 = sps.scaling_list_8x8; | |
412 | } | |
413 | let off = br.read_se()?; | |
414 | validate!(off >= -12 && off <= 12); | |
415 | pps.second_chroma_qp_index_offset = off as i8; | |
416 | } else { | |
417 | pps.second_chroma_qp_index_offset = pps.chroma_qp_index_offset; | |
418 | } | |
419 | ||
420 | Ok(pps) | |
421 | } |