tor-browser

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

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