blob: 5382fbf8ebb3a3685b3cbb19d181c82838b209ce [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)),
perkjfa10b552016-10-02 23:45:26 -070029 codec_width_(320),
30 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -070031 fake_encoder_(),
32 stats_proxy_(Clock::GetRealTimeClock(),
33 video_send_config_,
34 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo),
35 sink_(&fake_encoder_) {}
36
37 void SetUp() override {
38 video_send_config_ = VideoSendStream::Config(nullptr);
39 video_send_config_.encoder_settings.encoder = &fake_encoder_;
40 video_send_config_.encoder_settings.payload_name = "FAKE";
41 video_send_config_.encoder_settings.payload_type = 125;
42
Per512ecb32016-09-23 15:52:06 +020043 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -070044 test::FillEncoderConfiguration(1, &video_encoder_config);
perkj26091b12016-09-01 01:17:40 -070045 vie_encoder_.reset(new ViEEncoder(
46 1 /* number_of_cores */, &stats_proxy_,
47 video_send_config_.encoder_settings, nullptr /* pre_encode_callback */,
48 nullptr /* overuse_callback */, nullptr /* encoder_timing */));
49 vie_encoder_->SetSink(&sink_);
perkja49cbd32016-09-16 07:53:41 -070050 vie_encoder_->SetSource(&video_source_);
perkj26091b12016-09-01 01:17:40 -070051 vie_encoder_->SetStartBitrate(10000);
Per512ecb32016-09-23 15:52:06 +020052 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
perkj26091b12016-09-01 01:17:40 -070053 }
54
55 VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) const {
56 class TestBuffer : public webrtc::I420Buffer {
57 public:
58 TestBuffer(rtc::Event* event, int width, int height)
59 : I420Buffer(width, height), event_(event) {}
60
61 private:
62 friend class rtc::RefCountedObject<TestBuffer>;
63 ~TestBuffer() override {
64 if (event_)
65 event_->Set();
66 }
67 rtc::Event* const event_;
68 };
69
Per512ecb32016-09-23 15:52:06 +020070 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
71 destruction_event, codec_width_, codec_height_),
72 99, 99, kVideoRotation_0);
perkj26091b12016-09-01 01:17:40 -070073 frame.set_ntp_time_ms(ntp_ts);
74 return frame;
75 }
76
77 class TestEncoder : public test::FakeEncoder {
78 public:
79 TestEncoder()
80 : FakeEncoder(Clock::GetRealTimeClock()),
81 continue_encode_event_(false, false) {}
82
perkjfa10b552016-10-02 23:45:26 -070083 VideoCodec codec_config() {
84 rtc::CritScope lock(&crit_);
85 return config_;
86 }
87
88 void BlockNextEncode() {
89 rtc::CritScope lock(&crit_);
90 block_next_encode_ = true;
91 }
92
93 void ContinueEncode() { continue_encode_event_.Set(); }
94
95 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
96 uint32_t timestamp) const {
97 rtc::CritScope lock(&crit_);
98 EXPECT_EQ(timestamp_, timestamp);
99 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
100 }
101
102 private:
perkj26091b12016-09-01 01:17:40 -0700103 int32_t Encode(const VideoFrame& input_image,
104 const CodecSpecificInfo* codec_specific_info,
105 const std::vector<FrameType>* frame_types) override {
106 bool block_encode;
107 {
108 rtc::CritScope lock(&crit_);
109 EXPECT_GT(input_image.timestamp(), timestamp_);
110 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
111 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
112
113 timestamp_ = input_image.timestamp();
114 ntp_time_ms_ = input_image.ntp_time_ms();
115 block_encode = block_next_encode_;
116 block_next_encode_ = false;
117 }
118 int32_t result =
119 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
120 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700121 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700122 return result;
123 }
124
perkj26091b12016-09-01 01:17:40 -0700125
perkj26091b12016-09-01 01:17:40 -0700126
perkj26091b12016-09-01 01:17:40 -0700127 rtc::CriticalSection crit_;
128 bool block_next_encode_ = false;
129 rtc::Event continue_encode_event_;
130 uint32_t timestamp_ = 0;
131 int64_t ntp_time_ms_ = 0;
132 };
133
Per512ecb32016-09-23 15:52:06 +0200134 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700135 public:
136 explicit TestSink(TestEncoder* test_encoder)
137 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
138
perkj26091b12016-09-01 01:17:40 -0700139 void WaitForEncodedFrame(int64_t expected_ntp_time) {
140 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700141 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700142 {
143 rtc::CritScope lock(&crit_);
144 timestamp = timestamp_;
145 }
146 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
147 }
148
149 void SetExpectNoFrames() {
150 rtc::CritScope lock(&crit_);
151 expect_frames_ = false;
152 }
153
Per512ecb32016-09-23 15:52:06 +0200154 int number_of_reconfigurations() {
155 rtc::CritScope lock(&crit_);
156 return number_of_reconfigurations_;
157 }
158
159 int last_min_transmit_bitrate() {
160 rtc::CritScope lock(&crit_);
161 return min_transmit_bitrate_bps_;
162 }
163
perkj26091b12016-09-01 01:17:40 -0700164 private:
Per512ecb32016-09-23 15:52:06 +0200165 int32_t Encoded(const EncodedImage& encoded_image,
166 const CodecSpecificInfo* codec_specific_info,
167 const RTPFragmentationHeader* fragmentation) override {
168 rtc::CritScope lock(&crit_);
169 EXPECT_TRUE(expect_frames_);
170 timestamp_ = encoded_image._timeStamp;
171 encoded_frame_event_.Set();
172 return 0;
173 }
174
175 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
176 int min_transmit_bitrate_bps) override {
177 rtc::CriticalSection crit_;
178 ++number_of_reconfigurations_;
179 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
180 }
181
perkj26091b12016-09-01 01:17:40 -0700182 rtc::CriticalSection crit_;
183 TestEncoder* test_encoder_;
184 rtc::Event encoded_frame_event_;
185 uint32_t timestamp_ = 0;
186 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200187 int number_of_reconfigurations_ = 0;
188 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700189 };
190
191 VideoSendStream::Config video_send_config_;
Per512ecb32016-09-23 15:52:06 +0200192 int codec_width_;
193 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700194 TestEncoder fake_encoder_;
195 SendStatisticsProxy stats_proxy_;
196 TestSink sink_;
perkja49cbd32016-09-16 07:53:41 -0700197 test::FrameForwarder video_source_;
perkj26091b12016-09-01 01:17:40 -0700198 std::unique_ptr<ViEEncoder> vie_encoder_;
199};
200
201TEST_F(ViEEncoderTest, EncodeOneFrame) {
202 const int kTargetBitrateBps = 100000;
203 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
204 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700205 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700206 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700207 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700208 vie_encoder_->Stop();
209}
210
211TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
212 // Dropped since no target bitrate has been set.
213 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700214 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
215 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700216
217 const int kTargetBitrateBps = 100000;
218 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
219
perkja49cbd32016-09-16 07:53:41 -0700220 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700221 sink_.WaitForEncodedFrame(2);
222 vie_encoder_->Stop();
223}
224
225TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
226 const int kTargetBitrateBps = 100000;
227 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700228 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700229 sink_.WaitForEncodedFrame(1);
230
231 vie_encoder_->OnBitrateUpdated(0, 0, 0);
232 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700233 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700234
235 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700236 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700237 sink_.WaitForEncodedFrame(3);
238 vie_encoder_->Stop();
239}
240
241TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
242 const int kTargetBitrateBps = 100000;
243 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700244 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700245 sink_.WaitForEncodedFrame(1);
246
247 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700248 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700249
perkja49cbd32016-09-16 07:53:41 -0700250 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700251 sink_.WaitForEncodedFrame(2);
252 vie_encoder_->Stop();
253}
254
255TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
256 const int kTargetBitrateBps = 100000;
257 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
258
perkja49cbd32016-09-16 07:53:41 -0700259 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700260 sink_.WaitForEncodedFrame(1);
261
262 vie_encoder_->Stop();
263 sink_.SetExpectNoFrames();
264 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700265 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
266 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700267}
268
269TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
270 const int kTargetBitrateBps = 100000;
271 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
272
273 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700274 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700275 sink_.WaitForEncodedFrame(1);
276 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
277 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700278 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
279 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700280 fake_encoder_.ContinueEncode();
281 sink_.WaitForEncodedFrame(3);
282
283 vie_encoder_->Stop();
284}
285
Per512ecb32016-09-23 15:52:06 +0200286TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
287 const int kTargetBitrateBps = 100000;
288 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
289
290 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200291 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200292 sink_.WaitForEncodedFrame(1);
emircan05a55b52016-10-28 14:06:29 -0700293 // The encoder will have been configured twice. First time before the first
294 // frame has been received. Then a second time when the resolution is known.
295 EXPECT_EQ(2, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200296
297 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700298 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200299 video_encoder_config.min_transmit_bitrate_bps = 9999;
300 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
301
302 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200303 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200304 sink_.WaitForEncodedFrame(2);
emircan05a55b52016-10-28 14:06:29 -0700305 EXPECT_EQ(3, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700306 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700307
308 vie_encoder_->Stop();
309}
310
perkjfa10b552016-10-02 23:45:26 -0700311TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
312 const int kTargetBitrateBps = 100000;
313 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
314
315 // Capture a frame and wait for it to synchronize with the encoder thread.
316 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
317 sink_.WaitForEncodedFrame(1);
emircan05a55b52016-10-28 14:06:29 -0700318 // The encoder will have been configured twice. First time before the first
319 // frame has been received. Then a second time when the resolution is known.
320 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700321 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
322 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
323
324 codec_width_ *= 2;
325 codec_height_ *= 2;
326 // Capture a frame with a higher resolution and wait for it to synchronize
327 // with the encoder thread.
328 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
329 sink_.WaitForEncodedFrame(2);
330 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
331 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
emircan05a55b52016-10-28 14:06:29 -0700332 EXPECT_EQ(3, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700333
334 vie_encoder_->Stop();
335}
336
perkj26091b12016-09-01 01:17:40 -0700337} // namespace webrtc