blob: 427796ed5eb41afefe9202c0d442a22ae90e7b5c [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"
sprangb1ca0732017-02-01 08:38:12 -080016#include "webrtc/media/base/videoadapter.h"
sprang57c2fff2017-01-16 06:24:02 -080017#include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
perkj803d97f2016-11-01 11:45:46 -070018#include "webrtc/system_wrappers/include/metrics_default.h"
sprang57c2fff2017-01-16 06:24:02 -080019#include "webrtc/system_wrappers/include/sleep.h"
perkj26091b12016-09-01 01:17:40 -070020#include "webrtc/test/encoder_settings.h"
21#include "webrtc/test/fake_encoder.h"
perkja49cbd32016-09-16 07:53:41 -070022#include "webrtc/test/frame_generator.h"
sprang57c2fff2017-01-16 06:24:02 -080023#include "webrtc/test/gmock.h"
kwibergac9f8762016-09-30 22:29:43 -070024#include "webrtc/test/gtest.h"
perkj26091b12016-09-01 01:17:40 -070025#include "webrtc/video/send_statistics_proxy.h"
26#include "webrtc/video/vie_encoder.h"
27
kthelgason33ce8892016-12-09 03:53:59 -080028namespace {
29#if defined(WEBRTC_ANDROID)
30// TODO(kthelgason): Lower this limit when better testing
31// on MediaCodec and fallback implementations are in place.
32const int kMinPixelsPerFrame = 320 * 180;
33#else
34const int kMinPixelsPerFrame = 120 * 90;
35#endif
36}
37
perkj26091b12016-09-01 01:17:40 -070038namespace webrtc {
39
kthelgason876222f2016-11-29 01:44:11 -080040using DegredationPreference = VideoSendStream::DegradationPreference;
sprangb1ca0732017-02-01 08:38:12 -080041using ScaleReason = AdaptationObserverInterface::AdaptReason;
sprang57c2fff2017-01-16 06:24:02 -080042using ::testing::_;
43using ::testing::Return;
kthelgason876222f2016-11-29 01:44:11 -080044
perkj803d97f2016-11-01 11:45:46 -070045namespace {
asapersson5f7226f2016-11-25 04:37:00 -080046const size_t kMaxPayloadLength = 1440;
minyue35fc2aa2017-02-01 03:14:00 -080047const int kTargetBitrateBps = 100000;
asapersson5f7226f2016-11-25 04:37:00 -080048
perkj803d97f2016-11-01 11:45:46 -070049class TestBuffer : public webrtc::I420Buffer {
50 public:
51 TestBuffer(rtc::Event* event, int width, int height)
52 : I420Buffer(width, height), event_(event) {}
53
54 private:
55 friend class rtc::RefCountedObject<TestBuffer>;
56 ~TestBuffer() override {
57 if (event_)
58 event_->Set();
59 }
60 rtc::Event* const event_;
61};
62
63class ViEEncoderUnderTest : public ViEEncoder {
64 public:
kthelgason876222f2016-11-29 01:44:11 -080065 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
66 const VideoSendStream::Config::EncoderSettings& settings)
perkj803d97f2016-11-01 11:45:46 -070067 : ViEEncoder(1 /* number_of_cores */,
68 stats_proxy,
69 settings,
70 nullptr /* pre_encode_callback */,
71 nullptr /* encoder_timing */) {}
72
sprangb1ca0732017-02-01 08:38:12 -080073 void PostTaskAndWait(bool down, AdaptReason reason) {
perkj803d97f2016-11-01 11:45:46 -070074 rtc::Event event(false, false);
kthelgason876222f2016-11-29 01:44:11 -080075 encoder_queue()->PostTask([this, &event, reason, down] {
sprangb1ca0732017-02-01 08:38:12 -080076 down ? AdaptDown(reason) : AdaptUp(reason);
perkj803d97f2016-11-01 11:45:46 -070077 event.Set();
78 });
kthelgason876222f2016-11-29 01:44:11 -080079 RTC_DCHECK(event.Wait(5000));
perkj803d97f2016-11-01 11:45:46 -070080 }
81
sprangb1ca0732017-02-01 08:38:12 -080082 void TriggerCpuOveruse() { PostTaskAndWait(true, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080083
sprangb1ca0732017-02-01 08:38:12 -080084 void TriggerCpuNormalUsage() { PostTaskAndWait(false, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080085
sprangb1ca0732017-02-01 08:38:12 -080086 void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); }
kthelgason876222f2016-11-29 01:44:11 -080087
sprangb1ca0732017-02-01 08:38:12 -080088 void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); }
perkj803d97f2016-11-01 11:45:46 -070089};
90
asapersson5f7226f2016-11-25 04:37:00 -080091class VideoStreamFactory
92 : public VideoEncoderConfig::VideoStreamFactoryInterface {
93 public:
94 explicit VideoStreamFactory(size_t num_temporal_layers)
95 : num_temporal_layers_(num_temporal_layers) {
96 EXPECT_GT(num_temporal_layers, 0u);
97 }
98
99 private:
100 std::vector<VideoStream> CreateEncoderStreams(
101 int width,
102 int height,
103 const VideoEncoderConfig& encoder_config) override {
104 std::vector<VideoStream> streams =
105 test::CreateVideoStreams(width, height, encoder_config);
106 for (VideoStream& stream : streams) {
107 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
108 }
109 return streams;
110 }
111 const size_t num_temporal_layers_;
112};
113
sprangb1ca0732017-02-01 08:38:12 -0800114class AdaptingFrameForwarder : public test::FrameForwarder {
115 public:
116 AdaptingFrameForwarder() : adaptation_enabled_(false) {}
117 virtual ~AdaptingFrameForwarder() {}
118
119 void set_adaptation_enabled(bool enabled) {
120 rtc::CritScope cs(&crit_);
121 adaptation_enabled_ = enabled;
122 }
123
124 bool adaption_enabled() {
125 rtc::CritScope cs(&crit_);
126 return adaptation_enabled_;
127 }
128
129 void IncomingCapturedFrame(const VideoFrame& video_frame) override {
130 int cropped_width = 0;
131 int cropped_height = 0;
132 int out_width = 0;
133 int out_height = 0;
134 if (adaption_enabled() &&
135 adapter_.AdaptFrameResolution(video_frame.width(), video_frame.height(),
136 video_frame.timestamp_us() * 1000,
137 &cropped_width, &cropped_height,
138 &out_width, &out_height)) {
139 VideoFrame adapted_frame(
140 new rtc::RefCountedObject<TestBuffer>(nullptr, out_width, out_height),
141 99, 99, kVideoRotation_0);
142 adapted_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
143 test::FrameForwarder::IncomingCapturedFrame(adapted_frame);
144 } else {
145 test::FrameForwarder::IncomingCapturedFrame(video_frame);
146 }
147 }
148
149 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
150 const rtc::VideoSinkWants& wants) override {
151 rtc::CritScope cs(&crit_);
152 adapter_.OnResolutionRequest(wants.max_pixel_count,
153 wants.max_pixel_count_step_up);
154 test::FrameForwarder::AddOrUpdateSink(sink, wants);
155 }
156
157 cricket::VideoAdapter adapter_;
158 bool adaptation_enabled_ GUARDED_BY(crit_);
159};
perkj803d97f2016-11-01 11:45:46 -0700160} // namespace
161
perkj26091b12016-09-01 01:17:40 -0700162class ViEEncoderTest : public ::testing::Test {
163 public:
164 static const int kDefaultTimeoutMs = 30 * 1000;
165
166 ViEEncoderTest()
167 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -0700168 codec_width_(320),
169 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -0700170 fake_encoder_(),
perkj803d97f2016-11-01 11:45:46 -0700171 stats_proxy_(new SendStatisticsProxy(
172 Clock::GetRealTimeClock(),
173 video_send_config_,
174 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -0700175 sink_(&fake_encoder_) {}
176
177 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -0700178 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -0700179 video_send_config_ = VideoSendStream::Config(nullptr);
180 video_send_config_.encoder_settings.encoder = &fake_encoder_;
181 video_send_config_.encoder_settings.payload_name = "FAKE";
182 video_send_config_.encoder_settings.payload_type = 125;
183
Per512ecb32016-09-23 15:52:06 +0200184 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700185 test::FillEncoderConfiguration(1, &video_encoder_config);
Erik Språng08127a92016-11-16 16:41:30 +0100186 video_encoder_config_ = video_encoder_config.Copy();
asapersson5f7226f2016-11-25 04:37:00 -0800187 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
188 }
189
190 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
191 bool nack_enabled) {
192 if (vie_encoder_)
193 vie_encoder_->Stop();
perkj803d97f2016-11-01 11:45:46 -0700194 vie_encoder_.reset(new ViEEncoderUnderTest(
195 stats_proxy_.get(), video_send_config_.encoder_settings));
196 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
197 vie_encoder_->SetSource(&video_source_,
198 VideoSendStream::DegradationPreference::kBalanced);
minyue35fc2aa2017-02-01 03:14:00 -0800199 vie_encoder_->SetStartBitrate(10000);
asapersson5f7226f2016-11-25 04:37:00 -0800200 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
201 kMaxPayloadLength, nack_enabled);
202 }
203
204 void ResetEncoder(const std::string& payload_name,
205 size_t num_streams,
206 size_t num_temporal_layers,
207 bool nack_enabled) {
208 video_send_config_.encoder_settings.payload_name = payload_name;
209
210 VideoEncoderConfig video_encoder_config;
211 video_encoder_config.number_of_streams = num_streams;
minyue35fc2aa2017-02-01 03:14:00 -0800212 video_encoder_config.max_bitrate_bps = 1000000;
asapersson5f7226f2016-11-25 04:37:00 -0800213 video_encoder_config.video_stream_factory =
214 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
215 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
perkj26091b12016-09-01 01:17:40 -0700216 }
217
sprang57c2fff2017-01-16 06:24:02 -0800218 VideoFrame CreateFrame(int64_t ntp_time_ms,
219 rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200220 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
221 destruction_event, codec_width_, codec_height_),
222 99, 99, kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800223 frame.set_ntp_time_ms(ntp_time_ms);
perkj26091b12016-09-01 01:17:40 -0700224 return frame;
225 }
226
sprang57c2fff2017-01-16 06:24:02 -0800227 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
perkj803d97f2016-11-01 11:45:46 -0700228 VideoFrame frame(
229 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
230 kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800231 frame.set_ntp_time_ms(ntp_time_ms);
perkj803d97f2016-11-01 11:45:46 -0700232 return frame;
233 }
234
perkj26091b12016-09-01 01:17:40 -0700235 class TestEncoder : public test::FakeEncoder {
236 public:
237 TestEncoder()
238 : FakeEncoder(Clock::GetRealTimeClock()),
239 continue_encode_event_(false, false) {}
240
perkjfa10b552016-10-02 23:45:26 -0700241 VideoCodec codec_config() {
brandtre78d2662017-01-16 05:57:16 -0800242 rtc::CritScope lock(&crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700243 return config_;
244 }
245
246 void BlockNextEncode() {
brandtre78d2662017-01-16 05:57:16 -0800247 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700248 block_next_encode_ = true;
249 }
250
kthelgason876222f2016-11-29 01:44:11 -0800251 VideoEncoder::ScalingSettings GetScalingSettings() const override {
252 return VideoEncoder::ScalingSettings(true, 1, 2);
253 }
254
perkjfa10b552016-10-02 23:45:26 -0700255 void ContinueEncode() { continue_encode_event_.Set(); }
256
257 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
258 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800259 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700260 EXPECT_EQ(timestamp_, timestamp);
261 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
262 }
263
264 private:
perkj26091b12016-09-01 01:17:40 -0700265 int32_t Encode(const VideoFrame& input_image,
266 const CodecSpecificInfo* codec_specific_info,
267 const std::vector<FrameType>* frame_types) override {
268 bool block_encode;
269 {
brandtre78d2662017-01-16 05:57:16 -0800270 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700271 EXPECT_GT(input_image.timestamp(), timestamp_);
272 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
273 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
274
275 timestamp_ = input_image.timestamp();
276 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700277 last_input_width_ = input_image.width();
278 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700279 block_encode = block_next_encode_;
280 block_next_encode_ = false;
281 }
282 int32_t result =
283 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
284 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700285 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700286 return result;
287 }
288
brandtre78d2662017-01-16 05:57:16 -0800289 rtc::CriticalSection local_crit_sect_;
perkj26091b12016-09-01 01:17:40 -0700290 bool block_next_encode_ = false;
291 rtc::Event continue_encode_event_;
292 uint32_t timestamp_ = 0;
293 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700294 int last_input_width_ = 0;
295 int last_input_height_ = 0;
perkj26091b12016-09-01 01:17:40 -0700296 };
297
Per512ecb32016-09-23 15:52:06 +0200298 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700299 public:
300 explicit TestSink(TestEncoder* test_encoder)
301 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
302
perkj26091b12016-09-01 01:17:40 -0700303 void WaitForEncodedFrame(int64_t expected_ntp_time) {
304 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700305 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700306 {
307 rtc::CritScope lock(&crit_);
sprangb1ca0732017-02-01 08:38:12 -0800308 timestamp = last_timestamp_;
perkj26091b12016-09-01 01:17:40 -0700309 }
310 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
311 }
312
sprangb1ca0732017-02-01 08:38:12 -0800313 void WaitForEncodedFrame(uint32_t expected_width,
314 uint32_t expected_height) {
315 uint32_t width = 0;
316 uint32_t height = 0;
317 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
318 {
319 rtc::CritScope lock(&crit_);
320 width = last_width_;
321 height = last_height_;
322 }
323 EXPECT_EQ(expected_height, height);
324 EXPECT_EQ(expected_width, width);
325 }
326
perkj26091b12016-09-01 01:17:40 -0700327 void SetExpectNoFrames() {
328 rtc::CritScope lock(&crit_);
329 expect_frames_ = false;
330 }
331
Per512ecb32016-09-23 15:52:06 +0200332 int number_of_reconfigurations() {
333 rtc::CritScope lock(&crit_);
334 return number_of_reconfigurations_;
335 }
336
337 int last_min_transmit_bitrate() {
338 rtc::CritScope lock(&crit_);
339 return min_transmit_bitrate_bps_;
340 }
341
perkj26091b12016-09-01 01:17:40 -0700342 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700343 Result OnEncodedImage(
344 const EncodedImage& encoded_image,
345 const CodecSpecificInfo* codec_specific_info,
346 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200347 rtc::CritScope lock(&crit_);
348 EXPECT_TRUE(expect_frames_);
sprangb1ca0732017-02-01 08:38:12 -0800349 last_timestamp_ = encoded_image._timeStamp;
350 last_width_ = encoded_image._encodedWidth;
351 last_height_ = encoded_image._encodedHeight;
Per512ecb32016-09-23 15:52:06 +0200352 encoded_frame_event_.Set();
sprangb1ca0732017-02-01 08:38:12 -0800353 return Result(Result::OK, last_timestamp_);
Per512ecb32016-09-23 15:52:06 +0200354 }
355
356 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
357 int min_transmit_bitrate_bps) override {
358 rtc::CriticalSection crit_;
359 ++number_of_reconfigurations_;
360 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
361 }
362
perkj26091b12016-09-01 01:17:40 -0700363 rtc::CriticalSection crit_;
364 TestEncoder* test_encoder_;
365 rtc::Event encoded_frame_event_;
sprangb1ca0732017-02-01 08:38:12 -0800366 uint32_t last_timestamp_ = 0;
367 uint32_t last_height_ = 0;
368 uint32_t last_width_ = 0;
perkj26091b12016-09-01 01:17:40 -0700369 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200370 int number_of_reconfigurations_ = 0;
371 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700372 };
373
374 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100375 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200376 int codec_width_;
377 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700378 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700379 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700380 TestSink sink_;
sprangb1ca0732017-02-01 08:38:12 -0800381 AdaptingFrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700382 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700383};
384
385TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700386 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
387 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700388 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700389 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700390 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700391 vie_encoder_->Stop();
392}
393
394TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
395 // Dropped since no target bitrate has been set.
396 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700397 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
398 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700399
perkj26091b12016-09-01 01:17:40 -0700400 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
401
perkja49cbd32016-09-16 07:53:41 -0700402 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700403 sink_.WaitForEncodedFrame(2);
404 vie_encoder_->Stop();
405}
406
407TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700408 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700409 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700410 sink_.WaitForEncodedFrame(1);
411
412 vie_encoder_->OnBitrateUpdated(0, 0, 0);
413 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700414 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700415
416 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700417 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700418 sink_.WaitForEncodedFrame(3);
419 vie_encoder_->Stop();
420}
421
422TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700423 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700424 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700425 sink_.WaitForEncodedFrame(1);
426
427 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700428 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700429
perkja49cbd32016-09-16 07:53:41 -0700430 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700431 sink_.WaitForEncodedFrame(2);
432 vie_encoder_->Stop();
433}
434
435TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700436 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
437
perkja49cbd32016-09-16 07:53:41 -0700438 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700439 sink_.WaitForEncodedFrame(1);
440
441 vie_encoder_->Stop();
442 sink_.SetExpectNoFrames();
443 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700444 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
445 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700446}
447
448TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700449 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
450
451 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700452 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700453 sink_.WaitForEncodedFrame(1);
454 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
455 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700456 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
457 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700458 fake_encoder_.ContinueEncode();
459 sink_.WaitForEncodedFrame(3);
460
461 vie_encoder_->Stop();
462}
463
Per512ecb32016-09-23 15:52:06 +0200464TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200465 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100466 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200467
468 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200469 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200470 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100471 // The encoder will have been configured once when the first frame is
472 // received.
473 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200474
475 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700476 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200477 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800478 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
479 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200480
481 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200482 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200483 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100484 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700485 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700486
487 vie_encoder_->Stop();
488}
489
perkjfa10b552016-10-02 23:45:26 -0700490TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700491 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
492
493 // Capture a frame and wait for it to synchronize with the encoder thread.
494 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
495 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100496 // The encoder will have been configured once.
497 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700498 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
499 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
500
501 codec_width_ *= 2;
502 codec_height_ *= 2;
503 // Capture a frame with a higher resolution and wait for it to synchronize
504 // with the encoder thread.
505 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
506 sink_.WaitForEncodedFrame(2);
507 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
508 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100509 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700510
511 vie_encoder_->Stop();
512}
513
asapersson5f7226f2016-11-25 04:37:00 -0800514TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
515 const bool kNackEnabled = true;
516 const size_t kNumStreams = 1;
517 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800518 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800519 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
520
521 // Capture a frame and wait for it to synchronize with the encoder thread.
522 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
523 sink_.WaitForEncodedFrame(1);
524 // The encoder have been configured once when the first frame is received.
525 EXPECT_EQ(1, sink_.number_of_reconfigurations());
526 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
527 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
528 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
529 // Resilience is off for no temporal layers with nack on.
530 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
531 vie_encoder_->Stop();
532}
533
534TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
535 const bool kNackEnabled = true;
536 const size_t kNumStreams = 2;
537 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800538 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800539 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
540
541 // Capture a frame and wait for it to synchronize with the encoder thread.
542 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
543 sink_.WaitForEncodedFrame(1);
544 // The encoder have been configured once when the first frame is received.
545 EXPECT_EQ(1, sink_.number_of_reconfigurations());
546 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
547 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
548 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
549 // Resilience is off for no temporal layers and >1 streams with nack on.
550 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
551 vie_encoder_->Stop();
552}
553
554TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
555 const bool kNackEnabled = false;
556 const size_t kNumStreams = 1;
557 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800558 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800559 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
560
561 // Capture a frame and wait for it to synchronize with the encoder thread.
562 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
563 sink_.WaitForEncodedFrame(1);
564 // The encoder have been configured once when the first frame is received.
565 EXPECT_EQ(1, sink_.number_of_reconfigurations());
566 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
567 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
568 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
569 // Resilience is on for no temporal layers with nack off.
570 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
571 vie_encoder_->Stop();
572}
573
574TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
575 const bool kNackEnabled = true;
576 const size_t kNumStreams = 1;
577 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800578 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800579 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
580
581 // Capture a frame and wait for it to synchronize with the encoder thread.
582 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
583 sink_.WaitForEncodedFrame(1);
584 // The encoder have been configured once when the first frame is received.
585 EXPECT_EQ(1, sink_.number_of_reconfigurations());
586 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
587 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
588 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
589 // Resilience is on for temporal layers.
590 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
591 vie_encoder_->Stop();
592}
593
perkj803d97f2016-11-01 11:45:46 -0700594TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
595 EXPECT_TRUE(video_source_.has_sinks());
596 test::FrameForwarder new_video_source;
597 vie_encoder_->SetSource(&new_video_source,
598 VideoSendStream::DegradationPreference::kBalanced);
599 EXPECT_FALSE(video_source_.has_sinks());
600 EXPECT_TRUE(new_video_source.has_sinks());
601
602 vie_encoder_->Stop();
603}
604
605TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
606 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
607 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
608 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
609 vie_encoder_->Stop();
610}
611
612TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700613 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
614
615 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
616 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
617
618 int frame_width = 1280;
619 int frame_height = 720;
620
621 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
622 // request lower resolution.
623 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
624 video_source_.IncomingCapturedFrame(
625 CreateFrame(i, frame_width, frame_height));
626 sink_.WaitForEncodedFrame(i);
627
628 vie_encoder_->TriggerCpuOveruse();
629
630 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
631 std::numeric_limits<int>::max()),
632 frame_width * frame_height);
633 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
634
635 frame_width /= 2;
636 frame_height /= 2;
637 }
638
kthelgason876222f2016-11-29 01:44:11 -0800639 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700640 // lower resolution.
641 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
642 video_source_.IncomingCapturedFrame(CreateFrame(
643 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
644 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
645 vie_encoder_->TriggerCpuOveruse();
646 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
647 current_wants.max_pixel_count);
648 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up,
649 current_wants.max_pixel_count_step_up);
650
651 // Trigger CPU normal use.
652 vie_encoder_->TriggerCpuNormalUsage();
653 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
654 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0),
655 frame_width * frame_height);
656
657 vie_encoder_->Stop();
658}
659
660TEST_F(ViEEncoderTest,
661 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700662 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
663
664 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
665 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
666
667 int frame_width = 1280;
668 int frame_height = 720;
669
kthelgason5e13d412016-12-01 03:59:51 -0800670 video_source_.IncomingCapturedFrame(
671 CreateFrame(1, frame_width, frame_height));
672 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700673 // Trigger CPU overuse.
674 vie_encoder_->TriggerCpuOveruse();
675
676 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800677 CreateFrame(2, frame_width, frame_height));
678 sink_.WaitForEncodedFrame(2);
perkj803d97f2016-11-01 11:45:46 -0700679 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
680 std::numeric_limits<int>::max()),
681 frame_width * frame_height);
682 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
683
684 // Set new source.
685 test::FrameForwarder new_video_source;
686 vie_encoder_->SetSource(
687 &new_video_source,
688 VideoSendStream::DegradationPreference::kMaintainResolution);
689
690 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
691 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
692
693 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800694 CreateFrame(3, frame_width, frame_height));
695 sink_.WaitForEncodedFrame(3);
perkj803d97f2016-11-01 11:45:46 -0700696 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
697 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
698
699 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
700 vie_encoder_->SetSource(&new_video_source,
701 VideoSendStream::DegradationPreference::kBalanced);
702 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
703 std::numeric_limits<int>::max()),
704 frame_width * frame_height);
705 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
706
707 vie_encoder_->Stop();
708}
709
710TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700711 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
712
713 int frame_width = 1280;
714 int frame_height = 720;
715
716 video_source_.IncomingCapturedFrame(
717 CreateFrame(1, frame_width, frame_height));
718 sink_.WaitForEncodedFrame(1);
719 VideoSendStream::Stats stats = stats_proxy_->GetStats();
720 EXPECT_FALSE(stats.cpu_limited_resolution);
721 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
722
723 // Trigger CPU overuse.
724 vie_encoder_->TriggerCpuOveruse();
725 video_source_.IncomingCapturedFrame(
726 CreateFrame(2, frame_width, frame_height));
727 sink_.WaitForEncodedFrame(2);
728
729 stats = stats_proxy_->GetStats();
730 EXPECT_TRUE(stats.cpu_limited_resolution);
731 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
732
733 // Trigger CPU normal use.
734 vie_encoder_->TriggerCpuNormalUsage();
735 video_source_.IncomingCapturedFrame(
736 CreateFrame(3, frame_width, frame_height));
737 sink_.WaitForEncodedFrame(3);
738
739 stats = stats_proxy_->GetStats();
740 EXPECT_FALSE(stats.cpu_limited_resolution);
741 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
742
743 vie_encoder_->Stop();
744}
745
kthelgason876222f2016-11-29 01:44:11 -0800746TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
minyue35fc2aa2017-02-01 03:14:00 -0800747 const int kTargetBitrateBps = 100000;
kthelgason876222f2016-11-29 01:44:11 -0800748 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
749
750 int frame_width = 1280;
751 int frame_height = 720;
752 video_source_.IncomingCapturedFrame(
753 CreateFrame(1, frame_width, frame_height));
754 sink_.WaitForEncodedFrame(1);
755
756 VideoSendStream::Stats stats = stats_proxy_->GetStats();
757 EXPECT_FALSE(stats.cpu_limited_resolution);
758 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
759
760 vie_encoder_->TriggerCpuOveruse();
761
762 video_source_.IncomingCapturedFrame(
763 CreateFrame(2, frame_width, frame_height));
764 sink_.WaitForEncodedFrame(2);
765 stats = stats_proxy_->GetStats();
766 EXPECT_TRUE(stats.cpu_limited_resolution);
767 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
768
769 // Set new source with adaptation still enabled.
770 test::FrameForwarder new_video_source;
771 vie_encoder_->SetSource(&new_video_source,
772 VideoSendStream::DegradationPreference::kBalanced);
773
774 new_video_source.IncomingCapturedFrame(
775 CreateFrame(3, frame_width, frame_height));
776 sink_.WaitForEncodedFrame(3);
777 stats = stats_proxy_->GetStats();
778 EXPECT_TRUE(stats.cpu_limited_resolution);
779 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
780
781 // Set adaptation disabled.
782 vie_encoder_->SetSource(
783 &new_video_source,
784 VideoSendStream::DegradationPreference::kMaintainResolution);
785
786 new_video_source.IncomingCapturedFrame(
787 CreateFrame(4, frame_width, frame_height));
788 sink_.WaitForEncodedFrame(4);
789 stats = stats_proxy_->GetStats();
790 EXPECT_FALSE(stats.cpu_limited_resolution);
791 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
792
793 // Set adaptation back to enabled.
794 vie_encoder_->SetSource(&new_video_source,
795 VideoSendStream::DegradationPreference::kBalanced);
796
797 new_video_source.IncomingCapturedFrame(
798 CreateFrame(5, frame_width, frame_height));
799 sink_.WaitForEncodedFrame(5);
800 stats = stats_proxy_->GetStats();
801 EXPECT_TRUE(stats.cpu_limited_resolution);
802 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
803
804 vie_encoder_->TriggerCpuNormalUsage();
805
806 new_video_source.IncomingCapturedFrame(
807 CreateFrame(6, frame_width, frame_height));
808 sink_.WaitForEncodedFrame(6);
809 stats = stats_proxy_->GetStats();
810 EXPECT_FALSE(stats.cpu_limited_resolution);
811 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
812
813 vie_encoder_->Stop();
814}
815
816TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
minyue35fc2aa2017-02-01 03:14:00 -0800817 const int kTargetBitrateBps = 100000;
kthelgason876222f2016-11-29 01:44:11 -0800818 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
819
820 int frame_width = 1280;
821 int frame_height = 720;
822 video_source_.IncomingCapturedFrame(
823 CreateFrame(1, frame_width, frame_height));
824 sink_.WaitForEncodedFrame(1);
825
826 VideoSendStream::Stats stats = stats_proxy_->GetStats();
827 EXPECT_FALSE(stats.cpu_limited_resolution);
828 EXPECT_FALSE(stats.bw_limited_resolution);
829 EXPECT_EQ(0, 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_FALSE(stats.cpu_limited_resolution);
841 EXPECT_FALSE(stats.bw_limited_resolution);
842 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
843
844 vie_encoder_->TriggerQualityLow();
845
846 new_video_source.IncomingCapturedFrame(
847 CreateFrame(3, frame_width, frame_height));
848 sink_.WaitForEncodedFrame(3);
849 stats = stats_proxy_->GetStats();
850 EXPECT_FALSE(stats.cpu_limited_resolution);
851 EXPECT_TRUE(stats.bw_limited_resolution);
852
853 vie_encoder_->SetSource(&new_video_source,
854 VideoSendStream::DegradationPreference::kBalanced);
855
856 new_video_source.IncomingCapturedFrame(
857 CreateFrame(4, frame_width, frame_height));
858 sink_.WaitForEncodedFrame(4);
859 stats = stats_proxy_->GetStats();
860 EXPECT_FALSE(stats.cpu_limited_resolution);
861 EXPECT_TRUE(stats.bw_limited_resolution);
862
863 // Set adaptation disabled.
864 vie_encoder_->SetSource(
865 &new_video_source,
866 VideoSendStream::DegradationPreference::kMaintainResolution);
867
868 new_video_source.IncomingCapturedFrame(
869 CreateFrame(5, frame_width, frame_height));
870 sink_.WaitForEncodedFrame(5);
871 stats = stats_proxy_->GetStats();
872 EXPECT_FALSE(stats.cpu_limited_resolution);
873 EXPECT_FALSE(stats.bw_limited_resolution);
874
875 vie_encoder_->Stop();
876}
877
perkj803d97f2016-11-01 11:45:46 -0700878TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700879 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
880
881 // Trigger CPU overuse.
882 vie_encoder_->TriggerCpuOveruse();
883 int frame_width = 1280;
884 int frame_height = 720;
885
886 video_source_.IncomingCapturedFrame(
887 CreateFrame(1, frame_width, frame_height));
888 sink_.WaitForEncodedFrame(1);
889
890 VideoSendStream::Stats stats = stats_proxy_->GetStats();
891 EXPECT_TRUE(stats.cpu_limited_resolution);
892 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
893
894 // Set new source with adaptation still enabled.
895 test::FrameForwarder new_video_source;
896 vie_encoder_->SetSource(&new_video_source,
897 VideoSendStream::DegradationPreference::kBalanced);
898
899 new_video_source.IncomingCapturedFrame(
900 CreateFrame(2, frame_width, frame_height));
901 sink_.WaitForEncodedFrame(2);
902 stats = stats_proxy_->GetStats();
903 EXPECT_TRUE(stats.cpu_limited_resolution);
904 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
905
906 // Set adaptation disabled.
907 vie_encoder_->SetSource(
908 &new_video_source,
909 VideoSendStream::DegradationPreference::kMaintainResolution);
910 new_video_source.IncomingCapturedFrame(
911 CreateFrame(3, frame_width, frame_height));
912 sink_.WaitForEncodedFrame(3);
913 stats = stats_proxy_->GetStats();
914 EXPECT_FALSE(stats.cpu_limited_resolution);
915 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
916
917 // Switch back the source with adaptation enabled.
918 vie_encoder_->SetSource(&video_source_,
919 VideoSendStream::DegradationPreference::kBalanced);
920 video_source_.IncomingCapturedFrame(
921 CreateFrame(4, frame_width, frame_height));
922 sink_.WaitForEncodedFrame(4);
923 stats = stats_proxy_->GetStats();
924 EXPECT_TRUE(stats.cpu_limited_resolution);
925 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
926
927 // Trigger CPU normal usage.
928 vie_encoder_->TriggerCpuNormalUsage();
929 video_source_.IncomingCapturedFrame(
930 CreateFrame(5, frame_width, frame_height));
931 sink_.WaitForEncodedFrame(5);
932 stats = stats_proxy_->GetStats();
933 EXPECT_FALSE(stats.cpu_limited_resolution);
934 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
935
936 vie_encoder_->Stop();
937}
938
Erik Språng08127a92016-11-16 16:41:30 +0100939TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100940 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
941
942 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
943 sink_.WaitForEncodedFrame(1);
944
945 VideoSendStream::Stats stats = stats_proxy_->GetStats();
946 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
947 stats.preferred_media_bitrate_bps);
948
949 vie_encoder_->Stop();
950}
951
kthelgason876222f2016-11-29 01:44:11 -0800952TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
minyue35fc2aa2017-02-01 03:14:00 -0800953 const int kTargetBitrateBps = 100000;
kthelgason876222f2016-11-29 01:44:11 -0800954 int frame_width = 1280;
955 int frame_height = 720;
956 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
957
958 // Expect no scaling to begin with
959 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
960 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
961
kthelgason876222f2016-11-29 01:44:11 -0800962 video_source_.IncomingCapturedFrame(
963 CreateFrame(1, frame_width, frame_height));
964 sink_.WaitForEncodedFrame(1);
965
kthelgason5e13d412016-12-01 03:59:51 -0800966 // Trigger scale down
967 vie_encoder_->TriggerQualityLow();
968
969 video_source_.IncomingCapturedFrame(
970 CreateFrame(2, frame_width, frame_height));
971 sink_.WaitForEncodedFrame(2);
972
kthelgason876222f2016-11-29 01:44:11 -0800973 // Expect a scale down.
974 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
975 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
976 frame_width * frame_height);
977
978 // Set adaptation disabled.
979 test::FrameForwarder new_video_source;
980 vie_encoder_->SetSource(
981 &new_video_source,
982 VideoSendStream::DegradationPreference::kMaintainResolution);
983
984 // Trigger scale down
985 vie_encoder_->TriggerQualityLow();
986 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800987 CreateFrame(3, frame_width, frame_height));
988 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -0800989
990 // Expect no scaling
991 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
992
993 // Trigger scale up
994 vie_encoder_->TriggerQualityHigh();
995 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800996 CreateFrame(4, frame_width, frame_height));
997 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -0800998
999 // Expect nothing to change, still no scaling
1000 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1001
1002 vie_encoder_->Stop();
1003}
1004
kthelgason5e13d412016-12-01 03:59:51 -08001005TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
minyue35fc2aa2017-02-01 03:14:00 -08001006 const int kTargetBitrateBps = 100000;
kthelgason5e13d412016-12-01 03:59:51 -08001007 int frame_width = 1280;
1008 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -08001009 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1010
1011 for (size_t i = 1; i <= 10; i++) {
1012 video_source_.IncomingCapturedFrame(
1013 CreateFrame(i, frame_width, frame_height));
1014 sink_.WaitForEncodedFrame(i);
1015 // Trigger scale down
1016 vie_encoder_->TriggerQualityLow();
1017 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
1018 }
1019
1020 vie_encoder_->Stop();
1021}
1022
perkj803d97f2016-11-01 11:45:46 -07001023TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -07001024 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1025
1026 int frame_width = 640;
1027 int frame_height = 360;
1028
1029 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1030 video_source_.IncomingCapturedFrame(
1031 CreateFrame(i, frame_width, frame_height));
1032 sink_.WaitForEncodedFrame(i);
1033 }
1034
1035 vie_encoder_->TriggerCpuOveruse();
1036 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1037 video_source_.IncomingCapturedFrame(
1038 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
1039 frame_width, frame_height));
1040 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
1041 i);
1042 }
1043
1044 vie_encoder_->Stop();
1045
1046 stats_proxy_.reset();
1047 EXPECT_EQ(1,
1048 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1049 EXPECT_EQ(
1050 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1051}
1052
sprang57c2fff2017-01-16 06:24:02 -08001053TEST_F(ViEEncoderTest, CallsBitrateObserver) {
1054 class MockBitrateObserver : public VideoBitrateAllocationObserver {
1055 public:
1056 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
1057 } bitrate_observer;
1058 vie_encoder_->SetBitrateObserver(&bitrate_observer);
1059
1060 const int kDefaultFps = 30;
1061 const BitrateAllocation expected_bitrate =
1062 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
minyue35fc2aa2017-02-01 03:14:00 -08001063 .GetAllocation(kTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -08001064
1065 // First called on bitrate updated, then again on first frame.
1066 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1067 .Times(2);
minyue35fc2aa2017-02-01 03:14:00 -08001068 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001069
1070 const int64_t kStartTimeMs = 1;
1071 video_source_.IncomingCapturedFrame(
1072 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1073 sink_.WaitForEncodedFrame(kStartTimeMs);
1074
1075 // Not called on second frame.
1076 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1077 .Times(0);
1078 video_source_.IncomingCapturedFrame(
1079 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1080 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1081
1082 // Called after a process interval.
1083 const int64_t kProcessIntervalMs =
1084 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1085 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1086 // Sleep for one processing interval plus one frame to avoid flakiness.
1087 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1088 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1089 .Times(1);
1090 video_source_.IncomingCapturedFrame(CreateFrame(
1091 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1092 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1093
1094 vie_encoder_->Stop();
1095}
1096
sprangb1ca0732017-02-01 08:38:12 -08001097// TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
1098TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) {
1099 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1100
1101 const int kFrameWidth = 1280;
1102 const int kFrameHeight = 720;
1103 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
1104 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
1105 video_source_.set_adaptation_enabled(true);
1106
1107 video_source_.IncomingCapturedFrame(
1108 CreateFrame(1, kFrameWidth, kFrameHeight));
1109 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1110
1111 // Trigger CPU overuse, downscale by 3/4.
1112 vie_encoder_->TriggerCpuOveruse();
1113 video_source_.IncomingCapturedFrame(
1114 CreateFrame(2, kFrameWidth, kFrameHeight));
1115 sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
1116
1117 // Trigger CPU normal use, return to original resoluton;
1118 vie_encoder_->TriggerCpuNormalUsage();
1119 video_source_.IncomingCapturedFrame(
1120 CreateFrame(3, kFrameWidth, kFrameHeight));
1121 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1122
1123 vie_encoder_->Stop();
1124}
perkj26091b12016-09-01 01:17:40 -07001125} // namespace webrtc