xref: /aosp_15_r20/external/webrtc/modules/video_coding/codecs/av1/libaom_av1_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2020 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 <stddef.h>
12 #include <stdint.h>
13 
14 #include <map>
15 #include <memory>
16 #include <ostream>
17 #include <tuple>
18 #include <vector>
19 
20 #include "absl/types/optional.h"
21 #include "api/units/data_size.h"
22 #include "api/units/time_delta.h"
23 #include "api/video_codecs/video_codec.h"
24 #include "api/video_codecs/video_encoder.h"
25 #include "modules/video_coding/codecs/av1/dav1d_decoder.h"
26 #include "modules/video_coding/codecs/av1/libaom_av1_encoder.h"
27 #include "modules/video_coding/codecs/test/encoded_video_frame_producer.h"
28 #include "modules/video_coding/include/video_codec_interface.h"
29 #include "modules/video_coding/include/video_error_codes.h"
30 #include "modules/video_coding/svc/create_scalability_structure.h"
31 #include "modules/video_coding/svc/scalability_mode_util.h"
32 #include "modules/video_coding/svc/scalable_video_controller.h"
33 #include "modules/video_coding/svc/scalable_video_controller_no_layering.h"
34 #include "test/gmock.h"
35 #include "test/gtest.h"
36 
37 namespace webrtc {
38 namespace {
39 
40 using ::testing::ContainerEq;
41 using ::testing::Each;
42 using ::testing::ElementsAreArray;
43 using ::testing::Ge;
44 using ::testing::IsEmpty;
45 using ::testing::Not;
46 using ::testing::NotNull;
47 using ::testing::Pointwise;
48 using ::testing::SizeIs;
49 using ::testing::Truly;
50 using ::testing::Values;
51 
52 // Use small resolution for this test to make it faster.
53 constexpr int kWidth = 320;
54 constexpr int kHeight = 180;
55 constexpr int kFramerate = 30;
56 
DefaultCodecSettings()57 VideoCodec DefaultCodecSettings() {
58   VideoCodec codec_settings;
59   codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
60   codec_settings.width = kWidth;
61   codec_settings.height = kHeight;
62   codec_settings.maxFramerate = kFramerate;
63   codec_settings.maxBitrate = 1000;
64   codec_settings.qpMax = 63;
65   return codec_settings;
66 }
DefaultEncoderSettings()67 VideoEncoder::Settings DefaultEncoderSettings() {
68   return VideoEncoder::Settings(
69       VideoEncoder::Capabilities(/*loss_notification=*/false),
70       /*number_of_cores=*/1, /*max_payload_size=*/1200);
71 }
72 
73 class TestAv1Decoder {
74  public:
TestAv1Decoder(int decoder_id)75   explicit TestAv1Decoder(int decoder_id)
76       : decoder_id_(decoder_id), decoder_(CreateDav1dDecoder()) {
77     if (decoder_ == nullptr) {
78       ADD_FAILURE() << "Failed to create a decoder#" << decoder_id_;
79       return;
80     }
81     EXPECT_TRUE(decoder_->Configure({}));
82     EXPECT_EQ(decoder_->RegisterDecodeCompleteCallback(&callback_),
83               WEBRTC_VIDEO_CODEC_OK);
84   }
85   // This class requires pointer stability and thus not copyable nor movable.
86   TestAv1Decoder(const TestAv1Decoder&) = delete;
87   TestAv1Decoder& operator=(const TestAv1Decoder&) = delete;
88 
Decode(int64_t frame_id,const EncodedImage & image)89   void Decode(int64_t frame_id, const EncodedImage& image) {
90     ASSERT_THAT(decoder_, NotNull());
91     int32_t error = decoder_->Decode(image, /*missing_frames=*/false,
92                                      /*render_time_ms=*/image.capture_time_ms_);
93     if (error != WEBRTC_VIDEO_CODEC_OK) {
94       ADD_FAILURE() << "Failed to decode frame id " << frame_id
95                     << " with error code " << error << " by decoder#"
96                     << decoder_id_;
97       return;
98     }
99     decoded_ids_.push_back(frame_id);
100   }
101 
decoded_frame_ids() const102   const std::vector<int64_t>& decoded_frame_ids() const { return decoded_ids_; }
num_output_frames() const103   size_t num_output_frames() const { return callback_.num_called(); }
104 
105  private:
106   // Decoder callback that only counts how many times it was called.
107   // While it is tempting to replace it with a simple mock, that one requires
108   // to set expectation on number of calls in advance. Tests below unsure about
109   // expected number of calls until after calls are done.
110   class DecoderCallback : public DecodedImageCallback {
111    public:
num_called() const112     size_t num_called() const { return num_called_; }
113 
114    private:
Decoded(VideoFrame &)115     int32_t Decoded(VideoFrame& /*decoded_image*/) override {
116       ++num_called_;
117       return 0;
118     }
Decoded(VideoFrame &,absl::optional<int32_t>,absl::optional<uint8_t>)119     void Decoded(VideoFrame& /*decoded_image*/,
120                  absl::optional<int32_t> /*decode_time_ms*/,
121                  absl::optional<uint8_t> /*qp*/) override {
122       ++num_called_;
123     }
124 
125     int num_called_ = 0;
126   };
127 
128   const int decoder_id_;
129   std::vector<int64_t> decoded_ids_;
130   DecoderCallback callback_;
131   const std::unique_ptr<VideoDecoder> decoder_;
132 };
133 
TEST(LibaomAv1Test,EncodeDecode)134 TEST(LibaomAv1Test, EncodeDecode) {
135   TestAv1Decoder decoder(0);
136   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
137   VideoCodec codec_settings = DefaultCodecSettings();
138   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
139             WEBRTC_VIDEO_CODEC_OK);
140 
141   VideoBitrateAllocation allocation;
142   allocation.SetBitrate(0, 0, 300000);
143   encoder->SetRates(VideoEncoder::RateControlParameters(
144       allocation, codec_settings.maxFramerate));
145 
146   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
147       EncodedVideoFrameProducer(*encoder).SetNumInputFrames(4).Encode();
148   for (size_t frame_id = 0; frame_id < encoded_frames.size(); ++frame_id) {
149     decoder.Decode(static_cast<int64_t>(frame_id),
150                    encoded_frames[frame_id].encoded_image);
151   }
152 
153   // Check encoder produced some frames for decoder to decode.
154   ASSERT_THAT(encoded_frames, Not(IsEmpty()));
155   // Check decoder found all of them valid.
156   EXPECT_THAT(decoder.decoded_frame_ids(), SizeIs(encoded_frames.size()));
157   // Check each of them produced an output frame.
158   EXPECT_EQ(decoder.num_output_frames(), decoder.decoded_frame_ids().size());
159 }
160 
161 struct LayerId {
operator ==(const LayerId & lhs,const LayerId & rhs)162   friend bool operator==(const LayerId& lhs, const LayerId& rhs) {
163     return std::tie(lhs.spatial_id, lhs.temporal_id) ==
164            std::tie(rhs.spatial_id, rhs.temporal_id);
165   }
operator <(const LayerId & lhs,const LayerId & rhs)166   friend bool operator<(const LayerId& lhs, const LayerId& rhs) {
167     return std::tie(lhs.spatial_id, lhs.temporal_id) <
168            std::tie(rhs.spatial_id, rhs.temporal_id);
169   }
operator <<(std::ostream & s,const LayerId & layer)170   friend std::ostream& operator<<(std::ostream& s, const LayerId& layer) {
171     return s << "S" << layer.spatial_id << "T" << layer.temporal_id;
172   }
173 
174   int spatial_id = 0;
175   int temporal_id = 0;
176 };
177 
178 struct SvcTestParam {
GetScalabilityModewebrtc::__anond8652c030111::SvcTestParam179   ScalabilityMode GetScalabilityMode() const {
180     absl::optional<ScalabilityMode> scalability_mode =
181         ScalabilityModeFromString(name);
182     RTC_CHECK(scalability_mode.has_value());
183     return *scalability_mode;
184   }
185 
186   std::string name;
187   int num_frames_to_generate;
188   std::map<LayerId, DataRate> configured_bitrates;
189 };
190 
191 class LibaomAv1SvcTest : public ::testing::TestWithParam<SvcTestParam> {};
192 
TEST_P(LibaomAv1SvcTest,EncodeAndDecodeAllDecodeTargets)193 TEST_P(LibaomAv1SvcTest, EncodeAndDecodeAllDecodeTargets) {
194   const SvcTestParam param = GetParam();
195   std::unique_ptr<ScalableVideoController> svc_controller =
196       CreateScalabilityStructure(param.GetScalabilityMode());
197   ASSERT_TRUE(svc_controller);
198   VideoBitrateAllocation allocation;
199   if (param.configured_bitrates.empty()) {
200     ScalableVideoController::StreamLayersConfig config =
201         svc_controller->StreamConfig();
202     for (int sid = 0; sid < config.num_spatial_layers; ++sid) {
203       for (int tid = 0; tid < config.num_temporal_layers; ++tid) {
204         allocation.SetBitrate(sid, tid, 100'000);
205       }
206     }
207   } else {
208     for (const auto& kv : param.configured_bitrates) {
209       allocation.SetBitrate(kv.first.spatial_id, kv.first.temporal_id,
210                             kv.second.bps());
211     }
212   }
213 
214   size_t num_decode_targets =
215       svc_controller->DependencyStructure().num_decode_targets;
216 
217   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
218   VideoCodec codec_settings = DefaultCodecSettings();
219   codec_settings.SetScalabilityMode(GetParam().GetScalabilityMode());
220   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
221             WEBRTC_VIDEO_CODEC_OK);
222   encoder->SetRates(VideoEncoder::RateControlParameters(
223       allocation, codec_settings.maxFramerate));
224   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
225       EncodedVideoFrameProducer(*encoder)
226           .SetNumInputFrames(GetParam().num_frames_to_generate)
227           .SetResolution({kWidth, kHeight})
228           .Encode();
229 
230   ASSERT_THAT(
231       encoded_frames,
232       Each(Truly([&](const EncodedVideoFrameProducer::EncodedFrame& frame) {
233         return frame.codec_specific_info.generic_frame_info &&
234                frame.codec_specific_info.generic_frame_info
235                        ->decode_target_indications.size() == num_decode_targets;
236       })));
237 
238   for (size_t dt = 0; dt < num_decode_targets; ++dt) {
239     TestAv1Decoder decoder(dt);
240     std::vector<int64_t> requested_ids;
241     for (int64_t frame_id = 0;
242          frame_id < static_cast<int64_t>(encoded_frames.size()); ++frame_id) {
243       const EncodedVideoFrameProducer::EncodedFrame& frame =
244           encoded_frames[frame_id];
245       if (frame.codec_specific_info.generic_frame_info
246               ->decode_target_indications[dt] !=
247           DecodeTargetIndication::kNotPresent) {
248         requested_ids.push_back(frame_id);
249         decoder.Decode(frame_id, frame.encoded_image);
250       }
251     }
252 
253     ASSERT_THAT(requested_ids, SizeIs(Ge(2u)));
254     // Check decoder found all of them valid.
255     EXPECT_THAT(decoder.decoded_frame_ids(), ContainerEq(requested_ids))
256         << "Decoder#" << dt;
257     // Check each of them produced an output frame.
258     EXPECT_EQ(decoder.num_output_frames(), decoder.decoded_frame_ids().size())
259         << "Decoder#" << dt;
260   }
261 }
262 
263 MATCHER(SameLayerIdAndBitrateIsNear, "") {
264   // First check if layer id is the same.
265   return std::get<0>(arg).first == std::get<1>(arg).first &&
266          // check measured bitrate is not much lower than requested.
267          std::get<0>(arg).second >= std::get<1>(arg).second * 0.8 &&
268          // check measured bitrate is not much larger than requested.
269          std::get<0>(arg).second <= std::get<1>(arg).second * 1.1;
270 }
271 
TEST_P(LibaomAv1SvcTest,SetRatesMatchMeasuredBitrate)272 TEST_P(LibaomAv1SvcTest, SetRatesMatchMeasuredBitrate) {
273   const SvcTestParam param = GetParam();
274   if (param.configured_bitrates.empty()) {
275     // Rates are not configured for this particular structure, skip the test.
276     return;
277   }
278   constexpr TimeDelta kDuration = TimeDelta::Seconds(5);
279 
280   VideoBitrateAllocation allocation;
281   for (const auto& kv : param.configured_bitrates) {
282     allocation.SetBitrate(kv.first.spatial_id, kv.first.temporal_id,
283                           kv.second.bps());
284   }
285 
286   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
287   ASSERT_TRUE(encoder);
288   VideoCodec codec_settings = DefaultCodecSettings();
289   codec_settings.SetScalabilityMode(param.GetScalabilityMode());
290   codec_settings.maxBitrate = allocation.get_sum_kbps();
291   codec_settings.maxFramerate = 30;
292   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
293             WEBRTC_VIDEO_CODEC_OK);
294 
295   encoder->SetRates(VideoEncoder::RateControlParameters(
296       allocation, codec_settings.maxFramerate));
297 
298   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
299       EncodedVideoFrameProducer(*encoder)
300           .SetNumInputFrames(codec_settings.maxFramerate * kDuration.seconds())
301           .SetResolution({codec_settings.width, codec_settings.height})
302           .SetFramerateFps(codec_settings.maxFramerate)
303           .Encode();
304 
305   // Calculate size of each layer.
306   std::map<LayerId, DataSize> layer_size;
307   for (const auto& frame : encoded_frames) {
308     ASSERT_TRUE(frame.codec_specific_info.generic_frame_info);
309     const auto& layer = *frame.codec_specific_info.generic_frame_info;
310     LayerId layer_id = {layer.spatial_id, layer.temporal_id};
311     // This is almost same as
312     // layer_size[layer_id] += DataSize::Bytes(frame.encoded_image.size());
313     // but avoids calling deleted default constructor for DataSize.
314     layer_size.emplace(layer_id, DataSize::Zero()).first->second +=
315         DataSize::Bytes(frame.encoded_image.size());
316   }
317   // Convert size of the layer into bitrate of that layer.
318   std::vector<std::pair<LayerId, DataRate>> measured_bitrates;
319   for (const auto& kv : layer_size) {
320     measured_bitrates.emplace_back(kv.first, kv.second / kDuration);
321   }
322   EXPECT_THAT(measured_bitrates, Pointwise(SameLayerIdAndBitrateIsNear(),
323                                            param.configured_bitrates));
324 }
325 
326 INSTANTIATE_TEST_SUITE_P(
327     Svc,
328     LibaomAv1SvcTest,
329     Values(SvcTestParam{"L1T1", /*num_frames_to_generate=*/4},
330            SvcTestParam{"L1T2",
331                         /*num_frames_to_generate=*/4,
332                         /*configured_bitrates=*/
333                         {{{0, 0}, DataRate::KilobitsPerSec(60)},
334                          {{0, 1}, DataRate::KilobitsPerSec(40)}}},
335            SvcTestParam{"L1T3", /*num_frames_to_generate=*/8},
336            SvcTestParam{"L2T1",
337                         /*num_frames_to_generate=*/3,
338                         /*configured_bitrates=*/
339                         {{{0, 0}, DataRate::KilobitsPerSec(30)},
340                          {{1, 0}, DataRate::KilobitsPerSec(70)}}},
341            SvcTestParam{"L2T1h",
342                         /*num_frames_to_generate=*/3,
343                         /*configured_bitrates=*/
344                         {{{0, 0}, DataRate::KilobitsPerSec(30)},
345                          {{1, 0}, DataRate::KilobitsPerSec(70)}}},
346            SvcTestParam{"L2T1_KEY", /*num_frames_to_generate=*/3},
347            SvcTestParam{"L3T1", /*num_frames_to_generate=*/3},
348            SvcTestParam{"L3T3", /*num_frames_to_generate=*/8},
349            SvcTestParam{"S2T1", /*num_frames_to_generate=*/3},
350            SvcTestParam{"S3T3", /*num_frames_to_generate=*/8},
351            SvcTestParam{"L2T2", /*num_frames_to_generate=*/4},
352            SvcTestParam{"L2T2_KEY", /*num_frames_to_generate=*/4},
353            SvcTestParam{"L2T2_KEY_SHIFT",
354                         /*num_frames_to_generate=*/4,
355                         /*configured_bitrates=*/
356                         {{{0, 0}, DataRate::KilobitsPerSec(70)},
357                          {{0, 1}, DataRate::KilobitsPerSec(30)},
358                          {{1, 0}, DataRate::KilobitsPerSec(110)},
359                          {{1, 1}, DataRate::KilobitsPerSec(80)}}}),
__anond8652c030302(const testing::TestParamInfo<SvcTestParam>& info) 360     [](const testing::TestParamInfo<SvcTestParam>& info) {
361       return info.param.name;
362     });
363 
364 }  // namespace
365 }  // namespace webrtc
366