]>
Commit | Line | Data |
---|---|---|
1 | use nihav_core::codecs::{DecoderResult, DecoderError}; | |
2 | use nihav_core::io::bitreader::*; | |
3 | ||
4 | use super::ReadUE; | |
5 | ||
6 | #[derive(Clone)] | |
7 | pub struct SeqParameterSet { | |
8 | pub profile_idc: u8, | |
9 | pub high_profile: bool, | |
10 | pub constraint_set0: bool, | |
11 | pub constraint_set1: bool, | |
12 | pub constraint_set2: bool, | |
13 | pub level_idc: u8, | |
14 | pub seq_parameter_set_id: u32, | |
15 | pub chroma_format_idc: u8, | |
16 | pub separate_colour_plane: bool, | |
17 | pub bit_depth_luma: u8, | |
18 | pub bit_depth_chroma: u8, | |
19 | pub qpprime_y_zero_transform_bypass: bool, | |
20 | pub seq_scaling_matrix_present: bool, | |
21 | pub scaling_list_4x4: [[u8; 16]; 6], | |
22 | pub scaling_list_8x8: [[u8; 64]; 6], | |
23 | pub log2_max_frame_num: u8, | |
24 | pub pic_order_cnt_type: u8, | |
25 | pub log2_max_pic_order_cnt_lsb: u8, | |
26 | pub delta_pic_order_always_zero: bool, | |
27 | pub offset_for_non_ref_pic: i32, | |
28 | pub offset_for_top_to_bottom_field: i32, | |
29 | pub num_ref_frames_in_pic_order_cnt_cycle: usize, | |
30 | pub offset_for_ref_frame: [i32; 256], | |
31 | pub num_ref_frames: usize, | |
32 | pub gaps_in_frame_num_value_allowed: bool, | |
33 | pub pic_width_in_mbs: usize, | |
34 | pub pic_height_in_mbs: usize, | |
35 | pub frame_mbs_only: bool, | |
36 | pub mb_adaptive_frame_field: bool, | |
37 | pub direct_8x8_inference: bool, | |
38 | pub frame_cropping: bool, | |
39 | pub frame_crop_left_offset: usize, | |
40 | pub frame_crop_right_offset: usize, | |
41 | pub frame_crop_top_offset: usize, | |
42 | pub frame_crop_bottom_offset: usize, | |
43 | pub vui_parameters_present: bool, | |
44 | } | |
45 | ||
46 | pub fn is_high_profile(profile: u8) -> bool { | |
47 | match profile { | |
48 | 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 125 => true, | |
49 | _ => false, | |
50 | } | |
51 | } | |
52 | ||
53 | pub fn parse_sps(src: &[u8]) -> DecoderResult<SeqParameterSet> { | |
54 | let mut br = BitReader::new(src, BitReaderMode::BE); | |
55 | let mut sps: SeqParameterSet = unsafe { std::mem::zeroed() }; | |
56 | ||
57 | sps.profile_idc = br.read(8)? as u8; | |
58 | sps.constraint_set0 = br.read_bool()?; | |
59 | sps.constraint_set1 = br.read_bool()?; | |
60 | sps.constraint_set2 = br.read_bool()?; | |
61 | let reserved = br.read(5)?; | |
62 | validate!(reserved == 0); | |
63 | sps.level_idc = br.read(8)? as u8; | |
64 | sps.seq_parameter_set_id = br.read_ue()?; | |
65 | sps.high_profile = is_high_profile(sps.profile_idc); | |
66 | if sps.high_profile { | |
67 | sps.chroma_format_idc = br.read_ue_lim(3)? as u8; | |
68 | if sps.chroma_format_idc == 3 { | |
69 | sps.separate_colour_plane = br.read_bool()?; | |
70 | } | |
71 | sps.bit_depth_luma = br.read_ue_lim(6)? as u8 + 8; | |
72 | sps.bit_depth_chroma = br.read_ue_lim(6)? as u8 + 8; | |
73 | sps.qpprime_y_zero_transform_bypass = br.read_bool()?; | |
74 | sps.seq_scaling_matrix_present = br.read_bool()?; | |
75 | if sps.seq_scaling_matrix_present { | |
76 | let mut slist_present = [false; 6]; | |
77 | for (i, slist) in sps.scaling_list_4x4.iter_mut().enumerate() { | |
78 | slist_present[i] = br.read_bool()?; | |
79 | if slist_present[i] { | |
80 | parse_scaling_list(&mut br, slist, i < 3)?; | |
81 | } | |
82 | } | |
83 | for i in 1..6 { | |
84 | if i == 3 { | |
85 | continue; | |
86 | } | |
87 | if !slist_present[i] { | |
88 | sps.scaling_list_4x4[i] = sps.scaling_list_4x4[i - 1]; | |
89 | } | |
90 | } | |
91 | ||
92 | let mut slist_present = [false; 6]; | |
93 | let num_8x8 = if sps.chroma_format_idc != 3 { 2 } else { 6 }; | |
94 | for (i, slist) in sps.scaling_list_8x8.iter_mut().take(num_8x8).enumerate() { | |
95 | slist_present[i] = br.read_bool()?; | |
96 | if slist_present[i] { | |
97 | parse_scaling_list(&mut br, slist, (i & 1) == 0)?; | |
98 | } | |
99 | } | |
100 | if num_8x8 > 2 { | |
101 | for i in 2..6 { | |
102 | if !slist_present[i] { | |
103 | sps.scaling_list_8x8[i] = sps.scaling_list_8x8[i - 2]; | |
104 | } | |
105 | } | |
106 | } | |
107 | } else { | |
108 | sps.scaling_list_4x4 = [[16; 16]; 6]; | |
109 | sps.scaling_list_8x8 = [[16; 64]; 6]; | |
110 | } | |
111 | } else { | |
112 | sps.chroma_format_idc = 1; | |
113 | sps.bit_depth_luma = 8; | |
114 | sps.bit_depth_chroma = 8; | |
115 | } | |
116 | sps.log2_max_frame_num = (br.read_ue_lim(12)? + 4) as u8; | |
117 | sps.pic_order_cnt_type = br.read_ue_lim(2)? as u8; | |
118 | match sps.pic_order_cnt_type { | |
119 | 0 => { | |
120 | sps.log2_max_pic_order_cnt_lsb = (br.read_ue_lim(12)? + 4) as u8; | |
121 | }, | |
122 | 1 => { | |
123 | sps.delta_pic_order_always_zero = br.read_bool()?; | |
124 | sps.offset_for_non_ref_pic = br.read_se()?; | |
125 | sps.offset_for_top_to_bottom_field = br.read_se()?; | |
126 | sps.num_ref_frames_in_pic_order_cnt_cycle = br.read_ue_lim(255)? as usize; | |
127 | for offset in sps.offset_for_ref_frame[..sps.num_ref_frames_in_pic_order_cnt_cycle].iter_mut() { | |
128 | *offset = br.read_se()?; | |
129 | } | |
130 | }, | |
131 | _ => {}, | |
132 | }; | |
133 | sps.num_ref_frames = br.read_ue()? as usize; | |
134 | validate!(sps.num_ref_frames <= super::slice::MAX_FRAMES); | |
135 | sps.gaps_in_frame_num_value_allowed = br.read_bool()?; | |
136 | sps.pic_width_in_mbs = (br.read_ue()? + 1) as usize; | |
137 | sps.pic_height_in_mbs = (br.read_ue()? + 1) as usize; | |
138 | validate!(sps.pic_width_in_mbs <= 1024 && sps.pic_height_in_mbs <= 1024); | |
139 | sps.frame_mbs_only = br.read_bool()?; | |
140 | if !sps.frame_mbs_only { | |
141 | sps.mb_adaptive_frame_field = br.read_bool()?; | |
142 | } | |
143 | sps.direct_8x8_inference = br.read_bool()?; | |
144 | sps.frame_cropping = br.read_bool()?; | |
145 | if sps.frame_cropping { | |
146 | sps.frame_crop_left_offset = br.read_ue()? as usize; | |
147 | sps.frame_crop_right_offset = br.read_ue()? as usize; | |
148 | sps.frame_crop_top_offset = br.read_ue()? as usize; | |
149 | sps.frame_crop_bottom_offset = br.read_ue()? as usize; | |
150 | let l = sps.frame_crop_left_offset * 2; | |
151 | let r = sps.pic_width_in_mbs * 16 - sps.frame_crop_right_offset * 2; | |
152 | let t = sps.frame_crop_top_offset * 2; | |
153 | let d = sps.pic_height_in_mbs * 16 - sps.frame_crop_bottom_offset * 2; | |
154 | validate!(l < r && t < d); | |
155 | } | |
156 | sps.vui_parameters_present = br.read_bool()?; | |
157 | if sps.vui_parameters_present { | |
158 | // xxx: vui is ignored for now | |
159 | if br.read_bool()? { | |
160 | let idc = br.read(8)?; | |
161 | if idc == 255 { | |
162 | br.read(16)?; | |
163 | br.read(16)?; | |
164 | } | |
165 | } | |
166 | if br.read_bool()? { | |
167 | br.read_bool()?; | |
168 | } | |
169 | if br.read_bool()? { | |
170 | br.read(3)?; | |
171 | br.read_bool()?; | |
172 | if br.read_bool()? { | |
173 | br.read(8)?; | |
174 | br.read(8)?; | |
175 | br.read(8)?; | |
176 | } | |
177 | } | |
178 | if br.read_bool()? { | |
179 | br.read_ue()?; | |
180 | br.read_ue()?; | |
181 | } | |
182 | if br.read_bool()? { | |
183 | br.read(32)?; | |
184 | br.read(32)?; | |
185 | br.read_bool()?; | |
186 | } | |
187 | let nal_hrd_parameters_present = br.read_bool()?; | |
188 | if nal_hrd_parameters_present { | |
189 | skip_hrd_parameters(&mut br)?; | |
190 | } | |
191 | let vcl_hrd_parameters_present = br.read_bool()?; | |
192 | if vcl_hrd_parameters_present { | |
193 | skip_hrd_parameters(&mut br)?; | |
194 | } | |
195 | if nal_hrd_parameters_present || vcl_hrd_parameters_present { | |
196 | br.read_bool()?; | |
197 | } | |
198 | br.read_bool()?; | |
199 | if br.read_bool()? { | |
200 | br.read_bool()?; | |
201 | br.read_ue()?; | |
202 | br.read_ue()?; | |
203 | br.read_ue()?; | |
204 | br.read_ue()?; | |
205 | br.read_ue()?; | |
206 | br.read_ue()?; | |
207 | } | |
208 | } | |
209 | ||
210 | Ok(sps) | |
211 | } | |
212 | ||
213 | fn parse_scaling_list(br: &mut BitReader, slist: &mut[u8], is_intra: bool) -> DecoderResult<()> { | |
214 | const DEFAULT_INTRA_4X4: [u8; 16] = [ | |
215 | 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 | |
216 | ]; | |
217 | const DEFAULT_INTER_4X4: [u8; 16] = [ | |
218 | 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34 | |
219 | ]; | |
220 | const DEFAULT_INTRA_8X8: [u8; 64] = [ | |
221 | 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, | |
222 | 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, | |
223 | 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, | |
224 | 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 | |
225 | ]; | |
226 | const DEFAULT_INTER_8X8: [u8; 64] = [ | |
227 | 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, | |
228 | 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, | |
229 | 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, | |
230 | 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 | |
231 | ]; | |
232 | let mut last_scale = 8u8; | |
233 | let mut next_scale = 8u8; | |
234 | let mut use_default = false; | |
235 | for (j, elem) in slist.iter_mut().enumerate() { | |
236 | if next_scale != 0 { | |
237 | let delta = br.read_se()?; | |
238 | next_scale = last_scale.wrapping_add(delta as u8); | |
239 | if (j == 0) && (next_scale == 0) { | |
240 | use_default = true; | |
241 | break; | |
242 | } | |
243 | } | |
244 | *elem = if next_scale == 0 { last_scale } else { next_scale }; | |
245 | last_scale = *elem; | |
246 | } | |
247 | if use_default { | |
248 | match (slist.len(), is_intra) { | |
249 | (16, true) => slist.copy_from_slice(&DEFAULT_INTRA_4X4), | |
250 | (16, false) => slist.copy_from_slice(&DEFAULT_INTER_4X4), | |
251 | (64, true) => slist.copy_from_slice(&DEFAULT_INTRA_8X8), | |
252 | (64, false) => slist.copy_from_slice(&DEFAULT_INTER_8X8), | |
253 | _ => unreachable!(), | |
254 | }; | |
255 | } | |
256 | Ok(()) | |
257 | } | |
258 | ||
259 | fn skip_hrd_parameters(br: &mut BitReader) -> DecoderResult<()> { | |
260 | let cpb_cnt = br.read_ue()? as usize + 1; | |
261 | br.read(4)?; | |
262 | br.read(4)?; | |
263 | for _ in 0..cpb_cnt { | |
264 | br.read_ue()?; | |
265 | br.read_ue()?; | |
266 | br.read_bool()?; | |
267 | } | |
268 | br.read(5)?; | |
269 | br.read(5)?; | |
270 | br.read(5)?; | |
271 | br.read(5)?; | |
272 | Ok(()) | |
273 | } | |
274 | ||
275 | const MAX_SLICE_GROUPS: usize = 8; | |
276 | ||
277 | #[derive(Clone)] | |
278 | pub struct PicParameterSet { | |
279 | pub pic_parameter_set_id: u32, | |
280 | pub seq_parameter_set_id: u32, | |
281 | pub entropy_coding_mode: bool, | |
282 | pub pic_order_present: bool, | |
283 | pub num_slice_groups: usize, | |
284 | pub slice_group_map_type: u8, | |
285 | pub run_length: [u32; MAX_SLICE_GROUPS], | |
286 | pub top_left: [u32; MAX_SLICE_GROUPS], | |
287 | pub bottom_right: [u32; MAX_SLICE_GROUPS], | |
288 | pub slice_group_change_direction: bool, | |
289 | pub slice_group_change_rate: u32, | |
290 | pub pic_size_in_map_units: u32, | |
291 | pub num_ref_idx_l0_active: usize, | |
292 | pub num_ref_idx_l1_active: usize, | |
293 | pub weighted_pred: bool, | |
294 | pub weighted_bipred_idc: u8, | |
295 | pub pic_init_qp: u8, | |
296 | pub pic_init_qs: u8, | |
297 | pub chroma_qp_index_offset: i8, | |
298 | pub deblocking_filter_control_present: bool, | |
299 | pub constrained_intra_pred: bool, | |
300 | pub redundant_pic_cnt_present: bool, | |
301 | pub transform_8x8_mode: bool, | |
302 | pub pic_scaling_matrix_present: bool, | |
303 | pub scaling_list_4x4: [[u8; 16]; 6], | |
304 | pub scaling_list_8x8: [[u8; 64]; 6], | |
305 | pub second_chroma_qp_index_offset: i8, | |
306 | } | |
307 | ||
308 | pub fn parse_pps(src: &[u8], sps_arr: &[SeqParameterSet], full_size: usize) -> DecoderResult<PicParameterSet> { | |
309 | let mut br = BitReader::new(src, BitReaderMode::BE); | |
310 | let mut pps: PicParameterSet = unsafe { std::mem::zeroed() }; | |
311 | ||
312 | pps.pic_parameter_set_id = br.read_ue()?; | |
313 | pps.seq_parameter_set_id = br.read_ue()?; | |
314 | let mut found = false; | |
315 | let mut cur_sps = None; | |
316 | for sps in sps_arr.iter() { | |
317 | if sps.seq_parameter_set_id == pps.seq_parameter_set_id { | |
318 | found = true; | |
319 | cur_sps = Some(sps); | |
320 | break; | |
321 | } | |
322 | } | |
323 | validate!(found); | |
324 | let sps = cur_sps.unwrap(); | |
325 | pps.entropy_coding_mode = br.read_bool()?; | |
326 | pps.pic_order_present = br.read_bool()?; | |
327 | pps.num_slice_groups = (br.read_ue()? + 1) as usize; | |
328 | validate!(pps.num_slice_groups <= MAX_SLICE_GROUPS); | |
329 | if pps.num_slice_groups > 1 { | |
330 | let smtype = br.read_ue()?; | |
331 | validate!(smtype <= 6); | |
332 | pps.slice_group_map_type = smtype as u8; | |
333 | match pps.slice_group_map_type { | |
334 | 0 => { | |
335 | for elem in pps.run_length[..pps.num_slice_groups].iter_mut() { | |
336 | *elem = br.read_ue()?; | |
337 | } | |
338 | }, | |
339 | 2 => { | |
340 | for i in 0..pps.num_slice_groups - 1 { | |
341 | pps.top_left[i] = br.read_ue()?; | |
342 | pps.bottom_right[i] = br.read_ue()?; | |
343 | } | |
344 | }, | |
345 | 3 | 4 | 5 => { | |
346 | pps.slice_group_change_direction = br.read_bool()?; | |
347 | pps.slice_group_change_rate = br.read_ue()?; | |
348 | }, | |
349 | 6 => { | |
350 | pps.pic_size_in_map_units = br.read_ue()? + 1; | |
351 | for _ in 0..pps.pic_size_in_map_units { | |
352 | let _slice_group_id = br.read_ue()?; | |
353 | } | |
354 | }, | |
355 | _ => {}, | |
356 | }; | |
357 | println!("slice mode!"); | |
358 | return Err(DecoderError::NotImplemented); | |
359 | } | |
360 | pps.num_ref_idx_l0_active = (br.read_ue()? + 1) as usize; | |
361 | pps.num_ref_idx_l1_active = (br.read_ue()? + 1) as usize; | |
362 | pps.weighted_pred = br.read_bool()?; | |
363 | pps.weighted_bipred_idc = br.read(2)? as u8; | |
364 | let qp = br.read_se()? + 26; | |
365 | validate!(qp > 0 && qp < 52); | |
366 | pps.pic_init_qp = qp as u8; | |
367 | let qs = br.read_se()? + 26; | |
368 | validate!(qs > 0 && qs < 52); | |
369 | pps.pic_init_qs = qs as u8; | |
370 | let off = br.read_se()?; | |
371 | validate!(off >= -12 && off <= 12); | |
372 | pps.chroma_qp_index_offset = off as i8; | |
373 | pps.deblocking_filter_control_present = br.read_bool()?; | |
374 | pps.constrained_intra_pred = br.read_bool()?; | |
375 | pps.redundant_pic_cnt_present = br.read_bool()?; | |
376 | if br.tell() < full_size { | |
377 | pps.transform_8x8_mode = br.read_bool()?; | |
378 | pps.pic_scaling_matrix_present = br.read_bool()?; | |
379 | if pps.pic_scaling_matrix_present { | |
380 | let mut slist_present = [false; 6]; | |
381 | for (i, slist) in pps.scaling_list_4x4.iter_mut().enumerate() { | |
382 | slist_present[i] = br.read_bool()?; | |
383 | if slist_present[i] { | |
384 | parse_scaling_list(&mut br, slist, i < 3)?; | |
385 | } | |
386 | } | |
387 | for i in 1..6 { | |
388 | if i == 3 { | |
389 | continue; | |
390 | } | |
391 | if !slist_present[i] { | |
392 | pps.scaling_list_4x4[i] = pps.scaling_list_4x4[i - 1]; | |
393 | } | |
394 | } | |
395 | ||
396 | let mut slist_present = [false; 6]; | |
397 | let num_8x8 = if !pps.transform_8x8_mode { 0 } else if sps.chroma_format_idc != 3 { 2 } else { 6 }; | |
398 | for (i, slist) in pps.scaling_list_8x8.iter_mut().take(num_8x8).enumerate() { | |
399 | slist_present[i] = br.read_bool()?; | |
400 | if slist_present[i] { | |
401 | parse_scaling_list(&mut br, slist, (i & 1) == 0)?; | |
402 | } | |
403 | } | |
404 | if num_8x8 > 2 { | |
405 | for i in 2..6 { | |
406 | if !slist_present[i] { | |
407 | pps.scaling_list_8x8[i] = pps.scaling_list_8x8[i - 2]; | |
408 | } | |
409 | } | |
410 | } | |
411 | } else { | |
412 | pps.scaling_list_4x4 = sps.scaling_list_4x4; | |
413 | pps.scaling_list_8x8 = sps.scaling_list_8x8; | |
414 | } | |
415 | let off = br.read_se()?; | |
416 | validate!(off >= -12 && off <= 12); | |
417 | pps.second_chroma_qp_index_offset = off as i8; | |
418 | } else { | |
419 | pps.second_chroma_qp_index_offset = pps.chroma_qp_index_offset; | |
420 | } | |
421 | ||
422 | Ok(pps) | |
423 | } |