tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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