blob: ae8fc663b57601d286d157d8a62daf2bf77c7425 [file] [log] [blame]
perkj26091b12016-09-01 01:17:40 -07001/*
2 * Copyright (c) 2016 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
Per512ecb32016-09-23 15:52:06 +020011#include <utility>
12
perkj26091b12016-09-01 01:17:40 -070013#include "webrtc/base/logging.h"
14#include "webrtc/test/encoder_settings.h"
15#include "webrtc/test/fake_encoder.h"
perkja49cbd32016-09-16 07:53:41 -070016#include "webrtc/test/frame_generator.h"
kwibergac9f8762016-09-30 22:29:43 -070017#include "webrtc/test/gtest.h"
perkj26091b12016-09-01 01:17:40 -070018#include "webrtc/video/send_statistics_proxy.h"
19#include "webrtc/video/vie_encoder.h"
20
21namespace webrtc {
22
23class ViEEncoderTest : public ::testing::Test {
24 public:
25 static const int kDefaultTimeoutMs = 30 * 1000;
26
27 ViEEncoderTest()
28 : video_send_config_(VideoSendStream::Config(nullptr)),
29 fake_encoder_(),
30 stats_proxy_(Clock::GetRealTimeClock(),
31 video_send_config_,
32 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo),
33 sink_(&fake_encoder_) {}
34
35 void SetUp() override {
36 video_send_config_ = VideoSendStream::Config(nullptr);
37 video_send_config_.encoder_settings.encoder = &fake_encoder_;
38 video_send_config_.encoder_settings.payload_name = "FAKE";
39 video_send_config_.encoder_settings.payload_type = 125;
40
Per512ecb32016-09-23 15:52:06 +020041 VideoEncoderConfig video_encoder_config;
perkj3b703ed2016-09-29 23:25:40 -070042 video_encoder_config.streams = test::CreateVideoStreams(1);
43 codec_width_ = static_cast<int>(video_encoder_config.streams[0].width);
44 codec_height_ = static_cast<int>(video_encoder_config.streams[0].height);
45
perkj26091b12016-09-01 01:17:40 -070046 vie_encoder_.reset(new ViEEncoder(
47 1 /* number_of_cores */, &stats_proxy_,
48 video_send_config_.encoder_settings, nullptr /* pre_encode_callback */,
49 nullptr /* overuse_callback */, nullptr /* encoder_timing */));
50 vie_encoder_->SetSink(&sink_);
perkja49cbd32016-09-16 07:53:41 -070051 vie_encoder_->SetSource(&video_source_);
perkj26091b12016-09-01 01:17:40 -070052 vie_encoder_->SetStartBitrate(10000);
Per512ecb32016-09-23 15:52:06 +020053 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
perkj26091b12016-09-01 01:17:40 -070054 }
55
56 VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) const {
57 class TestBuffer : public webrtc::I420Buffer {
58 public:
59 TestBuffer(rtc::Event* event, int width, int height)
60 : I420Buffer(width, height), event_(event) {}
61
62 private:
63 friend class rtc::RefCountedObject<TestBuffer>;
64 ~TestBuffer() override {
65 if (event_)
66 event_->Set();
67 }
68 rtc::Event* const event_;
69 };
70
Per512ecb32016-09-23 15:52:06 +020071 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
72 destruction_event, codec_width_, codec_height_),
73 99, 99, kVideoRotation_0);
perkj26091b12016-09-01 01:17:40 -070074 frame.set_ntp_time_ms(ntp_ts);
75 return frame;
76 }
77
78 class TestEncoder : public test::FakeEncoder {
79 public:
80 TestEncoder()
81 : FakeEncoder(Clock::GetRealTimeClock()),
82 continue_encode_event_(false, false) {}
83
84 int32_t Encode(const VideoFrame& input_image,
85 const CodecSpecificInfo* codec_specific_info,
86 const std::vector<FrameType>* frame_types) override {
87 bool block_encode;
88 {
89 rtc::CritScope lock(&crit_);
90 EXPECT_GT(input_image.timestamp(), timestamp_);
91 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
92 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
93
94 timestamp_ = input_image.timestamp();
95 ntp_time_ms_ = input_image.ntp_time_ms();
96 block_encode = block_next_encode_;
97 block_next_encode_ = false;
98 }
99 int32_t result =
100 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
101 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700102 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700103 return result;
104 }
105
perkj3b703ed2016-09-29 23:25:40 -0700106 void BlockNextEncode() {
107 rtc::CritScope lock(&crit_);
108 block_next_encode_ = true;
109 }
perkj26091b12016-09-01 01:17:40 -0700110
perkj3b703ed2016-09-29 23:25:40 -0700111 void ContinueEncode() { continue_encode_event_.Set(); }
perkj26091b12016-09-01 01:17:40 -0700112
perkj3b703ed2016-09-29 23:25:40 -0700113 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
114 uint32_t timestamp) const {
115 rtc::CritScope lock(&crit_);
116 EXPECT_EQ(timestamp_, timestamp);
117 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
118 }
119
120 private:
perkj26091b12016-09-01 01:17:40 -0700121 rtc::CriticalSection crit_;
122 bool block_next_encode_ = false;
123 rtc::Event continue_encode_event_;
124 uint32_t timestamp_ = 0;
125 int64_t ntp_time_ms_ = 0;
126 };
127
Per512ecb32016-09-23 15:52:06 +0200128 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700129 public:
130 explicit TestSink(TestEncoder* test_encoder)
131 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
132
perkj26091b12016-09-01 01:17:40 -0700133 void WaitForEncodedFrame(int64_t expected_ntp_time) {
134 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700135 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700136 {
137 rtc::CritScope lock(&crit_);
138 timestamp = timestamp_;
139 }
140 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
141 }
142
143 void SetExpectNoFrames() {
144 rtc::CritScope lock(&crit_);
145 expect_frames_ = false;
146 }
147
Per512ecb32016-09-23 15:52:06 +0200148 int number_of_reconfigurations() {
149 rtc::CritScope lock(&crit_);
150 return number_of_reconfigurations_;
151 }
152
153 int last_min_transmit_bitrate() {
154 rtc::CritScope lock(&crit_);
155 return min_transmit_bitrate_bps_;
156 }
157
perkj26091b12016-09-01 01:17:40 -0700158 private:
Per512ecb32016-09-23 15:52:06 +0200159 int32_t Encoded(const EncodedImage& encoded_image,
160 const CodecSpecificInfo* codec_specific_info,
161 const RTPFragmentationHeader* fragmentation) override {
162 rtc::CritScope lock(&crit_);
163 EXPECT_TRUE(expect_frames_);
164 timestamp_ = encoded_image._timeStamp;
165 encoded_frame_event_.Set();
166 return 0;
167 }
168
169 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
170 int min_transmit_bitrate_bps) override {
171 rtc::CriticalSection crit_;
172 ++number_of_reconfigurations_;
173 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
174 }
175
perkj26091b12016-09-01 01:17:40 -0700176 rtc::CriticalSection crit_;
177 TestEncoder* test_encoder_;
178 rtc::Event encoded_frame_event_;
179 uint32_t timestamp_ = 0;
180 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200181 int number_of_reconfigurations_ = 0;
182 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700183 };
184
185 VideoSendStream::Config video_send_config_;
Per512ecb32016-09-23 15:52:06 +0200186 int codec_width_;
187 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700188 TestEncoder fake_encoder_;
189 SendStatisticsProxy stats_proxy_;
190 TestSink sink_;
perkja49cbd32016-09-16 07:53:41 -0700191 test::FrameForwarder video_source_;
perkj26091b12016-09-01 01:17:40 -0700192 std::unique_ptr<ViEEncoder> vie_encoder_;
193};
194
195TEST_F(ViEEncoderTest, EncodeOneFrame) {
196 const int kTargetBitrateBps = 100000;
197 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
198 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700199 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700200 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700201 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700202 vie_encoder_->Stop();
203}
204
205TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
206 // Dropped since no target bitrate has been set.
207 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700208 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
209 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700210
211 const int kTargetBitrateBps = 100000;
212 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
213
perkja49cbd32016-09-16 07:53:41 -0700214 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700215 sink_.WaitForEncodedFrame(2);
216 vie_encoder_->Stop();
217}
218
219TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
220 const int kTargetBitrateBps = 100000;
221 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700222 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700223 sink_.WaitForEncodedFrame(1);
224
225 vie_encoder_->OnBitrateUpdated(0, 0, 0);
226 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700227 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700228
229 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700230 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700231 sink_.WaitForEncodedFrame(3);
232 vie_encoder_->Stop();
233}
234
235TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
236 const int kTargetBitrateBps = 100000;
237 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700238 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700239 sink_.WaitForEncodedFrame(1);
240
241 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700242 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700243
perkja49cbd32016-09-16 07:53:41 -0700244 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700245 sink_.WaitForEncodedFrame(2);
246 vie_encoder_->Stop();
247}
248
249TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
250 const int kTargetBitrateBps = 100000;
251 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
252
perkja49cbd32016-09-16 07:53:41 -0700253 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700254 sink_.WaitForEncodedFrame(1);
255
256 vie_encoder_->Stop();
257 sink_.SetExpectNoFrames();
258 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700259 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
260 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700261}
262
263TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
264 const int kTargetBitrateBps = 100000;
265 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
266
267 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700268 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700269 sink_.WaitForEncodedFrame(1);
270 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
271 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700272 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
273 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700274 fake_encoder_.ContinueEncode();
275 sink_.WaitForEncodedFrame(3);
276
277 vie_encoder_->Stop();
278}
279
Per512ecb32016-09-23 15:52:06 +0200280TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
281 const int kTargetBitrateBps = 100000;
282 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
283
284 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200285 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200286 sink_.WaitForEncodedFrame(1);
perkj3b703ed2016-09-29 23:25:40 -0700287 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200288
289 VideoEncoderConfig video_encoder_config;
perkj3b703ed2016-09-29 23:25:40 -0700290 video_encoder_config.streams = test::CreateVideoStreams(1);
Per512ecb32016-09-23 15:52:06 +0200291 video_encoder_config.min_transmit_bitrate_bps = 9999;
292 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
293
294 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200295 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200296 sink_.WaitForEncodedFrame(2);
perkj26105b42016-09-29 22:39:10 -0700297 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700298 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700299
300 vie_encoder_->Stop();
301}
302
perkj26091b12016-09-01 01:17:40 -0700303} // namespace webrtc