blob: 895109773f16a0837742c6730e2523143f3d1afb [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
perkj26091b12016-09-01 01:17:40 -070014#include "webrtc/base/logging.h"
perkj803d97f2016-11-01 11:45:46 -070015#include "webrtc/system_wrappers/include/metrics_default.h"
perkj26091b12016-09-01 01:17:40 -070016#include "webrtc/test/encoder_settings.h"
17#include "webrtc/test/fake_encoder.h"
perkja49cbd32016-09-16 07:53:41 -070018#include "webrtc/test/frame_generator.h"
kwibergac9f8762016-09-30 22:29:43 -070019#include "webrtc/test/gtest.h"
perkj26091b12016-09-01 01:17:40 -070020#include "webrtc/video/send_statistics_proxy.h"
21#include "webrtc/video/vie_encoder.h"
22
23namespace webrtc {
24
perkj803d97f2016-11-01 11:45:46 -070025namespace {
26class TestBuffer : public webrtc::I420Buffer {
27 public:
28 TestBuffer(rtc::Event* event, int width, int height)
29 : I420Buffer(width, height), event_(event) {}
30
31 private:
32 friend class rtc::RefCountedObject<TestBuffer>;
33 ~TestBuffer() override {
34 if (event_)
35 event_->Set();
36 }
37 rtc::Event* const event_;
38};
39
40class ViEEncoderUnderTest : public ViEEncoder {
41 public:
42 ViEEncoderUnderTest(
43 SendStatisticsProxy* stats_proxy,
44 const webrtc::VideoSendStream::Config::EncoderSettings& settings)
45 : ViEEncoder(1 /* number_of_cores */,
46 stats_proxy,
47 settings,
48 nullptr /* pre_encode_callback */,
49 nullptr /* encoder_timing */) {}
50
51 void TriggerCpuOveruse() {
52 rtc::Event event(false, false);
53 encoder_queue()->PostTask([this, &event] {
54 OveruseDetected();
55 event.Set();
56 });
57 event.Wait(rtc::Event::kForever);
58 }
59
60 void TriggerCpuNormalUsage() {
61 rtc::Event event(false, false);
62 encoder_queue()->PostTask([this, &event] {
63 NormalUsage();
64 event.Set();
65 });
66 event.Wait(rtc::Event::kForever);
67 }
68};
69
70} // namespace
71
perkj26091b12016-09-01 01:17:40 -070072class ViEEncoderTest : public ::testing::Test {
73 public:
74 static const int kDefaultTimeoutMs = 30 * 1000;
75
76 ViEEncoderTest()
77 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -070078 codec_width_(320),
79 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -070080 fake_encoder_(),
perkj803d97f2016-11-01 11:45:46 -070081 stats_proxy_(new SendStatisticsProxy(
82 Clock::GetRealTimeClock(),
83 video_send_config_,
84 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -070085 sink_(&fake_encoder_) {}
86
87 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -070088 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -070089 video_send_config_ = VideoSendStream::Config(nullptr);
90 video_send_config_.encoder_settings.encoder = &fake_encoder_;
91 video_send_config_.encoder_settings.payload_name = "FAKE";
92 video_send_config_.encoder_settings.payload_type = 125;
93
Per512ecb32016-09-23 15:52:06 +020094 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -070095 test::FillEncoderConfiguration(1, &video_encoder_config);
perkj803d97f2016-11-01 11:45:46 -070096 vie_encoder_.reset(new ViEEncoderUnderTest(
97 stats_proxy_.get(), video_send_config_.encoder_settings));
98 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
99 vie_encoder_->SetSource(&video_source_,
100 VideoSendStream::DegradationPreference::kBalanced);
perkj26091b12016-09-01 01:17:40 -0700101 vie_encoder_->SetStartBitrate(10000);
Per512ecb32016-09-23 15:52:06 +0200102 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
perkj26091b12016-09-01 01:17:40 -0700103 }
104
105 VideoFrame CreateFrame(int64_t ntp_ts, rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200106 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
107 destruction_event, codec_width_, codec_height_),
108 99, 99, kVideoRotation_0);
perkj26091b12016-09-01 01:17:40 -0700109 frame.set_ntp_time_ms(ntp_ts);
110 return frame;
111 }
112
perkj803d97f2016-11-01 11:45:46 -0700113 VideoFrame CreateFrame(int64_t ntp_ts, int width, int height) const {
114 VideoFrame frame(
115 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
116 kVideoRotation_0);
117 frame.set_ntp_time_ms(ntp_ts);
118 return frame;
119 }
120
perkj26091b12016-09-01 01:17:40 -0700121 class TestEncoder : public test::FakeEncoder {
122 public:
123 TestEncoder()
124 : FakeEncoder(Clock::GetRealTimeClock()),
125 continue_encode_event_(false, false) {}
126
perkjfa10b552016-10-02 23:45:26 -0700127 VideoCodec codec_config() {
128 rtc::CritScope lock(&crit_);
129 return config_;
130 }
131
132 void BlockNextEncode() {
133 rtc::CritScope lock(&crit_);
134 block_next_encode_ = true;
135 }
136
137 void ContinueEncode() { continue_encode_event_.Set(); }
138
139 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
140 uint32_t timestamp) const {
141 rtc::CritScope lock(&crit_);
142 EXPECT_EQ(timestamp_, timestamp);
143 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
144 }
145
146 private:
perkj26091b12016-09-01 01:17:40 -0700147 int32_t Encode(const VideoFrame& input_image,
148 const CodecSpecificInfo* codec_specific_info,
149 const std::vector<FrameType>* frame_types) override {
150 bool block_encode;
151 {
152 rtc::CritScope lock(&crit_);
153 EXPECT_GT(input_image.timestamp(), timestamp_);
154 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
155 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
156
157 timestamp_ = input_image.timestamp();
158 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700159 last_input_width_ = input_image.width();
160 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700161 block_encode = block_next_encode_;
162 block_next_encode_ = false;
163 }
164 int32_t result =
165 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
166 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700167 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700168 return result;
169 }
170
perkj26091b12016-09-01 01:17:40 -0700171 rtc::CriticalSection crit_;
172 bool block_next_encode_ = false;
173 rtc::Event continue_encode_event_;
174 uint32_t timestamp_ = 0;
175 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700176 int last_input_width_ = 0;
177 int last_input_height_ = 0;
perkj26091b12016-09-01 01:17:40 -0700178 };
179
Per512ecb32016-09-23 15:52:06 +0200180 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700181 public:
182 explicit TestSink(TestEncoder* test_encoder)
183 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
184
perkj26091b12016-09-01 01:17:40 -0700185 void WaitForEncodedFrame(int64_t expected_ntp_time) {
186 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700187 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700188 {
189 rtc::CritScope lock(&crit_);
190 timestamp = timestamp_;
191 }
192 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
193 }
194
195 void SetExpectNoFrames() {
196 rtc::CritScope lock(&crit_);
197 expect_frames_ = false;
198 }
199
Per512ecb32016-09-23 15:52:06 +0200200 int number_of_reconfigurations() {
201 rtc::CritScope lock(&crit_);
202 return number_of_reconfigurations_;
203 }
204
205 int last_min_transmit_bitrate() {
206 rtc::CritScope lock(&crit_);
207 return min_transmit_bitrate_bps_;
208 }
209
perkj26091b12016-09-01 01:17:40 -0700210 private:
Per512ecb32016-09-23 15:52:06 +0200211 int32_t Encoded(const EncodedImage& encoded_image,
212 const CodecSpecificInfo* codec_specific_info,
213 const RTPFragmentationHeader* fragmentation) override {
214 rtc::CritScope lock(&crit_);
215 EXPECT_TRUE(expect_frames_);
216 timestamp_ = encoded_image._timeStamp;
217 encoded_frame_event_.Set();
218 return 0;
219 }
220
221 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
222 int min_transmit_bitrate_bps) override {
223 rtc::CriticalSection crit_;
224 ++number_of_reconfigurations_;
225 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
226 }
227
perkj26091b12016-09-01 01:17:40 -0700228 rtc::CriticalSection crit_;
229 TestEncoder* test_encoder_;
230 rtc::Event encoded_frame_event_;
231 uint32_t timestamp_ = 0;
232 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200233 int number_of_reconfigurations_ = 0;
234 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700235 };
236
237 VideoSendStream::Config video_send_config_;
Per512ecb32016-09-23 15:52:06 +0200238 int codec_width_;
239 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700240 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700241 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700242 TestSink sink_;
perkja49cbd32016-09-16 07:53:41 -0700243 test::FrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700244 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700245};
246
247TEST_F(ViEEncoderTest, EncodeOneFrame) {
248 const int kTargetBitrateBps = 100000;
249 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
250 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700251 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700252 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700253 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700254 vie_encoder_->Stop();
255}
256
257TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
258 // Dropped since no target bitrate has been set.
259 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700260 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
261 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700262
263 const int kTargetBitrateBps = 100000;
264 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
265
perkja49cbd32016-09-16 07:53:41 -0700266 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700267 sink_.WaitForEncodedFrame(2);
268 vie_encoder_->Stop();
269}
270
271TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
272 const int kTargetBitrateBps = 100000;
273 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700274 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700275 sink_.WaitForEncodedFrame(1);
276
277 vie_encoder_->OnBitrateUpdated(0, 0, 0);
278 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700279 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700280
281 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700282 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700283 sink_.WaitForEncodedFrame(3);
284 vie_encoder_->Stop();
285}
286
287TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
288 const int kTargetBitrateBps = 100000;
289 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700290 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700291 sink_.WaitForEncodedFrame(1);
292
293 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700294 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700295
perkja49cbd32016-09-16 07:53:41 -0700296 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700297 sink_.WaitForEncodedFrame(2);
298 vie_encoder_->Stop();
299}
300
301TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
302 const int kTargetBitrateBps = 100000;
303 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
304
perkja49cbd32016-09-16 07:53:41 -0700305 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700306 sink_.WaitForEncodedFrame(1);
307
308 vie_encoder_->Stop();
309 sink_.SetExpectNoFrames();
310 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700311 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
312 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700313}
314
315TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
316 const int kTargetBitrateBps = 100000;
317 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
318
319 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700320 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700321 sink_.WaitForEncodedFrame(1);
322 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
323 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700324 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
325 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700326 fake_encoder_.ContinueEncode();
327 sink_.WaitForEncodedFrame(3);
328
329 vie_encoder_->Stop();
330}
331
Per512ecb32016-09-23 15:52:06 +0200332TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
333 const int kTargetBitrateBps = 100000;
334 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100335 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200336
337 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200338 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200339 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100340 // The encoder will have been configured once when the first frame is
341 // received.
342 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200343
344 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700345 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200346 video_encoder_config.min_transmit_bitrate_bps = 9999;
347 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config), 1440);
348
349 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200350 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200351 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100352 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700353 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700354
355 vie_encoder_->Stop();
356}
357
perkjfa10b552016-10-02 23:45:26 -0700358TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
359 const int kTargetBitrateBps = 100000;
360 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
361
362 // Capture a frame and wait for it to synchronize with the encoder thread.
363 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
364 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100365 // The encoder will have been configured once.
366 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700367 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
368 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
369
370 codec_width_ *= 2;
371 codec_height_ *= 2;
372 // Capture a frame with a higher resolution and wait for it to synchronize
373 // with the encoder thread.
374 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
375 sink_.WaitForEncodedFrame(2);
376 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
377 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100378 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700379
380 vie_encoder_->Stop();
381}
382
perkj803d97f2016-11-01 11:45:46 -0700383TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
384 EXPECT_TRUE(video_source_.has_sinks());
385 test::FrameForwarder new_video_source;
386 vie_encoder_->SetSource(&new_video_source,
387 VideoSendStream::DegradationPreference::kBalanced);
388 EXPECT_FALSE(video_source_.has_sinks());
389 EXPECT_TRUE(new_video_source.has_sinks());
390
391 vie_encoder_->Stop();
392}
393
394TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
395 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
396 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
397 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
398 vie_encoder_->Stop();
399}
400
401TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
402 const int kTargetBitrateBps = 100000;
403 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
404
405 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
406 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
407
408 int frame_width = 1280;
409 int frame_height = 720;
410
411 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
412 // request lower resolution.
413 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
414 video_source_.IncomingCapturedFrame(
415 CreateFrame(i, frame_width, frame_height));
416 sink_.WaitForEncodedFrame(i);
417
418 vie_encoder_->TriggerCpuOveruse();
419
420 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
421 std::numeric_limits<int>::max()),
422 frame_width * frame_height);
423 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
424
425 frame_width /= 2;
426 frame_height /= 2;
427 }
428
429 // Trigger CPU overuse a one more time. This should not trigger request for
430 // lower resolution.
431 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
432 video_source_.IncomingCapturedFrame(CreateFrame(
433 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
434 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
435 vie_encoder_->TriggerCpuOveruse();
436 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
437 current_wants.max_pixel_count);
438 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up,
439 current_wants.max_pixel_count_step_up);
440
441 // Trigger CPU normal use.
442 vie_encoder_->TriggerCpuNormalUsage();
443 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
444 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0),
445 frame_width * frame_height);
446
447 vie_encoder_->Stop();
448}
449
450TEST_F(ViEEncoderTest,
451 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
452 const int kTargetBitrateBps = 100000;
453 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
454
455 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
456 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
457
458 int frame_width = 1280;
459 int frame_height = 720;
460
461 // Trigger CPU overuse.
462 vie_encoder_->TriggerCpuOveruse();
463
464 video_source_.IncomingCapturedFrame(
465 CreateFrame(1, frame_width, frame_height));
466 sink_.WaitForEncodedFrame(1);
467 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
468 std::numeric_limits<int>::max()),
469 frame_width * frame_height);
470 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
471
472 // Set new source.
473 test::FrameForwarder new_video_source;
474 vie_encoder_->SetSource(
475 &new_video_source,
476 VideoSendStream::DegradationPreference::kMaintainResolution);
477
478 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
479 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
480
481 new_video_source.IncomingCapturedFrame(
482 CreateFrame(2, frame_width, frame_height));
483 sink_.WaitForEncodedFrame(2);
484 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
485 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
486
487 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
488 vie_encoder_->SetSource(&new_video_source,
489 VideoSendStream::DegradationPreference::kBalanced);
490 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
491 std::numeric_limits<int>::max()),
492 frame_width * frame_height);
493 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
494
495 vie_encoder_->Stop();
496}
497
498TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
499 const int kTargetBitrateBps = 100000;
500 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
501
502 int frame_width = 1280;
503 int frame_height = 720;
504
505 video_source_.IncomingCapturedFrame(
506 CreateFrame(1, frame_width, frame_height));
507 sink_.WaitForEncodedFrame(1);
508 VideoSendStream::Stats stats = stats_proxy_->GetStats();
509 EXPECT_FALSE(stats.cpu_limited_resolution);
510 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
511
512 // Trigger CPU overuse.
513 vie_encoder_->TriggerCpuOveruse();
514 video_source_.IncomingCapturedFrame(
515 CreateFrame(2, frame_width, frame_height));
516 sink_.WaitForEncodedFrame(2);
517
518 stats = stats_proxy_->GetStats();
519 EXPECT_TRUE(stats.cpu_limited_resolution);
520 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
521
522 // Trigger CPU normal use.
523 vie_encoder_->TriggerCpuNormalUsage();
524 video_source_.IncomingCapturedFrame(
525 CreateFrame(3, frame_width, frame_height));
526 sink_.WaitForEncodedFrame(3);
527
528 stats = stats_proxy_->GetStats();
529 EXPECT_FALSE(stats.cpu_limited_resolution);
530 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
531
532 vie_encoder_->Stop();
533}
534
535TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
536 const int kTargetBitrateBps = 100000;
537 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
538
539 // Trigger CPU overuse.
540 vie_encoder_->TriggerCpuOveruse();
541 int frame_width = 1280;
542 int frame_height = 720;
543
544 video_source_.IncomingCapturedFrame(
545 CreateFrame(1, frame_width, frame_height));
546 sink_.WaitForEncodedFrame(1);
547
548 VideoSendStream::Stats stats = stats_proxy_->GetStats();
549 EXPECT_TRUE(stats.cpu_limited_resolution);
550 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
551
552 // Set new source with adaptation still enabled.
553 test::FrameForwarder new_video_source;
554 vie_encoder_->SetSource(&new_video_source,
555 VideoSendStream::DegradationPreference::kBalanced);
556
557 new_video_source.IncomingCapturedFrame(
558 CreateFrame(2, frame_width, frame_height));
559 sink_.WaitForEncodedFrame(2);
560 stats = stats_proxy_->GetStats();
561 EXPECT_TRUE(stats.cpu_limited_resolution);
562 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
563
564 // Set adaptation disabled.
565 vie_encoder_->SetSource(
566 &new_video_source,
567 VideoSendStream::DegradationPreference::kMaintainResolution);
568 new_video_source.IncomingCapturedFrame(
569 CreateFrame(3, frame_width, frame_height));
570 sink_.WaitForEncodedFrame(3);
571 stats = stats_proxy_->GetStats();
572 EXPECT_FALSE(stats.cpu_limited_resolution);
573 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
574
575 // Switch back the source with adaptation enabled.
576 vie_encoder_->SetSource(&video_source_,
577 VideoSendStream::DegradationPreference::kBalanced);
578 video_source_.IncomingCapturedFrame(
579 CreateFrame(4, frame_width, frame_height));
580 sink_.WaitForEncodedFrame(4);
581 stats = stats_proxy_->GetStats();
582 EXPECT_TRUE(stats.cpu_limited_resolution);
583 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
584
585 // Trigger CPU normal usage.
586 vie_encoder_->TriggerCpuNormalUsage();
587 video_source_.IncomingCapturedFrame(
588 CreateFrame(5, frame_width, frame_height));
589 sink_.WaitForEncodedFrame(5);
590 stats = stats_proxy_->GetStats();
591 EXPECT_FALSE(stats.cpu_limited_resolution);
592 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
593
594 vie_encoder_->Stop();
595}
596
597TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
598 const int kTargetBitrateBps = 100000;
599 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
600
601 int frame_width = 640;
602 int frame_height = 360;
603
604 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
605 video_source_.IncomingCapturedFrame(
606 CreateFrame(i, frame_width, frame_height));
607 sink_.WaitForEncodedFrame(i);
608 }
609
610 vie_encoder_->TriggerCpuOveruse();
611 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
612 video_source_.IncomingCapturedFrame(
613 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
614 frame_width, frame_height));
615 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
616 i);
617 }
618
619 vie_encoder_->Stop();
620
621 stats_proxy_.reset();
622 EXPECT_EQ(1,
623 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
624 EXPECT_EQ(
625 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
626}
627
perkj26091b12016-09-01 01:17:40 -0700628} // namespace webrtc