summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/common_video/h265/h265_pps_parser_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/common_video/h265/h265_pps_parser_unittest.cc')
-rw-r--r--third_party/libwebrtc/common_video/h265/h265_pps_parser_unittest.cc249
1 files changed, 249 insertions, 0 deletions
diff --git a/third_party/libwebrtc/common_video/h265/h265_pps_parser_unittest.cc b/third_party/libwebrtc/common_video/h265/h265_pps_parser_unittest.cc
new file mode 100644
index 0000000000..d91fc1a55c
--- /dev/null
+++ b/third_party/libwebrtc/common_video/h265/h265_pps_parser_unittest.cc
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2023 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "common_video/h265/h265_pps_parser.h"
+
+#include <algorithm>
+
+#include "common_video/h265/h265_common.h"
+#include "rtc_base/arraysize.h"
+#include "rtc_base/bit_buffer.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+constexpr size_t kPpsBufferMaxSize = 256;
+constexpr uint32_t kIgnored = 0;
+} // namespace
+
+void WritePps(const H265PpsParser::PpsState& pps,
+ bool cu_qp_delta_enabled_flag,
+ bool tiles_enabled_flag,
+ bool uniform_spacing_flag,
+ bool deblocking_filter_control_present_flag,
+ bool pps_deblocking_filter_disabled_flag,
+ bool pps_scaling_list_data_present_flag,
+ bool scaling_list_pred_mode_flag,
+ rtc::Buffer* out_buffer) {
+ uint8_t data[kPpsBufferMaxSize] = {0};
+ rtc::BitBufferWriter bit_buffer(data, kPpsBufferMaxSize);
+
+ // pic_parameter_set_id: ue(v)
+ bit_buffer.WriteExponentialGolomb(pps.pps_id);
+ // seq_parameter_set_id: ue(v)
+ bit_buffer.WriteExponentialGolomb(pps.sps_id);
+ // dependent_slice_segments_enabled_flag: u(1)
+ bit_buffer.WriteBits(pps.dependent_slice_segments_enabled_flag, 1);
+ // output_flag_present_flag: u(1)
+ bit_buffer.WriteBits(pps.output_flag_present_flag, 1);
+ // num_extra_slice_header_bits: u(3)
+ bit_buffer.WriteBits(pps.num_extra_slice_header_bits, 3);
+ // sign_data_hiding_enabled_flag: u(1)
+ bit_buffer.WriteBits(1, 1);
+ // cabac_init_present_flag: u(1)
+ bit_buffer.WriteBits(pps.cabac_init_present_flag, 1);
+ // num_ref_idx_l0_default_active_minus1: ue(v)
+ bit_buffer.WriteExponentialGolomb(pps.num_ref_idx_l0_default_active_minus1);
+ // num_ref_idx_l1_default_active_minus1: ue(v)
+ bit_buffer.WriteExponentialGolomb(pps.num_ref_idx_l1_default_active_minus1);
+ // init_qp_minus26: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(pps.init_qp_minus26);
+ // constrained_intra_pred_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ // transform_skip_enabled_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ // cu_qp_delta_enabled_flag: u(1)
+ bit_buffer.WriteBits(cu_qp_delta_enabled_flag, 1);
+ if (cu_qp_delta_enabled_flag) {
+ // diff_cu_qp_delta_depth: ue(v)
+ bit_buffer.WriteExponentialGolomb(kIgnored);
+ }
+ // pps_cb_qp_offset: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(kIgnored);
+ // pps_cr_qp_offset: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(kIgnored);
+ // pps_slice_chroma_qp_offsets_present_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ // weighted_pred_flag: u(1)
+ bit_buffer.WriteBits(pps.weighted_pred_flag, 1);
+ // weighted_bipred_flag: u(1)
+ bit_buffer.WriteBits(pps.weighted_bipred_flag, 1);
+ // transquant_bypass_enabled_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ // tiles_enabled_flag: u(1)
+ bit_buffer.WriteBits(tiles_enabled_flag, 1);
+ // entropy_coding_sync_enabled_flag: u(1)
+ bit_buffer.WriteBits(1, 1);
+ if (tiles_enabled_flag) {
+ // num_tile_columns_minus1: ue(v)
+ bit_buffer.WriteExponentialGolomb(6);
+ // num_tile_rows_minus1: ue(v)
+ bit_buffer.WriteExponentialGolomb(1);
+ // uniform_spacing_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ if (!uniform_spacing_flag) {
+ for (uint32_t i = 0; i < 6; i++) {
+ // column_width_minus1: ue(v)
+ bit_buffer.WriteExponentialGolomb(kIgnored);
+ }
+ for (uint32_t i = 0; i < 1; i++) {
+ // row_height_minus1: ue(v)
+ bit_buffer.WriteExponentialGolomb(kIgnored);
+ }
+ // loop_filter_across_tiles_enabled_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ }
+ }
+ // pps_loop_filter_across_slices_enabled_flag: u(1)
+ bit_buffer.WriteBits(1, 1);
+ // deblocking_filter_control_present_flag: u(1)
+ bit_buffer.WriteBits(deblocking_filter_control_present_flag, 1);
+ if (deblocking_filter_control_present_flag) {
+ // deblocking_filter_override_enabled_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+ // pps_deblocking_filter_disabled_flag: u(1)
+ bit_buffer.WriteBits(pps_deblocking_filter_disabled_flag, 1);
+ if (!pps_deblocking_filter_disabled_flag) {
+ // pps_beta_offset_div2: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(kIgnored);
+ // pps_tc_offset_div2: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(kIgnored);
+ }
+ }
+ // pps_scaling_list_data_present_flag: u(1)
+ bit_buffer.WriteBits(pps_scaling_list_data_present_flag, 1);
+ if (pps_scaling_list_data_present_flag) {
+ for (int size_id = 0; size_id < 4; size_id++) {
+ for (int matrix_id = 0; matrix_id < 6;
+ matrix_id += (size_id == 3) ? 3 : 1) {
+ // scaling_list_pred_mode_flag: u(1)
+ bit_buffer.WriteBits(scaling_list_pred_mode_flag, 1);
+ if (!scaling_list_pred_mode_flag) {
+ // scaling_list_pred_matrix_id_delta: ue(v)
+ bit_buffer.WriteExponentialGolomb(kIgnored);
+ } else {
+ uint32_t coef_num = std::min(64, 1 << (4 + (size_id << 1)));
+ if (size_id > 1) {
+ // scaling_list_dc_coef_minus8: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(kIgnored);
+ }
+ for (uint32_t i = 0; i < coef_num; i++) {
+ // scaling_list_delta_coef: se(v)
+ bit_buffer.WriteSignedExponentialGolomb(kIgnored);
+ }
+ }
+ }
+ }
+ }
+ // lists_modification_present_flag: u(1)
+ bit_buffer.WriteBits(pps.lists_modification_present_flag, 1);
+ // log2_parallel_merge_level_minus2: ue(v)
+ bit_buffer.WriteExponentialGolomb(kIgnored);
+ // slice_segment_header_extension_present_flag: u(1)
+ bit_buffer.WriteBits(0, 1);
+
+ size_t byte_offset;
+ size_t bit_offset;
+ bit_buffer.GetCurrentOffset(&byte_offset, &bit_offset);
+ if (bit_offset > 0) {
+ bit_buffer.WriteBits(0, 8 - bit_offset);
+ bit_buffer.GetCurrentOffset(&byte_offset, &bit_offset);
+ }
+
+ H265::WriteRbsp(data, byte_offset, out_buffer);
+}
+
+class H265PpsParserTest : public ::testing::Test {
+ public:
+ H265PpsParserTest() {}
+ ~H265PpsParserTest() override {}
+
+ void RunTest() {
+ VerifyParsing(generated_pps_, false, false, false, false, false, false,
+ false);
+ // Enable flags to cover more path
+ VerifyParsing(generated_pps_, true, true, false, true, true, true, false);
+ }
+
+ void VerifyParsing(const H265PpsParser::PpsState& pps,
+ bool cu_qp_delta_enabled_flag,
+ bool tiles_enabled_flag,
+ bool uniform_spacing_flag,
+ bool deblocking_filter_control_present_flag,
+ bool pps_deblocking_filter_disabled_flag,
+ bool pps_scaling_list_data_present_flag,
+ bool scaling_list_pred_mode_flag) {
+ buffer_.Clear();
+ WritePps(pps, cu_qp_delta_enabled_flag, tiles_enabled_flag,
+ uniform_spacing_flag, deblocking_filter_control_present_flag,
+ pps_deblocking_filter_disabled_flag,
+ pps_scaling_list_data_present_flag, scaling_list_pred_mode_flag,
+ &buffer_);
+ const uint8_t sps_buffer[] = {
+ 0x01, 0x04, 0x08, 0x00, 0x00, 0x03, 0x00, 0x9d, 0x08, 0x00,
+ 0x00, 0x03, 0x00, 0x00, 0x5d, 0xb0, 0x02, 0x80, 0x80, 0x2d,
+ 0x16, 0x59, 0x59, 0xa4, 0x93, 0x2b, 0x80, 0x40, 0x00, 0x00,
+ 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82};
+ H265SpsParser::SpsState parsed_sps =
+ H265SpsParser::ParseSps(sps_buffer, arraysize(sps_buffer)).value();
+ parsed_pps_ =
+ H265PpsParser::ParsePps(buffer_.data(), buffer_.size(), &parsed_sps);
+ ASSERT_TRUE(parsed_pps_);
+ EXPECT_EQ(pps.dependent_slice_segments_enabled_flag,
+ parsed_pps_->dependent_slice_segments_enabled_flag);
+ EXPECT_EQ(pps.cabac_init_present_flag,
+ parsed_pps_->cabac_init_present_flag);
+ EXPECT_EQ(pps.output_flag_present_flag,
+ parsed_pps_->output_flag_present_flag);
+ EXPECT_EQ(pps.num_extra_slice_header_bits,
+ parsed_pps_->num_extra_slice_header_bits);
+ EXPECT_EQ(pps.num_ref_idx_l0_default_active_minus1,
+ parsed_pps_->num_ref_idx_l0_default_active_minus1);
+ EXPECT_EQ(pps.num_ref_idx_l1_default_active_minus1,
+ parsed_pps_->num_ref_idx_l1_default_active_minus1);
+ EXPECT_EQ(pps.init_qp_minus26, parsed_pps_->init_qp_minus26);
+ EXPECT_EQ(pps.weighted_pred_flag, parsed_pps_->weighted_pred_flag);
+ EXPECT_EQ(pps.weighted_bipred_flag, parsed_pps_->weighted_bipred_flag);
+ EXPECT_EQ(pps.lists_modification_present_flag,
+ parsed_pps_->lists_modification_present_flag);
+ EXPECT_EQ(pps.pps_id, parsed_pps_->pps_id);
+ EXPECT_EQ(pps.sps_id, parsed_pps_->sps_id);
+ }
+
+ H265PpsParser::PpsState generated_pps_;
+ rtc::Buffer buffer_;
+ absl::optional<H265PpsParser::PpsState> parsed_pps_;
+ absl::optional<H265SpsParser::SpsState> parsed_sps_;
+};
+
+TEST_F(H265PpsParserTest, ZeroPps) {
+ RunTest();
+}
+
+TEST_F(H265PpsParserTest, MaxPps) {
+ generated_pps_.dependent_slice_segments_enabled_flag = true;
+ generated_pps_.init_qp_minus26 = 25;
+ generated_pps_.num_extra_slice_header_bits = 1; // 1 bit value.
+ generated_pps_.weighted_bipred_flag = true;
+ generated_pps_.weighted_pred_flag = true;
+ generated_pps_.cabac_init_present_flag = true;
+ generated_pps_.pps_id = 2;
+ generated_pps_.sps_id = 1;
+ RunTest();
+
+ generated_pps_.init_qp_minus26 = -25;
+ RunTest();
+}
+
+} // namespace webrtc