h264: add SIMD optimisations for x86_64 (not enabled by default)
[nihav.git] / nihav-itu / src / codecs / h264 / sets.rs
CommitLineData
696e4e20
KS
1use nihav_core::codecs::{DecoderResult, DecoderError};
2use nihav_core::io::bitreader::*;
3
4use super::ReadUE;
5
6#[derive(Clone)]
7pub 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
46pub 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
51pub 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
211fn 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
257fn 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
273const MAX_SLICE_GROUPS: usize = 8;
274
275#[derive(Clone)]
276pub 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
306pub 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 };
355println!("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}