h265_pps_parser_unittest.cc (9732B)
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 <algorithm> 14 #include <cstddef> 15 #include <cstdint> 16 #include <optional> 17 18 #include "api/array_view.h" 19 #include "common_video/h265/h265_common.h" 20 #include "common_video/h265/h265_sps_parser.h" 21 #include "rtc_base/bit_buffer.h" 22 #include "rtc_base/buffer.h" 23 #include "test/gtest.h" 24 25 namespace webrtc { 26 27 namespace { 28 29 constexpr size_t kPpsBufferMaxSize = 256; 30 constexpr uint32_t kIgnored = 0; 31 } // namespace 32 33 void WritePps(const H265PpsParser::PpsState& pps, 34 bool cu_qp_delta_enabled_flag, 35 bool tiles_enabled_flag, 36 bool uniform_spacing_flag, 37 bool deblocking_filter_control_present_flag, 38 bool pps_deblocking_filter_disabled_flag, 39 bool pps_scaling_list_data_present_flag, 40 bool scaling_list_pred_mode_flag, 41 Buffer* out_buffer) { 42 uint8_t data[kPpsBufferMaxSize] = {0}; 43 BitBufferWriter bit_buffer(data, kPpsBufferMaxSize); 44 45 // pic_parameter_set_id: ue(v) 46 bit_buffer.WriteExponentialGolomb(pps.pps_id); 47 // seq_parameter_set_id: ue(v) 48 bit_buffer.WriteExponentialGolomb(pps.sps_id); 49 // dependent_slice_segments_enabled_flag: u(1) 50 bit_buffer.WriteBits(pps.dependent_slice_segments_enabled_flag, 1); 51 // output_flag_present_flag: u(1) 52 bit_buffer.WriteBits(pps.output_flag_present_flag, 1); 53 // num_extra_slice_header_bits: u(3) 54 bit_buffer.WriteBits(pps.num_extra_slice_header_bits, 3); 55 // sign_data_hiding_enabled_flag: u(1) 56 bit_buffer.WriteBits(1, 1); 57 // cabac_init_present_flag: u(1) 58 bit_buffer.WriteBits(pps.cabac_init_present_flag, 1); 59 // num_ref_idx_l0_default_active_minus1: ue(v) 60 bit_buffer.WriteExponentialGolomb(pps.num_ref_idx_l0_default_active_minus1); 61 // num_ref_idx_l1_default_active_minus1: ue(v) 62 bit_buffer.WriteExponentialGolomb(pps.num_ref_idx_l1_default_active_minus1); 63 // init_qp_minus26: se(v) 64 bit_buffer.WriteSignedExponentialGolomb(pps.init_qp_minus26); 65 // constrained_intra_pred_flag: u(1) 66 bit_buffer.WriteBits(0, 1); 67 // transform_skip_enabled_flag: u(1) 68 bit_buffer.WriteBits(0, 1); 69 // cu_qp_delta_enabled_flag: u(1) 70 bit_buffer.WriteBits(cu_qp_delta_enabled_flag, 1); 71 if (cu_qp_delta_enabled_flag) { 72 // diff_cu_qp_delta_depth: ue(v) 73 bit_buffer.WriteExponentialGolomb(kIgnored); 74 } 75 // pps_cb_qp_offset: se(v) 76 bit_buffer.WriteSignedExponentialGolomb(kIgnored); 77 // pps_cr_qp_offset: se(v) 78 bit_buffer.WriteSignedExponentialGolomb(kIgnored); 79 // pps_slice_chroma_qp_offsets_present_flag: u(1) 80 bit_buffer.WriteBits(0, 1); 81 // weighted_pred_flag: u(1) 82 bit_buffer.WriteBits(pps.weighted_pred_flag, 1); 83 // weighted_bipred_flag: u(1) 84 bit_buffer.WriteBits(pps.weighted_bipred_flag, 1); 85 // transquant_bypass_enabled_flag: u(1) 86 bit_buffer.WriteBits(0, 1); 87 // tiles_enabled_flag: u(1) 88 bit_buffer.WriteBits(tiles_enabled_flag, 1); 89 // entropy_coding_sync_enabled_flag: u(1) 90 bit_buffer.WriteBits(1, 1); 91 if (tiles_enabled_flag) { 92 // num_tile_columns_minus1: ue(v) 93 bit_buffer.WriteExponentialGolomb(6); 94 // num_tile_rows_minus1: ue(v) 95 bit_buffer.WriteExponentialGolomb(1); 96 // uniform_spacing_flag: u(1) 97 bit_buffer.WriteBits(0, 1); 98 if (!uniform_spacing_flag) { 99 for (uint32_t i = 0; i < 6; i++) { 100 // column_width_minus1: ue(v) 101 bit_buffer.WriteExponentialGolomb(kIgnored); 102 } 103 for (uint32_t i = 0; i < 1; i++) { 104 // row_height_minus1: ue(v) 105 bit_buffer.WriteExponentialGolomb(kIgnored); 106 } 107 // loop_filter_across_tiles_enabled_flag: u(1) 108 bit_buffer.WriteBits(0, 1); 109 } 110 } 111 // pps_loop_filter_across_slices_enabled_flag: u(1) 112 bit_buffer.WriteBits(1, 1); 113 // deblocking_filter_control_present_flag: u(1) 114 bit_buffer.WriteBits(deblocking_filter_control_present_flag, 1); 115 if (deblocking_filter_control_present_flag) { 116 // deblocking_filter_override_enabled_flag: u(1) 117 bit_buffer.WriteBits(0, 1); 118 // pps_deblocking_filter_disabled_flag: u(1) 119 bit_buffer.WriteBits(pps_deblocking_filter_disabled_flag, 1); 120 if (!pps_deblocking_filter_disabled_flag) { 121 // pps_beta_offset_div2: se(v) 122 bit_buffer.WriteSignedExponentialGolomb(kIgnored); 123 // pps_tc_offset_div2: se(v) 124 bit_buffer.WriteSignedExponentialGolomb(kIgnored); 125 } 126 } 127 // pps_scaling_list_data_present_flag: u(1) 128 bit_buffer.WriteBits(pps_scaling_list_data_present_flag, 1); 129 if (pps_scaling_list_data_present_flag) { 130 for (int size_id = 0; size_id < 4; size_id++) { 131 for (int matrix_id = 0; matrix_id < 6; 132 matrix_id += (size_id == 3) ? 3 : 1) { 133 // scaling_list_pred_mode_flag: u(1) 134 bit_buffer.WriteBits(scaling_list_pred_mode_flag, 1); 135 if (!scaling_list_pred_mode_flag) { 136 // scaling_list_pred_matrix_id_delta: ue(v) 137 bit_buffer.WriteExponentialGolomb(kIgnored); 138 } else { 139 uint32_t coef_num = std::min(64, 1 << (4 + (size_id << 1))); 140 if (size_id > 1) { 141 // scaling_list_dc_coef_minus8: se(v) 142 bit_buffer.WriteSignedExponentialGolomb(kIgnored); 143 } 144 for (uint32_t i = 0; i < coef_num; i++) { 145 // scaling_list_delta_coef: se(v) 146 bit_buffer.WriteSignedExponentialGolomb(kIgnored); 147 } 148 } 149 } 150 } 151 } 152 // lists_modification_present_flag: u(1) 153 bit_buffer.WriteBits(pps.lists_modification_present_flag, 1); 154 // log2_parallel_merge_level_minus2: ue(v) 155 bit_buffer.WriteExponentialGolomb(kIgnored); 156 // slice_segment_header_extension_present_flag: u(1) 157 bit_buffer.WriteBits(0, 1); 158 159 size_t byte_offset; 160 size_t bit_offset; 161 bit_buffer.GetCurrentOffset(&byte_offset, &bit_offset); 162 if (bit_offset > 0) { 163 bit_buffer.WriteBits(0, 8 - bit_offset); 164 bit_buffer.GetCurrentOffset(&byte_offset, &bit_offset); 165 } 166 167 H265::WriteRbsp(MakeArrayView(data, byte_offset), out_buffer); 168 } 169 170 class H265PpsParserTest : public ::testing::Test { 171 public: 172 H265PpsParserTest() {} 173 ~H265PpsParserTest() override {} 174 175 void RunTest() { 176 VerifyParsing(generated_pps_, false, false, false, false, false, false, 177 false); 178 // Enable flags to cover more path 179 VerifyParsing(generated_pps_, true, true, false, true, true, true, false); 180 } 181 182 void VerifyParsing(const H265PpsParser::PpsState& pps, 183 bool cu_qp_delta_enabled_flag, 184 bool tiles_enabled_flag, 185 bool uniform_spacing_flag, 186 bool deblocking_filter_control_present_flag, 187 bool pps_deblocking_filter_disabled_flag, 188 bool pps_scaling_list_data_present_flag, 189 bool scaling_list_pred_mode_flag) { 190 buffer_.Clear(); 191 WritePps(pps, cu_qp_delta_enabled_flag, tiles_enabled_flag, 192 uniform_spacing_flag, deblocking_filter_control_present_flag, 193 pps_deblocking_filter_disabled_flag, 194 pps_scaling_list_data_present_flag, scaling_list_pred_mode_flag, 195 &buffer_); 196 const uint8_t sps_buffer[] = { 197 0x01, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00, 198 0x00, 0x03, 0x00, 0x00, 0x5d, 0xb0, 0x02, 0x80, 0x80, 0x2d, 199 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40, 0x00, 0x00, 200 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82}; 201 H265SpsParser::SpsState parsed_sps = 202 H265SpsParser::ParseSps(sps_buffer).value(); 203 parsed_pps_ = H265PpsParser::ParsePps(buffer_, &parsed_sps); 204 ASSERT_TRUE(parsed_pps_); 205 EXPECT_EQ(pps.dependent_slice_segments_enabled_flag, 206 parsed_pps_->dependent_slice_segments_enabled_flag); 207 EXPECT_EQ(pps.cabac_init_present_flag, 208 parsed_pps_->cabac_init_present_flag); 209 EXPECT_EQ(pps.output_flag_present_flag, 210 parsed_pps_->output_flag_present_flag); 211 EXPECT_EQ(pps.num_extra_slice_header_bits, 212 parsed_pps_->num_extra_slice_header_bits); 213 EXPECT_EQ(pps.num_ref_idx_l0_default_active_minus1, 214 parsed_pps_->num_ref_idx_l0_default_active_minus1); 215 EXPECT_EQ(pps.num_ref_idx_l1_default_active_minus1, 216 parsed_pps_->num_ref_idx_l1_default_active_minus1); 217 EXPECT_EQ(pps.init_qp_minus26, parsed_pps_->init_qp_minus26); 218 EXPECT_EQ(pps.weighted_pred_flag, parsed_pps_->weighted_pred_flag); 219 EXPECT_EQ(pps.weighted_bipred_flag, parsed_pps_->weighted_bipred_flag); 220 EXPECT_EQ(pps.lists_modification_present_flag, 221 parsed_pps_->lists_modification_present_flag); 222 EXPECT_EQ(pps.pps_id, parsed_pps_->pps_id); 223 EXPECT_EQ(pps.sps_id, parsed_pps_->sps_id); 224 } 225 226 H265PpsParser::PpsState generated_pps_; 227 Buffer buffer_; 228 std::optional<H265PpsParser::PpsState> parsed_pps_; 229 std::optional<H265SpsParser::SpsState> parsed_sps_; 230 }; 231 232 TEST_F(H265PpsParserTest, ZeroPps) { 233 RunTest(); 234 } 235 236 TEST_F(H265PpsParserTest, MaxPps) { 237 generated_pps_.dependent_slice_segments_enabled_flag = true; 238 generated_pps_.init_qp_minus26 = 25; 239 generated_pps_.num_extra_slice_header_bits = 1; // 1 bit value. 240 generated_pps_.weighted_bipred_flag = true; 241 generated_pps_.weighted_pred_flag = true; 242 generated_pps_.cabac_init_present_flag = true; 243 generated_pps_.pps_id = 2; 244 generated_pps_.sps_id = 1; 245 RunTest(); 246 247 generated_pps_.init_qp_minus26 = -25; 248 RunTest(); 249 } 250 251 } // namespace webrtc