xref: /aosp_15_r20/external/webrtc/modules/video_coding/codecs/test/video_codec_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2017 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/test/video_codec_unittest.h"
12 
13 #include <utility>
14 
15 #include "api/test/create_frame_generator.h"
16 #include "api/video_codecs/video_encoder.h"
17 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
18 #include "modules/video_coding/include/video_error_codes.h"
19 #include "test/video_codec_settings.h"
20 
21 static constexpr webrtc::TimeDelta kEncodeTimeout =
22     webrtc::TimeDelta::Millis(100);
23 static constexpr webrtc::TimeDelta kDecodeTimeout =
24     webrtc::TimeDelta::Millis(25);
25 // Set bitrate to get higher quality.
26 static const int kStartBitrate = 300;
27 static const int kMaxBitrate = 4000;
28 static const int kWidth = 176;        // Width of the input image.
29 static const int kHeight = 144;       // Height of the input image.
30 static const int kMaxFramerate = 30;  // Arbitrary value.
31 
32 namespace webrtc {
33 namespace {
34 const VideoEncoder::Capabilities kCapabilities(false);
35 }
36 
37 EncodedImageCallback::Result
OnEncodedImage(const EncodedImage & frame,const CodecSpecificInfo * codec_specific_info)38 VideoCodecUnitTest::FakeEncodeCompleteCallback::OnEncodedImage(
39     const EncodedImage& frame,
40     const CodecSpecificInfo* codec_specific_info) {
41   MutexLock lock(&test_->encoded_frame_section_);
42   test_->encoded_frames_.push_back(frame);
43   RTC_DCHECK(codec_specific_info);
44   test_->codec_specific_infos_.push_back(*codec_specific_info);
45   if (!test_->wait_for_encoded_frames_threshold_) {
46     test_->encoded_frame_event_.Set();
47     return Result(Result::OK);
48   }
49 
50   if (test_->encoded_frames_.size() ==
51       test_->wait_for_encoded_frames_threshold_) {
52     test_->wait_for_encoded_frames_threshold_ = 1;
53     test_->encoded_frame_event_.Set();
54   }
55   return Result(Result::OK);
56 }
57 
Decoded(VideoFrame & frame,absl::optional<int32_t> decode_time_ms,absl::optional<uint8_t> qp)58 void VideoCodecUnitTest::FakeDecodeCompleteCallback::Decoded(
59     VideoFrame& frame,
60     absl::optional<int32_t> decode_time_ms,
61     absl::optional<uint8_t> qp) {
62   MutexLock lock(&test_->decoded_frame_section_);
63   test_->decoded_frame_.emplace(frame);
64   test_->decoded_qp_ = qp;
65   test_->decoded_frame_event_.Set();
66 }
67 
SetUp()68 void VideoCodecUnitTest::SetUp() {
69   webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_);
70   codec_settings_.startBitrate = kStartBitrate;
71   codec_settings_.maxBitrate = kMaxBitrate;
72   codec_settings_.maxFramerate = kMaxFramerate;
73   codec_settings_.width = kWidth;
74   codec_settings_.height = kHeight;
75 
76   ModifyCodecSettings(&codec_settings_);
77 
78   input_frame_generator_ = test::CreateSquareFrameGenerator(
79       codec_settings_.width, codec_settings_.height,
80       test::FrameGeneratorInterface::OutputType::kI420, absl::optional<int>());
81 
82   encoder_ = CreateEncoder();
83   decoder_ = CreateDecoder();
84   encoder_->RegisterEncodeCompleteCallback(&encode_complete_callback_);
85   decoder_->RegisterDecodeCompleteCallback(&decode_complete_callback_);
86 
87   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
88             encoder_->InitEncode(
89                 &codec_settings_,
90                 VideoEncoder::Settings(kCapabilities, 1 /* number of cores */,
91                                        0 /* max payload size (unused) */)));
92 
93   VideoDecoder::Settings decoder_settings;
94   decoder_settings.set_codec_type(codec_settings_.codecType);
95   decoder_settings.set_max_render_resolution(
96       {codec_settings_.width, codec_settings_.height});
97   EXPECT_TRUE(decoder_->Configure(decoder_settings));
98 }
99 
ModifyCodecSettings(VideoCodec * codec_settings)100 void VideoCodecUnitTest::ModifyCodecSettings(VideoCodec* codec_settings) {}
101 
NextInputFrame()102 VideoFrame VideoCodecUnitTest::NextInputFrame() {
103   test::FrameGeneratorInterface::VideoFrameData frame_data =
104       input_frame_generator_->NextFrame();
105   VideoFrame input_frame = VideoFrame::Builder()
106                                .set_video_frame_buffer(frame_data.buffer)
107                                .set_update_rect(frame_data.update_rect)
108                                .build();
109 
110   const uint32_t timestamp =
111       last_input_frame_timestamp_ +
112       kVideoPayloadTypeFrequency / codec_settings_.maxFramerate;
113   input_frame.set_timestamp(timestamp);
114 
115   last_input_frame_timestamp_ = timestamp;
116   return input_frame;
117 }
118 
WaitForEncodedFrame(EncodedImage * frame,CodecSpecificInfo * codec_specific_info)119 bool VideoCodecUnitTest::WaitForEncodedFrame(
120     EncodedImage* frame,
121     CodecSpecificInfo* codec_specific_info) {
122   std::vector<EncodedImage> frames;
123   std::vector<CodecSpecificInfo> codec_specific_infos;
124   if (!WaitForEncodedFrames(&frames, &codec_specific_infos))
125     return false;
126   EXPECT_EQ(frames.size(), static_cast<size_t>(1));
127   EXPECT_EQ(frames.size(), codec_specific_infos.size());
128   *frame = frames[0];
129   *codec_specific_info = codec_specific_infos[0];
130   return true;
131 }
132 
SetWaitForEncodedFramesThreshold(size_t num_frames)133 void VideoCodecUnitTest::SetWaitForEncodedFramesThreshold(size_t num_frames) {
134   MutexLock lock(&encoded_frame_section_);
135   wait_for_encoded_frames_threshold_ = num_frames;
136 }
137 
WaitForEncodedFrames(std::vector<EncodedImage> * frames,std::vector<CodecSpecificInfo> * codec_specific_info)138 bool VideoCodecUnitTest::WaitForEncodedFrames(
139     std::vector<EncodedImage>* frames,
140     std::vector<CodecSpecificInfo>* codec_specific_info) {
141   EXPECT_TRUE(encoded_frame_event_.Wait(kEncodeTimeout))
142       << "Timed out while waiting for encoded frame.";
143   // This becomes unsafe if there are multiple threads waiting for frames.
144   MutexLock lock(&encoded_frame_section_);
145   EXPECT_FALSE(encoded_frames_.empty());
146   EXPECT_FALSE(codec_specific_infos_.empty());
147   EXPECT_EQ(encoded_frames_.size(), codec_specific_infos_.size());
148   if (!encoded_frames_.empty()) {
149     *frames = encoded_frames_;
150     encoded_frames_.clear();
151     RTC_DCHECK(!codec_specific_infos_.empty());
152     *codec_specific_info = codec_specific_infos_;
153     codec_specific_infos_.clear();
154     return true;
155   } else {
156     return false;
157   }
158 }
159 
WaitForDecodedFrame(std::unique_ptr<VideoFrame> * frame,absl::optional<uint8_t> * qp)160 bool VideoCodecUnitTest::WaitForDecodedFrame(std::unique_ptr<VideoFrame>* frame,
161                                              absl::optional<uint8_t>* qp) {
162   bool ret = decoded_frame_event_.Wait(kDecodeTimeout);
163   EXPECT_TRUE(ret) << "Timed out while waiting for a decoded frame.";
164   // This becomes unsafe if there are multiple threads waiting for frames.
165   MutexLock lock(&decoded_frame_section_);
166   EXPECT_TRUE(decoded_frame_);
167   if (decoded_frame_) {
168     frame->reset(new VideoFrame(std::move(*decoded_frame_)));
169     *qp = decoded_qp_;
170     decoded_frame_.reset();
171     return true;
172   } else {
173     return false;
174   }
175 }
176 
GetNumEncodedFrames()177 size_t VideoCodecUnitTest::GetNumEncodedFrames() {
178   MutexLock lock(&encoded_frame_section_);
179   return encoded_frames_.size();
180 }
181 
182 }  // namespace webrtc
183