mostly working ITU H.264 decoder
[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 pub fn parse_slice_header(br: &mut BitReader, sps_arr: &[SeqParameterSet], pps_arr: &[PicParameterSet], is_idr: bool, nal_ref_idc: u8) -> DecoderResult<SliceHeader> {
128 let mut hdr: SliceHeader = unsafe { std::mem::zeroed() };
129
130 hdr.first_mb_in_slice = br.read_ue()? as usize;
131 let stype = br.read_ue_lim(SLICE_TYPES.len() as u32 - 1)?;
132 hdr.slice_type = SLICE_TYPES[stype as usize];
133 hdr.same_slice_type = stype >= 5;
134 hdr.pic_parameter_set_id = br.read_ue()?;
135
136 let mut pps_ptr = None;
137 for pps in pps_arr.iter() {
138 if pps.pic_parameter_set_id == hdr.pic_parameter_set_id {
139 pps_ptr = Some(pps);
140 break;
141 }
142 }
143 validate!(pps_ptr.is_some());
144 let pps = pps_ptr.unwrap();
145 let mut sps_ptr = None;
146 for sps in sps_arr.iter() {
147 if sps.seq_parameter_set_id == pps.seq_parameter_set_id {
148 sps_ptr = Some(sps);
149 break;
150 }
151 }
152 validate!(sps_ptr.is_some());
153 let sps = sps_ptr.unwrap();
154
155 hdr.frame_num = br.read(sps.log2_max_frame_num)? as u16;
156 if !sps.frame_mbs_only {
157 hdr.field_pic = br.read_bool()?;
158 if hdr.field_pic {
159 hdr.bottom_field = br.read_bool()?;
160 }
161 }
162
163 if is_idr {
164 hdr.idr_pic_id = br.read_ue_lim(65535)? as u16;
165 }
166 if sps.pic_order_cnt_type == 0 {
167 hdr.pic_order_cnt_lsb = br.read(sps.log2_max_pic_order_cnt_lsb)? as u16;
168 if pps.pic_order_present && !hdr.field_pic {
169 hdr.delta_pic_order_cnt_bottom = br.read_se()?;
170 }
171 } else if sps.pic_order_cnt_type == 1 && !sps.delta_pic_order_always_zero {
172 hdr.delta_pic_order_cnt[0] = br.read_se()?;
173 if pps.pic_order_present && !hdr.field_pic {
174 hdr.delta_pic_order_cnt[1] = br.read_se()?;
175 }
176 }
177 if pps.redundant_pic_cnt_present {
178 hdr.redundant_pic_cnt = br.read_ue_lim(127)? as u8;
179 }
180 if hdr.slice_type.is_b() {
181 hdr.direct_spatial_mv_pred = br.read_bool()?;
182 }
183 if !hdr.slice_type.is_intra() {
184 hdr.num_ref_idx_active_override = br.read_bool()?;
185 if hdr.num_ref_idx_active_override {
186 hdr.num_ref_idx_l0_active = (br.read_ue_lim(15)? + 1) as usize;
187 if hdr.slice_type.is_b() {
188 hdr.num_ref_idx_l1_active = (br.read_ue_lim(15)? + 1) as usize;
189 }
190 } else {
191 hdr.num_ref_idx_l0_active = pps.num_ref_idx_l0_active;
192 if hdr.slice_type.is_b() {
193 hdr.num_ref_idx_l1_active = pps.num_ref_idx_l1_active;
194 }
195 }
196 }
197 parse_ref_pic_list_reordering(&mut hdr, br)?;
198 if (pps.weighted_pred && hdr.slice_type.is_p()) ||
199 (pps.weighted_bipred_idc == 1 && hdr.slice_type.is_b()) {
200 parse_pred_weight_table(&mut hdr, br)?;
201 }
202 if nal_ref_idc != 0 {
203 if is_idr {
204 hdr.no_output_of_prior_pics = br.read_bool()?;
205 hdr.long_term_reference = br.read_bool()?;
206 } else {
207 hdr.adaptive_ref_pic_marking_mode = br.read_bool()?;
208 if hdr.adaptive_ref_pic_marking_mode {
209 let mark_info = &mut hdr.adaptive_ref_pic_marking;
210 loop {
211 let memory_management_control_op = br.read_ue_lim(6)? as u8;
212 if memory_management_control_op == 0 {
213 break;
214 }
215 if mark_info.num_ops >= mark_info.memory_management_control_op.len() {
216 return Err(DecoderError::NotImplemented);
217 }
218 mark_info.memory_management_control_op[mark_info.num_ops] = memory_management_control_op;
219 mark_info.operation_arg[mark_info.num_ops] = match memory_management_control_op {
220 1 | 3 => {
221 let difference_of_pic_nums = br.read_ue()? + 1;
222 difference_of_pic_nums as u16
223 },
224 2 => {
225 let long_term_pic_num = br.read_ue_lim(65535)?;
226 long_term_pic_num as u16
227 },
228 6 => {
229 let long_term_frame_idx = br.read_ue_lim(65536)?;
230 long_term_frame_idx as u16
231 },
232 4 => {
233 let max_long_term_frame_idx_plus1 = br.read_ue()?;
234 max_long_term_frame_idx_plus1 as u16
235 },
236 _ => 0,
237 };
238 mark_info.operation_arg2[mark_info.num_ops] = if memory_management_control_op == 3 {
239 let long_term_frame_idx = br.read_ue_lim(65536)?;
240 long_term_frame_idx as u16
241 } else {
242 0
243 };
244 mark_info.num_ops += 1;
245 }
246 }
247 }
248 }
249 if pps.entropy_coding_mode && !hdr.slice_type.is_intra() {
250 hdr.cabac_init_idc = br.read_ue_lim(2)? as u8;
251 }
252 hdr.slice_qp_delta = br.read_se()?;
253 let qp = i32::from(pps.pic_init_qp) + hdr.slice_qp_delta;
254 validate!(qp >= 0 && qp <= 51);
255 hdr.slice_qp = qp as u8;
256 if hdr.slice_type.is_s() {
257 if hdr.slice_type == SliceType::SP {
258 hdr.sp_for_switch = br.read_bool()?;
259 }
260 hdr.slice_qs_delta = br.read_se()?;
261 let qs = i32::from(pps.pic_init_qs) + hdr.slice_qs_delta;
262 validate!(qs >= 0 && qs <= 51);
263 hdr.slice_qs = qs as u8;
264 }
265 if pps.deblocking_filter_control_present {
266 hdr.disable_deblocking_filter_idc = br.read_ue_lim(2)? as u8;
267 if hdr.disable_deblocking_filter_idc != 1 {
268 let val = br.read_se()?;
269 validate!(val >= -6 && val <= 6);
270 hdr.slice_alpha_c0_offset = val as i8 * 2;
271 let val = br.read_se()?;
272 validate!(val >= -6 && val <= 6);
273 hdr.slice_beta_offset = val as i8 * 2;
274 }
275 }
276 if pps.num_slice_groups > 1 && pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5 {
277 hdr.slice_group_change_cycle = br.read_ue()?;
278 }
279
280 Ok(hdr)
281 }
282
283 fn parse_ref_pic_list_reordering(hdr: &mut SliceHeader, br: &mut BitReader) -> DecoderResult<()> {
284 if !hdr.slice_type.is_intra() {
285 hdr.ref_pic_list_reordering_l0 = br.read_bool()?;
286 let reord_list = &mut hdr.reordering_list_l0;
287 reord_list.num_ops = 0;
288 if hdr.ref_pic_list_reordering_l0 {
289 loop {
290 let reordering_of_pic_nums_idc = br.read_ue_lim(3)?;
291 if reordering_of_pic_nums_idc == 3 {
292 break;
293 }
294 validate!(reord_list.num_ops < MAX_FRAMES);
295 reord_list.reordering_of_pic_nums_idc[reord_list.num_ops] = reordering_of_pic_nums_idc as u8;
296 if reordering_of_pic_nums_idc != 2 {
297 let abs_diff_pic_num = br.read_ue()? + 1;
298 reord_list.abs_diff_or_num[reord_list.num_ops] = abs_diff_pic_num as u16;
299 } else {
300 let long_term_pic_num = br.read_ue()?;
301 reord_list.abs_diff_or_num[reord_list.num_ops] = long_term_pic_num as u16;
302 }
303 reord_list.num_ops += 1;
304 }
305 validate!(reord_list.num_ops > 0);
306 }
307 }
308 if hdr.slice_type.is_b() {
309 hdr.ref_pic_list_reordering_l1 = br.read_bool()?;
310 let reord_list = &mut hdr.reordering_list_l1;
311 reord_list.num_ops = 0;
312 if hdr.ref_pic_list_reordering_l1 {
313 loop {
314 let reordering_of_pic_nums_idc = br.read_ue_lim(3)?;
315 if reordering_of_pic_nums_idc == 3 {
316 break;
317 }
318 validate!(reord_list.num_ops < MAX_FRAMES);
319 reord_list.reordering_of_pic_nums_idc[reord_list.num_ops] = reordering_of_pic_nums_idc as u8;
320 if reordering_of_pic_nums_idc != 2 {
321 let abs_diff_pic_num = br.read_ue()? + 1;
322 reord_list.abs_diff_or_num[reord_list.num_ops] = abs_diff_pic_num as u16;
323 } else {
324 let long_term_pic_num = br.read_ue()?;
325 reord_list.abs_diff_or_num[reord_list.num_ops] = long_term_pic_num as u16;
326 }
327 reord_list.num_ops += 1;
328 }
329 validate!(reord_list.num_ops > 0);
330 }
331 }
332 Ok(())
333 }
334
335 fn parse_pred_weight_table(hdr: &mut SliceHeader, br: &mut BitReader) -> DecoderResult<()> {
336 hdr.luma_log2_weight_denom = br.read_ue_lim(7)? as u8;
337 hdr.chroma_log2_weight_denom = br.read_ue_lim(7)? as u8;
338 for weight in hdr.weights_l0[..hdr.num_ref_idx_l0_active].iter_mut() {
339 weight.luma_weighted = br.read_bool()?;
340 if weight.luma_weighted {
341 let w = br.read_se()?;
342 validate!(w >= -128 && w <= 127);
343 weight.luma_weight = w as i8;
344 let offset = br.read_se()?;
345 validate!(offset >= -128 && offset <= 127);
346 weight.luma_offset = offset as i8;
347 }
348 weight.chroma_weighted = br.read_bool()?;
349 if weight.chroma_weighted {
350 for i in 0..2 {
351 let w = br.read_se()?;
352 validate!(w >= -128 && w <= 127);
353 weight.chroma_weight[i] = w as i8;
354 let offset = br.read_se()?;
355 validate!(offset >= -128 && offset <= 127);
356 weight.chroma_offset[i] = offset as i8;
357 }
358 }
359 }
360 for weight in hdr.weights_l1[..hdr.num_ref_idx_l1_active].iter_mut() {
361 weight.luma_weighted = br.read_bool()?;
362 if weight.luma_weighted {
363 let w = br.read_se()?;
364 validate!(w >= -128 && w <= 127);
365 weight.luma_weight = w as i8;
366 let offset = br.read_se()?;
367 validate!(offset >= -128 && offset <= 127);
368 weight.luma_offset = offset as i8;
369 }
370 weight.chroma_weighted = br.read_bool()?;
371 if weight.chroma_weighted {
372 for i in 0..2 {
373 let w = br.read_se()?;
374 validate!(w >= -128 && w <= 127);
375 weight.chroma_weight[i] = w as i8;
376 let offset = br.read_se()?;
377 validate!(offset >= -128 && offset <= 127);
378 weight.chroma_offset[i] = offset as i8;
379 }
380 }
381 }
382
383 Ok(())
384 }