| 1 | use std::sync::Arc; |
| 2 | |
| 3 | use nihav_core::codecs::{DecoderResult, DecoderError}; |
| 4 | use nihav_core::io::bitreader::*; |
| 5 | |
| 6 | use super::ReadUE; |
| 7 | |
| 8 | #[derive(Clone)] |
| 9 | pub struct SeqParameterSet { |
| 10 | pub profile_idc: u8, |
| 11 | pub high_profile: bool, |
| 12 | pub constraint_set0: bool, |
| 13 | pub constraint_set1: bool, |
| 14 | pub constraint_set2: bool, |
| 15 | pub level_idc: u8, |
| 16 | pub seq_parameter_set_id: u32, |
| 17 | pub chroma_format_idc: u8, |
| 18 | pub separate_colour_plane: bool, |
| 19 | pub bit_depth_luma: u8, |
| 20 | pub bit_depth_chroma: u8, |
| 21 | pub qpprime_y_zero_transform_bypass: bool, |
| 22 | pub seq_scaling_matrix_present: bool, |
| 23 | pub scaling_list_4x4: [[u8; 16]; 6], |
| 24 | pub scaling_list_8x8: [[u8; 64]; 6], |
| 25 | pub log2_max_frame_num: u8, |
| 26 | pub pic_order_cnt_type: u8, |
| 27 | pub log2_max_pic_order_cnt_lsb: u8, |
| 28 | pub delta_pic_order_always_zero: bool, |
| 29 | pub offset_for_non_ref_pic: i32, |
| 30 | pub offset_for_top_to_bottom_field: i32, |
| 31 | pub num_ref_frames_in_pic_order_cnt_cycle: usize, |
| 32 | pub offset_for_ref_frame: [i32; 256], |
| 33 | pub num_ref_frames: usize, |
| 34 | pub gaps_in_frame_num_value_allowed: bool, |
| 35 | pub pic_width_in_mbs: usize, |
| 36 | pub pic_height_in_mbs: usize, |
| 37 | pub frame_mbs_only: bool, |
| 38 | pub mb_adaptive_frame_field: bool, |
| 39 | pub direct_8x8_inference: bool, |
| 40 | pub frame_cropping: bool, |
| 41 | pub frame_crop_left_offset: usize, |
| 42 | pub frame_crop_right_offset: usize, |
| 43 | pub frame_crop_top_offset: usize, |
| 44 | pub frame_crop_bottom_offset: usize, |
| 45 | pub vui_parameters_present: bool, |
| 46 | } |
| 47 | |
| 48 | pub fn is_high_profile(profile: u8) -> bool { |
| 49 | matches!(profile, 100 | 110 | 122 | 244 | 44 | 83 | 86 | 118 | 128 | 138 | 139 | 134 | 125) |
| 50 | } |
| 51 | |
| 52 | #[allow(clippy::cognitive_complexity)] |
| 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: &[Arc<SeqParameterSet>], full_size: usize) -> DecoderResult<Arc<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(Arc::new(pps)) |
| 423 | } |