blob: dae172dea353e5d198584f8a01921fbb86103c69 [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
perkj803d97f2016-11-01 11:45:46 -070011#include <limits>
Per512ecb32016-09-23 15:52:06 +020012#include <utility>
13
nisseaf916892017-01-10 07:44:26 -080014#include "webrtc/api/video/i420_buffer.h"
perkj26091b12016-09-01 01:17:40 -070015#include "webrtc/base/logging.h"
sprang57c2fff2017-01-16 06:24:02 -080016#include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
perkj803d97f2016-11-01 11:45:46 -070017#include "webrtc/system_wrappers/include/metrics_default.h"
sprang57c2fff2017-01-16 06:24:02 -080018#include "webrtc/system_wrappers/include/sleep.h"
perkj26091b12016-09-01 01:17:40 -070019#include "webrtc/test/encoder_settings.h"
20#include "webrtc/test/fake_encoder.h"
perkja49cbd32016-09-16 07:53:41 -070021#include "webrtc/test/frame_generator.h"
sprang57c2fff2017-01-16 06:24:02 -080022#include "webrtc/test/gmock.h"
kwibergac9f8762016-09-30 22:29:43 -070023#include "webrtc/test/gtest.h"
perkj26091b12016-09-01 01:17:40 -070024#include "webrtc/video/send_statistics_proxy.h"
25#include "webrtc/video/vie_encoder.h"
26
kthelgason33ce8892016-12-09 03:53:59 -080027namespace {
28#if defined(WEBRTC_ANDROID)
29// TODO(kthelgason): Lower this limit when better testing
30// on MediaCodec and fallback implementations are in place.
31const int kMinPixelsPerFrame = 320 * 180;
32#else
33const int kMinPixelsPerFrame = 120 * 90;
34#endif
35}
36
perkj26091b12016-09-01 01:17:40 -070037namespace webrtc {
38
kthelgason876222f2016-11-29 01:44:11 -080039using DegredationPreference = VideoSendStream::DegradationPreference;
40using ScaleReason = ScalingObserverInterface::ScaleReason;
sprang57c2fff2017-01-16 06:24:02 -080041using ::testing::_;
42using ::testing::Return;
kthelgason876222f2016-11-29 01:44:11 -080043
perkj803d97f2016-11-01 11:45:46 -070044namespace {
asapersson5f7226f2016-11-25 04:37:00 -080045const size_t kMaxPayloadLength = 1440;
minyue35fc2aa2017-02-01 03:14:00 -080046const int kTargetBitrateBps = 100000;
asapersson5f7226f2016-11-25 04:37:00 -080047
perkj803d97f2016-11-01 11:45:46 -070048class TestBuffer : public webrtc::I420Buffer {
49 public:
50 TestBuffer(rtc::Event* event, int width, int height)
51 : I420Buffer(width, height), event_(event) {}
52
53 private:
54 friend class rtc::RefCountedObject<TestBuffer>;
55 ~TestBuffer() override {
56 if (event_)
57 event_->Set();
58 }
59 rtc::Event* const event_;
60};
61
62class ViEEncoderUnderTest : public ViEEncoder {
63 public:
kthelgason876222f2016-11-29 01:44:11 -080064 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
65 const VideoSendStream::Config::EncoderSettings& settings)
perkj803d97f2016-11-01 11:45:46 -070066 : ViEEncoder(1 /* number_of_cores */,
67 stats_proxy,
68 settings,
69 nullptr /* pre_encode_callback */,
70 nullptr /* encoder_timing */) {}
71
kthelgason876222f2016-11-29 01:44:11 -080072 void PostTaskAndWait(bool down, ScaleReason reason) {
perkj803d97f2016-11-01 11:45:46 -070073 rtc::Event event(false, false);
kthelgason876222f2016-11-29 01:44:11 -080074 encoder_queue()->PostTask([this, &event, reason, down] {
75 down ? ScaleDown(reason) : ScaleUp(reason);
perkj803d97f2016-11-01 11:45:46 -070076 event.Set();
77 });
kthelgason876222f2016-11-29 01:44:11 -080078 RTC_DCHECK(event.Wait(5000));
perkj803d97f2016-11-01 11:45:46 -070079 }
80
kthelgason876222f2016-11-29 01:44:11 -080081 void TriggerCpuOveruse() { PostTaskAndWait(true, ScaleReason::kCpu); }
82
83 void TriggerCpuNormalUsage() { PostTaskAndWait(false, ScaleReason::kCpu); }
84
85 void TriggerQualityLow() { PostTaskAndWait(true, ScaleReason::kQuality); }
86
87 void TriggerQualityHigh() { PostTaskAndWait(false, ScaleReason::kQuality); }
perkj803d97f2016-11-01 11:45:46 -070088};
89
asapersson5f7226f2016-11-25 04:37:00 -080090class VideoStreamFactory
91 : public VideoEncoderConfig::VideoStreamFactoryInterface {
92 public:
93 explicit VideoStreamFactory(size_t num_temporal_layers)
94 : num_temporal_layers_(num_temporal_layers) {
95 EXPECT_GT(num_temporal_layers, 0u);
96 }
97
98 private:
99 std::vector<VideoStream> CreateEncoderStreams(
100 int width,
101 int height,
102 const VideoEncoderConfig& encoder_config) override {
103 std::vector<VideoStream> streams =
104 test::CreateVideoStreams(width, height, encoder_config);
105 for (VideoStream& stream : streams) {
106 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
107 }
108 return streams;
109 }
110 const size_t num_temporal_layers_;
111};
112
perkj803d97f2016-11-01 11:45:46 -0700113} // namespace
114
perkj26091b12016-09-01 01:17:40 -0700115class ViEEncoderTest : public ::testing::Test {
116 public:
117 static const int kDefaultTimeoutMs = 30 * 1000;
118
119 ViEEncoderTest()
120 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -0700121 codec_width_(320),
122 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -0700123 fake_encoder_(),
perkj803d97f2016-11-01 11:45:46 -0700124 stats_proxy_(new SendStatisticsProxy(
125 Clock::GetRealTimeClock(),
126 video_send_config_,
127 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -0700128 sink_(&fake_encoder_) {}
129
130 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -0700131 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -0700132 video_send_config_ = VideoSendStream::Config(nullptr);
133 video_send_config_.encoder_settings.encoder = &fake_encoder_;
134 video_send_config_.encoder_settings.payload_name = "FAKE";
135 video_send_config_.encoder_settings.payload_type = 125;
136
Per512ecb32016-09-23 15:52:06 +0200137 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700138 test::FillEncoderConfiguration(1, &video_encoder_config);
Erik Språng08127a92016-11-16 16:41:30 +0100139 video_encoder_config_ = video_encoder_config.Copy();
asapersson5f7226f2016-11-25 04:37:00 -0800140 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
141 }
142
143 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
144 bool nack_enabled) {
145 if (vie_encoder_)
146 vie_encoder_->Stop();
perkj803d97f2016-11-01 11:45:46 -0700147 vie_encoder_.reset(new ViEEncoderUnderTest(
148 stats_proxy_.get(), video_send_config_.encoder_settings));
149 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
150 vie_encoder_->SetSource(&video_source_,
151 VideoSendStream::DegradationPreference::kBalanced);
minyue35fc2aa2017-02-01 03:14:00 -0800152 vie_encoder_->SetStartBitrate(10000);
asapersson5f7226f2016-11-25 04:37:00 -0800153 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
154 kMaxPayloadLength, nack_enabled);
155 }
156
157 void ResetEncoder(const std::string& payload_name,
158 size_t num_streams,
159 size_t num_temporal_layers,
160 bool nack_enabled) {
161 video_send_config_.encoder_settings.payload_name = payload_name;
162
163 VideoEncoderConfig video_encoder_config;
164 video_encoder_config.number_of_streams = num_streams;
minyue35fc2aa2017-02-01 03:14:00 -0800165 video_encoder_config.max_bitrate_bps = 1000000;
asapersson5f7226f2016-11-25 04:37:00 -0800166 video_encoder_config.video_stream_factory =
167 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
168 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
perkj26091b12016-09-01 01:17:40 -0700169 }
170
sprang57c2fff2017-01-16 06:24:02 -0800171 VideoFrame CreateFrame(int64_t ntp_time_ms,
172 rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200173 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
174 destruction_event, codec_width_, codec_height_),
175 99, 99, kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800176 frame.set_ntp_time_ms(ntp_time_ms);
perkj26091b12016-09-01 01:17:40 -0700177 return frame;
178 }
179
sprang57c2fff2017-01-16 06:24:02 -0800180 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
perkj803d97f2016-11-01 11:45:46 -0700181 VideoFrame frame(
182 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
183 kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800184 frame.set_ntp_time_ms(ntp_time_ms);
perkj803d97f2016-11-01 11:45:46 -0700185 return frame;
186 }
187
perkj26091b12016-09-01 01:17:40 -0700188 class TestEncoder : public test::FakeEncoder {
189 public:
190 TestEncoder()
191 : FakeEncoder(Clock::GetRealTimeClock()),
192 continue_encode_event_(false, false) {}
193
perkjfa10b552016-10-02 23:45:26 -0700194 VideoCodec codec_config() {
brandtre78d2662017-01-16 05:57:16 -0800195 rtc::CritScope lock(&crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700196 return config_;
197 }
198
199 void BlockNextEncode() {
brandtre78d2662017-01-16 05:57:16 -0800200 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700201 block_next_encode_ = true;
202 }
203
kthelgason876222f2016-11-29 01:44:11 -0800204 VideoEncoder::ScalingSettings GetScalingSettings() const override {
205 return VideoEncoder::ScalingSettings(true, 1, 2);
206 }
207
perkjfa10b552016-10-02 23:45:26 -0700208 void ContinueEncode() { continue_encode_event_.Set(); }
209
210 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
211 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800212 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700213 EXPECT_EQ(timestamp_, timestamp);
214 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
215 }
216
217 private:
perkj26091b12016-09-01 01:17:40 -0700218 int32_t Encode(const VideoFrame& input_image,
219 const CodecSpecificInfo* codec_specific_info,
220 const std::vector<FrameType>* frame_types) override {
221 bool block_encode;
222 {
brandtre78d2662017-01-16 05:57:16 -0800223 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700224 EXPECT_GT(input_image.timestamp(), timestamp_);
225 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
226 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
227
228 timestamp_ = input_image.timestamp();
229 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700230 last_input_width_ = input_image.width();
231 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700232 block_encode = block_next_encode_;
233 block_next_encode_ = false;
234 }
235 int32_t result =
236 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
237 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700238 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700239 return result;
240 }
241
brandtre78d2662017-01-16 05:57:16 -0800242 rtc::CriticalSection local_crit_sect_;
perkj26091b12016-09-01 01:17:40 -0700243 bool block_next_encode_ = false;
244 rtc::Event continue_encode_event_;
245 uint32_t timestamp_ = 0;
246 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700247 int last_input_width_ = 0;
248 int last_input_height_ = 0;
perkj26091b12016-09-01 01:17:40 -0700249 };
250
Per512ecb32016-09-23 15:52:06 +0200251 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700252 public:
253 explicit TestSink(TestEncoder* test_encoder)
254 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
255
perkj26091b12016-09-01 01:17:40 -0700256 void WaitForEncodedFrame(int64_t expected_ntp_time) {
257 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700258 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700259 {
260 rtc::CritScope lock(&crit_);
261 timestamp = timestamp_;
262 }
263 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
264 }
265
266 void SetExpectNoFrames() {
267 rtc::CritScope lock(&crit_);
268 expect_frames_ = false;
269 }
270
Per512ecb32016-09-23 15:52:06 +0200271 int number_of_reconfigurations() {
272 rtc::CritScope lock(&crit_);
273 return number_of_reconfigurations_;
274 }
275
276 int last_min_transmit_bitrate() {
277 rtc::CritScope lock(&crit_);
278 return min_transmit_bitrate_bps_;
279 }
280
perkj26091b12016-09-01 01:17:40 -0700281 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700282 Result OnEncodedImage(
283 const EncodedImage& encoded_image,
284 const CodecSpecificInfo* codec_specific_info,
285 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200286 rtc::CritScope lock(&crit_);
287 EXPECT_TRUE(expect_frames_);
288 timestamp_ = encoded_image._timeStamp;
289 encoded_frame_event_.Set();
sergeyu2cb155a2016-11-04 11:39:29 -0700290 return Result(Result::OK, timestamp_);
Per512ecb32016-09-23 15:52:06 +0200291 }
292
293 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
294 int min_transmit_bitrate_bps) override {
295 rtc::CriticalSection crit_;
296 ++number_of_reconfigurations_;
297 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
298 }
299
perkj26091b12016-09-01 01:17:40 -0700300 rtc::CriticalSection crit_;
301 TestEncoder* test_encoder_;
302 rtc::Event encoded_frame_event_;
303 uint32_t timestamp_ = 0;
304 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200305 int number_of_reconfigurations_ = 0;
306 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700307 };
308
309 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100310 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200311 int codec_width_;
312 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700313 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700314 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700315 TestSink sink_;
perkja49cbd32016-09-16 07:53:41 -0700316 test::FrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700317 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700318};
319
320TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700321 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
322 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700323 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700324 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700325 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700326 vie_encoder_->Stop();
327}
328
329TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
330 // Dropped since no target bitrate has been set.
331 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700332 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
333 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700334
perkj26091b12016-09-01 01:17:40 -0700335 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
336
perkja49cbd32016-09-16 07:53:41 -0700337 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700338 sink_.WaitForEncodedFrame(2);
339 vie_encoder_->Stop();
340}
341
342TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700343 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700344 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700345 sink_.WaitForEncodedFrame(1);
346
347 vie_encoder_->OnBitrateUpdated(0, 0, 0);
348 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700349 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700350
351 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700352 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700353 sink_.WaitForEncodedFrame(3);
354 vie_encoder_->Stop();
355}
356
357TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700358 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700359 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700360 sink_.WaitForEncodedFrame(1);
361
362 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700363 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700364
perkja49cbd32016-09-16 07:53:41 -0700365 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700366 sink_.WaitForEncodedFrame(2);
367 vie_encoder_->Stop();
368}
369
370TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700371 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
372
perkja49cbd32016-09-16 07:53:41 -0700373 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700374 sink_.WaitForEncodedFrame(1);
375
376 vie_encoder_->Stop();
377 sink_.SetExpectNoFrames();
378 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700379 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
380 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700381}
382
383TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700384 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
385
386 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700387 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700388 sink_.WaitForEncodedFrame(1);
389 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
390 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700391 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
392 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700393 fake_encoder_.ContinueEncode();
394 sink_.WaitForEncodedFrame(3);
395
396 vie_encoder_->Stop();
397}
398
Per512ecb32016-09-23 15:52:06 +0200399TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200400 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100401 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200402
403 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200404 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200405 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100406 // The encoder will have been configured once when the first frame is
407 // received.
408 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200409
410 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700411 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200412 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800413 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
414 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200415
416 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200417 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200418 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100419 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700420 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700421
422 vie_encoder_->Stop();
423}
424
perkjfa10b552016-10-02 23:45:26 -0700425TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700426 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
427
428 // Capture a frame and wait for it to synchronize with the encoder thread.
429 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
430 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100431 // The encoder will have been configured once.
432 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700433 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
434 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
435
436 codec_width_ *= 2;
437 codec_height_ *= 2;
438 // Capture a frame with a higher resolution and wait for it to synchronize
439 // with the encoder thread.
440 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
441 sink_.WaitForEncodedFrame(2);
442 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
443 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100444 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700445
446 vie_encoder_->Stop();
447}
448
asapersson5f7226f2016-11-25 04:37:00 -0800449TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
450 const bool kNackEnabled = true;
451 const size_t kNumStreams = 1;
452 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800453 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800454 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
455
456 // Capture a frame and wait for it to synchronize with the encoder thread.
457 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
458 sink_.WaitForEncodedFrame(1);
459 // The encoder have been configured once when the first frame is received.
460 EXPECT_EQ(1, sink_.number_of_reconfigurations());
461 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
462 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
463 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
464 // Resilience is off for no temporal layers with nack on.
465 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
466 vie_encoder_->Stop();
467}
468
469TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
470 const bool kNackEnabled = true;
471 const size_t kNumStreams = 2;
472 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800473 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800474 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
475
476 // Capture a frame and wait for it to synchronize with the encoder thread.
477 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
478 sink_.WaitForEncodedFrame(1);
479 // The encoder have been configured once when the first frame is received.
480 EXPECT_EQ(1, sink_.number_of_reconfigurations());
481 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
482 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
483 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
484 // Resilience is off for no temporal layers and >1 streams with nack on.
485 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
486 vie_encoder_->Stop();
487}
488
489TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
490 const bool kNackEnabled = false;
491 const size_t kNumStreams = 1;
492 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800493 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800494 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
495
496 // Capture a frame and wait for it to synchronize with the encoder thread.
497 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
498 sink_.WaitForEncodedFrame(1);
499 // The encoder have been configured once when the first frame is received.
500 EXPECT_EQ(1, sink_.number_of_reconfigurations());
501 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
502 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
503 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
504 // Resilience is on for no temporal layers with nack off.
505 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
506 vie_encoder_->Stop();
507}
508
509TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
510 const bool kNackEnabled = true;
511 const size_t kNumStreams = 1;
512 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800513 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800514 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
515
516 // Capture a frame and wait for it to synchronize with the encoder thread.
517 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
518 sink_.WaitForEncodedFrame(1);
519 // The encoder have been configured once when the first frame is received.
520 EXPECT_EQ(1, sink_.number_of_reconfigurations());
521 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
522 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
523 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
524 // Resilience is on for temporal layers.
525 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
526 vie_encoder_->Stop();
527}
528
perkj803d97f2016-11-01 11:45:46 -0700529TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
530 EXPECT_TRUE(video_source_.has_sinks());
531 test::FrameForwarder new_video_source;
532 vie_encoder_->SetSource(&new_video_source,
533 VideoSendStream::DegradationPreference::kBalanced);
534 EXPECT_FALSE(video_source_.has_sinks());
535 EXPECT_TRUE(new_video_source.has_sinks());
536
537 vie_encoder_->Stop();
538}
539
540TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
541 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
542 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
543 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
544 vie_encoder_->Stop();
545}
546
547TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700548 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
549
550 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
551 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
552
553 int frame_width = 1280;
554 int frame_height = 720;
555
556 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
557 // request lower resolution.
558 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
559 video_source_.IncomingCapturedFrame(
560 CreateFrame(i, frame_width, frame_height));
561 sink_.WaitForEncodedFrame(i);
562
563 vie_encoder_->TriggerCpuOveruse();
564
565 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
566 std::numeric_limits<int>::max()),
567 frame_width * frame_height);
568 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
569
570 frame_width /= 2;
571 frame_height /= 2;
572 }
573
kthelgason876222f2016-11-29 01:44:11 -0800574 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700575 // lower resolution.
576 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
577 video_source_.IncomingCapturedFrame(CreateFrame(
578 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
579 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
580 vie_encoder_->TriggerCpuOveruse();
581 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
582 current_wants.max_pixel_count);
583 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up,
584 current_wants.max_pixel_count_step_up);
585
586 // Trigger CPU normal use.
587 vie_encoder_->TriggerCpuNormalUsage();
588 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
589 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0),
590 frame_width * frame_height);
591
592 vie_encoder_->Stop();
593}
594
595TEST_F(ViEEncoderTest,
596 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700597 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
598
599 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
600 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
601
602 int frame_width = 1280;
603 int frame_height = 720;
604
kthelgason5e13d412016-12-01 03:59:51 -0800605 video_source_.IncomingCapturedFrame(
606 CreateFrame(1, frame_width, frame_height));
607 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700608 // Trigger CPU overuse.
609 vie_encoder_->TriggerCpuOveruse();
610
611 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800612 CreateFrame(2, frame_width, frame_height));
613 sink_.WaitForEncodedFrame(2);
perkj803d97f2016-11-01 11:45:46 -0700614 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
615 std::numeric_limits<int>::max()),
616 frame_width * frame_height);
617 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
618
619 // Set new source.
620 test::FrameForwarder new_video_source;
621 vie_encoder_->SetSource(
622 &new_video_source,
623 VideoSendStream::DegradationPreference::kMaintainResolution);
624
625 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
626 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
627
628 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800629 CreateFrame(3, frame_width, frame_height));
630 sink_.WaitForEncodedFrame(3);
perkj803d97f2016-11-01 11:45:46 -0700631 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
632 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
633
634 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
635 vie_encoder_->SetSource(&new_video_source,
636 VideoSendStream::DegradationPreference::kBalanced);
637 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
638 std::numeric_limits<int>::max()),
639 frame_width * frame_height);
640 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
641
642 vie_encoder_->Stop();
643}
644
645TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700646 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
647
648 int frame_width = 1280;
649 int frame_height = 720;
650
651 video_source_.IncomingCapturedFrame(
652 CreateFrame(1, frame_width, frame_height));
653 sink_.WaitForEncodedFrame(1);
654 VideoSendStream::Stats stats = stats_proxy_->GetStats();
655 EXPECT_FALSE(stats.cpu_limited_resolution);
656 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
657
658 // Trigger CPU overuse.
659 vie_encoder_->TriggerCpuOveruse();
660 video_source_.IncomingCapturedFrame(
661 CreateFrame(2, frame_width, frame_height));
662 sink_.WaitForEncodedFrame(2);
663
664 stats = stats_proxy_->GetStats();
665 EXPECT_TRUE(stats.cpu_limited_resolution);
666 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
667
668 // Trigger CPU normal use.
669 vie_encoder_->TriggerCpuNormalUsage();
670 video_source_.IncomingCapturedFrame(
671 CreateFrame(3, frame_width, frame_height));
672 sink_.WaitForEncodedFrame(3);
673
674 stats = stats_proxy_->GetStats();
675 EXPECT_FALSE(stats.cpu_limited_resolution);
676 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
677
678 vie_encoder_->Stop();
679}
680
kthelgason876222f2016-11-29 01:44:11 -0800681TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
minyue35fc2aa2017-02-01 03:14:00 -0800682 const int kTargetBitrateBps = 100000;
kthelgason876222f2016-11-29 01:44:11 -0800683 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
684
685 int frame_width = 1280;
686 int frame_height = 720;
687 video_source_.IncomingCapturedFrame(
688 CreateFrame(1, frame_width, frame_height));
689 sink_.WaitForEncodedFrame(1);
690
691 VideoSendStream::Stats stats = stats_proxy_->GetStats();
692 EXPECT_FALSE(stats.cpu_limited_resolution);
693 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
694
695 vie_encoder_->TriggerCpuOveruse();
696
697 video_source_.IncomingCapturedFrame(
698 CreateFrame(2, frame_width, frame_height));
699 sink_.WaitForEncodedFrame(2);
700 stats = stats_proxy_->GetStats();
701 EXPECT_TRUE(stats.cpu_limited_resolution);
702 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
703
704 // Set new source with adaptation still enabled.
705 test::FrameForwarder new_video_source;
706 vie_encoder_->SetSource(&new_video_source,
707 VideoSendStream::DegradationPreference::kBalanced);
708
709 new_video_source.IncomingCapturedFrame(
710 CreateFrame(3, frame_width, frame_height));
711 sink_.WaitForEncodedFrame(3);
712 stats = stats_proxy_->GetStats();
713 EXPECT_TRUE(stats.cpu_limited_resolution);
714 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
715
716 // Set adaptation disabled.
717 vie_encoder_->SetSource(
718 &new_video_source,
719 VideoSendStream::DegradationPreference::kMaintainResolution);
720
721 new_video_source.IncomingCapturedFrame(
722 CreateFrame(4, frame_width, frame_height));
723 sink_.WaitForEncodedFrame(4);
724 stats = stats_proxy_->GetStats();
725 EXPECT_FALSE(stats.cpu_limited_resolution);
726 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
727
728 // Set adaptation back to enabled.
729 vie_encoder_->SetSource(&new_video_source,
730 VideoSendStream::DegradationPreference::kBalanced);
731
732 new_video_source.IncomingCapturedFrame(
733 CreateFrame(5, frame_width, frame_height));
734 sink_.WaitForEncodedFrame(5);
735 stats = stats_proxy_->GetStats();
736 EXPECT_TRUE(stats.cpu_limited_resolution);
737 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
738
739 vie_encoder_->TriggerCpuNormalUsage();
740
741 new_video_source.IncomingCapturedFrame(
742 CreateFrame(6, frame_width, frame_height));
743 sink_.WaitForEncodedFrame(6);
744 stats = stats_proxy_->GetStats();
745 EXPECT_FALSE(stats.cpu_limited_resolution);
746 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
747
748 vie_encoder_->Stop();
749}
750
751TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
minyue35fc2aa2017-02-01 03:14:00 -0800752 const int kTargetBitrateBps = 100000;
kthelgason876222f2016-11-29 01:44:11 -0800753 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
754
755 int frame_width = 1280;
756 int frame_height = 720;
757 video_source_.IncomingCapturedFrame(
758 CreateFrame(1, frame_width, frame_height));
759 sink_.WaitForEncodedFrame(1);
760
761 VideoSendStream::Stats stats = stats_proxy_->GetStats();
762 EXPECT_FALSE(stats.cpu_limited_resolution);
763 EXPECT_FALSE(stats.bw_limited_resolution);
764 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
765
766 // Set new source with adaptation still enabled.
767 test::FrameForwarder new_video_source;
768 vie_encoder_->SetSource(&new_video_source,
769 VideoSendStream::DegradationPreference::kBalanced);
770
771 new_video_source.IncomingCapturedFrame(
772 CreateFrame(2, frame_width, frame_height));
773 sink_.WaitForEncodedFrame(2);
774 stats = stats_proxy_->GetStats();
775 EXPECT_FALSE(stats.cpu_limited_resolution);
776 EXPECT_FALSE(stats.bw_limited_resolution);
777 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
778
779 vie_encoder_->TriggerQualityLow();
780
781 new_video_source.IncomingCapturedFrame(
782 CreateFrame(3, frame_width, frame_height));
783 sink_.WaitForEncodedFrame(3);
784 stats = stats_proxy_->GetStats();
785 EXPECT_FALSE(stats.cpu_limited_resolution);
786 EXPECT_TRUE(stats.bw_limited_resolution);
787
788 vie_encoder_->SetSource(&new_video_source,
789 VideoSendStream::DegradationPreference::kBalanced);
790
791 new_video_source.IncomingCapturedFrame(
792 CreateFrame(4, frame_width, frame_height));
793 sink_.WaitForEncodedFrame(4);
794 stats = stats_proxy_->GetStats();
795 EXPECT_FALSE(stats.cpu_limited_resolution);
796 EXPECT_TRUE(stats.bw_limited_resolution);
797
798 // Set adaptation disabled.
799 vie_encoder_->SetSource(
800 &new_video_source,
801 VideoSendStream::DegradationPreference::kMaintainResolution);
802
803 new_video_source.IncomingCapturedFrame(
804 CreateFrame(5, frame_width, frame_height));
805 sink_.WaitForEncodedFrame(5);
806 stats = stats_proxy_->GetStats();
807 EXPECT_FALSE(stats.cpu_limited_resolution);
808 EXPECT_FALSE(stats.bw_limited_resolution);
809
810 vie_encoder_->Stop();
811}
812
perkj803d97f2016-11-01 11:45:46 -0700813TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700814 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
815
816 // Trigger CPU overuse.
817 vie_encoder_->TriggerCpuOveruse();
818 int frame_width = 1280;
819 int frame_height = 720;
820
821 video_source_.IncomingCapturedFrame(
822 CreateFrame(1, frame_width, frame_height));
823 sink_.WaitForEncodedFrame(1);
824
825 VideoSendStream::Stats stats = stats_proxy_->GetStats();
826 EXPECT_TRUE(stats.cpu_limited_resolution);
827 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
828
829 // Set new source with adaptation still enabled.
830 test::FrameForwarder new_video_source;
831 vie_encoder_->SetSource(&new_video_source,
832 VideoSendStream::DegradationPreference::kBalanced);
833
834 new_video_source.IncomingCapturedFrame(
835 CreateFrame(2, frame_width, frame_height));
836 sink_.WaitForEncodedFrame(2);
837 stats = stats_proxy_->GetStats();
838 EXPECT_TRUE(stats.cpu_limited_resolution);
839 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
840
841 // Set adaptation disabled.
842 vie_encoder_->SetSource(
843 &new_video_source,
844 VideoSendStream::DegradationPreference::kMaintainResolution);
845 new_video_source.IncomingCapturedFrame(
846 CreateFrame(3, frame_width, frame_height));
847 sink_.WaitForEncodedFrame(3);
848 stats = stats_proxy_->GetStats();
849 EXPECT_FALSE(stats.cpu_limited_resolution);
850 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
851
852 // Switch back the source with adaptation enabled.
853 vie_encoder_->SetSource(&video_source_,
854 VideoSendStream::DegradationPreference::kBalanced);
855 video_source_.IncomingCapturedFrame(
856 CreateFrame(4, frame_width, frame_height));
857 sink_.WaitForEncodedFrame(4);
858 stats = stats_proxy_->GetStats();
859 EXPECT_TRUE(stats.cpu_limited_resolution);
860 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
861
862 // Trigger CPU normal usage.
863 vie_encoder_->TriggerCpuNormalUsage();
864 video_source_.IncomingCapturedFrame(
865 CreateFrame(5, frame_width, frame_height));
866 sink_.WaitForEncodedFrame(5);
867 stats = stats_proxy_->GetStats();
868 EXPECT_FALSE(stats.cpu_limited_resolution);
869 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
870
871 vie_encoder_->Stop();
872}
873
Erik Språng08127a92016-11-16 16:41:30 +0100874TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100875 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
876
877 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
878 sink_.WaitForEncodedFrame(1);
879
880 VideoSendStream::Stats stats = stats_proxy_->GetStats();
881 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
882 stats.preferred_media_bitrate_bps);
883
884 vie_encoder_->Stop();
885}
886
kthelgason876222f2016-11-29 01:44:11 -0800887TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
minyue35fc2aa2017-02-01 03:14:00 -0800888 const int kTargetBitrateBps = 100000;
kthelgason876222f2016-11-29 01:44:11 -0800889 int frame_width = 1280;
890 int frame_height = 720;
891 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
892
893 // Expect no scaling to begin with
894 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
895 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
896
kthelgason876222f2016-11-29 01:44:11 -0800897 video_source_.IncomingCapturedFrame(
898 CreateFrame(1, frame_width, frame_height));
899 sink_.WaitForEncodedFrame(1);
900
kthelgason5e13d412016-12-01 03:59:51 -0800901 // Trigger scale down
902 vie_encoder_->TriggerQualityLow();
903
904 video_source_.IncomingCapturedFrame(
905 CreateFrame(2, frame_width, frame_height));
906 sink_.WaitForEncodedFrame(2);
907
kthelgason876222f2016-11-29 01:44:11 -0800908 // Expect a scale down.
909 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
910 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
911 frame_width * frame_height);
912
913 // Set adaptation disabled.
914 test::FrameForwarder new_video_source;
915 vie_encoder_->SetSource(
916 &new_video_source,
917 VideoSendStream::DegradationPreference::kMaintainResolution);
918
919 // Trigger scale down
920 vie_encoder_->TriggerQualityLow();
921 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800922 CreateFrame(3, frame_width, frame_height));
923 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -0800924
925 // Expect no scaling
926 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
927
928 // Trigger scale up
929 vie_encoder_->TriggerQualityHigh();
930 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800931 CreateFrame(4, frame_width, frame_height));
932 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -0800933
934 // Expect nothing to change, still no scaling
935 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
936
937 vie_encoder_->Stop();
938}
939
kthelgason5e13d412016-12-01 03:59:51 -0800940TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
minyue35fc2aa2017-02-01 03:14:00 -0800941 const int kTargetBitrateBps = 100000;
kthelgason5e13d412016-12-01 03:59:51 -0800942 int frame_width = 1280;
943 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -0800944 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
945
946 for (size_t i = 1; i <= 10; i++) {
947 video_source_.IncomingCapturedFrame(
948 CreateFrame(i, frame_width, frame_height));
949 sink_.WaitForEncodedFrame(i);
950 // Trigger scale down
951 vie_encoder_->TriggerQualityLow();
952 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
953 }
954
955 vie_encoder_->Stop();
956}
957
perkj803d97f2016-11-01 11:45:46 -0700958TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -0700959 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
960
961 int frame_width = 640;
962 int frame_height = 360;
963
964 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
965 video_source_.IncomingCapturedFrame(
966 CreateFrame(i, frame_width, frame_height));
967 sink_.WaitForEncodedFrame(i);
968 }
969
970 vie_encoder_->TriggerCpuOveruse();
971 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
972 video_source_.IncomingCapturedFrame(
973 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
974 frame_width, frame_height));
975 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
976 i);
977 }
978
979 vie_encoder_->Stop();
980
981 stats_proxy_.reset();
982 EXPECT_EQ(1,
983 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
984 EXPECT_EQ(
985 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
986}
987
sprang57c2fff2017-01-16 06:24:02 -0800988TEST_F(ViEEncoderTest, CallsBitrateObserver) {
989 class MockBitrateObserver : public VideoBitrateAllocationObserver {
990 public:
991 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
992 } bitrate_observer;
993 vie_encoder_->SetBitrateObserver(&bitrate_observer);
994
995 const int kDefaultFps = 30;
996 const BitrateAllocation expected_bitrate =
997 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
minyue35fc2aa2017-02-01 03:14:00 -0800998 .GetAllocation(kTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -0800999
1000 // First called on bitrate updated, then again on first frame.
1001 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1002 .Times(2);
minyue35fc2aa2017-02-01 03:14:00 -08001003 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001004
1005 const int64_t kStartTimeMs = 1;
1006 video_source_.IncomingCapturedFrame(
1007 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1008 sink_.WaitForEncodedFrame(kStartTimeMs);
1009
1010 // Not called on second frame.
1011 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1012 .Times(0);
1013 video_source_.IncomingCapturedFrame(
1014 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1015 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1016
1017 // Called after a process interval.
1018 const int64_t kProcessIntervalMs =
1019 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1020 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1021 // Sleep for one processing interval plus one frame to avoid flakiness.
1022 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1023 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1024 .Times(1);
1025 video_source_.IncomingCapturedFrame(CreateFrame(
1026 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1027 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1028
1029 vie_encoder_->Stop();
1030}
1031
perkj26091b12016-09-01 01:17:40 -07001032} // namespace webrtc