blob: 2c5609756dd6f02b9c862a735ad178a4d25d86d4 [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;
kthelgason2bc68642017-02-07 07:02:22 -080047const int kTargetBitrateBps = 1000000;
48const int kLowTargetBitrateBps = kTargetBitrateBps / 10;
49const int kMaxInitialFramedrop = 4;
asapersson5f7226f2016-11-25 04:37:00 -080050
perkj803d97f2016-11-01 11:45:46 -070051class TestBuffer : public webrtc::I420Buffer {
52 public:
53 TestBuffer(rtc::Event* event, int width, int height)
54 : I420Buffer(width, height), event_(event) {}
55
56 private:
57 friend class rtc::RefCountedObject<TestBuffer>;
58 ~TestBuffer() override {
59 if (event_)
60 event_->Set();
61 }
62 rtc::Event* const event_;
63};
64
65class ViEEncoderUnderTest : public ViEEncoder {
66 public:
kthelgason876222f2016-11-29 01:44:11 -080067 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
68 const VideoSendStream::Config::EncoderSettings& settings)
perkj803d97f2016-11-01 11:45:46 -070069 : ViEEncoder(1 /* number_of_cores */,
70 stats_proxy,
71 settings,
72 nullptr /* pre_encode_callback */,
73 nullptr /* encoder_timing */) {}
74
sprangb1ca0732017-02-01 08:38:12 -080075 void PostTaskAndWait(bool down, AdaptReason reason) {
perkj803d97f2016-11-01 11:45:46 -070076 rtc::Event event(false, false);
kthelgason876222f2016-11-29 01:44:11 -080077 encoder_queue()->PostTask([this, &event, reason, down] {
sprangb1ca0732017-02-01 08:38:12 -080078 down ? AdaptDown(reason) : AdaptUp(reason);
perkj803d97f2016-11-01 11:45:46 -070079 event.Set();
80 });
perkj070ba852017-02-16 15:46:27 -080081 ASSERT_TRUE(event.Wait(5000));
perkj803d97f2016-11-01 11:45:46 -070082 }
83
sprangb1ca0732017-02-01 08:38:12 -080084 void TriggerCpuOveruse() { PostTaskAndWait(true, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080085
sprangb1ca0732017-02-01 08:38:12 -080086 void TriggerCpuNormalUsage() { PostTaskAndWait(false, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080087
sprangb1ca0732017-02-01 08:38:12 -080088 void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); }
kthelgason876222f2016-11-29 01:44:11 -080089
sprangb1ca0732017-02-01 08:38:12 -080090 void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); }
perkj803d97f2016-11-01 11:45:46 -070091};
92
asapersson5f7226f2016-11-25 04:37:00 -080093class VideoStreamFactory
94 : public VideoEncoderConfig::VideoStreamFactoryInterface {
95 public:
96 explicit VideoStreamFactory(size_t num_temporal_layers)
97 : num_temporal_layers_(num_temporal_layers) {
98 EXPECT_GT(num_temporal_layers, 0u);
99 }
100
101 private:
102 std::vector<VideoStream> CreateEncoderStreams(
103 int width,
104 int height,
105 const VideoEncoderConfig& encoder_config) override {
106 std::vector<VideoStream> streams =
107 test::CreateVideoStreams(width, height, encoder_config);
108 for (VideoStream& stream : streams) {
109 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
110 }
111 return streams;
112 }
113 const size_t num_temporal_layers_;
114};
115
sprangb1ca0732017-02-01 08:38:12 -0800116class AdaptingFrameForwarder : public test::FrameForwarder {
117 public:
118 AdaptingFrameForwarder() : adaptation_enabled_(false) {}
119 virtual ~AdaptingFrameForwarder() {}
120
121 void set_adaptation_enabled(bool enabled) {
122 rtc::CritScope cs(&crit_);
123 adaptation_enabled_ = enabled;
124 }
125
126 bool adaption_enabled() {
127 rtc::CritScope cs(&crit_);
128 return adaptation_enabled_;
129 }
130
131 void IncomingCapturedFrame(const VideoFrame& video_frame) override {
132 int cropped_width = 0;
133 int cropped_height = 0;
134 int out_width = 0;
135 int out_height = 0;
136 if (adaption_enabled() &&
137 adapter_.AdaptFrameResolution(video_frame.width(), video_frame.height(),
138 video_frame.timestamp_us() * 1000,
139 &cropped_width, &cropped_height,
140 &out_width, &out_height)) {
141 VideoFrame adapted_frame(
142 new rtc::RefCountedObject<TestBuffer>(nullptr, out_width, out_height),
143 99, 99, kVideoRotation_0);
144 adapted_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
145 test::FrameForwarder::IncomingCapturedFrame(adapted_frame);
146 } else {
147 test::FrameForwarder::IncomingCapturedFrame(video_frame);
148 }
149 }
150
151 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
152 const rtc::VideoSinkWants& wants) override {
153 rtc::CritScope cs(&crit_);
sprang84a37592017-02-10 07:04:27 -0800154 adapter_.OnResolutionRequest(wants.target_pixel_count,
155 wants.max_pixel_count);
sprangb1ca0732017-02-01 08:38:12 -0800156 test::FrameForwarder::AddOrUpdateSink(sink, wants);
157 }
158
159 cricket::VideoAdapter adapter_;
160 bool adaptation_enabled_ GUARDED_BY(crit_);
161};
perkj803d97f2016-11-01 11:45:46 -0700162} // namespace
163
perkj26091b12016-09-01 01:17:40 -0700164class ViEEncoderTest : public ::testing::Test {
165 public:
166 static const int kDefaultTimeoutMs = 30 * 1000;
167
168 ViEEncoderTest()
169 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -0700170 codec_width_(320),
171 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -0700172 fake_encoder_(),
perkj803d97f2016-11-01 11:45:46 -0700173 stats_proxy_(new SendStatisticsProxy(
174 Clock::GetRealTimeClock(),
175 video_send_config_,
176 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -0700177 sink_(&fake_encoder_) {}
178
179 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -0700180 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -0700181 video_send_config_ = VideoSendStream::Config(nullptr);
182 video_send_config_.encoder_settings.encoder = &fake_encoder_;
183 video_send_config_.encoder_settings.payload_name = "FAKE";
184 video_send_config_.encoder_settings.payload_type = 125;
185
Per512ecb32016-09-23 15:52:06 +0200186 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700187 test::FillEncoderConfiguration(1, &video_encoder_config);
Erik Språng08127a92016-11-16 16:41:30 +0100188 video_encoder_config_ = video_encoder_config.Copy();
asapersson5f7226f2016-11-25 04:37:00 -0800189 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
190 }
191
192 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
193 bool nack_enabled) {
194 if (vie_encoder_)
195 vie_encoder_->Stop();
perkj803d97f2016-11-01 11:45:46 -0700196 vie_encoder_.reset(new ViEEncoderUnderTest(
197 stats_proxy_.get(), video_send_config_.encoder_settings));
198 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
199 vie_encoder_->SetSource(&video_source_,
200 VideoSendStream::DegradationPreference::kBalanced);
kthelgason2bc68642017-02-07 07:02:22 -0800201 vie_encoder_->SetStartBitrate(kTargetBitrateBps);
asapersson5f7226f2016-11-25 04:37:00 -0800202 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
203 kMaxPayloadLength, nack_enabled);
204 }
205
206 void ResetEncoder(const std::string& payload_name,
207 size_t num_streams,
208 size_t num_temporal_layers,
209 bool nack_enabled) {
210 video_send_config_.encoder_settings.payload_name = payload_name;
211
212 VideoEncoderConfig video_encoder_config;
213 video_encoder_config.number_of_streams = num_streams;
kthelgason2bc68642017-02-07 07:02:22 -0800214 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
asapersson5f7226f2016-11-25 04:37:00 -0800215 video_encoder_config.video_stream_factory =
216 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
217 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
perkj26091b12016-09-01 01:17:40 -0700218 }
219
sprang57c2fff2017-01-16 06:24:02 -0800220 VideoFrame CreateFrame(int64_t ntp_time_ms,
221 rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200222 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
223 destruction_event, codec_width_, codec_height_),
224 99, 99, kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800225 frame.set_ntp_time_ms(ntp_time_ms);
perkj26091b12016-09-01 01:17:40 -0700226 return frame;
227 }
228
sprang57c2fff2017-01-16 06:24:02 -0800229 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
perkj803d97f2016-11-01 11:45:46 -0700230 VideoFrame frame(
231 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
232 kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800233 frame.set_ntp_time_ms(ntp_time_ms);
perkj803d97f2016-11-01 11:45:46 -0700234 return frame;
235 }
236
perkj26091b12016-09-01 01:17:40 -0700237 class TestEncoder : public test::FakeEncoder {
238 public:
239 TestEncoder()
240 : FakeEncoder(Clock::GetRealTimeClock()),
241 continue_encode_event_(false, false) {}
242
perkjfa10b552016-10-02 23:45:26 -0700243 VideoCodec codec_config() {
brandtre78d2662017-01-16 05:57:16 -0800244 rtc::CritScope lock(&crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700245 return config_;
246 }
247
248 void BlockNextEncode() {
brandtre78d2662017-01-16 05:57:16 -0800249 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700250 block_next_encode_ = true;
251 }
252
kthelgason876222f2016-11-29 01:44:11 -0800253 VideoEncoder::ScalingSettings GetScalingSettings() const override {
kthelgasonad9010c2017-02-14 00:46:51 -0800254 if (quality_scaling_)
255 return VideoEncoder::ScalingSettings(true, 1, 2);
256 return VideoEncoder::ScalingSettings(false);
kthelgason876222f2016-11-29 01:44:11 -0800257 }
258
perkjfa10b552016-10-02 23:45:26 -0700259 void ContinueEncode() { continue_encode_event_.Set(); }
260
261 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
262 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800263 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700264 EXPECT_EQ(timestamp_, timestamp);
265 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
266 }
267
kthelgasonad9010c2017-02-14 00:46:51 -0800268 void SetQualityScaling(bool b) { quality_scaling_ = b; }
269
perkjfa10b552016-10-02 23:45:26 -0700270 private:
perkj26091b12016-09-01 01:17:40 -0700271 int32_t Encode(const VideoFrame& input_image,
272 const CodecSpecificInfo* codec_specific_info,
273 const std::vector<FrameType>* frame_types) override {
274 bool block_encode;
275 {
brandtre78d2662017-01-16 05:57:16 -0800276 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700277 EXPECT_GT(input_image.timestamp(), timestamp_);
278 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
279 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
280
281 timestamp_ = input_image.timestamp();
282 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700283 last_input_width_ = input_image.width();
284 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700285 block_encode = block_next_encode_;
286 block_next_encode_ = false;
287 }
288 int32_t result =
289 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
290 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700291 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700292 return result;
293 }
294
brandtre78d2662017-01-16 05:57:16 -0800295 rtc::CriticalSection local_crit_sect_;
perkj26091b12016-09-01 01:17:40 -0700296 bool block_next_encode_ = false;
297 rtc::Event continue_encode_event_;
298 uint32_t timestamp_ = 0;
299 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700300 int last_input_width_ = 0;
301 int last_input_height_ = 0;
kthelgasonad9010c2017-02-14 00:46:51 -0800302 bool quality_scaling_ = true;
perkj26091b12016-09-01 01:17:40 -0700303 };
304
Per512ecb32016-09-23 15:52:06 +0200305 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700306 public:
307 explicit TestSink(TestEncoder* test_encoder)
308 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
309
perkj26091b12016-09-01 01:17:40 -0700310 void WaitForEncodedFrame(int64_t expected_ntp_time) {
311 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700312 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700313 {
314 rtc::CritScope lock(&crit_);
sprangb1ca0732017-02-01 08:38:12 -0800315 timestamp = last_timestamp_;
perkj26091b12016-09-01 01:17:40 -0700316 }
317 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
318 }
319
sprangb1ca0732017-02-01 08:38:12 -0800320 void WaitForEncodedFrame(uint32_t expected_width,
321 uint32_t expected_height) {
322 uint32_t width = 0;
323 uint32_t height = 0;
324 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
325 {
326 rtc::CritScope lock(&crit_);
327 width = last_width_;
328 height = last_height_;
329 }
330 EXPECT_EQ(expected_height, height);
331 EXPECT_EQ(expected_width, width);
332 }
333
kthelgason2bc68642017-02-07 07:02:22 -0800334 void ExpectDroppedFrame() { EXPECT_FALSE(encoded_frame_event_.Wait(20)); }
335
perkj26091b12016-09-01 01:17:40 -0700336 void SetExpectNoFrames() {
337 rtc::CritScope lock(&crit_);
338 expect_frames_ = false;
339 }
340
Per512ecb32016-09-23 15:52:06 +0200341 int number_of_reconfigurations() {
342 rtc::CritScope lock(&crit_);
343 return number_of_reconfigurations_;
344 }
345
346 int last_min_transmit_bitrate() {
347 rtc::CritScope lock(&crit_);
348 return min_transmit_bitrate_bps_;
349 }
350
perkj26091b12016-09-01 01:17:40 -0700351 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700352 Result OnEncodedImage(
353 const EncodedImage& encoded_image,
354 const CodecSpecificInfo* codec_specific_info,
355 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200356 rtc::CritScope lock(&crit_);
357 EXPECT_TRUE(expect_frames_);
sprangb1ca0732017-02-01 08:38:12 -0800358 last_timestamp_ = encoded_image._timeStamp;
359 last_width_ = encoded_image._encodedWidth;
360 last_height_ = encoded_image._encodedHeight;
Per512ecb32016-09-23 15:52:06 +0200361 encoded_frame_event_.Set();
sprangb1ca0732017-02-01 08:38:12 -0800362 return Result(Result::OK, last_timestamp_);
Per512ecb32016-09-23 15:52:06 +0200363 }
364
365 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
366 int min_transmit_bitrate_bps) override {
367 rtc::CriticalSection crit_;
368 ++number_of_reconfigurations_;
369 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
370 }
371
perkj26091b12016-09-01 01:17:40 -0700372 rtc::CriticalSection crit_;
373 TestEncoder* test_encoder_;
374 rtc::Event encoded_frame_event_;
sprangb1ca0732017-02-01 08:38:12 -0800375 uint32_t last_timestamp_ = 0;
376 uint32_t last_height_ = 0;
377 uint32_t last_width_ = 0;
perkj26091b12016-09-01 01:17:40 -0700378 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200379 int number_of_reconfigurations_ = 0;
380 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700381 };
382
383 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100384 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200385 int codec_width_;
386 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700387 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700388 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700389 TestSink sink_;
sprangb1ca0732017-02-01 08:38:12 -0800390 AdaptingFrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700391 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700392};
393
394TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700395 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
396 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700397 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700398 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700399 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700400 vie_encoder_->Stop();
401}
402
403TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
404 // Dropped since no target bitrate has been set.
405 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700406 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
407 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700408
perkj26091b12016-09-01 01:17:40 -0700409 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
410
perkja49cbd32016-09-16 07:53:41 -0700411 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700412 sink_.WaitForEncodedFrame(2);
413 vie_encoder_->Stop();
414}
415
416TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700417 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700418 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700419 sink_.WaitForEncodedFrame(1);
420
421 vie_encoder_->OnBitrateUpdated(0, 0, 0);
422 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700423 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700424
425 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700426 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700427 sink_.WaitForEncodedFrame(3);
428 vie_encoder_->Stop();
429}
430
431TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700432 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700433 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700434 sink_.WaitForEncodedFrame(1);
435
436 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700437 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700438
perkja49cbd32016-09-16 07:53:41 -0700439 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700440 sink_.WaitForEncodedFrame(2);
441 vie_encoder_->Stop();
442}
443
444TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700445 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
446
perkja49cbd32016-09-16 07:53:41 -0700447 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700448 sink_.WaitForEncodedFrame(1);
449
450 vie_encoder_->Stop();
451 sink_.SetExpectNoFrames();
452 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700453 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
454 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700455}
456
457TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700458 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
459
460 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700461 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700462 sink_.WaitForEncodedFrame(1);
463 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
464 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700465 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
466 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700467 fake_encoder_.ContinueEncode();
468 sink_.WaitForEncodedFrame(3);
469
470 vie_encoder_->Stop();
471}
472
Per512ecb32016-09-23 15:52:06 +0200473TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200474 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100475 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200476
477 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200478 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200479 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100480 // The encoder will have been configured once when the first frame is
481 // received.
482 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200483
484 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700485 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200486 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800487 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
488 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200489
490 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200491 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200492 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100493 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700494 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700495
496 vie_encoder_->Stop();
497}
498
perkjfa10b552016-10-02 23:45:26 -0700499TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700500 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
501
502 // Capture a frame and wait for it to synchronize with the encoder thread.
503 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
504 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100505 // The encoder will have been configured once.
506 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700507 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
508 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
509
510 codec_width_ *= 2;
511 codec_height_ *= 2;
512 // Capture a frame with a higher resolution and wait for it to synchronize
513 // with the encoder thread.
514 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
515 sink_.WaitForEncodedFrame(2);
516 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
517 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100518 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700519
520 vie_encoder_->Stop();
521}
522
asapersson5f7226f2016-11-25 04:37:00 -0800523TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
524 const bool kNackEnabled = true;
525 const size_t kNumStreams = 1;
526 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800527 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800528 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
529
530 // Capture a frame and wait for it to synchronize with the encoder thread.
531 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
532 sink_.WaitForEncodedFrame(1);
533 // The encoder have been configured once when the first frame is received.
534 EXPECT_EQ(1, sink_.number_of_reconfigurations());
535 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
536 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
537 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
538 // Resilience is off for no temporal layers with nack on.
539 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
540 vie_encoder_->Stop();
541}
542
543TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
544 const bool kNackEnabled = true;
545 const size_t kNumStreams = 2;
546 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800547 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800548 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
549
550 // Capture a frame and wait for it to synchronize with the encoder thread.
551 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
552 sink_.WaitForEncodedFrame(1);
553 // The encoder have been configured once when the first frame is received.
554 EXPECT_EQ(1, sink_.number_of_reconfigurations());
555 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
556 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
557 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
558 // Resilience is off for no temporal layers and >1 streams with nack on.
559 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
560 vie_encoder_->Stop();
561}
562
563TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
564 const bool kNackEnabled = false;
565 const size_t kNumStreams = 1;
566 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800567 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800568 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
569
570 // Capture a frame and wait for it to synchronize with the encoder thread.
571 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
572 sink_.WaitForEncodedFrame(1);
573 // The encoder have been configured once when the first frame is received.
574 EXPECT_EQ(1, sink_.number_of_reconfigurations());
575 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
576 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
577 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
578 // Resilience is on for no temporal layers with nack off.
579 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
580 vie_encoder_->Stop();
581}
582
583TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
584 const bool kNackEnabled = true;
585 const size_t kNumStreams = 1;
586 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800587 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800588 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
589
590 // Capture a frame and wait for it to synchronize with the encoder thread.
591 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
592 sink_.WaitForEncodedFrame(1);
593 // The encoder have been configured once when the first frame is received.
594 EXPECT_EQ(1, sink_.number_of_reconfigurations());
595 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
596 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
597 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
598 // Resilience is on for temporal layers.
599 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
600 vie_encoder_->Stop();
601}
602
perkj803d97f2016-11-01 11:45:46 -0700603TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
604 EXPECT_TRUE(video_source_.has_sinks());
605 test::FrameForwarder new_video_source;
606 vie_encoder_->SetSource(&new_video_source,
607 VideoSendStream::DegradationPreference::kBalanced);
608 EXPECT_FALSE(video_source_.has_sinks());
609 EXPECT_TRUE(new_video_source.has_sinks());
610
611 vie_encoder_->Stop();
612}
613
614TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
615 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
616 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
617 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
618 vie_encoder_->Stop();
619}
620
621TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700622 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
623
sprang84a37592017-02-10 07:04:27 -0800624 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700625 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700626
627 int frame_width = 1280;
628 int frame_height = 720;
629
630 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
631 // request lower resolution.
632 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
633 video_source_.IncomingCapturedFrame(
634 CreateFrame(i, frame_width, frame_height));
635 sink_.WaitForEncodedFrame(i);
636
637 vie_encoder_->TriggerCpuOveruse();
638
sprang84a37592017-02-10 07:04:27 -0800639 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700640 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
641 std::numeric_limits<int>::max()),
642 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700643
644 frame_width /= 2;
645 frame_height /= 2;
646 }
647
kthelgason876222f2016-11-29 01:44:11 -0800648 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700649 // lower resolution.
650 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
651 video_source_.IncomingCapturedFrame(CreateFrame(
652 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
653 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
654 vie_encoder_->TriggerCpuOveruse();
sprang84a37592017-02-10 07:04:27 -0800655 EXPECT_EQ(video_source_.sink_wants().target_pixel_count,
656 current_wants.target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700657 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
658 current_wants.max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700659
660 // Trigger CPU normal use.
661 vie_encoder_->TriggerCpuNormalUsage();
sprang84a37592017-02-10 07:04:27 -0800662 EXPECT_EQ(frame_width * frame_height * 5 / 3,
663 video_source_.sink_wants().target_pixel_count.value_or(0));
664 EXPECT_EQ(frame_width * frame_height * 4,
665 video_source_.sink_wants().max_pixel_count.value_or(0));
perkj803d97f2016-11-01 11:45:46 -0700666
667 vie_encoder_->Stop();
668}
669
670TEST_F(ViEEncoderTest,
671 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700672 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
673
sprang84a37592017-02-10 07:04:27 -0800674 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700675 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700676
677 int frame_width = 1280;
678 int frame_height = 720;
679
kthelgason5e13d412016-12-01 03:59:51 -0800680 video_source_.IncomingCapturedFrame(
681 CreateFrame(1, frame_width, frame_height));
682 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700683 // Trigger CPU overuse.
684 vie_encoder_->TriggerCpuOveruse();
685
686 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800687 CreateFrame(2, frame_width, frame_height));
688 sink_.WaitForEncodedFrame(2);
sprang84a37592017-02-10 07:04:27 -0800689 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700690 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
691 std::numeric_limits<int>::max()),
692 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700693
694 // Set new source.
695 test::FrameForwarder new_video_source;
696 vie_encoder_->SetSource(
697 &new_video_source,
698 VideoSendStream::DegradationPreference::kMaintainResolution);
699
sprang84a37592017-02-10 07:04:27 -0800700 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700701 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700702
703 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800704 CreateFrame(3, frame_width, frame_height));
705 sink_.WaitForEncodedFrame(3);
sprang84a37592017-02-10 07:04:27 -0800706 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700707 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700708
709 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
710 vie_encoder_->SetSource(&new_video_source,
711 VideoSendStream::DegradationPreference::kBalanced);
712 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
713 std::numeric_limits<int>::max()),
714 frame_width * frame_height);
sprang84a37592017-02-10 07:04:27 -0800715 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700716
717 vie_encoder_->Stop();
718}
719
720TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700721 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
722
723 int frame_width = 1280;
724 int frame_height = 720;
725
726 video_source_.IncomingCapturedFrame(
727 CreateFrame(1, frame_width, frame_height));
728 sink_.WaitForEncodedFrame(1);
729 VideoSendStream::Stats stats = stats_proxy_->GetStats();
730 EXPECT_FALSE(stats.cpu_limited_resolution);
731 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
732
733 // Trigger CPU overuse.
734 vie_encoder_->TriggerCpuOveruse();
735 video_source_.IncomingCapturedFrame(
736 CreateFrame(2, frame_width, frame_height));
737 sink_.WaitForEncodedFrame(2);
738
739 stats = stats_proxy_->GetStats();
740 EXPECT_TRUE(stats.cpu_limited_resolution);
741 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
742
743 // Trigger CPU normal use.
744 vie_encoder_->TriggerCpuNormalUsage();
745 video_source_.IncomingCapturedFrame(
746 CreateFrame(3, frame_width, frame_height));
747 sink_.WaitForEncodedFrame(3);
748
749 stats = stats_proxy_->GetStats();
750 EXPECT_FALSE(stats.cpu_limited_resolution);
751 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
752
753 vie_encoder_->Stop();
754}
755
kthelgason876222f2016-11-29 01:44:11 -0800756TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800757 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
758
759 int frame_width = 1280;
760 int frame_height = 720;
761 video_source_.IncomingCapturedFrame(
762 CreateFrame(1, frame_width, frame_height));
763 sink_.WaitForEncodedFrame(1);
764
765 VideoSendStream::Stats stats = stats_proxy_->GetStats();
766 EXPECT_FALSE(stats.cpu_limited_resolution);
767 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
768
769 vie_encoder_->TriggerCpuOveruse();
770
771 video_source_.IncomingCapturedFrame(
772 CreateFrame(2, frame_width, frame_height));
773 sink_.WaitForEncodedFrame(2);
774 stats = stats_proxy_->GetStats();
775 EXPECT_TRUE(stats.cpu_limited_resolution);
776 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
777
778 // Set new source with adaptation still enabled.
779 test::FrameForwarder new_video_source;
780 vie_encoder_->SetSource(&new_video_source,
781 VideoSendStream::DegradationPreference::kBalanced);
782
783 new_video_source.IncomingCapturedFrame(
784 CreateFrame(3, frame_width, frame_height));
785 sink_.WaitForEncodedFrame(3);
786 stats = stats_proxy_->GetStats();
787 EXPECT_TRUE(stats.cpu_limited_resolution);
788 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
789
790 // Set adaptation disabled.
791 vie_encoder_->SetSource(
792 &new_video_source,
793 VideoSendStream::DegradationPreference::kMaintainResolution);
794
795 new_video_source.IncomingCapturedFrame(
796 CreateFrame(4, frame_width, frame_height));
797 sink_.WaitForEncodedFrame(4);
798 stats = stats_proxy_->GetStats();
799 EXPECT_FALSE(stats.cpu_limited_resolution);
800 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
801
802 // Set adaptation back to enabled.
803 vie_encoder_->SetSource(&new_video_source,
804 VideoSendStream::DegradationPreference::kBalanced);
805
806 new_video_source.IncomingCapturedFrame(
807 CreateFrame(5, frame_width, frame_height));
808 sink_.WaitForEncodedFrame(5);
809 stats = stats_proxy_->GetStats();
810 EXPECT_TRUE(stats.cpu_limited_resolution);
811 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
812
813 vie_encoder_->TriggerCpuNormalUsage();
814
815 new_video_source.IncomingCapturedFrame(
816 CreateFrame(6, frame_width, frame_height));
817 sink_.WaitForEncodedFrame(6);
818 stats = stats_proxy_->GetStats();
819 EXPECT_FALSE(stats.cpu_limited_resolution);
820 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
821
822 vie_encoder_->Stop();
823}
824
825TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800826 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
827
828 int frame_width = 1280;
829 int frame_height = 720;
830 video_source_.IncomingCapturedFrame(
831 CreateFrame(1, frame_width, frame_height));
832 sink_.WaitForEncodedFrame(1);
833
834 VideoSendStream::Stats stats = stats_proxy_->GetStats();
835 EXPECT_FALSE(stats.cpu_limited_resolution);
836 EXPECT_FALSE(stats.bw_limited_resolution);
837 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
838
839 // Set new source with adaptation still enabled.
840 test::FrameForwarder new_video_source;
841 vie_encoder_->SetSource(&new_video_source,
842 VideoSendStream::DegradationPreference::kBalanced);
843
844 new_video_source.IncomingCapturedFrame(
845 CreateFrame(2, frame_width, frame_height));
846 sink_.WaitForEncodedFrame(2);
847 stats = stats_proxy_->GetStats();
848 EXPECT_FALSE(stats.cpu_limited_resolution);
849 EXPECT_FALSE(stats.bw_limited_resolution);
850 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
851
852 vie_encoder_->TriggerQualityLow();
853
854 new_video_source.IncomingCapturedFrame(
855 CreateFrame(3, frame_width, frame_height));
856 sink_.WaitForEncodedFrame(3);
857 stats = stats_proxy_->GetStats();
858 EXPECT_FALSE(stats.cpu_limited_resolution);
859 EXPECT_TRUE(stats.bw_limited_resolution);
860
861 vie_encoder_->SetSource(&new_video_source,
862 VideoSendStream::DegradationPreference::kBalanced);
863
864 new_video_source.IncomingCapturedFrame(
865 CreateFrame(4, frame_width, frame_height));
866 sink_.WaitForEncodedFrame(4);
867 stats = stats_proxy_->GetStats();
868 EXPECT_FALSE(stats.cpu_limited_resolution);
869 EXPECT_TRUE(stats.bw_limited_resolution);
870
871 // Set adaptation disabled.
872 vie_encoder_->SetSource(
873 &new_video_source,
874 VideoSendStream::DegradationPreference::kMaintainResolution);
875
876 new_video_source.IncomingCapturedFrame(
877 CreateFrame(5, frame_width, frame_height));
878 sink_.WaitForEncodedFrame(5);
879 stats = stats_proxy_->GetStats();
880 EXPECT_FALSE(stats.cpu_limited_resolution);
881 EXPECT_FALSE(stats.bw_limited_resolution);
882
883 vie_encoder_->Stop();
884}
885
perkj803d97f2016-11-01 11:45:46 -0700886TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700887 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
888
perkj803d97f2016-11-01 11:45:46 -0700889 int frame_width = 1280;
890 int frame_height = 720;
sprang84a37592017-02-10 07:04:27 -0800891 int sequence = 1;
perkj803d97f2016-11-01 11:45:46 -0700892
893 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800894 CreateFrame(sequence, frame_width, frame_height));
895 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700896
897 VideoSendStream::Stats stats = stats_proxy_->GetStats();
sprang84a37592017-02-10 07:04:27 -0800898 EXPECT_FALSE(stats.cpu_limited_resolution);
899 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
900
901 // Trigger CPU overuse again, should now adapt down.
902 vie_encoder_->TriggerCpuOveruse();
903 video_source_.IncomingCapturedFrame(
904 CreateFrame(sequence, frame_width, frame_height));
905 sink_.WaitForEncodedFrame(sequence++);
906
907 stats = stats_proxy_->GetStats();
perkj803d97f2016-11-01 11:45:46 -0700908 EXPECT_TRUE(stats.cpu_limited_resolution);
909 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
910
911 // Set new source with adaptation still enabled.
912 test::FrameForwarder new_video_source;
913 vie_encoder_->SetSource(&new_video_source,
914 VideoSendStream::DegradationPreference::kBalanced);
915
916 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800917 CreateFrame(sequence, frame_width, frame_height));
918 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700919 stats = stats_proxy_->GetStats();
920 EXPECT_TRUE(stats.cpu_limited_resolution);
921 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
922
923 // Set adaptation disabled.
924 vie_encoder_->SetSource(
925 &new_video_source,
926 VideoSendStream::DegradationPreference::kMaintainResolution);
927 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800928 CreateFrame(sequence, frame_width, frame_height));
929 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700930 stats = stats_proxy_->GetStats();
931 EXPECT_FALSE(stats.cpu_limited_resolution);
932 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
933
934 // Switch back the source with adaptation enabled.
935 vie_encoder_->SetSource(&video_source_,
936 VideoSendStream::DegradationPreference::kBalanced);
937 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800938 CreateFrame(sequence, frame_width, frame_height));
939 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700940 stats = stats_proxy_->GetStats();
941 EXPECT_TRUE(stats.cpu_limited_resolution);
942 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
943
944 // Trigger CPU normal usage.
945 vie_encoder_->TriggerCpuNormalUsage();
946 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800947 CreateFrame(sequence, frame_width, frame_height));
948 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700949 stats = stats_proxy_->GetStats();
950 EXPECT_FALSE(stats.cpu_limited_resolution);
951 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
952
953 vie_encoder_->Stop();
954}
955
Erik Språng08127a92016-11-16 16:41:30 +0100956TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100957 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
958
959 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
960 sink_.WaitForEncodedFrame(1);
961
962 VideoSendStream::Stats stats = stats_proxy_->GetStats();
963 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
964 stats.preferred_media_bitrate_bps);
965
966 vie_encoder_->Stop();
967}
968
kthelgason876222f2016-11-29 01:44:11 -0800969TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
kthelgason876222f2016-11-29 01:44:11 -0800970 int frame_width = 1280;
971 int frame_height = 720;
972 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
973
974 // Expect no scaling to begin with
sprang84a37592017-02-10 07:04:27 -0800975 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -0800976 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -0800977
kthelgason876222f2016-11-29 01:44:11 -0800978 video_source_.IncomingCapturedFrame(
979 CreateFrame(1, frame_width, frame_height));
980 sink_.WaitForEncodedFrame(1);
981
kthelgason5e13d412016-12-01 03:59:51 -0800982 // Trigger scale down
983 vie_encoder_->TriggerQualityLow();
984
985 video_source_.IncomingCapturedFrame(
986 CreateFrame(2, frame_width, frame_height));
987 sink_.WaitForEncodedFrame(2);
988
kthelgason876222f2016-11-29 01:44:11 -0800989 // Expect a scale down.
990 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
991 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
992 frame_width * frame_height);
993
994 // Set adaptation disabled.
995 test::FrameForwarder new_video_source;
996 vie_encoder_->SetSource(
997 &new_video_source,
998 VideoSendStream::DegradationPreference::kMaintainResolution);
999
1000 // Trigger scale down
1001 vie_encoder_->TriggerQualityLow();
1002 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001003 CreateFrame(3, frame_width, frame_height));
1004 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -08001005
1006 // Expect no scaling
1007 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1008
1009 // Trigger scale up
1010 vie_encoder_->TriggerQualityHigh();
1011 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001012 CreateFrame(4, frame_width, frame_height));
1013 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -08001014
1015 // Expect nothing to change, still no scaling
1016 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1017
1018 vie_encoder_->Stop();
1019}
1020
kthelgason5e13d412016-12-01 03:59:51 -08001021TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
kthelgason5e13d412016-12-01 03:59:51 -08001022 int frame_width = 1280;
1023 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -08001024 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1025
1026 for (size_t i = 1; i <= 10; i++) {
1027 video_source_.IncomingCapturedFrame(
1028 CreateFrame(i, frame_width, frame_height));
1029 sink_.WaitForEncodedFrame(i);
1030 // Trigger scale down
1031 vie_encoder_->TriggerQualityLow();
1032 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
1033 }
1034
1035 vie_encoder_->Stop();
1036}
1037
perkj803d97f2016-11-01 11:45:46 -07001038TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -07001039 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1040
1041 int frame_width = 640;
1042 int frame_height = 360;
1043
1044 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1045 video_source_.IncomingCapturedFrame(
1046 CreateFrame(i, frame_width, frame_height));
1047 sink_.WaitForEncodedFrame(i);
1048 }
1049
1050 vie_encoder_->TriggerCpuOveruse();
1051 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1052 video_source_.IncomingCapturedFrame(
1053 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
1054 frame_width, frame_height));
1055 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
1056 i);
1057 }
1058
1059 vie_encoder_->Stop();
sprangf8ee65e2017-02-28 08:49:33 -08001060 vie_encoder_.reset();
perkj803d97f2016-11-01 11:45:46 -07001061 stats_proxy_.reset();
sprangf8ee65e2017-02-28 08:49:33 -08001062
perkj803d97f2016-11-01 11:45:46 -07001063 EXPECT_EQ(1,
1064 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1065 EXPECT_EQ(
1066 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1067}
1068
sprang57c2fff2017-01-16 06:24:02 -08001069TEST_F(ViEEncoderTest, CallsBitrateObserver) {
1070 class MockBitrateObserver : public VideoBitrateAllocationObserver {
1071 public:
1072 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
1073 } bitrate_observer;
1074 vie_encoder_->SetBitrateObserver(&bitrate_observer);
1075
1076 const int kDefaultFps = 30;
1077 const BitrateAllocation expected_bitrate =
1078 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
kthelgason2bc68642017-02-07 07:02:22 -08001079 .GetAllocation(kLowTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -08001080
1081 // First called on bitrate updated, then again on first frame.
1082 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1083 .Times(2);
kthelgason2bc68642017-02-07 07:02:22 -08001084 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001085
1086 const int64_t kStartTimeMs = 1;
1087 video_source_.IncomingCapturedFrame(
1088 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1089 sink_.WaitForEncodedFrame(kStartTimeMs);
1090
1091 // Not called on second frame.
1092 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1093 .Times(0);
1094 video_source_.IncomingCapturedFrame(
1095 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1096 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1097
1098 // Called after a process interval.
1099 const int64_t kProcessIntervalMs =
1100 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1101 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1102 // Sleep for one processing interval plus one frame to avoid flakiness.
1103 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1104 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1105 .Times(1);
1106 video_source_.IncomingCapturedFrame(CreateFrame(
1107 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1108 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1109
1110 vie_encoder_->Stop();
1111}
1112
kthelgason2bc68642017-02-07 07:02:22 -08001113TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
1114 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1115 int frame_width = 640;
1116 int frame_height = 360;
1117
1118 video_source_.IncomingCapturedFrame(
1119 CreateFrame(1, frame_width, frame_height));
1120
1121 // Expect to drop this frame, the wait should time out.
1122 sink_.ExpectDroppedFrame();
1123
1124 // Expect the sink_wants to specify a scaled frame.
1125 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1126 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1127
1128 int last_pixel_count = *video_source_.sink_wants().max_pixel_count;
1129
1130 // Next frame is scaled
1131 video_source_.IncomingCapturedFrame(
1132 CreateFrame(2, frame_width * 3 / 4, frame_height * 3 / 4));
1133
1134 // Expect to drop this frame, the wait should time out.
1135 sink_.ExpectDroppedFrame();
1136
1137 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, last_pixel_count);
1138
1139 vie_encoder_->Stop();
1140}
1141
danilchapf8475432017-02-27 09:21:14 -08001142#if defined(MEMORY_SANITIZER)
1143// Fails under MemorySanitizer: See http://crbug.com/webrtc/7232
1144#define MAYBE_NrOfDroppedFramesLimited DISABLED_NrOfDroppedFramesLimited
1145#else
1146#define MAYBE_NrOfDroppedFramesLimited NrOfDroppedFramesLimited
1147#endif
1148TEST_F(ViEEncoderTest, MAYBE_NrOfDroppedFramesLimited) {
kthelgason2bc68642017-02-07 07:02:22 -08001149 // 1kbps. This can never be achieved.
1150 vie_encoder_->OnBitrateUpdated(1000, 0, 0);
1151 int frame_width = 640;
1152 int frame_height = 360;
1153
1154 // We expect the n initial frames to get dropped.
1155 int i;
1156 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
1157 video_source_.IncomingCapturedFrame(
1158 CreateFrame(i, frame_width, frame_height));
1159 sink_.ExpectDroppedFrame();
1160 }
1161 // The n+1th frame should not be dropped, even though it's size is too large.
1162 video_source_.IncomingCapturedFrame(
1163 CreateFrame(i, frame_width, frame_height));
1164 sink_.WaitForEncodedFrame(i);
1165
1166 // Expect the sink_wants to specify a scaled frame.
1167 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1168 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1169
1170 vie_encoder_->Stop();
1171}
1172
1173TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
1174 int frame_width = 640;
1175 int frame_height = 360;
1176 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1177
1178 // Set degradation preference.
1179 vie_encoder_->SetSource(
1180 &video_source_,
1181 VideoSendStream::DegradationPreference::kMaintainResolution);
1182
1183 video_source_.IncomingCapturedFrame(
1184 CreateFrame(1, frame_width, frame_height));
1185 // Frame should not be dropped, even if it's too large.
1186 sink_.WaitForEncodedFrame(1);
1187
1188 vie_encoder_->Stop();
1189}
1190
kthelgasonad9010c2017-02-14 00:46:51 -08001191TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
1192 int frame_width = 640;
1193 int frame_height = 360;
1194 fake_encoder_.SetQualityScaling(false);
1195 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
kthelgasonb83797b2017-02-14 11:57:25 -08001196 // Force quality scaler reconfiguration by resetting the source.
1197 vie_encoder_->SetSource(&video_source_,
1198 VideoSendStream::DegradationPreference::kBalanced);
kthelgasonad9010c2017-02-14 00:46:51 -08001199
1200 video_source_.IncomingCapturedFrame(
1201 CreateFrame(1, frame_width, frame_height));
1202 // Frame should not be dropped, even if it's too large.
1203 sink_.WaitForEncodedFrame(1);
1204
1205 vie_encoder_->Stop();
1206 fake_encoder_.SetQualityScaling(true);
1207}
1208
sprangb1ca0732017-02-01 08:38:12 -08001209// TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
1210TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) {
1211 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1212
1213 const int kFrameWidth = 1280;
1214 const int kFrameHeight = 720;
1215 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
1216 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
1217 video_source_.set_adaptation_enabled(true);
1218
1219 video_source_.IncomingCapturedFrame(
1220 CreateFrame(1, kFrameWidth, kFrameHeight));
1221 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1222
1223 // Trigger CPU overuse, downscale by 3/4.
1224 vie_encoder_->TriggerCpuOveruse();
1225 video_source_.IncomingCapturedFrame(
1226 CreateFrame(2, kFrameWidth, kFrameHeight));
1227 sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
1228
1229 // Trigger CPU normal use, return to original resoluton;
1230 vie_encoder_->TriggerCpuNormalUsage();
1231 video_source_.IncomingCapturedFrame(
1232 CreateFrame(3, kFrameWidth, kFrameHeight));
1233 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1234
1235 vie_encoder_->Stop();
1236}
perkj26091b12016-09-01 01:17:40 -07001237} // namespace webrtc