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