1 use nihav_core::codecs::{DecoderResult, DecoderError};
2 use nihav_core::frame::FrameType;
3 use nihav_core::io::bitreader::*;
8 pub const MAX_FRAMES: usize = 32;
10 #[derive(Clone,Copy,Debug,PartialEq)]
20 pub fn is_intra(self) -> bool {
21 matches!(self, SliceType::I | SliceType::SI)
23 pub fn is_p(self) -> bool {
24 matches!(self, SliceType::P | SliceType::SP)
26 pub fn is_b(self) -> bool { self == SliceType::B }
27 pub fn is_s(self) -> bool {
28 matches!(self, SliceType::SI | SliceType::SP)
30 pub fn to_frame_type(self) -> FrameType {
32 SliceType::I | SliceType::SI => FrameType::I,
33 SliceType::P | SliceType::SP => FrameType::P,
34 SliceType::B => FrameType::B,
39 const SLICE_TYPES: [SliceType; 10] = [
40 SliceType::P, SliceType::B, SliceType::I, SliceType::SP, SliceType::SI,
41 SliceType::P, SliceType::B, SliceType::I, SliceType::SP, SliceType::SI,
44 #[derive(Clone,Copy,Default)]
45 pub struct WeightInfo {
46 pub luma_weighted: bool,
50 pub chroma_weighted: bool,
51 pub chroma_weight: [i8; 2],
52 pub chroma_offset: [i8; 2],
57 pub fn is_weighted(&self) -> bool {
58 self.luma_weighted || self.chroma_weighted
63 pub struct ReorderingInfo {
64 pub reordering_of_pic_nums_idc: [u8; MAX_FRAMES],
65 pub abs_diff_or_num: [u16; MAX_FRAMES],
70 pub struct AdaptiveMarking {
71 pub memory_management_control_op: [u8; MAX_FRAMES],
72 pub operation_arg: [u16; MAX_FRAMES],
73 pub operation_arg2: [u16; MAX_FRAMES],
78 pub struct SliceHeader {
79 pub first_mb_in_slice: usize,
80 pub slice_type: SliceType,
81 pub same_slice_type: bool,
82 pub pic_parameter_set_id: u32,
85 pub bottom_field: bool,
87 pub pic_order_cnt_lsb: u16,
88 pub delta_pic_order_cnt_bottom: i32,
89 pub delta_pic_order_cnt: [i32; 2],
90 pub redundant_pic_cnt: u8,
91 pub direct_spatial_mv_pred: bool,
92 pub num_ref_idx_active_override: bool,
93 pub num_ref_idx_l0_active: usize,
94 pub num_ref_idx_l1_active: usize,
95 pub ref_pic_list_reordering_l0: bool,
96 pub reordering_list_l0: ReorderingInfo,
97 pub ref_pic_list_reordering_l1: bool,
98 pub reordering_list_l1: ReorderingInfo,
99 pub luma_log2_weight_denom: u8,
100 pub chroma_log2_weight_denom: u8,
101 pub weights_l0: [WeightInfo; MAX_FRAMES],
102 pub weights_l1: [WeightInfo; MAX_FRAMES],
103 pub no_output_of_prior_pics: bool,
104 pub long_term_reference: bool,
105 pub adaptive_ref_pic_marking_mode: bool,
106 pub adaptive_ref_pic_marking: AdaptiveMarking,
107 pub cabac_init_idc: u8,
108 pub slice_qp_delta: i32,
110 pub sp_for_switch: bool,
111 pub slice_qs_delta: i32,
113 pub disable_deblocking_filter_idc: u8,
114 pub slice_alpha_c0_offset: i8,
115 pub slice_beta_offset: i8,
116 pub slice_group_change_cycle: u32,
119 pub const DEF_WEIGHT_INFO: WeightInfo = WeightInfo {
120 luma_weighted: false,
124 chroma_weighted: false,
125 chroma_weight: [0; 2],
126 chroma_offset: [0; 2],
131 pub fn get_weight(&self, list_id: u8, idx: usize) -> WeightInfo {
133 if idx < self.num_ref_idx_l0_active {
139 if idx < self.num_ref_idx_l1_active {
148 pub fn parse_slice_header_minimal(br: &mut BitReader) -> DecoderResult<(usize, SliceType)> {
149 let first_mb_in_slice = br.read_ue()? as usize;
150 let stype = br.read_ue_lim(SLICE_TYPES.len() as u32 - 1)?;
151 let slice_type = SLICE_TYPES[stype as usize];
152 Ok((first_mb_in_slice, slice_type))
155 #[allow(clippy::cognitive_complexity)]
156 #[allow(clippy::manual_range_contains)]
157 pub fn parse_slice_header(br: &mut BitReader, sps_arr: &[SeqParameterSet], pps_arr: &[PicParameterSet], is_idr: bool, nal_ref_idc: u8) -> DecoderResult<SliceHeader> {
158 let mut hdr: SliceHeader = unsafe { std::mem::zeroed() };
160 hdr.first_mb_in_slice = br.read_ue()? as usize;
161 let stype = br.read_ue_lim(SLICE_TYPES.len() as u32 - 1)?;
162 hdr.slice_type = SLICE_TYPES[stype as usize];
163 hdr.same_slice_type = stype >= 5;
164 hdr.pic_parameter_set_id = br.read_ue()?;
166 let mut pps_ptr = None;
167 for pps in pps_arr.iter() {
168 if pps.pic_parameter_set_id == hdr.pic_parameter_set_id {
173 validate!(pps_ptr.is_some());
174 let pps = pps_ptr.unwrap();
175 let mut sps_ptr = None;
176 for sps in sps_arr.iter() {
177 if sps.seq_parameter_set_id == pps.seq_parameter_set_id {
182 validate!(sps_ptr.is_some());
183 let sps = sps_ptr.unwrap();
185 hdr.frame_num = br.read(sps.log2_max_frame_num)? as u16;
186 if !sps.frame_mbs_only {
187 hdr.field_pic = br.read_bool()?;
189 hdr.bottom_field = br.read_bool()?;
194 hdr.idr_pic_id = br.read_ue_lim(65535)? as u16;
196 if sps.pic_order_cnt_type == 0 {
197 hdr.pic_order_cnt_lsb = br.read(sps.log2_max_pic_order_cnt_lsb)? as u16;
198 if pps.pic_order_present && !hdr.field_pic {
199 hdr.delta_pic_order_cnt_bottom = br.read_se()?;
201 } else if sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero {
202 hdr.delta_pic_order_cnt[0] = br.read_se()?;
203 if pps.pic_order_present && !hdr.field_pic {
204 hdr.delta_pic_order_cnt[1] = br.read_se()?;
207 if pps.redundant_pic_cnt_present {
208 hdr.redundant_pic_cnt = br.read_ue_lim(127)? as u8;
210 if hdr.slice_type.is_b() {
211 hdr.direct_spatial_mv_pred = br.read_bool()?;
213 if !hdr.slice_type.is_intra() {
214 hdr.num_ref_idx_active_override = br.read_bool()?;
215 if hdr.num_ref_idx_active_override {
216 hdr.num_ref_idx_l0_active = (br.read_ue_lim(15)? + 1) as usize;
217 if hdr.slice_type.is_b() {
218 hdr.num_ref_idx_l1_active = (br.read_ue_lim(15)? + 1) as usize;
221 hdr.num_ref_idx_l0_active = pps.num_ref_idx_l0_active;
222 if hdr.slice_type.is_b() {
223 hdr.num_ref_idx_l1_active = pps.num_ref_idx_l1_active;
227 parse_ref_pic_list_reordering(&mut hdr, br)?;
228 if (pps.weighted_pred && hdr.slice_type.is_p()) ||
229 (pps.weighted_bipred_idc == 1 && hdr.slice_type.is_b()) {
230 parse_pred_weight_table(&mut hdr, br)?;
232 for weight in hdr.weights_l0[..hdr.num_ref_idx_l0_active].iter_mut() {
233 weight.luma_weighted = false;
234 weight.chroma_weighted = false;
236 for weight in hdr.weights_l1[..hdr.num_ref_idx_l1_active].iter_mut() {
237 weight.luma_weighted = false;
238 weight.chroma_weighted = false;
241 if nal_ref_idc != 0 {
243 hdr.no_output_of_prior_pics = br.read_bool()?;
244 hdr.long_term_reference = br.read_bool()?;
246 hdr.adaptive_ref_pic_marking_mode = br.read_bool()?;
247 if hdr.adaptive_ref_pic_marking_mode {
248 let mark_info = &mut hdr.adaptive_ref_pic_marking;
250 let memory_management_control_op = br.read_ue_lim(6)? as u8;
251 if memory_management_control_op == 0 {
254 if mark_info.num_ops >= mark_info.memory_management_control_op.len() {
255 return Err(DecoderError::NotImplemented);
257 mark_info.memory_management_control_op[mark_info.num_ops] = memory_management_control_op;
258 mark_info.operation_arg[mark_info.num_ops] = match memory_management_control_op {
260 let difference_of_pic_nums = br.read_ue()? + 1;
261 difference_of_pic_nums as u16
264 let long_term_pic_num = br.read_ue_lim(65535)?;
265 long_term_pic_num as u16
268 let long_term_frame_idx = br.read_ue_lim(65536)?;
269 long_term_frame_idx as u16
272 let max_long_term_frame_idx_plus1 = br.read_ue()?;
273 max_long_term_frame_idx_plus1 as u16
277 mark_info.operation_arg2[mark_info.num_ops] = if memory_management_control_op == 3 {
278 let long_term_frame_idx = br.read_ue_lim(65536)?;
279 long_term_frame_idx as u16
283 mark_info.num_ops += 1;
288 if pps.entropy_coding_mode && !hdr.slice_type.is_intra() {
289 hdr.cabac_init_idc = br.read_ue_lim(2)? as u8;
291 hdr.slice_qp_delta = br.read_se()?;
292 let qp = i32::from(pps.pic_init_qp) + hdr.slice_qp_delta;
293 validate!(qp >= 0 && qp <= 51);
294 hdr.slice_qp = qp as u8;
295 if hdr.slice_type.is_s() {
296 if hdr.slice_type == SliceType::SP {
297 hdr.sp_for_switch = br.read_bool()?;
299 hdr.slice_qs_delta = br.read_se()?;
300 let qs = i32::from(pps.pic_init_qs) + hdr.slice_qs_delta;
301 validate!(qs >= 0 && qs <= 51);
302 hdr.slice_qs = qs as u8;
304 if pps.deblocking_filter_control_present {
305 hdr.disable_deblocking_filter_idc = br.read_ue_lim(2)? as u8;
306 if hdr.disable_deblocking_filter_idc != 1 {
307 let val = br.read_se()?;
308 validate!(val >= -6 && val <= 6);
309 hdr.slice_alpha_c0_offset = val as i8 * 2;
310 let val = br.read_se()?;
311 validate!(val >= -6 && val <= 6);
312 hdr.slice_beta_offset = val as i8 * 2;
315 if pps.num_slice_groups > 1 && pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5 {
316 hdr.slice_group_change_cycle = br.read_ue()?;
322 fn parse_ref_pic_list_reordering(hdr: &mut SliceHeader, br: &mut BitReader) -> DecoderResult<()> {
323 if !hdr.slice_type.is_intra() {
324 hdr.ref_pic_list_reordering_l0 = br.read_bool()?;
325 let reord_list = &mut hdr.reordering_list_l0;
326 reord_list.num_ops = 0;
327 if hdr.ref_pic_list_reordering_l0 {
329 let reordering_of_pic_nums_idc = br.read_ue_lim(3)?;
330 if reordering_of_pic_nums_idc == 3 {
333 validate!(reord_list.num_ops < MAX_FRAMES);
334 reord_list.reordering_of_pic_nums_idc[reord_list.num_ops] = reordering_of_pic_nums_idc as u8;
335 if reordering_of_pic_nums_idc != 2 {
336 let abs_diff_pic_num = br.read_ue()? + 1;
337 reord_list.abs_diff_or_num[reord_list.num_ops] = abs_diff_pic_num as u16;
339 let long_term_pic_num = br.read_ue()?;
340 reord_list.abs_diff_or_num[reord_list.num_ops] = long_term_pic_num as u16;
342 reord_list.num_ops += 1;
344 validate!(reord_list.num_ops > 0);
347 if hdr.slice_type.is_b() {
348 hdr.ref_pic_list_reordering_l1 = br.read_bool()?;
349 let reord_list = &mut hdr.reordering_list_l1;
350 reord_list.num_ops = 0;
351 if hdr.ref_pic_list_reordering_l1 {
353 let reordering_of_pic_nums_idc = br.read_ue_lim(3)?;
354 if reordering_of_pic_nums_idc == 3 {
357 validate!(reord_list.num_ops < MAX_FRAMES);
358 reord_list.reordering_of_pic_nums_idc[reord_list.num_ops] = reordering_of_pic_nums_idc as u8;
359 if reordering_of_pic_nums_idc != 2 {
360 let abs_diff_pic_num = br.read_ue()? + 1;
361 reord_list.abs_diff_or_num[reord_list.num_ops] = abs_diff_pic_num as u16;
363 let long_term_pic_num = br.read_ue()?;
364 reord_list.abs_diff_or_num[reord_list.num_ops] = long_term_pic_num as u16;
366 reord_list.num_ops += 1;
368 validate!(reord_list.num_ops > 0);
374 fn parse_pred_weight_table(hdr: &mut SliceHeader, br: &mut BitReader) -> DecoderResult<()> {
375 hdr.luma_log2_weight_denom = br.read_ue_lim(7)? as u8;
376 hdr.chroma_log2_weight_denom = br.read_ue_lim(7)? as u8;
377 for weight in hdr.weights_l0[..hdr.num_ref_idx_l0_active].iter_mut() {
378 weight.luma_weighted = br.read_bool()?;
379 if weight.luma_weighted {
380 let w = br.read_se()?;
381 validate!(w >= -128 && w <= 127);
382 weight.luma_weight = w as i8;
383 let offset = br.read_se()?;
384 validate!(offset >= -128 && offset <= 127);
385 weight.luma_offset = offset as i8;
387 weight.luma_shift = hdr.luma_log2_weight_denom;
389 weight.chroma_weighted = br.read_bool()?;
390 if weight.chroma_weighted {
392 let w = br.read_se()?;
393 validate!(w >= -128 && w <= 127);
394 weight.chroma_weight[i] = w as i8;
395 let offset = br.read_se()?;
396 validate!(offset >= -128 && offset <= 127);
397 weight.chroma_offset[i] = offset as i8;
400 weight.chroma_shift = hdr.chroma_log2_weight_denom;
402 for weight in hdr.weights_l1[..hdr.num_ref_idx_l1_active].iter_mut() {
403 weight.luma_weighted = br.read_bool()?;
404 if weight.luma_weighted {
405 let w = br.read_se()?;
406 validate!(w >= -128 && w <= 127);
407 weight.luma_weight = w as i8;
408 let offset = br.read_se()?;
409 validate!(offset >= -128 && offset <= 127);
410 weight.luma_offset = offset as i8;
412 weight.luma_shift = hdr.luma_log2_weight_denom;
414 weight.chroma_weighted = br.read_bool()?;
415 if weight.chroma_weighted {
417 let w = br.read_se()?;
418 validate!(w >= -128 && w <= 127);
419 weight.chroma_weight[i] = w as i8;
420 let offset = br.read_se()?;
421 validate!(offset >= -128 && offset <= 127);
422 weight.chroma_offset[i] = offset as i8;
425 weight.chroma_shift = hdr.chroma_log2_weight_denom;