tor-browser

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

simple_encoder_wrapper_unittests.cc (11775B)


      1 /*
      2 *  Copyright (c) 2024 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 <memory>
     12 #include <optional>
     13 #include <utility>
     14 
     15 #include "api/video/i420_buffer.h"  // IWYU pragma: keep
     16 #include "api/video_codecs/libaom_av1_encoder_factory.h"
     17 #include "api/video_codecs/simple_encoder_wrapper.h"
     18 #include "api/video_codecs/video_encoder_factory_interface.h"
     19 #include "api/video_codecs/video_encoding_general.h"
     20 #include "test/gmock.h"
     21 #include "test/gtest.h"
     22 #include "test/testsupport/file_utils.h"
     23 #include "test/testsupport/frame_reader.h"
     24 
     25 namespace webrtc {
     26 
     27 using ::testing::Eq;
     28 using ::testing::Gt;
     29 using ::testing::IsEmpty;
     30 using ::testing::Ne;
     31 using ::testing::Not;
     32 using ::testing::NotNull;
     33 using ::testing::UnorderedElementsAre;
     34 using PredictionConstraints =
     35    VideoEncoderFactoryInterface::Capabilities::PredictionConstraints;
     36 
     37 namespace {
     38 
     39 std::unique_ptr<test::FrameReader> CreateFrameReader() {
     40  return CreateY4mFrameReader(
     41      test::ResourcePath("reference_video_640x360_30fps", "y4m"),
     42      test::YuvFrameReaderImpl::RepeatMode::kPingPong);
     43 }
     44 
     45 TEST(SimpleEncoderWrapper, SupportedSvcModesOnlyL1T1) {
     46  PredictionConstraints constraints = {
     47      .num_buffers = 2,
     48      .max_references = 2,
     49      .max_temporal_layers = 1,
     50      .buffer_space_type =
     51          PredictionConstraints::BufferSpaceType::kSingleKeyframe,
     52      .max_spatial_layers = 1,
     53      .scaling_factors = {{1, 1}},
     54  };
     55 
     56  EXPECT_THAT(SimpleEncoderWrapper::SupportedWebrtcSvcModes(constraints),
     57              UnorderedElementsAre("L1T1"));
     58 }
     59 
     60 TEST(SimpleEncoderWrapper, SupportedSvcModesUpToL1T3) {
     61  PredictionConstraints constraints = {
     62      .num_buffers = 8,
     63      .max_references = 1,
     64      .max_temporal_layers = 3,
     65      .buffer_space_type =
     66          PredictionConstraints::BufferSpaceType::kSingleKeyframe,
     67      .max_spatial_layers = 1,
     68      .scaling_factors = {{1, 1}, {1, 2}},
     69  };
     70 
     71  EXPECT_THAT(SimpleEncoderWrapper::SupportedWebrtcSvcModes(constraints),
     72              UnorderedElementsAre("L1T1", "L1T2", "L1T3"));
     73 }
     74 
     75 TEST(SimpleEncoderWrapper, SupportedSvcModesUpToL3T3Key) {
     76  PredictionConstraints constraints = {
     77      .num_buffers = 8,
     78      .max_references = 2,
     79      .max_temporal_layers = 3,
     80      .buffer_space_type =
     81          PredictionConstraints::BufferSpaceType::kSingleKeyframe,
     82      .max_spatial_layers = 3,
     83      .scaling_factors = {{1, 1}, {1, 2}},
     84  };
     85 
     86  EXPECT_THAT(
     87      SimpleEncoderWrapper::SupportedWebrtcSvcModes(constraints),
     88      UnorderedElementsAre("L1T1", "L1T2", "L1T3", "L2T1", "L2T1_KEY", "L2T2",
     89                           "L2T2_KEY", "L2T3", "L2T3_KEY", "L3T1", "L3T1_KEY",
     90                           "L3T2", "L3T2_KEY", "L3T3", "L3T3_KEY", "S2T1",
     91                           "S2T2", "S2T3", "S3T1", "S3T2", "S3T3"));
     92 }
     93 
     94 TEST(SimpleEncoderWrapper, SupportedSvcModesUpToS3T3) {
     95  PredictionConstraints constraints = {
     96      .num_buffers = 8,
     97      .max_references = 2,
     98      .max_temporal_layers = 3,
     99      .buffer_space_type =
    100          PredictionConstraints::BufferSpaceType::kMultiInstance,
    101      .max_spatial_layers = 3,
    102      .scaling_factors = {{1, 1}, {1, 2}},
    103  };
    104 
    105  EXPECT_THAT(SimpleEncoderWrapper::SupportedWebrtcSvcModes(constraints),
    106              UnorderedElementsAre("L1T1", "L1T2", "L1T3", "S2T1", "S2T2",
    107                                   "S2T3", "S3T1", "S3T2", "S3T3"));
    108 }
    109 
    110 TEST(SimpleEncoderWrapper, SupportedSvcModesUpToL3T3KeyWithHScaling) {
    111  PredictionConstraints constraints = {
    112      .num_buffers = 8,
    113      .max_references = 2,
    114      .max_temporal_layers = 3,
    115      .buffer_space_type =
    116          PredictionConstraints::BufferSpaceType::kSingleKeyframe,
    117      .max_spatial_layers = 3,
    118      .scaling_factors = {{1, 1}, {1, 2}, {2, 3}},
    119  };
    120 
    121  EXPECT_THAT(
    122      SimpleEncoderWrapper::SupportedWebrtcSvcModes(constraints),
    123      UnorderedElementsAre(
    124          "L1T1", "L1T2", "L1T3", "L2T1", "L2T1h", "L2T1_KEY", "L2T1h_KEY",
    125          "L2T2", "L2T2h", "L2T2_KEY", "L2T2h_KEY", "L2T3", "L2T3h", "L2T3_KEY",
    126          "L2T3h_KEY", "L3T1", "L3T1h", "L3T1_KEY", "L3T1h_KEY", "L3T2",
    127          "L3T2h", "L3T2_KEY", "L3T2h_KEY", "L3T3", "L3T3h", "L3T3_KEY",
    128          "L3T3h_KEY", "S2T1", "S2T1h", "S2T2", "S2T2h", "S2T3", "S2T3h",
    129          "S3T1", "S3T1h", "S3T2", "S3T2h", "S3T3", "S3T3h"));
    130 }
    131 
    132 // TD: The encoder wrapper shouldn't really use an actual encoder
    133 // implementation for testing, but hey, this is just a PoC.
    134 TEST(SimpleEncoderWrapper, EncodeL1T1) {
    135  auto encoder = LibaomAv1EncoderFactory().CreateEncoder(
    136      {.max_encode_dimensions = {.width = 1080, .height = 720},
    137       .encoding_format = {.sub_sampling = EncodingFormat::k420,
    138                           .bit_depth = 8},
    139       .rc_mode = VideoEncoderFactoryInterface::StaticEncoderSettings::Cqp(),
    140       .max_number_of_threads = 1},
    141      {});
    142 
    143  std::unique_ptr<SimpleEncoderWrapper> simple_encoder =
    144      SimpleEncoderWrapper::Create(std::move(encoder), "L1T1");
    145 
    146  ASSERT_THAT(simple_encoder, NotNull());
    147 
    148  simple_encoder->SetEncodeQp(30);
    149  simple_encoder->SetEncodeFps(15);
    150  auto frame_reader = CreateFrameReader();
    151 
    152  int num_callbacks = 0;
    153  simple_encoder->Encode(
    154      frame_reader->PullFrame(), /*force_keyframe=*/true,
    155      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    156        ++num_callbacks;
    157        ASSERT_THAT(result.oh_no, Eq(false));
    158        EXPECT_THAT(result.dependency_structure, Ne(std::nullopt));
    159        EXPECT_THAT(result.bitstream_data, Not(IsEmpty()));
    160        EXPECT_THAT(result.frame_type, Eq(FrameType::kKeyframe));
    161        EXPECT_THAT(result.generic_frame_info.spatial_id, Eq(0));
    162        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(0));
    163      });
    164 
    165  simple_encoder->Encode(
    166      frame_reader->PullFrame(), /*force_keyframe=*/false,
    167      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    168        ++num_callbacks;
    169        ASSERT_THAT(result.oh_no, Eq(false));
    170        EXPECT_THAT(result.dependency_structure, Eq(std::nullopt));
    171        EXPECT_THAT(result.bitstream_data, Not(IsEmpty()));
    172        EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    173        EXPECT_THAT(result.generic_frame_info.spatial_id, Eq(0));
    174        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(0));
    175      });
    176 }
    177 
    178 TEST(SimpleEncoderWrapper, EncodeL2T2_KEY) {
    179  auto encoder = LibaomAv1EncoderFactory().CreateEncoder(
    180      {.max_encode_dimensions = {.width = 1080, .height = 720},
    181       .encoding_format = {.sub_sampling = EncodingFormat::k420,
    182                           .bit_depth = 8},
    183       .rc_mode = VideoEncoderFactoryInterface::StaticEncoderSettings::Cqp(),
    184       .max_number_of_threads = 1},
    185      {});
    186 
    187  std::unique_ptr<SimpleEncoderWrapper> simple_encoder =
    188      SimpleEncoderWrapper::Create(std::move(encoder), "L2T2_KEY");
    189 
    190  ASSERT_THAT(simple_encoder, NotNull());
    191 
    192  simple_encoder->SetEncodeQp(30);
    193  simple_encoder->SetEncodeFps(15);
    194  auto frame_reader = CreateFrameReader();
    195 
    196  int num_callbacks = 0;
    197  simple_encoder->Encode(
    198      frame_reader->PullFrame(), /*force_keyframe=*/true,
    199      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    200        ASSERT_THAT(result.oh_no, Eq(false));
    201        if (result.generic_frame_info.spatial_id == 0) {
    202          ++num_callbacks;
    203          EXPECT_THAT(result.dependency_structure, Ne(std::nullopt));
    204          EXPECT_THAT(result.bitstream_data, Not(IsEmpty()));
    205          EXPECT_THAT(result.frame_type, Eq(FrameType::kKeyframe));
    206          EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(0));
    207        } else if (result.generic_frame_info.spatial_id == 1) {
    208          ++num_callbacks;
    209          EXPECT_THAT(result.dependency_structure, Eq(std::nullopt));
    210          EXPECT_THAT(result.bitstream_data, Not(IsEmpty()));
    211          EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    212          EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(0));
    213        }
    214      });
    215 
    216  simple_encoder->Encode(
    217      frame_reader->PullFrame(), /*force_keyframe=*/false,
    218      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    219        ASSERT_THAT(result.oh_no, Eq(false));
    220        if (result.generic_frame_info.spatial_id == 0) {
    221          ++num_callbacks;
    222          EXPECT_THAT(result.dependency_structure, Eq(std::nullopt));
    223          EXPECT_THAT(result.bitstream_data, Not(IsEmpty()));
    224          EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    225          EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(1));
    226        } else if (result.generic_frame_info.spatial_id == 1) {
    227          ++num_callbacks;
    228          EXPECT_THAT(result.dependency_structure, Eq(std::nullopt));
    229          EXPECT_THAT(result.bitstream_data, Not(IsEmpty()));
    230          EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    231          EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(1));
    232        }
    233      });
    234 
    235  EXPECT_THAT(num_callbacks, Eq(4));
    236 }
    237 
    238 TEST(SimpleEncoderWrapper, EncodeL1T3ForceKeyframe) {
    239  auto encoder = LibaomAv1EncoderFactory().CreateEncoder(
    240      {.max_encode_dimensions = {.width = 1080, .height = 720},
    241       .encoding_format = {.sub_sampling = EncodingFormat::k420,
    242                           .bit_depth = 8},
    243       .rc_mode = VideoEncoderFactoryInterface::StaticEncoderSettings::Cqp(),
    244       .max_number_of_threads = 1},
    245      {});
    246 
    247  std::unique_ptr<SimpleEncoderWrapper> simple_encoder =
    248      SimpleEncoderWrapper::Create(std::move(encoder), "L1T3");
    249 
    250  ASSERT_THAT(simple_encoder, NotNull());
    251 
    252  simple_encoder->SetEncodeQp(30);
    253  simple_encoder->SetEncodeFps(15);
    254  auto frame_reader = CreateFrameReader();
    255 
    256  int num_callbacks = 0;
    257  simple_encoder->Encode(
    258      frame_reader->PullFrame(), /*force_keyframe=*/true,
    259      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    260        ++num_callbacks;
    261        ASSERT_THAT(result.oh_no, Eq(false));
    262        EXPECT_THAT(result.frame_type, Eq(FrameType::kKeyframe));
    263        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(0));
    264      });
    265 
    266  simple_encoder->Encode(
    267      frame_reader->PullFrame(), /*force_keyframe=*/false,
    268      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    269        ++num_callbacks;
    270        ASSERT_THAT(result.oh_no, Eq(false));
    271        EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    272        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(2));
    273      });
    274 
    275  simple_encoder->Encode(
    276      frame_reader->PullFrame(), /*force_keyframe=*/false,
    277      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    278        ++num_callbacks;
    279        ASSERT_THAT(result.oh_no, Eq(false));
    280        EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    281        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(1));
    282      });
    283 
    284  simple_encoder->Encode(
    285      frame_reader->PullFrame(), /*force_keyframe=*/true,
    286      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    287        ++num_callbacks;
    288        ASSERT_THAT(result.oh_no, Eq(false));
    289        EXPECT_THAT(result.frame_type, Eq(FrameType::kKeyframe));
    290        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(0));
    291      });
    292 
    293  simple_encoder->Encode(
    294      frame_reader->PullFrame(), /*force_keyframe=*/false,
    295      [&](const SimpleEncoderWrapper::EncodeResult& result) {
    296        ++num_callbacks;
    297        ASSERT_THAT(result.oh_no, Eq(false));
    298        EXPECT_THAT(result.frame_type, Eq(FrameType::kDeltaFrame));
    299        EXPECT_THAT(result.generic_frame_info.temporal_id, Eq(2));
    300      });
    301 
    302  EXPECT_THAT(num_callbacks, Eq(5));
    303 }
    304 
    305 }  // namespace
    306 }  // namespace webrtc