blob: 5dee314683ac3368cf2739e74e8cae64dda09b5f [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;
kthelgason83399ca2017-02-01 01:31:52 -080046const int kTargetBitrateBps = 1000000;
47const int kLowTargetBitrateBps = kTargetBitrateBps / 10;
48const int kMaxInitialFramedrop = 4;
asapersson5f7226f2016-11-25 04:37:00 -080049
perkj803d97f2016-11-01 11:45:46 -070050class TestBuffer : public webrtc::I420Buffer {
51 public:
52 TestBuffer(rtc::Event* event, int width, int height)
53 : I420Buffer(width, height), event_(event) {}
54
55 private:
56 friend class rtc::RefCountedObject<TestBuffer>;
57 ~TestBuffer() override {
58 if (event_)
59 event_->Set();
60 }
61 rtc::Event* const event_;
62};
63
64class ViEEncoderUnderTest : public ViEEncoder {
65 public:
kthelgason876222f2016-11-29 01:44:11 -080066 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
67 const VideoSendStream::Config::EncoderSettings& settings)
perkj803d97f2016-11-01 11:45:46 -070068 : ViEEncoder(1 /* number_of_cores */,
69 stats_proxy,
70 settings,
71 nullptr /* pre_encode_callback */,
72 nullptr /* encoder_timing */) {}
73
kthelgason876222f2016-11-29 01:44:11 -080074 void PostTaskAndWait(bool down, ScaleReason reason) {
perkj803d97f2016-11-01 11:45:46 -070075 rtc::Event event(false, false);
kthelgason876222f2016-11-29 01:44:11 -080076 encoder_queue()->PostTask([this, &event, reason, down] {
77 down ? ScaleDown(reason) : ScaleUp(reason);
perkj803d97f2016-11-01 11:45:46 -070078 event.Set();
79 });
kthelgason876222f2016-11-29 01:44:11 -080080 RTC_DCHECK(event.Wait(5000));
perkj803d97f2016-11-01 11:45:46 -070081 }
82
kthelgason876222f2016-11-29 01:44:11 -080083 void TriggerCpuOveruse() { PostTaskAndWait(true, ScaleReason::kCpu); }
84
85 void TriggerCpuNormalUsage() { PostTaskAndWait(false, ScaleReason::kCpu); }
86
87 void TriggerQualityLow() { PostTaskAndWait(true, ScaleReason::kQuality); }
88
89 void TriggerQualityHigh() { PostTaskAndWait(false, ScaleReason::kQuality); }
perkj803d97f2016-11-01 11:45:46 -070090};
91
asapersson5f7226f2016-11-25 04:37:00 -080092class VideoStreamFactory
93 : public VideoEncoderConfig::VideoStreamFactoryInterface {
94 public:
95 explicit VideoStreamFactory(size_t num_temporal_layers)
96 : num_temporal_layers_(num_temporal_layers) {
97 EXPECT_GT(num_temporal_layers, 0u);
98 }
99
100 private:
101 std::vector<VideoStream> CreateEncoderStreams(
102 int width,
103 int height,
104 const VideoEncoderConfig& encoder_config) override {
105 std::vector<VideoStream> streams =
106 test::CreateVideoStreams(width, height, encoder_config);
107 for (VideoStream& stream : streams) {
108 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
109 }
110 return streams;
111 }
112 const size_t num_temporal_layers_;
113};
114
perkj803d97f2016-11-01 11:45:46 -0700115} // namespace
116
perkj26091b12016-09-01 01:17:40 -0700117class ViEEncoderTest : public ::testing::Test {
118 public:
119 static const int kDefaultTimeoutMs = 30 * 1000;
120
121 ViEEncoderTest()
122 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -0700123 codec_width_(320),
124 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -0700125 fake_encoder_(),
perkj803d97f2016-11-01 11:45:46 -0700126 stats_proxy_(new SendStatisticsProxy(
127 Clock::GetRealTimeClock(),
128 video_send_config_,
129 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -0700130 sink_(&fake_encoder_) {}
131
132 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -0700133 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -0700134 video_send_config_ = VideoSendStream::Config(nullptr);
135 video_send_config_.encoder_settings.encoder = &fake_encoder_;
136 video_send_config_.encoder_settings.payload_name = "FAKE";
137 video_send_config_.encoder_settings.payload_type = 125;
138
Per512ecb32016-09-23 15:52:06 +0200139 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700140 test::FillEncoderConfiguration(1, &video_encoder_config);
Erik Språng08127a92016-11-16 16:41:30 +0100141 video_encoder_config_ = video_encoder_config.Copy();
asapersson5f7226f2016-11-25 04:37:00 -0800142 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
143 }
144
145 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
146 bool nack_enabled) {
147 if (vie_encoder_)
148 vie_encoder_->Stop();
perkj803d97f2016-11-01 11:45:46 -0700149 vie_encoder_.reset(new ViEEncoderUnderTest(
150 stats_proxy_.get(), video_send_config_.encoder_settings));
151 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
152 vie_encoder_->SetSource(&video_source_,
153 VideoSendStream::DegradationPreference::kBalanced);
kthelgason83399ca2017-02-01 01:31:52 -0800154 vie_encoder_->SetStartBitrate(kTargetBitrateBps);
asapersson5f7226f2016-11-25 04:37:00 -0800155 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
156 kMaxPayloadLength, nack_enabled);
157 }
158
159 void ResetEncoder(const std::string& payload_name,
160 size_t num_streams,
161 size_t num_temporal_layers,
162 bool nack_enabled) {
163 video_send_config_.encoder_settings.payload_name = payload_name;
164
165 VideoEncoderConfig video_encoder_config;
166 video_encoder_config.number_of_streams = num_streams;
kthelgason83399ca2017-02-01 01:31:52 -0800167 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
asapersson5f7226f2016-11-25 04:37:00 -0800168 video_encoder_config.video_stream_factory =
169 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
170 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
perkj26091b12016-09-01 01:17:40 -0700171 }
172
sprang57c2fff2017-01-16 06:24:02 -0800173 VideoFrame CreateFrame(int64_t ntp_time_ms,
174 rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200175 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
176 destruction_event, codec_width_, codec_height_),
177 99, 99, kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800178 frame.set_ntp_time_ms(ntp_time_ms);
perkj26091b12016-09-01 01:17:40 -0700179 return frame;
180 }
181
sprang57c2fff2017-01-16 06:24:02 -0800182 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
perkj803d97f2016-11-01 11:45:46 -0700183 VideoFrame frame(
184 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
185 kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800186 frame.set_ntp_time_ms(ntp_time_ms);
perkj803d97f2016-11-01 11:45:46 -0700187 return frame;
188 }
189
perkj26091b12016-09-01 01:17:40 -0700190 class TestEncoder : public test::FakeEncoder {
191 public:
192 TestEncoder()
193 : FakeEncoder(Clock::GetRealTimeClock()),
194 continue_encode_event_(false, false) {}
195
perkjfa10b552016-10-02 23:45:26 -0700196 VideoCodec codec_config() {
brandtre78d2662017-01-16 05:57:16 -0800197 rtc::CritScope lock(&crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700198 return config_;
199 }
200
201 void BlockNextEncode() {
brandtre78d2662017-01-16 05:57:16 -0800202 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700203 block_next_encode_ = true;
204 }
205
kthelgason876222f2016-11-29 01:44:11 -0800206 VideoEncoder::ScalingSettings GetScalingSettings() const override {
207 return VideoEncoder::ScalingSettings(true, 1, 2);
208 }
209
perkjfa10b552016-10-02 23:45:26 -0700210 void ContinueEncode() { continue_encode_event_.Set(); }
211
212 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
213 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800214 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700215 EXPECT_EQ(timestamp_, timestamp);
216 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
217 }
218
219 private:
perkj26091b12016-09-01 01:17:40 -0700220 int32_t Encode(const VideoFrame& input_image,
221 const CodecSpecificInfo* codec_specific_info,
222 const std::vector<FrameType>* frame_types) override {
223 bool block_encode;
224 {
brandtre78d2662017-01-16 05:57:16 -0800225 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700226 EXPECT_GT(input_image.timestamp(), timestamp_);
227 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
228 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
229
230 timestamp_ = input_image.timestamp();
231 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700232 last_input_width_ = input_image.width();
233 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700234 block_encode = block_next_encode_;
235 block_next_encode_ = false;
236 }
237 int32_t result =
238 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
239 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700240 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700241 return result;
242 }
243
brandtre78d2662017-01-16 05:57:16 -0800244 rtc::CriticalSection local_crit_sect_;
perkj26091b12016-09-01 01:17:40 -0700245 bool block_next_encode_ = false;
246 rtc::Event continue_encode_event_;
247 uint32_t timestamp_ = 0;
248 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700249 int last_input_width_ = 0;
250 int last_input_height_ = 0;
perkj26091b12016-09-01 01:17:40 -0700251 };
252
Per512ecb32016-09-23 15:52:06 +0200253 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700254 public:
255 explicit TestSink(TestEncoder* test_encoder)
256 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
257
perkj26091b12016-09-01 01:17:40 -0700258 void WaitForEncodedFrame(int64_t expected_ntp_time) {
259 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700260 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700261 {
262 rtc::CritScope lock(&crit_);
263 timestamp = timestamp_;
264 }
265 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
266 }
267
kthelgason83399ca2017-02-01 01:31:52 -0800268 void ExpectDroppedFrame() { EXPECT_FALSE(encoded_frame_event_.Wait(20)); }
269
perkj26091b12016-09-01 01:17:40 -0700270 void SetExpectNoFrames() {
271 rtc::CritScope lock(&crit_);
272 expect_frames_ = false;
273 }
274
Per512ecb32016-09-23 15:52:06 +0200275 int number_of_reconfigurations() {
276 rtc::CritScope lock(&crit_);
277 return number_of_reconfigurations_;
278 }
279
280 int last_min_transmit_bitrate() {
281 rtc::CritScope lock(&crit_);
282 return min_transmit_bitrate_bps_;
283 }
284
perkj26091b12016-09-01 01:17:40 -0700285 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700286 Result OnEncodedImage(
287 const EncodedImage& encoded_image,
288 const CodecSpecificInfo* codec_specific_info,
289 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200290 rtc::CritScope lock(&crit_);
291 EXPECT_TRUE(expect_frames_);
292 timestamp_ = encoded_image._timeStamp;
293 encoded_frame_event_.Set();
sergeyu2cb155a2016-11-04 11:39:29 -0700294 return Result(Result::OK, timestamp_);
Per512ecb32016-09-23 15:52:06 +0200295 }
296
297 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
298 int min_transmit_bitrate_bps) override {
299 rtc::CriticalSection crit_;
300 ++number_of_reconfigurations_;
301 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
302 }
303
perkj26091b12016-09-01 01:17:40 -0700304 rtc::CriticalSection crit_;
305 TestEncoder* test_encoder_;
306 rtc::Event encoded_frame_event_;
307 uint32_t timestamp_ = 0;
308 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200309 int number_of_reconfigurations_ = 0;
310 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700311 };
312
313 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100314 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200315 int codec_width_;
316 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700317 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700318 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700319 TestSink sink_;
perkja49cbd32016-09-16 07:53:41 -0700320 test::FrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700321 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700322};
323
324TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700325 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
326 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700327 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700328 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700329 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700330 vie_encoder_->Stop();
331}
332
333TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
334 // Dropped since no target bitrate has been set.
335 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700336 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
337 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700338
perkj26091b12016-09-01 01:17:40 -0700339 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
340
perkja49cbd32016-09-16 07:53:41 -0700341 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700342 sink_.WaitForEncodedFrame(2);
343 vie_encoder_->Stop();
344}
345
346TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700347 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700348 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700349 sink_.WaitForEncodedFrame(1);
350
351 vie_encoder_->OnBitrateUpdated(0, 0, 0);
352 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700353 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700354
355 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700356 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700357 sink_.WaitForEncodedFrame(3);
358 vie_encoder_->Stop();
359}
360
361TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700362 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700363 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700364 sink_.WaitForEncodedFrame(1);
365
366 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700367 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700368
perkja49cbd32016-09-16 07:53:41 -0700369 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700370 sink_.WaitForEncodedFrame(2);
371 vie_encoder_->Stop();
372}
373
374TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700375 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
376
perkja49cbd32016-09-16 07:53:41 -0700377 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700378 sink_.WaitForEncodedFrame(1);
379
380 vie_encoder_->Stop();
381 sink_.SetExpectNoFrames();
382 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700383 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
384 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700385}
386
387TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700388 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
389
390 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700391 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700392 sink_.WaitForEncodedFrame(1);
393 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
394 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700395 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
396 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700397 fake_encoder_.ContinueEncode();
398 sink_.WaitForEncodedFrame(3);
399
400 vie_encoder_->Stop();
401}
402
Per512ecb32016-09-23 15:52:06 +0200403TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200404 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100405 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200406
407 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200408 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200409 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100410 // The encoder will have been configured once when the first frame is
411 // received.
412 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200413
414 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700415 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200416 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800417 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
418 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200419
420 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200421 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200422 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100423 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700424 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700425
426 vie_encoder_->Stop();
427}
428
perkjfa10b552016-10-02 23:45:26 -0700429TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700430 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
431
432 // Capture a frame and wait for it to synchronize with the encoder thread.
433 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
434 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100435 // The encoder will have been configured once.
436 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700437 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
438 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
439
440 codec_width_ *= 2;
441 codec_height_ *= 2;
442 // Capture a frame with a higher resolution and wait for it to synchronize
443 // with the encoder thread.
444 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
445 sink_.WaitForEncodedFrame(2);
446 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
447 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100448 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700449
450 vie_encoder_->Stop();
451}
452
asapersson5f7226f2016-11-25 04:37:00 -0800453TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
454 const bool kNackEnabled = true;
455 const size_t kNumStreams = 1;
456 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800457 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800458 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
459
460 // Capture a frame and wait for it to synchronize with the encoder thread.
461 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
462 sink_.WaitForEncodedFrame(1);
463 // The encoder have been configured once when the first frame is received.
464 EXPECT_EQ(1, sink_.number_of_reconfigurations());
465 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
466 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
467 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
468 // Resilience is off for no temporal layers with nack on.
469 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
470 vie_encoder_->Stop();
471}
472
473TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
474 const bool kNackEnabled = true;
475 const size_t kNumStreams = 2;
476 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800477 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800478 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
479
480 // Capture a frame and wait for it to synchronize with the encoder thread.
481 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
482 sink_.WaitForEncodedFrame(1);
483 // The encoder have been configured once when the first frame is received.
484 EXPECT_EQ(1, sink_.number_of_reconfigurations());
485 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
486 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
487 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
488 // Resilience is off for no temporal layers and >1 streams with nack on.
489 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
490 vie_encoder_->Stop();
491}
492
493TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
494 const bool kNackEnabled = false;
495 const size_t kNumStreams = 1;
496 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800497 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800498 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
499
500 // Capture a frame and wait for it to synchronize with the encoder thread.
501 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
502 sink_.WaitForEncodedFrame(1);
503 // The encoder have been configured once when the first frame is received.
504 EXPECT_EQ(1, sink_.number_of_reconfigurations());
505 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
506 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
507 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
508 // Resilience is on for no temporal layers with nack off.
509 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
510 vie_encoder_->Stop();
511}
512
513TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
514 const bool kNackEnabled = true;
515 const size_t kNumStreams = 1;
516 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800517 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800518 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
519
520 // Capture a frame and wait for it to synchronize with the encoder thread.
521 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
522 sink_.WaitForEncodedFrame(1);
523 // The encoder have been configured once when the first frame is received.
524 EXPECT_EQ(1, sink_.number_of_reconfigurations());
525 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
526 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
527 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
528 // Resilience is on for temporal layers.
529 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
530 vie_encoder_->Stop();
531}
532
perkj803d97f2016-11-01 11:45:46 -0700533TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
534 EXPECT_TRUE(video_source_.has_sinks());
535 test::FrameForwarder new_video_source;
536 vie_encoder_->SetSource(&new_video_source,
537 VideoSendStream::DegradationPreference::kBalanced);
538 EXPECT_FALSE(video_source_.has_sinks());
539 EXPECT_TRUE(new_video_source.has_sinks());
540
541 vie_encoder_->Stop();
542}
543
544TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
545 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
546 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
547 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
548 vie_encoder_->Stop();
549}
550
551TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700552 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
553
554 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
555 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
556
557 int frame_width = 1280;
558 int frame_height = 720;
559
560 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
561 // request lower resolution.
562 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
563 video_source_.IncomingCapturedFrame(
564 CreateFrame(i, frame_width, frame_height));
565 sink_.WaitForEncodedFrame(i);
566
567 vie_encoder_->TriggerCpuOveruse();
568
569 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
570 std::numeric_limits<int>::max()),
571 frame_width * frame_height);
572 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
573
574 frame_width /= 2;
575 frame_height /= 2;
576 }
577
kthelgason876222f2016-11-29 01:44:11 -0800578 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700579 // lower resolution.
580 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
581 video_source_.IncomingCapturedFrame(CreateFrame(
582 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
583 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
584 vie_encoder_->TriggerCpuOveruse();
585 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
586 current_wants.max_pixel_count);
587 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up,
588 current_wants.max_pixel_count_step_up);
589
590 // Trigger CPU normal use.
591 vie_encoder_->TriggerCpuNormalUsage();
592 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
593 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0),
594 frame_width * frame_height);
595
596 vie_encoder_->Stop();
597}
598
599TEST_F(ViEEncoderTest,
600 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700601 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
602
603 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
604 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
605
606 int frame_width = 1280;
607 int frame_height = 720;
608
kthelgason5e13d412016-12-01 03:59:51 -0800609 video_source_.IncomingCapturedFrame(
610 CreateFrame(1, frame_width, frame_height));
611 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700612 // Trigger CPU overuse.
613 vie_encoder_->TriggerCpuOveruse();
614
615 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800616 CreateFrame(2, frame_width, frame_height));
617 sink_.WaitForEncodedFrame(2);
perkj803d97f2016-11-01 11:45:46 -0700618 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
619 std::numeric_limits<int>::max()),
620 frame_width * frame_height);
621 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
622
623 // Set new source.
624 test::FrameForwarder new_video_source;
625 vie_encoder_->SetSource(
626 &new_video_source,
627 VideoSendStream::DegradationPreference::kMaintainResolution);
628
629 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
630 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
631
632 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800633 CreateFrame(3, frame_width, frame_height));
634 sink_.WaitForEncodedFrame(3);
perkj803d97f2016-11-01 11:45:46 -0700635 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
636 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
637
638 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
639 vie_encoder_->SetSource(&new_video_source,
640 VideoSendStream::DegradationPreference::kBalanced);
641 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
642 std::numeric_limits<int>::max()),
643 frame_width * frame_height);
644 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
645
646 vie_encoder_->Stop();
647}
648
649TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700650 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
651
652 int frame_width = 1280;
653 int frame_height = 720;
654
655 video_source_.IncomingCapturedFrame(
656 CreateFrame(1, frame_width, frame_height));
657 sink_.WaitForEncodedFrame(1);
658 VideoSendStream::Stats stats = stats_proxy_->GetStats();
659 EXPECT_FALSE(stats.cpu_limited_resolution);
660 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
661
662 // Trigger CPU overuse.
663 vie_encoder_->TriggerCpuOveruse();
664 video_source_.IncomingCapturedFrame(
665 CreateFrame(2, frame_width, frame_height));
666 sink_.WaitForEncodedFrame(2);
667
668 stats = stats_proxy_->GetStats();
669 EXPECT_TRUE(stats.cpu_limited_resolution);
670 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
671
672 // Trigger CPU normal use.
673 vie_encoder_->TriggerCpuNormalUsage();
674 video_source_.IncomingCapturedFrame(
675 CreateFrame(3, frame_width, frame_height));
676 sink_.WaitForEncodedFrame(3);
677
678 stats = stats_proxy_->GetStats();
679 EXPECT_FALSE(stats.cpu_limited_resolution);
680 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
681
682 vie_encoder_->Stop();
683}
684
kthelgason876222f2016-11-29 01:44:11 -0800685TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800686 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
687
688 int frame_width = 1280;
689 int frame_height = 720;
690 video_source_.IncomingCapturedFrame(
691 CreateFrame(1, frame_width, frame_height));
692 sink_.WaitForEncodedFrame(1);
693
694 VideoSendStream::Stats stats = stats_proxy_->GetStats();
695 EXPECT_FALSE(stats.cpu_limited_resolution);
696 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
697
698 vie_encoder_->TriggerCpuOveruse();
699
700 video_source_.IncomingCapturedFrame(
701 CreateFrame(2, frame_width, frame_height));
702 sink_.WaitForEncodedFrame(2);
703 stats = stats_proxy_->GetStats();
704 EXPECT_TRUE(stats.cpu_limited_resolution);
705 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
706
707 // Set new source with adaptation still enabled.
708 test::FrameForwarder new_video_source;
709 vie_encoder_->SetSource(&new_video_source,
710 VideoSendStream::DegradationPreference::kBalanced);
711
712 new_video_source.IncomingCapturedFrame(
713 CreateFrame(3, frame_width, frame_height));
714 sink_.WaitForEncodedFrame(3);
715 stats = stats_proxy_->GetStats();
716 EXPECT_TRUE(stats.cpu_limited_resolution);
717 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
718
719 // Set adaptation disabled.
720 vie_encoder_->SetSource(
721 &new_video_source,
722 VideoSendStream::DegradationPreference::kMaintainResolution);
723
724 new_video_source.IncomingCapturedFrame(
725 CreateFrame(4, frame_width, frame_height));
726 sink_.WaitForEncodedFrame(4);
727 stats = stats_proxy_->GetStats();
728 EXPECT_FALSE(stats.cpu_limited_resolution);
729 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
730
731 // Set adaptation back to enabled.
732 vie_encoder_->SetSource(&new_video_source,
733 VideoSendStream::DegradationPreference::kBalanced);
734
735 new_video_source.IncomingCapturedFrame(
736 CreateFrame(5, frame_width, frame_height));
737 sink_.WaitForEncodedFrame(5);
738 stats = stats_proxy_->GetStats();
739 EXPECT_TRUE(stats.cpu_limited_resolution);
740 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
741
742 vie_encoder_->TriggerCpuNormalUsage();
743
744 new_video_source.IncomingCapturedFrame(
745 CreateFrame(6, frame_width, frame_height));
746 sink_.WaitForEncodedFrame(6);
747 stats = stats_proxy_->GetStats();
748 EXPECT_FALSE(stats.cpu_limited_resolution);
749 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
750
751 vie_encoder_->Stop();
752}
753
754TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800755 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
756
757 int frame_width = 1280;
758 int frame_height = 720;
759 video_source_.IncomingCapturedFrame(
760 CreateFrame(1, frame_width, frame_height));
761 sink_.WaitForEncodedFrame(1);
762
763 VideoSendStream::Stats stats = stats_proxy_->GetStats();
764 EXPECT_FALSE(stats.cpu_limited_resolution);
765 EXPECT_FALSE(stats.bw_limited_resolution);
766 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
767
768 // Set new source with adaptation still enabled.
769 test::FrameForwarder new_video_source;
770 vie_encoder_->SetSource(&new_video_source,
771 VideoSendStream::DegradationPreference::kBalanced);
772
773 new_video_source.IncomingCapturedFrame(
774 CreateFrame(2, frame_width, frame_height));
775 sink_.WaitForEncodedFrame(2);
776 stats = stats_proxy_->GetStats();
777 EXPECT_FALSE(stats.cpu_limited_resolution);
778 EXPECT_FALSE(stats.bw_limited_resolution);
779 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
780
781 vie_encoder_->TriggerQualityLow();
782
783 new_video_source.IncomingCapturedFrame(
784 CreateFrame(3, frame_width, frame_height));
785 sink_.WaitForEncodedFrame(3);
786 stats = stats_proxy_->GetStats();
787 EXPECT_FALSE(stats.cpu_limited_resolution);
788 EXPECT_TRUE(stats.bw_limited_resolution);
789
790 vie_encoder_->SetSource(&new_video_source,
791 VideoSendStream::DegradationPreference::kBalanced);
792
793 new_video_source.IncomingCapturedFrame(
794 CreateFrame(4, frame_width, frame_height));
795 sink_.WaitForEncodedFrame(4);
796 stats = stats_proxy_->GetStats();
797 EXPECT_FALSE(stats.cpu_limited_resolution);
798 EXPECT_TRUE(stats.bw_limited_resolution);
799
800 // Set adaptation disabled.
801 vie_encoder_->SetSource(
802 &new_video_source,
803 VideoSendStream::DegradationPreference::kMaintainResolution);
804
805 new_video_source.IncomingCapturedFrame(
806 CreateFrame(5, frame_width, frame_height));
807 sink_.WaitForEncodedFrame(5);
808 stats = stats_proxy_->GetStats();
809 EXPECT_FALSE(stats.cpu_limited_resolution);
810 EXPECT_FALSE(stats.bw_limited_resolution);
811
812 vie_encoder_->Stop();
813}
814
perkj803d97f2016-11-01 11:45:46 -0700815TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700816 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
817
818 // Trigger CPU overuse.
819 vie_encoder_->TriggerCpuOveruse();
820 int frame_width = 1280;
821 int frame_height = 720;
822
823 video_source_.IncomingCapturedFrame(
824 CreateFrame(1, frame_width, frame_height));
825 sink_.WaitForEncodedFrame(1);
826
827 VideoSendStream::Stats stats = stats_proxy_->GetStats();
828 EXPECT_TRUE(stats.cpu_limited_resolution);
829 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
830
831 // Set new source with adaptation still enabled.
832 test::FrameForwarder new_video_source;
833 vie_encoder_->SetSource(&new_video_source,
834 VideoSendStream::DegradationPreference::kBalanced);
835
836 new_video_source.IncomingCapturedFrame(
837 CreateFrame(2, frame_width, frame_height));
838 sink_.WaitForEncodedFrame(2);
839 stats = stats_proxy_->GetStats();
840 EXPECT_TRUE(stats.cpu_limited_resolution);
841 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
842
843 // Set adaptation disabled.
844 vie_encoder_->SetSource(
845 &new_video_source,
846 VideoSendStream::DegradationPreference::kMaintainResolution);
847 new_video_source.IncomingCapturedFrame(
848 CreateFrame(3, frame_width, frame_height));
849 sink_.WaitForEncodedFrame(3);
850 stats = stats_proxy_->GetStats();
851 EXPECT_FALSE(stats.cpu_limited_resolution);
852 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
853
854 // Switch back the source with adaptation enabled.
855 vie_encoder_->SetSource(&video_source_,
856 VideoSendStream::DegradationPreference::kBalanced);
857 video_source_.IncomingCapturedFrame(
858 CreateFrame(4, frame_width, frame_height));
859 sink_.WaitForEncodedFrame(4);
860 stats = stats_proxy_->GetStats();
861 EXPECT_TRUE(stats.cpu_limited_resolution);
862 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
863
864 // Trigger CPU normal usage.
865 vie_encoder_->TriggerCpuNormalUsage();
866 video_source_.IncomingCapturedFrame(
867 CreateFrame(5, frame_width, frame_height));
868 sink_.WaitForEncodedFrame(5);
869 stats = stats_proxy_->GetStats();
870 EXPECT_FALSE(stats.cpu_limited_resolution);
871 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
872
873 vie_encoder_->Stop();
874}
875
Erik Språng08127a92016-11-16 16:41:30 +0100876TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100877 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
878
879 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
880 sink_.WaitForEncodedFrame(1);
881
882 VideoSendStream::Stats stats = stats_proxy_->GetStats();
883 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
884 stats.preferred_media_bitrate_bps);
885
886 vie_encoder_->Stop();
887}
888
kthelgason876222f2016-11-29 01:44:11 -0800889TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
kthelgason876222f2016-11-29 01:44:11 -0800890 int frame_width = 1280;
891 int frame_height = 720;
892 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
893
894 // Expect no scaling to begin with
895 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
896 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
897
kthelgason876222f2016-11-29 01:44:11 -0800898 video_source_.IncomingCapturedFrame(
899 CreateFrame(1, frame_width, frame_height));
900 sink_.WaitForEncodedFrame(1);
901
kthelgason5e13d412016-12-01 03:59:51 -0800902 // Trigger scale down
903 vie_encoder_->TriggerQualityLow();
904
905 video_source_.IncomingCapturedFrame(
906 CreateFrame(2, frame_width, frame_height));
907 sink_.WaitForEncodedFrame(2);
908
kthelgason876222f2016-11-29 01:44:11 -0800909 // Expect a scale down.
910 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
911 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
912 frame_width * frame_height);
913
914 // Set adaptation disabled.
915 test::FrameForwarder new_video_source;
916 vie_encoder_->SetSource(
917 &new_video_source,
918 VideoSendStream::DegradationPreference::kMaintainResolution);
919
920 // Trigger scale down
921 vie_encoder_->TriggerQualityLow();
922 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800923 CreateFrame(3, frame_width, frame_height));
924 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -0800925
926 // Expect no scaling
927 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
928
929 // Trigger scale up
930 vie_encoder_->TriggerQualityHigh();
931 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800932 CreateFrame(4, frame_width, frame_height));
933 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -0800934
935 // Expect nothing to change, still no scaling
936 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
937
938 vie_encoder_->Stop();
939}
940
kthelgason5e13d412016-12-01 03:59:51 -0800941TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
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())
kthelgason83399ca2017-02-01 01:31:52 -0800998 .GetAllocation(kLowTargetBitrateBps, 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);
kthelgason83399ca2017-02-01 01:31:52 -08001003 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 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
kthelgason83399ca2017-02-01 01:31:52 -08001032TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
1033 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1034 int frame_width = 640;
1035 int frame_height = 360;
1036
1037 video_source_.IncomingCapturedFrame(
1038 CreateFrame(1, frame_width, frame_height));
1039
1040 // Expect to drop this frame, the wait should time out.
1041 sink_.ExpectDroppedFrame();
1042
1043 // Expect the sink_wants to specify a scaled frame.
1044 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1045 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1046
1047 int last_pixel_count = *video_source_.sink_wants().max_pixel_count;
1048
1049 // Next frame is scaled
1050 video_source_.IncomingCapturedFrame(
1051 CreateFrame(2, frame_width * 3 / 4, frame_height * 3 / 4));
1052
1053 // Expect to drop this frame, the wait should time out.
1054 sink_.ExpectDroppedFrame();
1055
1056 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, last_pixel_count);
1057
1058 vie_encoder_->Stop();
1059}
1060
1061TEST_F(ViEEncoderTest, NrOfDroppedFramesLimited) {
1062 // 1kbps. This can never be achieved.
1063 vie_encoder_->OnBitrateUpdated(1000, 0, 0);
1064 int frame_width = 640;
1065 int frame_height = 360;
1066
1067 // We expect the n initial frames to get dropped.
1068 int i;
1069 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
1070 video_source_.IncomingCapturedFrame(
1071 CreateFrame(i, frame_width, frame_height));
1072 sink_.ExpectDroppedFrame();
1073 }
1074 // The n+1th frame should not be dropped, even though it's size is too large.
1075 video_source_.IncomingCapturedFrame(
1076 CreateFrame(i, frame_width, frame_height));
1077 sink_.WaitForEncodedFrame(i);
1078
1079 // Expect the sink_wants to specify a scaled frame.
1080 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1081 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1082
1083 vie_encoder_->Stop();
1084}
1085
1086TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
1087 int frame_width = 640;
1088 int frame_height = 360;
1089 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1090
1091 // Set degradation preference.
1092 vie_encoder_->SetSource(
1093 &video_source_,
1094 VideoSendStream::DegradationPreference::kMaintainResolution);
1095
1096 video_source_.IncomingCapturedFrame(
1097 CreateFrame(1, frame_width, frame_height));
1098 // Frame should not be dropped, even if it's too large.
1099 sink_.WaitForEncodedFrame(1);
1100
1101 vie_encoder_->Stop();
1102}
1103
perkj26091b12016-09-01 01:17:40 -07001104} // namespace webrtc