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