h265_pps_parser.cc (10838B)
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_pps_parser.h" 12 13 #include <cstdint> 14 #include <optional> 15 #include <vector> 16 17 #include "api/array_view.h" 18 #include "common_video/h265/h265_common.h" 19 #include "common_video/h265/h265_sps_parser.h" 20 #include "rtc_base/bitstream_reader.h" 21 #include "rtc_base/checks.h" 22 #include "rtc_base/logging.h" 23 24 #define IN_RANGE_OR_RETURN_NULL(val, min, max) \ 25 do { \ 26 if (!reader.Ok() || (val) < (min) || (val) > (max)) { \ 27 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 28 " to be" \ 29 << " in range [" << (min) << ":" << (max) << "]" \ 30 << " found " << (val) << " instead"; \ 31 return std::nullopt; \ 32 } \ 33 } while (0) 34 35 #define IN_RANGE_OR_RETURN_FALSE(val, min, max) \ 36 do { \ 37 if (!reader.Ok() || (val) < (min) || (val) > (max)) { \ 38 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " #val \ 39 " to be" \ 40 << " in range [" << (min) << ":" << (max) << "]" \ 41 << " found " << (val) << " instead"; \ 42 return false; \ 43 } \ 44 } while (0) 45 46 #define TRUE_OR_RETURN(a) \ 47 do { \ 48 if (!reader.Ok() || !(a)) { \ 49 RTC_LOG(LS_WARNING) << "Error in stream: invalid value, expected " \ 50 << #a; \ 51 return std::nullopt; \ 52 } \ 53 } while (0) 54 55 namespace { 56 constexpr int kMaxNumTileColumnWidth = 19; 57 constexpr int kMaxNumTileRowHeight = 21; 58 constexpr int kMaxRefIdxActive = 15; 59 } // namespace 60 61 namespace webrtc { 62 63 // General note: this is based off the 08/2021 version of the H.265 standard. 64 // You can find it on this page: 65 // http://www.itu.int/rec/T-REC-H.265 66 67 std::optional<H265PpsParser::PpsState> H265PpsParser::ParsePps( 68 ArrayView<const uint8_t> data, 69 const H265SpsParser::SpsState* sps) { 70 // First, parse out rbsp, which is basically the source buffer minus emulation 71 // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in 72 // section 7.3.1.1 of the H.265 standard. 73 return ParseInternal(H265::ParseRbsp(data), sps); 74 } 75 76 bool H265PpsParser::ParsePpsIds(ArrayView<const uint8_t> data, 77 uint32_t* pps_id, 78 uint32_t* sps_id) { 79 RTC_DCHECK(pps_id); 80 RTC_DCHECK(sps_id); 81 // First, parse out rbsp, which is basically the source buffer minus emulation 82 // bytes (the last byte of a 0x00 0x00 0x03 sequence). RBSP is defined in 83 // section 7.3.1.1 of the H.265 standard. 84 std::vector<uint8_t> unpacked_buffer = H265::ParseRbsp(data); 85 BitstreamReader reader(unpacked_buffer); 86 *pps_id = reader.ReadExponentialGolomb(); 87 IN_RANGE_OR_RETURN_FALSE(*pps_id, 0, 63); 88 *sps_id = reader.ReadExponentialGolomb(); 89 IN_RANGE_OR_RETURN_FALSE(*sps_id, 0, 15); 90 return reader.Ok(); 91 } 92 93 std::optional<H265PpsParser::PpsState> H265PpsParser::ParseInternal( 94 ArrayView<const uint8_t> buffer, 95 const H265SpsParser::SpsState* sps) { 96 BitstreamReader reader(buffer); 97 PpsState pps; 98 99 if (!sps) { 100 return std::nullopt; 101 } 102 103 if (!ParsePpsIdsInternal(reader, pps.pps_id, pps.sps_id)) { 104 return std::nullopt; 105 } 106 107 // dependent_slice_segments_enabled_flag: u(1) 108 pps.dependent_slice_segments_enabled_flag = reader.Read<bool>(); 109 // output_flag_present_flag: u(1) 110 pps.output_flag_present_flag = reader.Read<bool>(); 111 // num_extra_slice_header_bits: u(3) 112 pps.num_extra_slice_header_bits = reader.ReadBits(3); 113 IN_RANGE_OR_RETURN_NULL(pps.num_extra_slice_header_bits, 0, 2); 114 // sign_data_hiding_enabled_flag: u(1) 115 reader.ConsumeBits(1); 116 // cabac_init_present_flag: u(1) 117 pps.cabac_init_present_flag = reader.Read<bool>(); 118 // num_ref_idx_l0_default_active_minus1: ue(v) 119 pps.num_ref_idx_l0_default_active_minus1 = reader.ReadExponentialGolomb(); 120 IN_RANGE_OR_RETURN_NULL(pps.num_ref_idx_l0_default_active_minus1, 0, 121 kMaxRefIdxActive - 1); 122 // num_ref_idx_l1_default_active_minus1: ue(v) 123 pps.num_ref_idx_l1_default_active_minus1 = reader.ReadExponentialGolomb(); 124 IN_RANGE_OR_RETURN_NULL(pps.num_ref_idx_l1_default_active_minus1, 0, 125 kMaxRefIdxActive - 1); 126 // init_qp_minus26: se(v) 127 pps.init_qp_minus26 = reader.ReadSignedExponentialGolomb(); 128 pps.qp_bd_offset_y = 6 * sps->bit_depth_luma_minus8; 129 // Sanity-check parsed value 130 IN_RANGE_OR_RETURN_NULL(pps.init_qp_minus26, -(26 + pps.qp_bd_offset_y), 25); 131 // constrained_intra_pred_flag: u(1)log2_min_pcm_luma_coding_block_size_minus3 132 reader.ConsumeBits(1); 133 // transform_skip_enabled_flag: u(1) 134 reader.ConsumeBits(1); 135 // cu_qp_delta_enabled_flag: u(1) 136 bool cu_qp_delta_enabled_flag = reader.Read<bool>(); 137 if (cu_qp_delta_enabled_flag) { 138 // diff_cu_qp_delta_depth: ue(v) 139 uint32_t diff_cu_qp_delta_depth = reader.ReadExponentialGolomb(); 140 IN_RANGE_OR_RETURN_NULL(diff_cu_qp_delta_depth, 0, 141 sps->log2_diff_max_min_luma_coding_block_size); 142 } 143 // pps_cb_qp_offset: se(v) 144 int32_t pps_cb_qp_offset = reader.ReadSignedExponentialGolomb(); 145 IN_RANGE_OR_RETURN_NULL(pps_cb_qp_offset, -12, 12); 146 // pps_cr_qp_offset: se(v) 147 int32_t pps_cr_qp_offset = reader.ReadSignedExponentialGolomb(); 148 IN_RANGE_OR_RETURN_NULL(pps_cr_qp_offset, -12, 12); 149 // pps_slice_chroma_qp_offsets_present_flag: u(1) 150 reader.ConsumeBits(1); 151 // weighted_pred_flag: u(1) 152 pps.weighted_pred_flag = reader.Read<bool>(); 153 // weighted_bipred_flag: u(1) 154 pps.weighted_bipred_flag = reader.Read<bool>(); 155 // transquant_bypass_enabled_flag: u(1) 156 reader.ConsumeBits(1); 157 // tiles_enabled_flag: u(1) 158 bool tiles_enabled_flag = reader.Read<bool>(); 159 // entropy_coding_sync_enabled_flag: u(1) 160 reader.ConsumeBits(1); 161 if (tiles_enabled_flag) { 162 // num_tile_columns_minus1: ue(v) 163 uint32_t num_tile_columns_minus1 = reader.ReadExponentialGolomb(); 164 IN_RANGE_OR_RETURN_NULL(num_tile_columns_minus1, 0, 165 sps->pic_width_in_ctbs_y - 1); 166 TRUE_OR_RETURN(num_tile_columns_minus1 < kMaxNumTileColumnWidth); 167 // num_tile_rows_minus1: ue(v) 168 uint32_t num_tile_rows_minus1 = reader.ReadExponentialGolomb(); 169 IN_RANGE_OR_RETURN_NULL(num_tile_rows_minus1, 0, 170 sps->pic_height_in_ctbs_y - 1); 171 TRUE_OR_RETURN((num_tile_columns_minus1 != 0) || 172 (num_tile_rows_minus1 != 0)); 173 TRUE_OR_RETURN(num_tile_rows_minus1 < kMaxNumTileRowHeight); 174 // uniform_spacing_flag: u(1) 175 bool uniform_spacing_flag = reader.Read<bool>(); 176 if (!uniform_spacing_flag) { 177 int column_width_minus1[kMaxNumTileColumnWidth]; 178 column_width_minus1[num_tile_columns_minus1] = 179 sps->pic_width_in_ctbs_y - 1; 180 for (uint32_t i = 0; i < num_tile_columns_minus1; i++) { 181 // column_width_minus1: ue(v) 182 column_width_minus1[i] = reader.ReadExponentialGolomb(); 183 IN_RANGE_OR_RETURN_NULL( 184 column_width_minus1[i], 0, 185 column_width_minus1[num_tile_columns_minus1] - 1); 186 column_width_minus1[num_tile_columns_minus1] -= 187 column_width_minus1[i] + 1; 188 } 189 int row_height_minus1[kMaxNumTileRowHeight]; 190 row_height_minus1[num_tile_rows_minus1] = sps->pic_height_in_ctbs_y - 1; 191 for (uint32_t i = 0; i < num_tile_rows_minus1; i++) { 192 // row_height_minus1: ue(v) 193 row_height_minus1[i] = reader.ReadExponentialGolomb(); 194 IN_RANGE_OR_RETURN_NULL(row_height_minus1[i], 0, 195 row_height_minus1[num_tile_rows_minus1] - 1); 196 row_height_minus1[num_tile_rows_minus1] -= row_height_minus1[i] + 1; 197 } 198 // loop_filter_across_tiles_enabled_flag: u(1) 199 reader.ConsumeBits(1); 200 } 201 } 202 // pps_loop_filter_across_slices_enabled_flag: u(1) 203 reader.ConsumeBits(1); 204 // deblocking_filter_control_present_flag: u(1) 205 bool deblocking_filter_control_present_flag = reader.Read<bool>(); 206 if (deblocking_filter_control_present_flag) { 207 // deblocking_filter_override_enabled_flag: u(1) 208 reader.ConsumeBits(1); 209 // pps_deblocking_filter_disabled_flag: u(1) 210 bool pps_deblocking_filter_disabled_flag = reader.Read<bool>(); 211 if (!pps_deblocking_filter_disabled_flag) { 212 // pps_beta_offset_div2: se(v) 213 int pps_beta_offset_div2 = reader.ReadSignedExponentialGolomb(); 214 IN_RANGE_OR_RETURN_NULL(pps_beta_offset_div2, -6, 6); 215 // pps_tc_offset_div2: se(v) 216 int pps_tc_offset_div2 = reader.ReadSignedExponentialGolomb(); 217 IN_RANGE_OR_RETURN_NULL(pps_tc_offset_div2, -6, 6); 218 } 219 } 220 // pps_scaling_list_data_present_flag: u(1) 221 bool pps_scaling_list_data_present_flag = 0; 222 pps_scaling_list_data_present_flag = reader.Read<bool>(); 223 if (pps_scaling_list_data_present_flag) { 224 // scaling_list_data() 225 if (!H265SpsParser::ParseScalingListData(reader)) { 226 return std::nullopt; 227 } 228 } 229 // lists_modification_present_flag: u(1) 230 pps.lists_modification_present_flag = reader.Read<bool>(); 231 232 if (!reader.Ok()) { 233 return std::nullopt; 234 } 235 236 return pps; 237 } 238 239 bool H265PpsParser::ParsePpsIdsInternal(BitstreamReader& reader, 240 uint32_t& pps_id, 241 uint32_t& sps_id) { 242 // pic_parameter_set_id: ue(v) 243 pps_id = reader.ReadExponentialGolomb(); 244 IN_RANGE_OR_RETURN_FALSE(pps_id, 0, 63); 245 // seq_parameter_set_id: ue(v) 246 sps_id = reader.ReadExponentialGolomb(); 247 IN_RANGE_OR_RETURN_FALSE(sps_id, 0, 15); 248 return true; 249 } 250 251 } // namespace webrtc