h264: make some structures shareable
[nihav.git] / nihav-itu / src / codecs / h264 / slice.rs
CommitLineData
93839abd
KS
1use std::sync::Arc;
2
696e4e20
KS
3use nihav_core::codecs::{DecoderResult, DecoderError};
4use nihav_core::frame::FrameType;
5use nihav_core::io::bitreader::*;
6
7use super::ReadUE;
8use super::sets::*;
9
10pub const MAX_FRAMES: usize = 32;
11
12#[derive(Clone,Copy,Debug,PartialEq)]
13pub enum SliceType {
14 I,
15 P,
16 B,
17 SI,
18 SP,
19}
20
21impl SliceType {
22 pub fn is_intra(self) -> bool {
42005e25 23 matches!(self, SliceType::I | SliceType::SI)
696e4e20
KS
24 }
25 pub fn is_p(self) -> bool {
42005e25 26 matches!(self, SliceType::P | SliceType::SP)
696e4e20
KS
27 }
28 pub fn is_b(self) -> bool { self == SliceType::B }
29 pub fn is_s(self) -> bool {
42005e25 30 matches!(self, SliceType::SI | SliceType::SP)
696e4e20
KS
31 }
32 pub fn to_frame_type(self) -> FrameType {
33 match self {
34 SliceType::I | SliceType::SI => FrameType::I,
35 SliceType::P | SliceType::SP => FrameType::P,
36 SliceType::B => FrameType::B,
37 }
38 }
39}
40
41const SLICE_TYPES: [SliceType; 10] = [
42 SliceType::P, SliceType::B, SliceType::I, SliceType::SP, SliceType::SI,
43 SliceType::P, SliceType::B, SliceType::I, SliceType::SP, SliceType::SI,
44];
45
495b7ec0 46#[derive(Clone,Copy,Default)]
696e4e20
KS
47pub struct WeightInfo {
48 pub luma_weighted: bool,
49 pub luma_weight: i8,
50 pub luma_offset: i8,
495b7ec0 51 pub luma_shift: u8,
696e4e20
KS
52 pub chroma_weighted: bool,
53 pub chroma_weight: [i8; 2],
54 pub chroma_offset: [i8; 2],
495b7ec0
KS
55 pub chroma_shift: u8,
56}
57
58impl WeightInfo {
59 pub fn is_weighted(&self) -> bool {
60 self.luma_weighted || self.chroma_weighted
61 }
696e4e20
KS
62}
63
64#[derive(Clone,Copy)]
65pub struct ReorderingInfo {
66 pub reordering_of_pic_nums_idc: [u8; MAX_FRAMES],
67 pub abs_diff_or_num: [u16; MAX_FRAMES],
68 pub num_ops: usize,
69}
70
71#[derive(Clone,Copy)]
72pub struct AdaptiveMarking {
73 pub memory_management_control_op: [u8; MAX_FRAMES],
74 pub operation_arg: [u16; MAX_FRAMES],
75 pub operation_arg2: [u16; MAX_FRAMES],
76 pub num_ops: usize,
77}
78
79#[derive(Clone)]
80pub struct SliceHeader {
81 pub first_mb_in_slice: usize,
82 pub slice_type: SliceType,
83 pub same_slice_type: bool,
84 pub pic_parameter_set_id: u32,
85 pub frame_num: u16,
86 pub field_pic: bool,
87 pub bottom_field: bool,
88 pub idr_pic_id: u16,
89 pub pic_order_cnt_lsb: u16,
90 pub delta_pic_order_cnt_bottom: i32,
91 pub delta_pic_order_cnt: [i32; 2],
92 pub redundant_pic_cnt: u8,
93 pub direct_spatial_mv_pred: bool,
94 pub num_ref_idx_active_override: bool,
95 pub num_ref_idx_l0_active: usize,
96 pub num_ref_idx_l1_active: usize,
97 pub ref_pic_list_reordering_l0: bool,
98 pub reordering_list_l0: ReorderingInfo,
99 pub ref_pic_list_reordering_l1: bool,
100 pub reordering_list_l1: ReorderingInfo,
101 pub luma_log2_weight_denom: u8,
102 pub chroma_log2_weight_denom: u8,
103 pub weights_l0: [WeightInfo; MAX_FRAMES],
104 pub weights_l1: [WeightInfo; MAX_FRAMES],
105 pub no_output_of_prior_pics: bool,
106 pub long_term_reference: bool,
107 pub adaptive_ref_pic_marking_mode: bool,
108 pub adaptive_ref_pic_marking: AdaptiveMarking,
109 pub cabac_init_idc: u8,
110 pub slice_qp_delta: i32,
111 pub slice_qp: u8,
112 pub sp_for_switch: bool,
113 pub slice_qs_delta: i32,
114 pub slice_qs: u8,
115 pub disable_deblocking_filter_idc: u8,
116 pub slice_alpha_c0_offset: i8,
117 pub slice_beta_offset: i8,
118 pub slice_group_change_cycle: u32,
119}
120
495b7ec0
KS
121pub const DEF_WEIGHT_INFO: WeightInfo = WeightInfo {
122 luma_weighted: false,
123 luma_weight: 0,
124 luma_offset: 0,
125 luma_shift: 0,
126 chroma_weighted: false,
127 chroma_weight: [0; 2],
128 chroma_offset: [0; 2],
129 chroma_shift: 0,
130};
131
132impl SliceHeader {
133 pub fn get_weight(&self, list_id: u8, idx: usize) -> WeightInfo {
134 if list_id == 0 {
135 if idx < self.num_ref_idx_l0_active {
136 self.weights_l0[idx]
137 } else {
138 DEF_WEIGHT_INFO
139 }
140 } else {
141 if idx < self.num_ref_idx_l1_active {
142 self.weights_l1[idx]
143 } else {
144 DEF_WEIGHT_INFO
145 }
146 }
147 }
148}
149
696e4e20
KS
150pub fn parse_slice_header_minimal(br: &mut BitReader) -> DecoderResult<(usize, SliceType)> {
151 let first_mb_in_slice = br.read_ue()? as usize;
152 let stype = br.read_ue_lim(SLICE_TYPES.len() as u32 - 1)?;
153 let slice_type = SLICE_TYPES[stype as usize];
154 Ok((first_mb_in_slice, slice_type))
155}
156
b7c882c1 157#[allow(clippy::cognitive_complexity)]
42005e25 158#[allow(clippy::manual_range_contains)]
93839abd 159pub fn parse_slice_header(br: &mut BitReader, sps_arr: &[Arc<SeqParameterSet>], pps_arr: &[Arc<PicParameterSet>], is_idr: bool, nal_ref_idc: u8) -> DecoderResult<SliceHeader> {
696e4e20
KS
160 let mut hdr: SliceHeader = unsafe { std::mem::zeroed() };
161
162 hdr.first_mb_in_slice = br.read_ue()? as usize;
163 let stype = br.read_ue_lim(SLICE_TYPES.len() as u32 - 1)?;
164 hdr.slice_type = SLICE_TYPES[stype as usize];
165 hdr.same_slice_type = stype >= 5;
166 hdr.pic_parameter_set_id = br.read_ue()?;
167
168 let mut pps_ptr = None;
169 for pps in pps_arr.iter() {
170 if pps.pic_parameter_set_id == hdr.pic_parameter_set_id {
171 pps_ptr = Some(pps);
172 break;
173 }
174 }
175 validate!(pps_ptr.is_some());
176 let pps = pps_ptr.unwrap();
177 let mut sps_ptr = None;
178 for sps in sps_arr.iter() {
179 if sps.seq_parameter_set_id == pps.seq_parameter_set_id {
180 sps_ptr = Some(sps);
181 break;
182 }
183 }
184 validate!(sps_ptr.is_some());
185 let sps = sps_ptr.unwrap();
186
187 hdr.frame_num = br.read(sps.log2_max_frame_num)? as u16;
188 if !sps.frame_mbs_only {
189 hdr.field_pic = br.read_bool()?;
190 if hdr.field_pic {
191 hdr.bottom_field = br.read_bool()?;
192 }
193 }
194
195 if is_idr {
196 hdr.idr_pic_id = br.read_ue_lim(65535)? as u16;
197 }
198 if sps.pic_order_cnt_type == 0 {
199 hdr.pic_order_cnt_lsb = br.read(sps.log2_max_pic_order_cnt_lsb)? as u16;
200 if pps.pic_order_present && !hdr.field_pic {
201 hdr.delta_pic_order_cnt_bottom = br.read_se()?;
202 }
203 } else if sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero {
204 hdr.delta_pic_order_cnt[0] = br.read_se()?;
205 if pps.pic_order_present && !hdr.field_pic {
206 hdr.delta_pic_order_cnt[1] = br.read_se()?;
207 }
208 }
209 if pps.redundant_pic_cnt_present {
210 hdr.redundant_pic_cnt = br.read_ue_lim(127)? as u8;
211 }
212 if hdr.slice_type.is_b() {
213 hdr.direct_spatial_mv_pred = br.read_bool()?;
214 }
215 if !hdr.slice_type.is_intra() {
216 hdr.num_ref_idx_active_override = br.read_bool()?;
217 if hdr.num_ref_idx_active_override {
218 hdr.num_ref_idx_l0_active = (br.read_ue_lim(15)? + 1) as usize;
219 if hdr.slice_type.is_b() {
220 hdr.num_ref_idx_l1_active = (br.read_ue_lim(15)? + 1) as usize;
221 }
222 } else {
223 hdr.num_ref_idx_l0_active = pps.num_ref_idx_l0_active;
224 if hdr.slice_type.is_b() {
225 hdr.num_ref_idx_l1_active = pps.num_ref_idx_l1_active;
226 }
227 }
228 }
229 parse_ref_pic_list_reordering(&mut hdr, br)?;
230 if (pps.weighted_pred && hdr.slice_type.is_p()) ||
231 (pps.weighted_bipred_idc == 1 && hdr.slice_type.is_b()) {
232 parse_pred_weight_table(&mut hdr, br)?;
495b7ec0
KS
233 } else {
234 for weight in hdr.weights_l0[..hdr.num_ref_idx_l0_active].iter_mut() {
235 weight.luma_weighted = false;
236 weight.chroma_weighted = false;
237 }
238 for weight in hdr.weights_l1[..hdr.num_ref_idx_l1_active].iter_mut() {
239 weight.luma_weighted = false;
240 weight.chroma_weighted = false;
241 }
696e4e20
KS
242 }
243 if nal_ref_idc != 0 {
244 if is_idr {
245 hdr.no_output_of_prior_pics = br.read_bool()?;
246 hdr.long_term_reference = br.read_bool()?;
247 } else {
248 hdr.adaptive_ref_pic_marking_mode = br.read_bool()?;
249 if hdr.adaptive_ref_pic_marking_mode {
250 let mark_info = &mut hdr.adaptive_ref_pic_marking;
251 loop {
252 let memory_management_control_op = br.read_ue_lim(6)? as u8;
253 if memory_management_control_op == 0 {
254 break;
255 }
256 if mark_info.num_ops >= mark_info.memory_management_control_op.len() {
257 return Err(DecoderError::NotImplemented);
258 }
259 mark_info.memory_management_control_op[mark_info.num_ops] = memory_management_control_op;
260 mark_info.operation_arg[mark_info.num_ops] = match memory_management_control_op {
261 1 | 3 => {
262 let difference_of_pic_nums = br.read_ue()? + 1;
263 difference_of_pic_nums as u16
264 },
265 2 => {
266 let long_term_pic_num = br.read_ue_lim(65535)?;
267 long_term_pic_num as u16
268 },
269 6 => {
270 let long_term_frame_idx = br.read_ue_lim(65536)?;
271 long_term_frame_idx as u16
272 },
273 4 => {
274 let max_long_term_frame_idx_plus1 = br.read_ue()?;
275 max_long_term_frame_idx_plus1 as u16
276 },
277 _ => 0,
278 };
279 mark_info.operation_arg2[mark_info.num_ops] = if memory_management_control_op == 3 {
280 let long_term_frame_idx = br.read_ue_lim(65536)?;
281 long_term_frame_idx as u16
282 } else {
283 0
284 };
285 mark_info.num_ops += 1;
286 }
287 }
288 }
289 }
290 if pps.entropy_coding_mode && !hdr.slice_type.is_intra() {
291 hdr.cabac_init_idc = br.read_ue_lim(2)? as u8;
292 }
293 hdr.slice_qp_delta = br.read_se()?;
294 let qp = i32::from(pps.pic_init_qp) + hdr.slice_qp_delta;
295 validate!(qp >= 0 && qp <= 51);
296 hdr.slice_qp = qp as u8;
297 if hdr.slice_type.is_s() {
298 if hdr.slice_type == SliceType::SP {
299 hdr.sp_for_switch = br.read_bool()?;
300 }
301 hdr.slice_qs_delta = br.read_se()?;
302 let qs = i32::from(pps.pic_init_qs) + hdr.slice_qs_delta;
303 validate!(qs >= 0 && qs <= 51);
304 hdr.slice_qs = qs as u8;
305 }
306 if pps.deblocking_filter_control_present {
307 hdr.disable_deblocking_filter_idc = br.read_ue_lim(2)? as u8;
308 if hdr.disable_deblocking_filter_idc != 1 {
309 let val = br.read_se()?;
310 validate!(val >= -6 && val <= 6);
311 hdr.slice_alpha_c0_offset = val as i8 * 2;
312 let val = br.read_se()?;
313 validate!(val >= -6 && val <= 6);
314 hdr.slice_beta_offset = val as i8 * 2;
315 }
316 }
317 if pps.num_slice_groups > 1 && pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5 {
318 hdr.slice_group_change_cycle = br.read_ue()?;
319 }
320
321 Ok(hdr)
322}
323
324fn parse_ref_pic_list_reordering(hdr: &mut SliceHeader, br: &mut BitReader) -> DecoderResult<()> {
325 if !hdr.slice_type.is_intra() {
326 hdr.ref_pic_list_reordering_l0 = br.read_bool()?;
327 let reord_list = &mut hdr.reordering_list_l0;
328 reord_list.num_ops = 0;
329 if hdr.ref_pic_list_reordering_l0 {
330 loop {
331 let reordering_of_pic_nums_idc = br.read_ue_lim(3)?;
332 if reordering_of_pic_nums_idc == 3 {
333 break;
334 }
335 validate!(reord_list.num_ops < MAX_FRAMES);
336 reord_list.reordering_of_pic_nums_idc[reord_list.num_ops] = reordering_of_pic_nums_idc as u8;
337 if reordering_of_pic_nums_idc != 2 {
338 let abs_diff_pic_num = br.read_ue()? + 1;
339 reord_list.abs_diff_or_num[reord_list.num_ops] = abs_diff_pic_num as u16;
340 } else {
341 let long_term_pic_num = br.read_ue()?;
342 reord_list.abs_diff_or_num[reord_list.num_ops] = long_term_pic_num as u16;
343 }
344 reord_list.num_ops += 1;
345 }
346 validate!(reord_list.num_ops > 0);
347 }
348 }
349 if hdr.slice_type.is_b() {
350 hdr.ref_pic_list_reordering_l1 = br.read_bool()?;
351 let reord_list = &mut hdr.reordering_list_l1;
352 reord_list.num_ops = 0;
353 if hdr.ref_pic_list_reordering_l1 {
354 loop {
355 let reordering_of_pic_nums_idc = br.read_ue_lim(3)?;
356 if reordering_of_pic_nums_idc == 3 {
357 break;
358 }
359 validate!(reord_list.num_ops < MAX_FRAMES);
360 reord_list.reordering_of_pic_nums_idc[reord_list.num_ops] = reordering_of_pic_nums_idc as u8;
361 if reordering_of_pic_nums_idc != 2 {
362 let abs_diff_pic_num = br.read_ue()? + 1;
363 reord_list.abs_diff_or_num[reord_list.num_ops] = abs_diff_pic_num as u16;
364 } else {
365 let long_term_pic_num = br.read_ue()?;
366 reord_list.abs_diff_or_num[reord_list.num_ops] = long_term_pic_num as u16;
367 }
368 reord_list.num_ops += 1;
369 }
370 validate!(reord_list.num_ops > 0);
371 }
372 }
373 Ok(())
374}
375
376fn parse_pred_weight_table(hdr: &mut SliceHeader, br: &mut BitReader) -> DecoderResult<()> {
377 hdr.luma_log2_weight_denom = br.read_ue_lim(7)? as u8;
378 hdr.chroma_log2_weight_denom = br.read_ue_lim(7)? as u8;
379 for weight in hdr.weights_l0[..hdr.num_ref_idx_l0_active].iter_mut() {
380 weight.luma_weighted = br.read_bool()?;
381 if weight.luma_weighted {
382 let w = br.read_se()?;
383 validate!(w >= -128 && w <= 127);
384 weight.luma_weight = w as i8;
385 let offset = br.read_se()?;
386 validate!(offset >= -128 && offset <= 127);
387 weight.luma_offset = offset as i8;
388 }
495b7ec0
KS
389 weight.luma_shift = hdr.luma_log2_weight_denom;
390
696e4e20
KS
391 weight.chroma_weighted = br.read_bool()?;
392 if weight.chroma_weighted {
393 for i in 0..2 {
394 let w = br.read_se()?;
395 validate!(w >= -128 && w <= 127);
396 weight.chroma_weight[i] = w as i8;
397 let offset = br.read_se()?;
398 validate!(offset >= -128 && offset <= 127);
399 weight.chroma_offset[i] = offset as i8;
400 }
401 }
495b7ec0 402 weight.chroma_shift = hdr.chroma_log2_weight_denom;
696e4e20
KS
403 }
404 for weight in hdr.weights_l1[..hdr.num_ref_idx_l1_active].iter_mut() {
405 weight.luma_weighted = br.read_bool()?;
406 if weight.luma_weighted {
407 let w = br.read_se()?;
408 validate!(w >= -128 && w <= 127);
409 weight.luma_weight = w as i8;
410 let offset = br.read_se()?;
411 validate!(offset >= -128 && offset <= 127);
412 weight.luma_offset = offset as i8;
413 }
495b7ec0
KS
414 weight.luma_shift = hdr.luma_log2_weight_denom;
415
696e4e20
KS
416 weight.chroma_weighted = br.read_bool()?;
417 if weight.chroma_weighted {
418 for i in 0..2 {
419 let w = br.read_se()?;
420 validate!(w >= -128 && w <= 127);
421 weight.chroma_weight[i] = w as i8;
422 let offset = br.read_se()?;
423 validate!(offset >= -128 && offset <= 127);
424 weight.chroma_offset[i] = offset as i8;
425 }
426 }
495b7ec0 427 weight.chroma_shift = hdr.chroma_log2_weight_denom;
696e4e20
KS
428 }
429
430 Ok(())
431}