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