h265_bitstream_parser.cc (27618B)
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 #include "common_video/h265/h265_bitstream_parser.h" 11 12 #include <cmath> 13 #include <cstdint> 14 #include <cstdlib> 15 #include <limits> 16 #include <optional> 17 #include <vector> 18 19 #include "api/array_view.h" 20 #include "common_video/h265/h265_common.h" 21 #include "common_video/h265/h265_pps_parser.h" 22 #include "common_video/h265/h265_sps_parser.h" 23 #include "common_video/h265/h265_vps_parser.h" 24 #include "rtc_base/bitstream_reader.h" 25 #include "rtc_base/logging.h" 26 27 #define IN_RANGE_OR_RETURN(val, min, max) \ 28 do { \ 29 if (!slice_reader.Ok() || (val) < (min) || (val) > (max)) { \ 30 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 31 " to be" \ 32 << " in range [" << (min) << ":" << (max) << "]" \ 33 << " found " << (val) << " instead"; \ 34 return kInvalidStream; \ 35 } \ 36 } while (0) 37 38 #define IN_RANGE_OR_RETURN_NULL(val, min, max) \ 39 do { \ 40 if (!slice_reader.Ok() || (val) < (min) || (val) > (max)) { \ 41 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 42 " to be" \ 43 << " in range [" << (min) << ":" << (max) << "]" \ 44 << " found " << (val) << " instead"; \ 45 return std::nullopt; \ 46 } \ 47 } while (0) 48 49 #define IN_RANGE_OR_RETURN_VOID(val, min, max) \ 50 do { \ 51 if (!slice_reader.Ok() || (val) < (min) || (val) > (max)) { \ 52 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 53 " to be" \ 54 << " in range [" << (min) << ":" << (max) << "]" \ 55 << " found " << (val) << " instead"; \ 56 return; \ 57 } \ 58 } while (0) 59 60 #define TRUE_OR_RETURN(a) \ 61 do { \ 62 if (!slice_reader.Ok() || !(a)) { \ 63 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " \ 64 << #a; \ 65 return kInvalidStream; \ 66 } \ 67 } while (0) 68 69 namespace { 70 71 constexpr int kMaxAbsQpDeltaValue = 51; 72 constexpr int kMinQpValue = 0; 73 constexpr int kMaxQpValue = 51; 74 constexpr int kMaxRefIdxActive = 15; 75 76 } // namespace 77 78 namespace webrtc { 79 80 H265BitstreamParser::H265BitstreamParser() = default; 81 H265BitstreamParser::~H265BitstreamParser() = default; 82 83 // General note: this is based off the 08/2021 version of the H.265 standard, 84 // section 7.3.6.1. You can find it on this page: 85 // http://www.itu.int/rec/T-REC-H.265 86 H265BitstreamParser::Result H265BitstreamParser::ParseNonParameterSetNalu( 87 ArrayView<const uint8_t> source, 88 uint8_t nalu_type) { 89 last_slice_qp_delta_ = std::nullopt; 90 last_slice_pps_id_ = std::nullopt; 91 const std::vector<uint8_t> slice_rbsp = H265::ParseRbsp(source); 92 if (slice_rbsp.size() < H265::kNaluHeaderSize) 93 return kInvalidStream; 94 95 BitstreamReader slice_reader(slice_rbsp); 96 slice_reader.ConsumeBits(H265::kNaluHeaderSize * 8); 97 98 // first_slice_segment_in_pic_flag: u(1) 99 bool first_slice_segment_in_pic_flag = slice_reader.Read<bool>(); 100 bool irap_pic = (H265::NaluType::kBlaWLp <= nalu_type && 101 nalu_type <= H265::NaluType::kRsvIrapVcl23); 102 if (irap_pic) { 103 // no_output_of_prior_pics_flag: u(1) 104 slice_reader.ConsumeBits(1); 105 } 106 // slice_pic_parameter_set_id: ue(v) 107 uint32_t pps_id = slice_reader.ReadExponentialGolomb(); 108 IN_RANGE_OR_RETURN(pps_id, 0, 63); 109 const H265PpsParser::PpsState* pps = GetPPS(pps_id); 110 TRUE_OR_RETURN(pps); 111 const H265SpsParser::SpsState* sps = GetSPS(pps->sps_id); 112 TRUE_OR_RETURN(sps); 113 bool dependent_slice_segment_flag = 0; 114 if (!first_slice_segment_in_pic_flag) { 115 if (pps->dependent_slice_segments_enabled_flag) { 116 // dependent_slice_segment_flag: u(1) 117 dependent_slice_segment_flag = slice_reader.Read<bool>(); 118 } 119 120 // slice_segment_address: u(v) 121 int32_t log2_ctb_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3 + 122 sps->log2_diff_max_min_luma_coding_block_size; 123 uint32_t ctb_size_y = 1 << log2_ctb_size_y; 124 uint32_t pic_width_in_ctbs_y = sps->pic_width_in_luma_samples / ctb_size_y; 125 if (sps->pic_width_in_luma_samples % ctb_size_y) 126 pic_width_in_ctbs_y++; 127 128 uint32_t pic_height_in_ctbs_y = 129 sps->pic_height_in_luma_samples / ctb_size_y; 130 if (sps->pic_height_in_luma_samples % ctb_size_y) 131 pic_height_in_ctbs_y++; 132 133 uint32_t slice_segment_address_bits = 134 H265::Log2Ceiling(pic_height_in_ctbs_y * pic_width_in_ctbs_y); 135 TRUE_OR_RETURN(slice_segment_address_bits != 136 std::numeric_limits<uint32_t>::max()); 137 slice_reader.ConsumeBits(slice_segment_address_bits); 138 } 139 140 if (dependent_slice_segment_flag == 0) { 141 for (uint32_t i = 0; i < pps->num_extra_slice_header_bits; i++) { 142 // slice_reserved_flag: u(1) 143 slice_reader.ConsumeBits(1); 144 } 145 // slice_type: ue(v) 146 uint32_t slice_type = slice_reader.ReadExponentialGolomb(); 147 IN_RANGE_OR_RETURN(slice_type, 0, 2); 148 if (pps->output_flag_present_flag) { 149 // pic_output_flag: u(1) 150 slice_reader.ConsumeBits(1); 151 } 152 if (sps->separate_colour_plane_flag) { 153 // colour_plane_id: u(2) 154 slice_reader.ConsumeBits(2); 155 } 156 uint32_t num_long_term_sps = 0; 157 uint32_t num_long_term_pics = 0; 158 std::vector<bool> used_by_curr_pic_lt_flag; 159 bool short_term_ref_pic_set_sps_flag = false; 160 uint32_t short_term_ref_pic_set_idx = 0; 161 H265SpsParser::ShortTermRefPicSet short_term_ref_pic_set; 162 bool slice_temporal_mvp_enabled_flag = 0; 163 if (nalu_type != H265::NaluType::kIdrWRadl && 164 nalu_type != H265::NaluType::kIdrNLp) { 165 // slice_pic_order_cnt_lsb: u(v) 166 uint32_t slice_pic_order_cnt_lsb_bits = 167 sps->log2_max_pic_order_cnt_lsb_minus4 + 4; 168 slice_reader.ConsumeBits(slice_pic_order_cnt_lsb_bits); 169 // short_term_ref_pic_set_sps_flag: u(1) 170 short_term_ref_pic_set_sps_flag = slice_reader.Read<bool>(); 171 if (!short_term_ref_pic_set_sps_flag) { 172 std::optional<H265SpsParser::ShortTermRefPicSet> ref_pic_set = 173 H265SpsParser::ParseShortTermRefPicSet( 174 sps->num_short_term_ref_pic_sets, 175 sps->num_short_term_ref_pic_sets, sps->short_term_ref_pic_set, 176 sps->sps_max_dec_pic_buffering_minus1 177 [sps->sps_max_sub_layers_minus1], 178 slice_reader); 179 TRUE_OR_RETURN(ref_pic_set); 180 short_term_ref_pic_set = *ref_pic_set; 181 182 } else if (sps->num_short_term_ref_pic_sets > 1) { 183 // short_term_ref_pic_set_idx: u(v) 184 uint32_t short_term_ref_pic_set_idx_bits = 185 H265::Log2Ceiling(sps->num_short_term_ref_pic_sets); 186 if ((1 << short_term_ref_pic_set_idx_bits) < 187 sps->num_short_term_ref_pic_sets) { 188 short_term_ref_pic_set_idx_bits++; 189 } 190 if (short_term_ref_pic_set_idx_bits > 0) { 191 short_term_ref_pic_set_idx = 192 slice_reader.ReadBits(short_term_ref_pic_set_idx_bits); 193 IN_RANGE_OR_RETURN(short_term_ref_pic_set_idx, 0, 194 sps->num_short_term_ref_pic_sets - 1); 195 } 196 } 197 if (sps->long_term_ref_pics_present_flag) { 198 if (sps->num_long_term_ref_pics_sps > 0) { 199 // num_long_term_sps: ue(v) 200 num_long_term_sps = slice_reader.ReadExponentialGolomb(); 201 IN_RANGE_OR_RETURN(num_long_term_sps, 0, 202 sps->num_long_term_ref_pics_sps); 203 } 204 // num_long_term_pics: ue(v) 205 num_long_term_pics = slice_reader.ReadExponentialGolomb(); 206 IN_RANGE_OR_RETURN(num_long_term_pics, 0, 207 kMaxLongTermRefPicSets - num_long_term_sps); 208 used_by_curr_pic_lt_flag.resize(num_long_term_sps + num_long_term_pics, 209 0); 210 for (uint32_t i = 0; i < num_long_term_sps + num_long_term_pics; i++) { 211 if (i < num_long_term_sps) { 212 uint32_t lt_idx_sps = 0; 213 if (sps->num_long_term_ref_pics_sps > 1) { 214 // lt_idx_sps: u(v) 215 uint32_t lt_idx_sps_bits = 216 H265::Log2Ceiling(sps->num_long_term_ref_pics_sps); 217 lt_idx_sps = slice_reader.ReadBits(lt_idx_sps_bits); 218 IN_RANGE_OR_RETURN(lt_idx_sps, 0, 219 sps->num_long_term_ref_pics_sps - 1); 220 } 221 used_by_curr_pic_lt_flag[i] = 222 sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps]; 223 } else { 224 // poc_lsb_lt: u(v) 225 uint32_t poc_lsb_lt_bits = 226 sps->log2_max_pic_order_cnt_lsb_minus4 + 4; 227 slice_reader.ConsumeBits(poc_lsb_lt_bits); 228 // used_by_curr_pic_lt_flag: u(1) 229 used_by_curr_pic_lt_flag[i] = slice_reader.Read<bool>(); 230 } 231 // delta_poc_msb_present_flag: u(1) 232 bool delta_poc_msb_present_flag = slice_reader.Read<bool>(); 233 if (delta_poc_msb_present_flag) { 234 // delta_poc_msb_cycle_lt: ue(v) 235 int delta_poc_msb_cycle_lt = slice_reader.ReadExponentialGolomb(); 236 IN_RANGE_OR_RETURN( 237 delta_poc_msb_cycle_lt, 0, 238 std::pow(2, 32 - sps->log2_max_pic_order_cnt_lsb_minus4 - 4)); 239 } 240 } 241 } 242 if (sps->sps_temporal_mvp_enabled_flag) { 243 // slice_temporal_mvp_enabled_flag: u(1) 244 slice_temporal_mvp_enabled_flag = slice_reader.Read<bool>(); 245 } 246 } 247 248 if (sps->sample_adaptive_offset_enabled_flag) { 249 // slice_sao_luma_flag: u(1) 250 slice_reader.ConsumeBits(1); 251 uint32_t chroma_array_type = 252 sps->separate_colour_plane_flag == 0 ? sps->chroma_format_idc : 0; 253 if (chroma_array_type != 0) { 254 // slice_sao_chroma_flag: u(1) 255 slice_reader.ConsumeBits(1); 256 } 257 } 258 259 if (slice_type == H265::SliceType::kP || 260 slice_type == H265::SliceType::kB) { 261 // num_ref_idx_active_override_flag: u(1) 262 bool num_ref_idx_active_override_flag = slice_reader.Read<bool>(); 263 uint32_t num_ref_idx_l0_active_minus1 = 264 pps->num_ref_idx_l0_default_active_minus1; 265 uint32_t num_ref_idx_l1_active_minus1 = 266 pps->num_ref_idx_l1_default_active_minus1; 267 if (num_ref_idx_active_override_flag) { 268 // num_ref_idx_l0_active_minus1: ue(v) 269 num_ref_idx_l0_active_minus1 = slice_reader.ReadExponentialGolomb(); 270 IN_RANGE_OR_RETURN(num_ref_idx_l0_active_minus1, 0, 271 kMaxRefIdxActive - 1); 272 if (slice_type == H265::SliceType::kB) { 273 // num_ref_idx_l1_active_minus1: ue(v) 274 num_ref_idx_l1_active_minus1 = slice_reader.ReadExponentialGolomb(); 275 IN_RANGE_OR_RETURN(num_ref_idx_l1_active_minus1, 0, 276 kMaxRefIdxActive - 1); 277 } 278 } 279 280 uint32_t num_pic_total_curr = 0; 281 uint32_t curr_rps_idx = 0; 282 if (short_term_ref_pic_set_sps_flag) { 283 curr_rps_idx = short_term_ref_pic_set_idx; 284 } else { 285 curr_rps_idx = sps->num_short_term_ref_pic_sets; 286 } 287 288 const H265SpsParser::ShortTermRefPicSet* ref_pic_set; 289 if (curr_rps_idx < sps->short_term_ref_pic_set.size()) { 290 ref_pic_set = &(sps->short_term_ref_pic_set[curr_rps_idx]); 291 } else { 292 ref_pic_set = &short_term_ref_pic_set; 293 } 294 295 // Equation 7-57 296 IN_RANGE_OR_RETURN(ref_pic_set->num_negative_pics, 0, 297 kMaxShortTermRefPicSets); 298 IN_RANGE_OR_RETURN(ref_pic_set->num_positive_pics, 0, 299 kMaxShortTermRefPicSets); 300 for (uint32_t i = 0; i < ref_pic_set->num_negative_pics; i++) { 301 if (ref_pic_set->used_by_curr_pic_s0[i]) { 302 num_pic_total_curr++; 303 } 304 } 305 for (uint32_t i = 0; i < ref_pic_set->num_positive_pics; i++) { 306 if (ref_pic_set->used_by_curr_pic_s1[i]) { 307 num_pic_total_curr++; 308 } 309 } 310 for (uint32_t i = 0; i < num_long_term_sps + num_long_term_pics; i++) { 311 if (used_by_curr_pic_lt_flag[i]) { 312 num_pic_total_curr++; 313 } 314 } 315 316 if (pps->lists_modification_present_flag && num_pic_total_curr > 1) { 317 // ref_pic_lists_modification() 318 uint32_t list_entry_bits = H265::Log2Ceiling(num_pic_total_curr); 319 if ((1 << list_entry_bits) < num_pic_total_curr) { 320 list_entry_bits++; 321 } 322 // ref_pic_list_modification_flag_l0: u(1) 323 bool ref_pic_list_modification_flag_l0 = slice_reader.Read<bool>(); 324 if (ref_pic_list_modification_flag_l0) { 325 for (uint32_t i = 0; i < num_ref_idx_l0_active_minus1; i++) { 326 // list_entry_l0: u(v) 327 slice_reader.ConsumeBits(list_entry_bits); 328 } 329 } 330 if (slice_type == H265::SliceType::kB) { 331 // ref_pic_list_modification_flag_l1: u(1) 332 bool ref_pic_list_modification_flag_l1 = slice_reader.Read<bool>(); 333 if (ref_pic_list_modification_flag_l1) { 334 for (uint32_t i = 0; i < num_ref_idx_l1_active_minus1; i++) { 335 // list_entry_l1: u(v) 336 slice_reader.ConsumeBits(list_entry_bits); 337 } 338 } 339 } 340 } 341 if (slice_type == H265::SliceType::kB) { 342 // mvd_l1_zero_flag: u(1) 343 slice_reader.ConsumeBits(1); 344 } 345 if (pps->cabac_init_present_flag) { 346 // cabac_init_flag: u(1) 347 slice_reader.ConsumeBits(1); 348 } 349 if (slice_temporal_mvp_enabled_flag) { 350 bool collocated_from_l0_flag = false; 351 if (slice_type == H265::SliceType::kB) { 352 // collocated_from_l0_flag: u(1) 353 collocated_from_l0_flag = slice_reader.Read<bool>(); 354 } 355 if ((collocated_from_l0_flag && num_ref_idx_l0_active_minus1 > 0) || 356 (!collocated_from_l0_flag && num_ref_idx_l1_active_minus1 > 0)) { 357 // collocated_ref_idx: ue(v) 358 uint32_t collocated_ref_idx = slice_reader.ReadExponentialGolomb(); 359 if ((slice_type == H265::SliceType::kP || 360 slice_type == H265::SliceType::kB) && 361 collocated_from_l0_flag) { 362 IN_RANGE_OR_RETURN(collocated_ref_idx, 0, 363 num_ref_idx_l0_active_minus1); 364 } 365 if (slice_type == H265::SliceType::kB && !collocated_from_l0_flag) { 366 IN_RANGE_OR_RETURN(collocated_ref_idx, 0, 367 num_ref_idx_l1_active_minus1); 368 } 369 } 370 } 371 372 // pred_weight_table() 373 if ((pps->weighted_pred_flag && slice_type == H265::SliceType::kP) || 374 (pps->weighted_bipred_flag && slice_type == H265::SliceType::kB)) { 375 uint32_t luma_log2_weight_denom = slice_reader.ReadExponentialGolomb(); 376 IN_RANGE_OR_RETURN(luma_log2_weight_denom, 0, 7); 377 uint32_t chroma_array_type = 378 sps->separate_colour_plane_flag == 0 ? sps->chroma_format_idc : 0; 379 int32_t chroma_log2_weight_denom = luma_log2_weight_denom; 380 // wp_offset_half_range_c and wp_offset_half_range_y depends on 381 // sps.high_precision_offsets_enable_flag. Since range extension is not 382 // supported, so for now below two are fixed to 128 instead of 1 << 383 // (sps.bit_depth_luma|chroma_minus8 + 7). 384 int32_t wp_offset_half_range_c = (1 << 7); 385 int32_t wp_offset_half_range_y = (1 << 7); 386 if (chroma_array_type != 0) { 387 // delta_chroma_log2_weight_denom: se(v) 388 int32_t delta_chroma_log2_weight_denom = 389 slice_reader.ReadSignedExponentialGolomb(); 390 IN_RANGE_OR_RETURN(delta_chroma_log2_weight_denom, -7, 7); 391 chroma_log2_weight_denom += delta_chroma_log2_weight_denom; 392 } 393 IN_RANGE_OR_RETURN(chroma_log2_weight_denom, 0, 7); 394 395 bool luma_weight_flag_l0[kMaxRefIdxActive] = {}; 396 bool chroma_weight_flag_l0[kMaxRefIdxActive] = {}; 397 int32_t delta_chroma_weight_l0[kMaxRefIdxActive][2] = {}; 398 int32_t luma_offset_l0[kMaxRefIdxActive] = {}; 399 int32_t delta_chroma_offset_l0[kMaxRefIdxActive][2] = {}; 400 for (uint32_t i = 0; i <= num_ref_idx_l0_active_minus1; i++) { 401 // luma_weight_l0_flag: u(1). By syntax this should conditionally 402 // check if the POC or layer ID of the reference picture is different, 403 // but we don't support encoding referencing different layers in the 404 // same AU. Skip the check for now. 405 luma_weight_flag_l0[i] = slice_reader.Read<bool>(); 406 } 407 if (chroma_array_type != 0) { 408 for (uint32_t i = 0; i <= num_ref_idx_l0_active_minus1; i++) { 409 // chroma_weight_l0_flag: u(1) 410 chroma_weight_flag_l0[i] = slice_reader.Read<bool>(); 411 } 412 } 413 for (uint32_t i = 0; i <= num_ref_idx_l0_active_minus1; i++) { 414 if (luma_weight_flag_l0[i]) { 415 int32_t delta_luma_weight_l0[kMaxRefIdxActive] = {}; 416 delta_luma_weight_l0[i] = 417 slice_reader.ReadSignedExponentialGolomb(); 418 IN_RANGE_OR_RETURN(delta_luma_weight_l0[i], -128, 127); 419 luma_offset_l0[i] = slice_reader.ReadSignedExponentialGolomb(); 420 IN_RANGE_OR_RETURN(luma_offset_l0[i], -wp_offset_half_range_y, 421 wp_offset_half_range_y - 1); 422 } 423 if (chroma_weight_flag_l0[i]) { 424 for (uint32_t j = 0; j < 2; j++) { 425 delta_chroma_weight_l0[i][j] = 426 slice_reader.ReadSignedExponentialGolomb(); 427 IN_RANGE_OR_RETURN(delta_chroma_weight_l0[i][j], -128, 127); 428 delta_chroma_offset_l0[i][j] = 429 slice_reader.ReadSignedExponentialGolomb(); 430 IN_RANGE_OR_RETURN(delta_chroma_offset_l0[i][j], 431 -4 * wp_offset_half_range_c, 432 4 * wp_offset_half_range_c - 1); 433 } 434 } 435 } 436 if (slice_type == H265::SliceType::kB) { 437 bool luma_weight_flag_l1[kMaxRefIdxActive] = {}; 438 bool chroma_weight_flag_l1[kMaxRefIdxActive] = {}; 439 int32_t delta_chroma_weight_l1[kMaxRefIdxActive][2] = {}; 440 int32_t luma_offset_l1[kMaxRefIdxActive] = {}; 441 int32_t delta_chroma_offset_l1[kMaxRefIdxActive][2] = {}; 442 for (uint32_t i = 0; i < num_ref_idx_l1_active_minus1; i++) { 443 luma_weight_flag_l1[i] = slice_reader.Read<bool>(); 444 } 445 if (chroma_array_type != 0) { 446 for (uint32_t i = 0; i <= num_ref_idx_l1_active_minus1; i++) { 447 chroma_weight_flag_l1[i] = slice_reader.Read<bool>(); 448 } 449 } 450 for (uint32_t i = 0; i <= num_ref_idx_l1_active_minus1; i++) { 451 if (luma_weight_flag_l1[i]) { 452 int32_t delta_luma_weight_l1[kMaxRefIdxActive] = {}; 453 delta_luma_weight_l1[i] = 454 slice_reader.ReadSignedExponentialGolomb(); 455 IN_RANGE_OR_RETURN(delta_luma_weight_l1[i], -128, 127); 456 luma_offset_l1[i] = slice_reader.ReadSignedExponentialGolomb(); 457 IN_RANGE_OR_RETURN(luma_offset_l1[i], -wp_offset_half_range_y, 458 wp_offset_half_range_y - 1); 459 } 460 if (chroma_weight_flag_l1[i]) { 461 for (uint32_t j = 0; j < 2; j++) { 462 delta_chroma_weight_l1[i][j] = 463 slice_reader.ReadSignedExponentialGolomb(); 464 IN_RANGE_OR_RETURN(delta_chroma_weight_l1[i][j], -128, 127); 465 delta_chroma_offset_l1[i][j] = 466 slice_reader.ReadSignedExponentialGolomb(); 467 IN_RANGE_OR_RETURN(delta_chroma_offset_l1[i][j], 468 -4 * wp_offset_half_range_c, 469 4 * wp_offset_half_range_c - 1); 470 } 471 } 472 } 473 } 474 } 475 476 // five_minus_max_num_merge_cand: ue(v) 477 uint32_t five_minus_max_num_merge_cand = 478 slice_reader.ReadExponentialGolomb(); 479 IN_RANGE_OR_RETURN(5 - five_minus_max_num_merge_cand, 1, 5); 480 } 481 } 482 483 // slice_qp_delta: se(v) 484 int32_t last_slice_qp_delta = slice_reader.ReadSignedExponentialGolomb(); 485 if (!slice_reader.Ok() || (abs(last_slice_qp_delta) > kMaxAbsQpDeltaValue)) { 486 // Something has gone wrong, and the parsed value is invalid. 487 RTC_LOG(LS_ERROR) << "Parsed QP value out of range."; 488 return kInvalidStream; 489 } 490 // 7-54 in H265 spec. 491 IN_RANGE_OR_RETURN(26 + pps->init_qp_minus26 + last_slice_qp_delta, 492 -pps->qp_bd_offset_y, 51); 493 494 last_slice_qp_delta_ = last_slice_qp_delta; 495 last_slice_pps_id_ = pps_id; 496 if (!slice_reader.Ok()) { 497 return kInvalidStream; 498 } 499 500 return kOk; 501 } 502 503 const H265PpsParser::PpsState* H265BitstreamParser::GetPPS(uint32_t id) const { 504 auto it = pps_.find(id); 505 if (it == pps_.end()) { 506 RTC_LOG(LS_WARNING) << "Requested a nonexistent PPS id " << id; 507 return nullptr; 508 } 509 510 return &it->second; 511 } 512 513 const H265SpsParser::SpsState* H265BitstreamParser::GetSPS(uint32_t id) const { 514 auto it = sps_.find(id); 515 if (it == sps_.end()) { 516 RTC_LOG(LS_WARNING) << "Requested a nonexistent SPS id " << id; 517 return nullptr; 518 } 519 520 return &it->second; 521 } 522 523 void H265BitstreamParser::ParseSlice(ArrayView<const uint8_t> slice) { 524 if (slice.empty()) { 525 RTC_LOG(LS_WARNING) << "Empty slice in H265 bitstream."; 526 return; 527 } 528 H265::NaluType nalu_type = H265::ParseNaluType(slice[0]); 529 switch (nalu_type) { 530 case H265::NaluType::kVps: { 531 std::optional<H265VpsParser::VpsState> vps_state; 532 if (slice.size() >= H265::kNaluHeaderSize) { 533 vps_state = 534 H265VpsParser::ParseVps(slice.subview(H265::kNaluHeaderSize)); 535 } 536 537 if (!vps_state) { 538 RTC_LOG(LS_WARNING) << "Unable to parse VPS from H265 bitstream."; 539 } else { 540 vps_[vps_state->id] = *vps_state; 541 } 542 break; 543 } 544 case H265::NaluType::kSps: { 545 std::optional<H265SpsParser::SpsState> sps_state; 546 if (slice.size() >= H265::kNaluHeaderSize) { 547 sps_state = 548 H265SpsParser::ParseSps(slice.subview(H265::kNaluHeaderSize)); 549 } 550 if (!sps_state) { 551 RTC_LOG(LS_WARNING) << "Unable to parse SPS from H265 bitstream."; 552 } else { 553 sps_[sps_state->sps_id] = *sps_state; 554 } 555 break; 556 } 557 case H265::NaluType::kPps: { 558 std::optional<H265PpsParser::PpsState> pps_state; 559 if (slice.size() >= H265::kNaluHeaderSize) { 560 std::vector<uint8_t> unpacked_buffer = 561 H265::ParseRbsp(slice.subview(H265::kNaluHeaderSize)); 562 BitstreamReader slice_reader(unpacked_buffer); 563 // pic_parameter_set_id: ue(v) 564 uint32_t pps_id = slice_reader.ReadExponentialGolomb(); 565 IN_RANGE_OR_RETURN_VOID(pps_id, 0, 63); 566 // seq_parameter_set_id: ue(v) 567 uint32_t sps_id = slice_reader.ReadExponentialGolomb(); 568 IN_RANGE_OR_RETURN_VOID(sps_id, 0, 15); 569 const H265SpsParser::SpsState* sps = GetSPS(sps_id); 570 pps_state = 571 H265PpsParser::ParsePps(slice.subview(H265::kNaluHeaderSize), sps); 572 } 573 if (!pps_state) { 574 RTC_LOG(LS_WARNING) << "Unable to parse PPS from H265 bitstream."; 575 } else { 576 pps_[pps_state->pps_id] = *pps_state; 577 } 578 break; 579 } 580 case H265::NaluType::kAud: 581 case H265::NaluType::kPrefixSei: 582 case H265::NaluType::kSuffixSei: 583 case H265::NaluType::kAp: 584 case H265::NaluType::kFu: 585 break; 586 default: 587 Result res = ParseNonParameterSetNalu(slice, nalu_type); 588 if (res != kOk) { 589 RTC_LOG(LS_INFO) << "Failed to parse bitstream. Error: " << res; 590 } 591 break; 592 } 593 } 594 595 std::optional<uint32_t> 596 H265BitstreamParser::ParsePpsIdFromSliceSegmentLayerRbsp( 597 ArrayView<const uint8_t> data, 598 uint8_t nalu_type) { 599 std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(data); 600 BitstreamReader slice_reader(unpacked_buffer); 601 602 // first_slice_segment_in_pic_flag: u(1) 603 slice_reader.ConsumeBits(1); 604 if (!slice_reader.Ok()) { 605 return std::nullopt; 606 } 607 608 if (nalu_type >= H265::NaluType::kBlaWLp && 609 nalu_type <= H265::NaluType::kRsvIrapVcl23) { 610 // no_output_of_prior_pics_flag: u(1) 611 slice_reader.ConsumeBits(1); 612 } 613 614 // slice_pic_parameter_set_id: ue(v) 615 uint32_t slice_pic_parameter_set_id = slice_reader.ReadExponentialGolomb(); 616 IN_RANGE_OR_RETURN_NULL(slice_pic_parameter_set_id, 0, 63); 617 if (!slice_reader.Ok()) { 618 return std::nullopt; 619 } 620 621 return slice_pic_parameter_set_id; 622 } 623 624 std::optional<bool> H265BitstreamParser::IsFirstSliceSegmentInPic( 625 ArrayView<const uint8_t> data) { 626 std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(data); 627 BitstreamReader slice_reader(unpacked_buffer); 628 629 // first_slice_segment_in_pic_flag: u(1) 630 bool first_slice_segment_in_pic_flag = slice_reader.Read<bool>(); 631 if (!slice_reader.Ok()) { 632 return std::nullopt; 633 } 634 635 return first_slice_segment_in_pic_flag; 636 } 637 638 void H265BitstreamParser::ParseBitstream(ArrayView<const uint8_t> bitstream) { 639 std::vector<H265::NaluIndex> nalu_indices = H265::FindNaluIndices(bitstream); 640 for (const H265::NaluIndex& index : nalu_indices) 641 ParseSlice( 642 bitstream.subview(index.payload_start_offset, index.payload_size)); 643 } 644 645 std::optional<int> H265BitstreamParser::GetLastSliceQp() const { 646 if (!last_slice_qp_delta_ || !last_slice_pps_id_) { 647 return std::nullopt; 648 } 649 const H265PpsParser::PpsState* pps = GetPPS(last_slice_pps_id_.value()); 650 if (!pps) 651 return std::nullopt; 652 const int parsed_qp = 26 + pps->init_qp_minus26 + *last_slice_qp_delta_; 653 if (parsed_qp < kMinQpValue || parsed_qp > kMaxQpValue) { 654 RTC_LOG(LS_ERROR) << "Parsed invalid QP from bitstream."; 655 return std::nullopt; 656 } 657 return parsed_qp; 658 } 659 660 std::optional<uint32_t> H265BitstreamParser::GetLastSlicePpsId() const { 661 if (!last_slice_pps_id_) { 662 RTC_LOG(LS_ERROR) << "Failed to parse PPS id from bitstream."; 663 return std::nullopt; 664 } 665 666 return last_slice_pps_id_; 667 } 668 669 } // namespace webrtc