tor-browser

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

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