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