h265_sps_parser.cc (28924B)
1 /* 2 * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "common_video/h265/h265_sps_parser.h" 12 13 #include <algorithm> 14 #include <cmath> 15 #include <cstddef> 16 #include <cstdint> 17 #include <optional> 18 #include <vector> 19 20 #include "api/array_view.h" 21 #include "common_video/h265/h265_common.h" 22 #include "rtc_base/bitstream_reader.h" 23 #include "rtc_base/logging.h" 24 25 #define IN_RANGE_OR_RETURN_NULL(val, min, max) \ 26 do { \ 27 if (!reader.Ok() || (val) < (min) || (val) > (max)) { \ 28 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 29 " to be" \ 30 << " in range [" << (min) << ":" << (max) << "]" \ 31 << " found " << (val) << " instead"; \ 32 return std::nullopt; \ 33 } \ 34 } while (0) 35 36 #define IN_RANGE_OR_RETURN_FALSE(val, min, max) \ 37 do { \ 38 if (!reader.Ok() || (val) < (min) || (val) > (max)) { \ 39 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 40 " to be" \ 41 << " in range [" << (min) << ":" << (max) << "]" \ 42 << " found " << (val) << " instead"; \ 43 return false; \ 44 } \ 45 } while (0) 46 47 #define TRUE_OR_RETURN(a) \ 48 do { \ 49 if (!reader.Ok() || !(a)) { \ 50 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " \ 51 << #a; \ 52 return std::nullopt; \ 53 } \ 54 } while (0) 55 56 namespace { 57 using OptionalSps = std::optional<webrtc::H265SpsParser::SpsState>; 58 using OptionalShortTermRefPicSet = 59 std::optional<webrtc::H265SpsParser::ShortTermRefPicSet>; 60 using OptionalProfileTierLevel = 61 std::optional<webrtc::H265SpsParser::ProfileTierLevel>; 62 63 constexpr int kMaxNumSizeIds = 4; 64 constexpr int kMaxNumMatrixIds = 6; 65 constexpr int kMaxNumCoefs = 64; 66 } // namespace 67 68 namespace webrtc { 69 70 H265SpsParser::ShortTermRefPicSet::ShortTermRefPicSet() = default; 71 72 H265SpsParser::ProfileTierLevel::ProfileTierLevel() = default; 73 74 int H265SpsParser::GetMaxLumaPs(int general_level_idc) { 75 // From Table A.8 - General tier and level limits. 76 // |general_level_idc| is 30x the actual level. 77 if (general_level_idc <= 30) // level 1 78 return 36864; 79 if (general_level_idc <= 60) // level 2 80 return 122880; 81 if (general_level_idc <= 63) // level 2.1 82 return 245760; 83 if (general_level_idc <= 90) // level 3 84 return 552960; 85 if (general_level_idc <= 93) // level 3.1 86 return 983040; 87 if (general_level_idc <= 123) // level 4, 4.1 88 return 2228224; 89 if (general_level_idc <= 156) // level 5, 5.1, 5.2 90 return 8912896; 91 // level 6, 6.1, 6.2 - beyond that there's no actual limit. 92 return 35651584; 93 } 94 95 size_t H265SpsParser::GetDpbMaxPicBuf(int general_profile_idc) { 96 // From A.4.2 - Profile-specific level limits for the video profiles. 97 // If sps_curr_pic_ref_enabled_flag is required to be zero, than this is 6 98 // otherwise it is 7. 99 return (general_profile_idc >= kProfileIdcMain && 100 general_profile_idc <= kProfileIdcHighThroughput) 101 ? 6 102 : 7; 103 } 104 105 // General note: this is based off the 08/2021 version of the H.265 standard. 106 // You can find it on this page: 107 // http://www.itu.int/rec/T-REC-H.265 108 109 // Unpack RBSP and parse SPS state from the supplied buffer. 110 std::optional<H265SpsParser::SpsState> H265SpsParser::ParseSps( 111 ArrayView<const uint8_t> data) { 112 return ParseSpsInternal(H265::ParseRbsp(data)); 113 } 114 115 bool H265SpsParser::ParseScalingListData(BitstreamReader& reader) { 116 int32_t scaling_list_dc_coef_minus8[kMaxNumSizeIds][kMaxNumMatrixIds] = {}; 117 for (int size_id = 0; size_id < kMaxNumSizeIds; size_id++) { 118 for (int matrix_id = 0; matrix_id < kMaxNumMatrixIds; 119 matrix_id += (size_id == 3) ? 3 : 1) { 120 // scaling_list_pred_mode_flag: u(1) 121 bool scaling_list_pred_mode_flag = reader.Read<bool>(); 122 if (!scaling_list_pred_mode_flag) { 123 // scaling_list_pred_matrix_id_delta: ue(v) 124 int scaling_list_pred_matrix_id_delta = reader.ReadExponentialGolomb(); 125 if (size_id <= 2) { 126 IN_RANGE_OR_RETURN_FALSE(scaling_list_pred_matrix_id_delta, 0, 127 matrix_id); 128 } else { // size_id == 3 129 IN_RANGE_OR_RETURN_FALSE(scaling_list_pred_matrix_id_delta, 0, 130 matrix_id / 3); 131 } 132 } else { 133 uint32_t coef_num = std::min(kMaxNumCoefs, 1 << (4 + (size_id << 1))); 134 if (size_id > 1) { 135 // scaling_list_dc_coef_minus8: se(v) 136 scaling_list_dc_coef_minus8[size_id - 2][matrix_id] = 137 reader.ReadSignedExponentialGolomb(); 138 IN_RANGE_OR_RETURN_FALSE( 139 scaling_list_dc_coef_minus8[size_id - 2][matrix_id], -7, 247); 140 } 141 for (uint32_t i = 0; i < coef_num; i++) { 142 // scaling_list_delta_coef: se(v) 143 int32_t scaling_list_delta_coef = 144 reader.ReadSignedExponentialGolomb(); 145 IN_RANGE_OR_RETURN_FALSE(scaling_list_delta_coef, -128, 127); 146 } 147 } 148 } 149 } 150 return reader.Ok(); 151 } 152 153 std::optional<H265SpsParser::ShortTermRefPicSet> 154 H265SpsParser::ParseShortTermRefPicSet( 155 uint32_t st_rps_idx, 156 uint32_t num_short_term_ref_pic_sets, 157 const std::vector<H265SpsParser::ShortTermRefPicSet>& 158 short_term_ref_pic_set, 159 uint32_t sps_max_dec_pic_buffering_minus1, 160 BitstreamReader& reader) { 161 H265SpsParser::ShortTermRefPicSet st_ref_pic_set; 162 163 bool inter_ref_pic_set_prediction_flag = false; 164 if (st_rps_idx != 0) { 165 // inter_ref_pic_set_prediction_flag: u(1) 166 inter_ref_pic_set_prediction_flag = reader.Read<bool>(); 167 } 168 169 if (inter_ref_pic_set_prediction_flag) { 170 uint32_t delta_idx_minus1 = 0; 171 if (st_rps_idx == num_short_term_ref_pic_sets) { 172 // delta_idx_minus1: ue(v) 173 delta_idx_minus1 = reader.ReadExponentialGolomb(); 174 IN_RANGE_OR_RETURN_NULL(delta_idx_minus1, 0, st_rps_idx - 1); 175 } 176 // delta_rps_sign: u(1) 177 int delta_rps_sign = reader.ReadBits(1); 178 // abs_delta_rps_minus1: ue(v) 179 int abs_delta_rps_minus1 = reader.ReadExponentialGolomb(); 180 IN_RANGE_OR_RETURN_NULL(abs_delta_rps_minus1, 0, 0x7FFF); 181 int delta_rps = (1 - 2 * delta_rps_sign) * (abs_delta_rps_minus1 + 1); 182 uint32_t ref_rps_idx = st_rps_idx - (delta_idx_minus1 + 1); 183 uint32_t num_delta_pocs = 184 short_term_ref_pic_set[ref_rps_idx].num_delta_pocs; 185 IN_RANGE_OR_RETURN_NULL(num_delta_pocs, 0, kMaxShortTermRefPicSets); 186 const ShortTermRefPicSet& ref_set = short_term_ref_pic_set[ref_rps_idx]; 187 bool used_by_curr_pic_flag[kMaxShortTermRefPicSets] = {}; 188 bool use_delta_flag[kMaxShortTermRefPicSets] = {}; 189 // 7.4.8 - use_delta_flag defaults to 1 if not present. 190 std::fill_n(use_delta_flag, kMaxShortTermRefPicSets, true); 191 192 for (uint32_t j = 0; j <= num_delta_pocs; j++) { 193 // used_by_curr_pic_flag: u(1) 194 used_by_curr_pic_flag[j] = reader.Read<bool>(); 195 if (!used_by_curr_pic_flag[j]) { 196 // use_delta_flag: u(1) 197 use_delta_flag[j] = reader.Read<bool>(); 198 } 199 } 200 201 // Calculate delta_poc_s{0,1}, used_by_curr_pic_s{0,1}, num_negative_pics 202 // and num_positive_pics. 203 // Equation 7-61 204 int i = 0; 205 IN_RANGE_OR_RETURN_NULL( 206 ref_set.num_negative_pics + ref_set.num_positive_pics, 0, 207 kMaxShortTermRefPicSets); 208 for (int j = ref_set.num_positive_pics - 1; j >= 0; --j) { 209 int d_poc = ref_set.delta_poc_s1[j] + delta_rps; 210 if (d_poc < 0 && use_delta_flag[ref_set.num_negative_pics + j]) { 211 st_ref_pic_set.delta_poc_s0[i] = d_poc; 212 st_ref_pic_set.used_by_curr_pic_s0[i++] = 213 used_by_curr_pic_flag[ref_set.num_negative_pics + j]; 214 } 215 } 216 if (delta_rps < 0 && use_delta_flag[ref_set.num_delta_pocs]) { 217 st_ref_pic_set.delta_poc_s0[i] = delta_rps; 218 st_ref_pic_set.used_by_curr_pic_s0[i++] = 219 used_by_curr_pic_flag[ref_set.num_delta_pocs]; 220 } 221 for (uint32_t j = 0; j < ref_set.num_negative_pics; ++j) { 222 int d_poc = ref_set.delta_poc_s0[j] + delta_rps; 223 if (d_poc < 0 && use_delta_flag[j]) { 224 st_ref_pic_set.delta_poc_s0[i] = d_poc; 225 st_ref_pic_set.used_by_curr_pic_s0[i++] = used_by_curr_pic_flag[j]; 226 } 227 } 228 st_ref_pic_set.num_negative_pics = i; 229 // Equation 7-62 230 i = 0; 231 for (int j = ref_set.num_negative_pics - 1; j >= 0; --j) { 232 int d_poc = ref_set.delta_poc_s0[j] + delta_rps; 233 if (d_poc > 0 && use_delta_flag[j]) { 234 st_ref_pic_set.delta_poc_s1[i] = d_poc; 235 st_ref_pic_set.used_by_curr_pic_s1[i++] = used_by_curr_pic_flag[j]; 236 } 237 } 238 if (delta_rps > 0 && use_delta_flag[ref_set.num_delta_pocs]) { 239 st_ref_pic_set.delta_poc_s1[i] = delta_rps; 240 st_ref_pic_set.used_by_curr_pic_s1[i++] = 241 used_by_curr_pic_flag[ref_set.num_delta_pocs]; 242 } 243 for (uint32_t j = 0; j < ref_set.num_positive_pics; ++j) { 244 int d_poc = ref_set.delta_poc_s1[j] + delta_rps; 245 if (d_poc > 0 && use_delta_flag[ref_set.num_negative_pics + j]) { 246 st_ref_pic_set.delta_poc_s1[i] = d_poc; 247 st_ref_pic_set.used_by_curr_pic_s1[i++] = 248 used_by_curr_pic_flag[ref_set.num_negative_pics + j]; 249 } 250 } 251 st_ref_pic_set.num_positive_pics = i; 252 IN_RANGE_OR_RETURN_NULL(st_ref_pic_set.num_negative_pics, 0, 253 sps_max_dec_pic_buffering_minus1); 254 IN_RANGE_OR_RETURN_NULL( 255 st_ref_pic_set.num_positive_pics, 0, 256 sps_max_dec_pic_buffering_minus1 - st_ref_pic_set.num_negative_pics); 257 258 } else { 259 // num_negative_pics: ue(v) 260 st_ref_pic_set.num_negative_pics = reader.ReadExponentialGolomb(); 261 // num_positive_pics: ue(v) 262 st_ref_pic_set.num_positive_pics = reader.ReadExponentialGolomb(); 263 IN_RANGE_OR_RETURN_NULL(st_ref_pic_set.num_negative_pics, 0, 264 sps_max_dec_pic_buffering_minus1); 265 IN_RANGE_OR_RETURN_NULL( 266 st_ref_pic_set.num_positive_pics, 0, 267 sps_max_dec_pic_buffering_minus1 - st_ref_pic_set.num_negative_pics); 268 269 for (uint32_t i = 0; i < st_ref_pic_set.num_negative_pics; i++) { 270 // delta_poc_s0_minus1: ue(v) 271 int delta_poc_s0_minus1 = 0; 272 delta_poc_s0_minus1 = reader.ReadExponentialGolomb(); 273 IN_RANGE_OR_RETURN_NULL(delta_poc_s0_minus1, 0, 0x7FFF); 274 if (i == 0) { 275 st_ref_pic_set.delta_poc_s0[i] = -(delta_poc_s0_minus1 + 1); 276 } else { 277 st_ref_pic_set.delta_poc_s0[i] = 278 st_ref_pic_set.delta_poc_s0[i - 1] - (delta_poc_s0_minus1 + 1); 279 } 280 // used_by_curr_pic_s0_flag: u(1) 281 st_ref_pic_set.used_by_curr_pic_s0[i] = reader.Read<bool>(); 282 } 283 284 for (uint32_t i = 0; i < st_ref_pic_set.num_positive_pics; i++) { 285 // delta_poc_s1_minus1: ue(v) 286 int delta_poc_s1_minus1 = 0; 287 delta_poc_s1_minus1 = reader.ReadExponentialGolomb(); 288 IN_RANGE_OR_RETURN_NULL(delta_poc_s1_minus1, 0, 0x7FFF); 289 if (i == 0) { 290 st_ref_pic_set.delta_poc_s1[i] = delta_poc_s1_minus1 + 1; 291 } else { 292 st_ref_pic_set.delta_poc_s1[i] = 293 st_ref_pic_set.delta_poc_s1[i - 1] + delta_poc_s1_minus1 + 1; 294 } 295 // used_by_curr_pic_s1_flag: u(1) 296 st_ref_pic_set.used_by_curr_pic_s1[i] = reader.Read<bool>(); 297 } 298 } 299 300 st_ref_pic_set.num_delta_pocs = 301 st_ref_pic_set.num_negative_pics + st_ref_pic_set.num_positive_pics; 302 303 if (!reader.Ok()) { 304 return std::nullopt; 305 } 306 307 return OptionalShortTermRefPicSet(st_ref_pic_set); 308 } 309 310 std::optional<H265SpsParser::ProfileTierLevel> 311 H265SpsParser::ParseProfileTierLevel(bool profile_present, 312 int max_num_sub_layers_minus1, 313 BitstreamReader& reader) { 314 H265SpsParser::ProfileTierLevel pf_tier_level; 315 // 7.4.4 316 if (profile_present) { 317 int general_profile_space; 318 general_profile_space = reader.ReadBits(2); 319 TRUE_OR_RETURN(general_profile_space == 0); 320 // general_tier_flag or reserved 0: u(1) 321 reader.ConsumeBits(1); 322 pf_tier_level.general_profile_idc = reader.ReadBits(5); 323 IN_RANGE_OR_RETURN_NULL(pf_tier_level.general_profile_idc, 0, 11); 324 uint16_t general_profile_compatibility_flag_high16 = reader.ReadBits(16); 325 uint16_t general_profile_compatibility_flag_low16 = reader.ReadBits(16); 326 pf_tier_level.general_profile_compatibility_flags = 327 (general_profile_compatibility_flag_high16 << 16) + 328 general_profile_compatibility_flag_low16; 329 pf_tier_level.general_progressive_source_flag = reader.ReadBits(1); 330 pf_tier_level.general_interlaced_source_flag = reader.ReadBits(1); 331 if (!reader.Ok() || (!pf_tier_level.general_progressive_source_flag && 332 pf_tier_level.general_interlaced_source_flag)) { 333 RTC_LOG(LS_WARNING) << "Interlaced streams not supported"; 334 return std::nullopt; 335 } 336 pf_tier_level.general_non_packed_constraint_flag = reader.ReadBits(1); 337 pf_tier_level.general_frame_only_constraint_flag = reader.ReadBits(1); 338 // general_reserved_zero_7bits 339 reader.ConsumeBits(7); 340 pf_tier_level.general_one_picture_only_constraint_flag = reader.ReadBits(1); 341 // general_reserved_zero_35bits 342 reader.ConsumeBits(35); 343 // general_inbld_flag 344 reader.ConsumeBits(1); 345 } 346 pf_tier_level.general_level_idc = reader.ReadBits(8); 347 bool sub_layer_profile_present_flag[8] = {}; 348 bool sub_layer_level_present_flag[8] = {}; 349 for (int i = 0; i < max_num_sub_layers_minus1; ++i) { 350 sub_layer_profile_present_flag[i] = reader.ReadBits(1); 351 sub_layer_level_present_flag[i] = reader.ReadBits(1); 352 } 353 if (max_num_sub_layers_minus1 > 0) { 354 for (int i = max_num_sub_layers_minus1; i < 8; i++) { 355 reader.ConsumeBits(2); 356 } 357 } 358 for (int i = 0; i < max_num_sub_layers_minus1; i++) { 359 if (sub_layer_profile_present_flag[i]) { 360 // sub_layer_profile_space 361 reader.ConsumeBits(2); 362 // sub_layer_tier_flag 363 reader.ConsumeBits(1); 364 // sub_layer_profile_idc 365 reader.ConsumeBits(5); 366 // sub_layer_profile_compatibility_flag 367 reader.ConsumeBits(32); 368 // sub_layer_{progressive,interlaced}_source_flag 369 reader.ConsumeBits(2); 370 // Ignore sub_layer_non_packed_constraint_flag and 371 // sub_layer_frame_only_constraint_flag. 372 reader.ConsumeBits(2); 373 // Skip the compatibility flags, they are always 43 bits. 374 reader.ConsumeBits(43); 375 // sub_layer_inbld_flag 376 reader.ConsumeBits(1); 377 } 378 if (sub_layer_level_present_flag[i]) { 379 // sub_layer_level_idc 380 reader.ConsumeBits(8); 381 } 382 } 383 384 if (!reader.Ok()) { 385 return std::nullopt; 386 } 387 388 return OptionalProfileTierLevel(pf_tier_level); 389 } 390 391 std::optional<H265SpsParser::SpsState> H265SpsParser::ParseSpsInternal( 392 ArrayView<const uint8_t> buffer) { 393 BitstreamReader reader(buffer); 394 395 // Now, we need to use a bit buffer to parse through the actual H265 SPS 396 // format. See Section 7.3.2.2.1 ("General sequence parameter set data 397 // syntax") of the H.265 standard for a complete description. 398 // Since we only care about resolution, we ignore the majority of fields, but 399 // we still have to actively parse through a lot of the data, since many of 400 // the fields have variable size. 401 // We're particularly interested in: 402 // chroma_format_idc -> affects crop units 403 // pic_{width,height}_* -> resolution of the frame in macroblocks (16x16). 404 // frame_crop_*_offset -> crop information 405 SpsState sps; 406 407 // sps_video_parameter_set_id: u(4) 408 uint32_t sps_video_parameter_set_id = 0; 409 sps_video_parameter_set_id = reader.ReadBits(4); 410 IN_RANGE_OR_RETURN_NULL(sps_video_parameter_set_id, 0, 15); 411 412 // sps_max_sub_layers_minus1: u(3) 413 uint32_t sps_max_sub_layers_minus1 = 0; 414 sps_max_sub_layers_minus1 = reader.ReadBits(3); 415 IN_RANGE_OR_RETURN_NULL(sps_max_sub_layers_minus1, 0, kMaxSubLayers - 1); 416 sps.sps_max_sub_layers_minus1 = sps_max_sub_layers_minus1; 417 // sps_temporal_id_nesting_flag: u(1) 418 reader.ConsumeBits(1); 419 // profile_tier_level(1, sps_max_sub_layers_minus1). 420 OptionalProfileTierLevel profile_tier_level = 421 ParseProfileTierLevel(true, sps.sps_max_sub_layers_minus1, reader); 422 if (!profile_tier_level) { 423 return std::nullopt; 424 } 425 // sps_seq_parameter_set_id: ue(v) 426 sps.sps_id = reader.ReadExponentialGolomb(); 427 IN_RANGE_OR_RETURN_NULL(sps.sps_id, 0, 15); 428 // chrome_format_idc: ue(v) 429 sps.chroma_format_idc = reader.ReadExponentialGolomb(); 430 IN_RANGE_OR_RETURN_NULL(sps.chroma_format_idc, 0, 3); 431 if (sps.chroma_format_idc == 3) { 432 // seperate_colour_plane_flag: u(1) 433 sps.separate_colour_plane_flag = reader.Read<bool>(); 434 } 435 uint32_t pic_width_in_luma_samples = 0; 436 uint32_t pic_height_in_luma_samples = 0; 437 // pic_width_in_luma_samples: ue(v) 438 pic_width_in_luma_samples = reader.ReadExponentialGolomb(); 439 TRUE_OR_RETURN(pic_width_in_luma_samples != 0); 440 // pic_height_in_luma_samples: ue(v) 441 pic_height_in_luma_samples = reader.ReadExponentialGolomb(); 442 TRUE_OR_RETURN(pic_height_in_luma_samples != 0); 443 444 // Equation A-2: Calculate max_dpb_size. 445 uint32_t max_luma_ps = GetMaxLumaPs(profile_tier_level->general_level_idc); 446 uint32_t max_dpb_size = 0; 447 uint32_t pic_size_in_samples_y = pic_height_in_luma_samples; 448 pic_size_in_samples_y *= pic_width_in_luma_samples; 449 size_t max_dpb_pic_buf = 450 GetDpbMaxPicBuf(profile_tier_level->general_profile_idc); 451 if (pic_size_in_samples_y <= (max_luma_ps >> 2)) 452 max_dpb_size = std::min(4 * max_dpb_pic_buf, size_t{16}); 453 else if (pic_size_in_samples_y <= (max_luma_ps >> 1)) 454 max_dpb_size = std::min(2 * max_dpb_pic_buf, size_t{16}); 455 else if (pic_size_in_samples_y <= ((3 * max_luma_ps) >> 2)) 456 max_dpb_size = std::min((4 * max_dpb_pic_buf) / 3, size_t{16}); 457 else 458 max_dpb_size = max_dpb_pic_buf; 459 460 // conformance_window_flag: u(1) 461 bool conformance_window_flag = reader.Read<bool>(); 462 463 uint32_t conf_win_left_offset = 0; 464 uint32_t conf_win_right_offset = 0; 465 uint32_t conf_win_top_offset = 0; 466 uint32_t conf_win_bottom_offset = 0; 467 const int sub_width_c = 468 ((1 == sps.chroma_format_idc) || (2 == sps.chroma_format_idc)) && 469 (0 == sps.separate_colour_plane_flag) 470 ? 2 471 : 1; 472 const int sub_height_c = 473 (1 == sps.chroma_format_idc) && (0 == sps.separate_colour_plane_flag) ? 2 474 : 1; 475 if (conformance_window_flag) { 476 // conf_win_left_offset: ue(v) 477 conf_win_left_offset = reader.ReadExponentialGolomb(); 478 // conf_win_right_offset: ue(v) 479 conf_win_right_offset = reader.ReadExponentialGolomb(); 480 // conf_win_top_offset: ue(v) 481 conf_win_top_offset = reader.ReadExponentialGolomb(); 482 // conf_win_bottom_offset: ue(v) 483 conf_win_bottom_offset = reader.ReadExponentialGolomb(); 484 uint32_t width_crop = conf_win_left_offset; 485 width_crop += conf_win_right_offset; 486 width_crop *= sub_width_c; 487 TRUE_OR_RETURN(width_crop < pic_width_in_luma_samples); 488 uint32_t height_crop = conf_win_top_offset; 489 height_crop += conf_win_bottom_offset; 490 height_crop *= sub_height_c; 491 TRUE_OR_RETURN(height_crop < pic_height_in_luma_samples); 492 } 493 494 // bit_depth_luma_minus8: ue(v) 495 sps.bit_depth_luma_minus8 = reader.ReadExponentialGolomb(); 496 IN_RANGE_OR_RETURN_NULL(sps.bit_depth_luma_minus8, 0, 8); 497 // bit_depth_chroma_minus8: ue(v) 498 uint32_t bit_depth_chroma_minus8 = reader.ReadExponentialGolomb(); 499 IN_RANGE_OR_RETURN_NULL(bit_depth_chroma_minus8, 0, 8); 500 // log2_max_pic_order_cnt_lsb_minus4: ue(v) 501 sps.log2_max_pic_order_cnt_lsb_minus4 = reader.ReadExponentialGolomb(); 502 IN_RANGE_OR_RETURN_NULL(sps.log2_max_pic_order_cnt_lsb_minus4, 0, 12); 503 uint32_t sps_sub_layer_ordering_info_present_flag = 0; 504 // sps_sub_layer_ordering_info_present_flag: u(1) 505 sps_sub_layer_ordering_info_present_flag = reader.Read<bool>(); 506 uint32_t sps_max_num_reorder_pics[kMaxSubLayers] = {}; 507 for (uint32_t i = (sps_sub_layer_ordering_info_present_flag != 0) 508 ? 0 509 : sps_max_sub_layers_minus1; 510 i <= sps_max_sub_layers_minus1; i++) { 511 // sps_max_dec_pic_buffering_minus1: ue(v) 512 sps.sps_max_dec_pic_buffering_minus1[i] = reader.ReadExponentialGolomb(); 513 IN_RANGE_OR_RETURN_NULL(sps.sps_max_dec_pic_buffering_minus1[i], 0, 514 max_dpb_size - 1); 515 // sps_max_num_reorder_pics: ue(v) 516 sps_max_num_reorder_pics[i] = reader.ReadExponentialGolomb(); 517 IN_RANGE_OR_RETURN_NULL(sps_max_num_reorder_pics[i], 0, 518 sps.sps_max_dec_pic_buffering_minus1[i]); 519 if (i > 0) { 520 TRUE_OR_RETURN(sps.sps_max_dec_pic_buffering_minus1[i] >= 521 sps.sps_max_dec_pic_buffering_minus1[i - 1]); 522 TRUE_OR_RETURN(sps_max_num_reorder_pics[i] >= 523 sps_max_num_reorder_pics[i - 1]); 524 } 525 // sps_max_latency_increase_plus1: ue(v) 526 reader.ReadExponentialGolomb(); 527 } 528 if (!sps_sub_layer_ordering_info_present_flag) { 529 // Fill in the default values for the other sublayers. 530 for (uint32_t i = 0; i < sps_max_sub_layers_minus1; ++i) { 531 sps.sps_max_dec_pic_buffering_minus1[i] = 532 sps.sps_max_dec_pic_buffering_minus1[sps_max_sub_layers_minus1]; 533 } 534 } 535 // log2_min_luma_coding_block_size_minus3: ue(v) 536 sps.log2_min_luma_coding_block_size_minus3 = reader.ReadExponentialGolomb(); 537 IN_RANGE_OR_RETURN_NULL(sps.log2_min_luma_coding_block_size_minus3, 0, 27); 538 // log2_diff_max_min_luma_coding_block_size: ue(v) 539 sps.log2_diff_max_min_luma_coding_block_size = reader.ReadExponentialGolomb(); 540 int min_cb_log2_size_y = sps.log2_min_luma_coding_block_size_minus3 + 3; 541 int ctb_log2_size_y = min_cb_log2_size_y; 542 ctb_log2_size_y += sps.log2_diff_max_min_luma_coding_block_size; 543 IN_RANGE_OR_RETURN_NULL(ctb_log2_size_y, 0, 30); 544 int min_cb_size_y = 1 << min_cb_log2_size_y; 545 int ctb_size_y = 1 << ctb_log2_size_y; 546 sps.pic_width_in_ctbs_y = 547 std::ceil(static_cast<float>(pic_width_in_luma_samples) / ctb_size_y); 548 sps.pic_height_in_ctbs_y = 549 std::ceil(static_cast<float>(pic_height_in_luma_samples) / ctb_size_y); 550 TRUE_OR_RETURN(pic_width_in_luma_samples % min_cb_size_y == 0); 551 TRUE_OR_RETURN(pic_height_in_luma_samples % min_cb_size_y == 0); 552 // log2_min_luma_transform_block_size_minus2: ue(v) 553 int log2_min_luma_transform_block_size_minus2 = 554 reader.ReadExponentialGolomb(); 555 IN_RANGE_OR_RETURN_NULL(log2_min_luma_transform_block_size_minus2, 0, 556 min_cb_log2_size_y - 3); 557 int min_tb_log2_size_y = log2_min_luma_transform_block_size_minus2 + 2; 558 // log2_diff_max_min_luma_transform_block_size: ue(v) 559 int log2_diff_max_min_luma_transform_block_size = 560 reader.ReadExponentialGolomb(); 561 TRUE_OR_RETURN(log2_diff_max_min_luma_transform_block_size <= 562 std::min(ctb_log2_size_y, 5) - min_tb_log2_size_y); 563 // max_transform_hierarchy_depth_inter: ue(v) 564 int max_transform_hierarchy_depth_inter = reader.ReadExponentialGolomb(); 565 IN_RANGE_OR_RETURN_NULL(max_transform_hierarchy_depth_inter, 0, 566 ctb_log2_size_y - min_tb_log2_size_y); 567 // max_transform_hierarchy_depth_intra: ue(v) 568 int max_transform_hierarchy_depth_intra = reader.ReadExponentialGolomb(); 569 IN_RANGE_OR_RETURN_NULL(max_transform_hierarchy_depth_intra, 0, 570 ctb_log2_size_y - min_tb_log2_size_y); 571 // scaling_list_enabled_flag: u(1) 572 bool scaling_list_enabled_flag = reader.Read<bool>(); 573 if (scaling_list_enabled_flag) { 574 // sps_scaling_list_data_present_flag: u(1) 575 bool sps_scaling_list_data_present_flag = reader.Read<bool>(); 576 if (sps_scaling_list_data_present_flag) { 577 // scaling_list_data() 578 if (!ParseScalingListData(reader)) { 579 return std::nullopt; 580 } 581 } 582 } 583 584 // amp_enabled_flag: u(1) 585 reader.ConsumeBits(1); 586 // sample_adaptive_offset_enabled_flag: u(1) 587 sps.sample_adaptive_offset_enabled_flag = reader.Read<bool>(); 588 // pcm_enabled_flag: u(1) 589 bool pcm_enabled_flag = reader.Read<bool>(); 590 if (pcm_enabled_flag) { 591 // pcm_sample_bit_depth_luma_minus1: u(4) 592 reader.ConsumeBits(4); 593 // pcm_sample_bit_depth_chroma_minus1: u(4) 594 reader.ConsumeBits(4); 595 // log2_min_pcm_luma_coding_block_size_minus3: ue(v) 596 int log2_min_pcm_luma_coding_block_size_minus3 = 597 reader.ReadExponentialGolomb(); 598 IN_RANGE_OR_RETURN_NULL(log2_min_pcm_luma_coding_block_size_minus3, 0, 2); 599 int log2_min_ipcm_cb_size_y = 600 log2_min_pcm_luma_coding_block_size_minus3 + 3; 601 IN_RANGE_OR_RETURN_NULL(log2_min_ipcm_cb_size_y, 602 std::min(min_cb_log2_size_y, 5), 603 std::min(ctb_log2_size_y, 5)); 604 // log2_diff_max_min_pcm_luma_coding_block_size: ue(v) 605 int log2_diff_max_min_pcm_luma_coding_block_size = 606 reader.ReadExponentialGolomb(); 607 TRUE_OR_RETURN(log2_diff_max_min_pcm_luma_coding_block_size <= 608 std::min(ctb_log2_size_y, 5) - log2_min_ipcm_cb_size_y); 609 // pcm_loop_filter_disabled_flag: u(1) 610 reader.ConsumeBits(1); 611 } 612 613 // num_short_term_ref_pic_sets: ue(v) 614 sps.num_short_term_ref_pic_sets = reader.ReadExponentialGolomb(); 615 IN_RANGE_OR_RETURN_NULL(sps.num_short_term_ref_pic_sets, 0, 616 kMaxShortTermRefPicSets); 617 sps.short_term_ref_pic_set.resize(sps.num_short_term_ref_pic_sets); 618 for (uint32_t st_rps_idx = 0; st_rps_idx < sps.num_short_term_ref_pic_sets; 619 st_rps_idx++) { 620 uint32_t sps_max_dec_pic_buffering_minus1 = 621 sps.sps_max_dec_pic_buffering_minus1[sps.sps_max_sub_layers_minus1]; 622 // st_ref_pic_set() 623 OptionalShortTermRefPicSet ref_pic_set = ParseShortTermRefPicSet( 624 st_rps_idx, sps.num_short_term_ref_pic_sets, sps.short_term_ref_pic_set, 625 sps_max_dec_pic_buffering_minus1, reader); 626 if (ref_pic_set) { 627 sps.short_term_ref_pic_set[st_rps_idx] = *ref_pic_set; 628 } else { 629 return std::nullopt; 630 } 631 } 632 633 // long_term_ref_pics_present_flag: u(1) 634 sps.long_term_ref_pics_present_flag = reader.Read<bool>(); 635 if (sps.long_term_ref_pics_present_flag) { 636 // num_long_term_ref_pics_sps: ue(v) 637 sps.num_long_term_ref_pics_sps = reader.ReadExponentialGolomb(); 638 IN_RANGE_OR_RETURN_NULL(sps.num_long_term_ref_pics_sps, 0, 639 kMaxLongTermRefPicSets); 640 sps.used_by_curr_pic_lt_sps_flag.resize(sps.num_long_term_ref_pics_sps, 0); 641 for (uint32_t i = 0; i < sps.num_long_term_ref_pics_sps; i++) { 642 // lt_ref_pic_poc_lsb_sps: u(v) 643 uint32_t lt_ref_pic_poc_lsb_sps_bits = 644 sps.log2_max_pic_order_cnt_lsb_minus4 + 4; 645 reader.ConsumeBits(lt_ref_pic_poc_lsb_sps_bits); 646 // used_by_curr_pic_lt_sps_flag: u(1) 647 sps.used_by_curr_pic_lt_sps_flag[i] = reader.Read<bool>(); 648 } 649 } 650 651 // sps_temporal_mvp_enabled_flag: u(1) 652 sps.sps_temporal_mvp_enabled_flag = reader.Read<bool>(); 653 654 // Far enough! We don't use the rest of the SPS. 655 656 sps.vps_id = sps_video_parameter_set_id; 657 658 sps.pic_width_in_luma_samples = pic_width_in_luma_samples; 659 sps.pic_height_in_luma_samples = pic_height_in_luma_samples; 660 661 // Start with the resolution determined by the pic_width/pic_height fields. 662 sps.width = pic_width_in_luma_samples; 663 sps.height = pic_height_in_luma_samples; 664 665 if (conformance_window_flag) { 666 // the offset includes the pixel within conformance window. so don't need to 667 // +1 as per spec 668 sps.width -= sub_width_c * (conf_win_right_offset + conf_win_left_offset); 669 sps.height -= sub_height_c * (conf_win_top_offset + conf_win_bottom_offset); 670 } 671 672 if (!reader.Ok()) { 673 return std::nullopt; 674 } 675 676 return OptionalSps(sps); 677 } 678 679 } // namespace webrtc