xref: /aosp_15_r20/external/webrtc/modules/video_coding/codecs/av1/libaom_av1_encoder_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 "modules/video_coding/codecs/av1/libaom_av1_encoder.h"
12 
13 #include <limits>
14 #include <memory>
15 #include <vector>
16 
17 #include "absl/types/optional.h"
18 #include "api/video_codecs/video_codec.h"
19 #include "api/video_codecs/video_encoder.h"
20 #include "modules/video_coding/codecs/test/encoded_video_frame_producer.h"
21 #include "modules/video_coding/include/video_error_codes.h"
22 #include "test/gmock.h"
23 #include "test/gtest.h"
24 
25 namespace webrtc {
26 namespace {
27 
28 using ::testing::ElementsAre;
29 using ::testing::Eq;
30 using ::testing::Field;
31 using ::testing::IsEmpty;
32 using ::testing::SizeIs;
33 
DefaultCodecSettings()34 VideoCodec DefaultCodecSettings() {
35   VideoCodec codec_settings;
36   codec_settings.width = 320;
37   codec_settings.height = 180;
38   codec_settings.maxFramerate = 30;
39   codec_settings.maxBitrate = 1000;
40   codec_settings.qpMax = 63;
41   return codec_settings;
42 }
43 
DefaultEncoderSettings()44 VideoEncoder::Settings DefaultEncoderSettings() {
45   return VideoEncoder::Settings(
46       VideoEncoder::Capabilities(/*loss_notification=*/false),
47       /*number_of_cores=*/1, /*max_payload_size=*/1200);
48 }
49 
TEST(LibaomAv1EncoderTest,CanCreate)50 TEST(LibaomAv1EncoderTest, CanCreate) {
51   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
52   EXPECT_TRUE(encoder);
53 }
54 
TEST(LibaomAv1EncoderTest,InitAndRelease)55 TEST(LibaomAv1EncoderTest, InitAndRelease) {
56   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
57   ASSERT_TRUE(encoder);
58   VideoCodec codec_settings = DefaultCodecSettings();
59   EXPECT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
60             WEBRTC_VIDEO_CODEC_OK);
61   EXPECT_EQ(encoder->Release(), WEBRTC_VIDEO_CODEC_OK);
62 }
63 
TEST(LibaomAv1EncoderTest,NoBitrateOnTopLayerRefecltedInActiveDecodeTargets)64 TEST(LibaomAv1EncoderTest, NoBitrateOnTopLayerRefecltedInActiveDecodeTargets) {
65   // Configure encoder with 2 temporal layers.
66   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
67   VideoCodec codec_settings = DefaultCodecSettings();
68   codec_settings.SetScalabilityMode(ScalabilityMode::kL1T2);
69   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
70             WEBRTC_VIDEO_CODEC_OK);
71 
72   VideoEncoder::RateControlParameters rate_parameters;
73   rate_parameters.framerate_fps = 30;
74   rate_parameters.bitrate.SetBitrate(0, /*temporal_index=*/0, 300'000);
75   rate_parameters.bitrate.SetBitrate(0, /*temporal_index=*/1, 0);
76   encoder->SetRates(rate_parameters);
77 
78   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
79       EncodedVideoFrameProducer(*encoder).SetNumInputFrames(1).Encode();
80   ASSERT_THAT(encoded_frames, SizeIs(1));
81   ASSERT_NE(encoded_frames[0].codec_specific_info.generic_frame_info,
82             absl::nullopt);
83   // Assuming L1T2 structure uses 1st decode target for T0 and 2nd decode target
84   // for T0+T1 frames, expect only 1st decode target is active.
85   EXPECT_EQ(encoded_frames[0]
86                 .codec_specific_info.generic_frame_info->active_decode_targets,
87             0b01);
88 }
89 
TEST(LibaomAv1EncoderTest,SpatialScalabilityInTemporalUnitReportedAsDeltaFrame)90 TEST(LibaomAv1EncoderTest,
91      SpatialScalabilityInTemporalUnitReportedAsDeltaFrame) {
92   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
93   VideoCodec codec_settings = DefaultCodecSettings();
94   codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1);
95   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
96             WEBRTC_VIDEO_CODEC_OK);
97 
98   VideoEncoder::RateControlParameters rate_parameters;
99   rate_parameters.framerate_fps = 30;
100   rate_parameters.bitrate.SetBitrate(/*spatial_index=*/0, 0, 300'000);
101   rate_parameters.bitrate.SetBitrate(/*spatial_index=*/1, 0, 300'000);
102   encoder->SetRates(rate_parameters);
103 
104   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
105       EncodedVideoFrameProducer(*encoder).SetNumInputFrames(1).Encode();
106   ASSERT_THAT(encoded_frames, SizeIs(2));
107   EXPECT_THAT(encoded_frames[0].encoded_image._frameType,
108               Eq(VideoFrameType::kVideoFrameKey));
109   EXPECT_THAT(encoded_frames[1].encoded_image._frameType,
110               Eq(VideoFrameType::kVideoFrameDelta));
111 }
112 
TEST(LibaomAv1EncoderTest,NoBitrateOnTopSpatialLayerProduceDeltaFrames)113 TEST(LibaomAv1EncoderTest, NoBitrateOnTopSpatialLayerProduceDeltaFrames) {
114   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
115   VideoCodec codec_settings = DefaultCodecSettings();
116   codec_settings.SetScalabilityMode(ScalabilityMode::kL2T1);
117   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
118             WEBRTC_VIDEO_CODEC_OK);
119 
120   VideoEncoder::RateControlParameters rate_parameters;
121   rate_parameters.framerate_fps = 30;
122   rate_parameters.bitrate.SetBitrate(/*spatial_index=*/0, 0, 300'000);
123   rate_parameters.bitrate.SetBitrate(/*spatial_index=*/1, 0, 0);
124   encoder->SetRates(rate_parameters);
125 
126   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
127       EncodedVideoFrameProducer(*encoder).SetNumInputFrames(2).Encode();
128   ASSERT_THAT(encoded_frames, SizeIs(2));
129   EXPECT_THAT(encoded_frames[0].encoded_image._frameType,
130               Eq(VideoFrameType::kVideoFrameKey));
131   EXPECT_THAT(encoded_frames[1].encoded_image._frameType,
132               Eq(VideoFrameType::kVideoFrameDelta));
133 }
134 
TEST(LibaomAv1EncoderTest,SetsEndOfPictureForLastFrameInTemporalUnit)135 TEST(LibaomAv1EncoderTest, SetsEndOfPictureForLastFrameInTemporalUnit) {
136   VideoBitrateAllocation allocation;
137   allocation.SetBitrate(0, 0, 30000);
138   allocation.SetBitrate(1, 0, 40000);
139   allocation.SetBitrate(2, 0, 30000);
140 
141   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
142   VideoCodec codec_settings = DefaultCodecSettings();
143   // Configure encoder with 3 spatial layers.
144   codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1);
145   codec_settings.maxBitrate = allocation.get_sum_kbps();
146   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
147             WEBRTC_VIDEO_CODEC_OK);
148 
149   encoder->SetRates(VideoEncoder::RateControlParameters(
150       allocation, codec_settings.maxFramerate));
151 
152   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
153       EncodedVideoFrameProducer(*encoder).SetNumInputFrames(2).Encode();
154   ASSERT_THAT(encoded_frames, SizeIs(6));
155   EXPECT_FALSE(encoded_frames[0].codec_specific_info.end_of_picture);
156   EXPECT_FALSE(encoded_frames[1].codec_specific_info.end_of_picture);
157   EXPECT_TRUE(encoded_frames[2].codec_specific_info.end_of_picture);
158   EXPECT_FALSE(encoded_frames[3].codec_specific_info.end_of_picture);
159   EXPECT_FALSE(encoded_frames[4].codec_specific_info.end_of_picture);
160   EXPECT_TRUE(encoded_frames[5].codec_specific_info.end_of_picture);
161 }
162 
TEST(LibaomAv1EncoderTest,CheckOddDimensionsWithSpatialLayers)163 TEST(LibaomAv1EncoderTest, CheckOddDimensionsWithSpatialLayers) {
164   VideoBitrateAllocation allocation;
165   allocation.SetBitrate(0, 0, 30000);
166   allocation.SetBitrate(1, 0, 40000);
167   allocation.SetBitrate(2, 0, 30000);
168   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
169   VideoCodec codec_settings = DefaultCodecSettings();
170   // Configure encoder with 3 spatial layers.
171   codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1);
172   // Odd width and height values should not make encoder crash.
173   codec_settings.width = 623;
174   codec_settings.height = 405;
175   codec_settings.maxBitrate = allocation.get_sum_kbps();
176   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
177             WEBRTC_VIDEO_CODEC_OK);
178   encoder->SetRates(VideoEncoder::RateControlParameters(
179       allocation, codec_settings.maxFramerate));
180   EncodedVideoFrameProducer evfp(*encoder);
181   evfp.SetResolution(RenderResolution{623, 405});
182   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
183       evfp.SetNumInputFrames(2).Encode();
184   ASSERT_THAT(encoded_frames, SizeIs(6));
185 }
186 
TEST(LibaomAv1EncoderTest,EncoderInfoProvidesFpsAllocation)187 TEST(LibaomAv1EncoderTest, EncoderInfoProvidesFpsAllocation) {
188   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
189   VideoCodec codec_settings = DefaultCodecSettings();
190   codec_settings.SetScalabilityMode(ScalabilityMode::kL3T3);
191   codec_settings.maxFramerate = 60;
192   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
193             WEBRTC_VIDEO_CODEC_OK);
194 
195   const auto& encoder_info = encoder->GetEncoderInfo();
196   EXPECT_THAT(encoder_info.fps_allocation[0], ElementsAre(15, 30, 60));
197   EXPECT_THAT(encoder_info.fps_allocation[1], ElementsAre(15, 30, 60));
198   EXPECT_THAT(encoder_info.fps_allocation[2], ElementsAre(15, 30, 60));
199   EXPECT_THAT(encoder_info.fps_allocation[3], IsEmpty());
200 }
201 
TEST(LibaomAv1EncoderTest,PopulatesEncodedFrameSize)202 TEST(LibaomAv1EncoderTest, PopulatesEncodedFrameSize) {
203   VideoBitrateAllocation allocation;
204   allocation.SetBitrate(0, 0, 30000);
205   allocation.SetBitrate(1, 0, 40000);
206   allocation.SetBitrate(2, 0, 30000);
207   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
208   VideoCodec codec_settings = DefaultCodecSettings();
209   codec_settings.maxBitrate = allocation.get_sum_kbps();
210   ASSERT_GT(codec_settings.width, 4);
211   // Configure encoder with 3 spatial layers.
212   codec_settings.SetScalabilityMode(ScalabilityMode::kL3T1);
213   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
214             WEBRTC_VIDEO_CODEC_OK);
215   encoder->SetRates(VideoEncoder::RateControlParameters(
216       allocation, codec_settings.maxFramerate));
217   using Frame = EncodedVideoFrameProducer::EncodedFrame;
218   std::vector<Frame> encoded_frames =
219       EncodedVideoFrameProducer(*encoder).SetNumInputFrames(1).Encode();
220   EXPECT_THAT(
221       encoded_frames,
222       ElementsAre(
223           Field(&Frame::encoded_image,
224                 AllOf(Field(&EncodedImage::_encodedWidth,
225                             codec_settings.width / 4),
226                       Field(&EncodedImage::_encodedHeight,
227                             codec_settings.height / 4))),
228           Field(&Frame::encoded_image,
229                 AllOf(Field(&EncodedImage::_encodedWidth,
230                             codec_settings.width / 2),
231                       Field(&EncodedImage::_encodedHeight,
232                             codec_settings.height / 2))),
233           Field(&Frame::encoded_image,
234                 AllOf(Field(&EncodedImage::_encodedWidth, codec_settings.width),
235                       Field(&EncodedImage::_encodedHeight,
236                             codec_settings.height)))));
237 }
238 
TEST(LibaomAv1EncoderTest,RtpTimestampWrap)239 TEST(LibaomAv1EncoderTest, RtpTimestampWrap) {
240   std::unique_ptr<VideoEncoder> encoder = CreateLibaomAv1Encoder();
241   VideoCodec codec_settings = DefaultCodecSettings();
242   codec_settings.SetScalabilityMode(ScalabilityMode::kL1T1);
243   ASSERT_EQ(encoder->InitEncode(&codec_settings, DefaultEncoderSettings()),
244             WEBRTC_VIDEO_CODEC_OK);
245 
246   VideoEncoder::RateControlParameters rate_parameters;
247   rate_parameters.framerate_fps = 30;
248   rate_parameters.bitrate.SetBitrate(/*spatial_index=*/0, 0, 300'000);
249   encoder->SetRates(rate_parameters);
250 
251   std::vector<EncodedVideoFrameProducer::EncodedFrame> encoded_frames =
252       EncodedVideoFrameProducer(*encoder)
253           .SetNumInputFrames(2)
254           .SetRtpTimestamp(std::numeric_limits<uint32_t>::max())
255           .Encode();
256   ASSERT_THAT(encoded_frames, SizeIs(2));
257   EXPECT_THAT(encoded_frames[0].encoded_image._frameType,
258               Eq(VideoFrameType::kVideoFrameKey));
259   EXPECT_THAT(encoded_frames[1].encoded_image._frameType,
260               Eq(VideoFrameType::kVideoFrameDelta));
261 }
262 
263 }  // namespace
264 }  // namespace webrtc
265