blob: 96d627b7fa55c30ec109fb4d3bf514d8f8db55df [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 });
kthelgason876222f2016-11-29 01:44:11 -080081 RTC_DCHECK(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 {
254 return VideoEncoder::ScalingSettings(true, 1, 2);
255 }
256
perkjfa10b552016-10-02 23:45:26 -0700257 void ContinueEncode() { continue_encode_event_.Set(); }
258
259 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
260 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800261 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700262 EXPECT_EQ(timestamp_, timestamp);
263 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
264 }
265
266 private:
perkj26091b12016-09-01 01:17:40 -0700267 int32_t Encode(const VideoFrame& input_image,
268 const CodecSpecificInfo* codec_specific_info,
269 const std::vector<FrameType>* frame_types) override {
270 bool block_encode;
271 {
brandtre78d2662017-01-16 05:57:16 -0800272 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700273 EXPECT_GT(input_image.timestamp(), timestamp_);
274 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
275 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
276
277 timestamp_ = input_image.timestamp();
278 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700279 last_input_width_ = input_image.width();
280 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700281 block_encode = block_next_encode_;
282 block_next_encode_ = false;
283 }
284 int32_t result =
285 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
286 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700287 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700288 return result;
289 }
290
brandtre78d2662017-01-16 05:57:16 -0800291 rtc::CriticalSection local_crit_sect_;
perkj26091b12016-09-01 01:17:40 -0700292 bool block_next_encode_ = false;
293 rtc::Event continue_encode_event_;
294 uint32_t timestamp_ = 0;
295 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700296 int last_input_width_ = 0;
297 int last_input_height_ = 0;
perkj26091b12016-09-01 01:17:40 -0700298 };
299
Per512ecb32016-09-23 15:52:06 +0200300 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700301 public:
302 explicit TestSink(TestEncoder* test_encoder)
303 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
304
perkj26091b12016-09-01 01:17:40 -0700305 void WaitForEncodedFrame(int64_t expected_ntp_time) {
306 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700307 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700308 {
309 rtc::CritScope lock(&crit_);
sprangb1ca0732017-02-01 08:38:12 -0800310 timestamp = last_timestamp_;
perkj26091b12016-09-01 01:17:40 -0700311 }
312 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
313 }
314
sprangb1ca0732017-02-01 08:38:12 -0800315 void WaitForEncodedFrame(uint32_t expected_width,
316 uint32_t expected_height) {
317 uint32_t width = 0;
318 uint32_t height = 0;
319 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
320 {
321 rtc::CritScope lock(&crit_);
322 width = last_width_;
323 height = last_height_;
324 }
325 EXPECT_EQ(expected_height, height);
326 EXPECT_EQ(expected_width, width);
327 }
328
kthelgason2bc68642017-02-07 07:02:22 -0800329 void ExpectDroppedFrame() { EXPECT_FALSE(encoded_frame_event_.Wait(20)); }
330
perkj26091b12016-09-01 01:17:40 -0700331 void SetExpectNoFrames() {
332 rtc::CritScope lock(&crit_);
333 expect_frames_ = false;
334 }
335
Per512ecb32016-09-23 15:52:06 +0200336 int number_of_reconfigurations() {
337 rtc::CritScope lock(&crit_);
338 return number_of_reconfigurations_;
339 }
340
341 int last_min_transmit_bitrate() {
342 rtc::CritScope lock(&crit_);
343 return min_transmit_bitrate_bps_;
344 }
345
perkj26091b12016-09-01 01:17:40 -0700346 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700347 Result OnEncodedImage(
348 const EncodedImage& encoded_image,
349 const CodecSpecificInfo* codec_specific_info,
350 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200351 rtc::CritScope lock(&crit_);
352 EXPECT_TRUE(expect_frames_);
sprangb1ca0732017-02-01 08:38:12 -0800353 last_timestamp_ = encoded_image._timeStamp;
354 last_width_ = encoded_image._encodedWidth;
355 last_height_ = encoded_image._encodedHeight;
Per512ecb32016-09-23 15:52:06 +0200356 encoded_frame_event_.Set();
sprangb1ca0732017-02-01 08:38:12 -0800357 return Result(Result::OK, last_timestamp_);
Per512ecb32016-09-23 15:52:06 +0200358 }
359
360 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
361 int min_transmit_bitrate_bps) override {
362 rtc::CriticalSection crit_;
363 ++number_of_reconfigurations_;
364 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
365 }
366
perkj26091b12016-09-01 01:17:40 -0700367 rtc::CriticalSection crit_;
368 TestEncoder* test_encoder_;
369 rtc::Event encoded_frame_event_;
sprangb1ca0732017-02-01 08:38:12 -0800370 uint32_t last_timestamp_ = 0;
371 uint32_t last_height_ = 0;
372 uint32_t last_width_ = 0;
perkj26091b12016-09-01 01:17:40 -0700373 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200374 int number_of_reconfigurations_ = 0;
375 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700376 };
377
378 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100379 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200380 int codec_width_;
381 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700382 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700383 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700384 TestSink sink_;
sprangb1ca0732017-02-01 08:38:12 -0800385 AdaptingFrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700386 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700387};
388
389TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700390 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
391 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700392 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700393 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700394 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700395 vie_encoder_->Stop();
396}
397
398TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
399 // Dropped since no target bitrate has been set.
400 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700401 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
402 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700403
perkj26091b12016-09-01 01:17:40 -0700404 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
405
perkja49cbd32016-09-16 07:53:41 -0700406 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700407 sink_.WaitForEncodedFrame(2);
408 vie_encoder_->Stop();
409}
410
411TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700412 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700413 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700414 sink_.WaitForEncodedFrame(1);
415
416 vie_encoder_->OnBitrateUpdated(0, 0, 0);
417 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700418 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700419
420 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700421 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700422 sink_.WaitForEncodedFrame(3);
423 vie_encoder_->Stop();
424}
425
426TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700427 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700428 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700429 sink_.WaitForEncodedFrame(1);
430
431 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700432 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700433
perkja49cbd32016-09-16 07:53:41 -0700434 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700435 sink_.WaitForEncodedFrame(2);
436 vie_encoder_->Stop();
437}
438
439TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700440 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
441
perkja49cbd32016-09-16 07:53:41 -0700442 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700443 sink_.WaitForEncodedFrame(1);
444
445 vie_encoder_->Stop();
446 sink_.SetExpectNoFrames();
447 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700448 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
449 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700450}
451
452TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700453 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
454
455 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700456 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700457 sink_.WaitForEncodedFrame(1);
458 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
459 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700460 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
461 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700462 fake_encoder_.ContinueEncode();
463 sink_.WaitForEncodedFrame(3);
464
465 vie_encoder_->Stop();
466}
467
Per512ecb32016-09-23 15:52:06 +0200468TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200469 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100470 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200471
472 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200473 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200474 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100475 // The encoder will have been configured once when the first frame is
476 // received.
477 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200478
479 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700480 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200481 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800482 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
483 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200484
485 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200486 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200487 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100488 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700489 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700490
491 vie_encoder_->Stop();
492}
493
perkjfa10b552016-10-02 23:45:26 -0700494TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700495 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
496
497 // Capture a frame and wait for it to synchronize with the encoder thread.
498 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
499 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100500 // The encoder will have been configured once.
501 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700502 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
503 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
504
505 codec_width_ *= 2;
506 codec_height_ *= 2;
507 // Capture a frame with a higher resolution and wait for it to synchronize
508 // with the encoder thread.
509 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
510 sink_.WaitForEncodedFrame(2);
511 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
512 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100513 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700514
515 vie_encoder_->Stop();
516}
517
asapersson5f7226f2016-11-25 04:37:00 -0800518TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
519 const bool kNackEnabled = true;
520 const size_t kNumStreams = 1;
521 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800522 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800523 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
524
525 // Capture a frame and wait for it to synchronize with the encoder thread.
526 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
527 sink_.WaitForEncodedFrame(1);
528 // The encoder have been configured once when the first frame is received.
529 EXPECT_EQ(1, sink_.number_of_reconfigurations());
530 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
531 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
532 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
533 // Resilience is off for no temporal layers with nack on.
534 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
535 vie_encoder_->Stop();
536}
537
538TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
539 const bool kNackEnabled = true;
540 const size_t kNumStreams = 2;
541 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800542 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800543 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
544
545 // Capture a frame and wait for it to synchronize with the encoder thread.
546 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
547 sink_.WaitForEncodedFrame(1);
548 // The encoder have been configured once when the first frame is received.
549 EXPECT_EQ(1, sink_.number_of_reconfigurations());
550 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
551 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
552 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
553 // Resilience is off for no temporal layers and >1 streams with nack on.
554 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
555 vie_encoder_->Stop();
556}
557
558TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
559 const bool kNackEnabled = false;
560 const size_t kNumStreams = 1;
561 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800562 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800563 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
564
565 // Capture a frame and wait for it to synchronize with the encoder thread.
566 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
567 sink_.WaitForEncodedFrame(1);
568 // The encoder have been configured once when the first frame is received.
569 EXPECT_EQ(1, sink_.number_of_reconfigurations());
570 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
571 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
572 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
573 // Resilience is on for no temporal layers with nack off.
574 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
575 vie_encoder_->Stop();
576}
577
578TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
579 const bool kNackEnabled = true;
580 const size_t kNumStreams = 1;
581 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800582 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800583 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
584
585 // Capture a frame and wait for it to synchronize with the encoder thread.
586 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
587 sink_.WaitForEncodedFrame(1);
588 // The encoder have been configured once when the first frame is received.
589 EXPECT_EQ(1, sink_.number_of_reconfigurations());
590 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
591 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
592 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
593 // Resilience is on for temporal layers.
594 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
595 vie_encoder_->Stop();
596}
597
perkj803d97f2016-11-01 11:45:46 -0700598TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
599 EXPECT_TRUE(video_source_.has_sinks());
600 test::FrameForwarder new_video_source;
601 vie_encoder_->SetSource(&new_video_source,
602 VideoSendStream::DegradationPreference::kBalanced);
603 EXPECT_FALSE(video_source_.has_sinks());
604 EXPECT_TRUE(new_video_source.has_sinks());
605
606 vie_encoder_->Stop();
607}
608
609TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
610 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
611 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
612 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
613 vie_encoder_->Stop();
614}
615
616TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700617 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
618
sprang84a37592017-02-10 07:04:27 -0800619 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700620 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700621
622 int frame_width = 1280;
623 int frame_height = 720;
624
625 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
626 // request lower resolution.
627 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
628 video_source_.IncomingCapturedFrame(
629 CreateFrame(i, frame_width, frame_height));
630 sink_.WaitForEncodedFrame(i);
631
632 vie_encoder_->TriggerCpuOveruse();
633
sprang84a37592017-02-10 07:04:27 -0800634 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700635 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
636 std::numeric_limits<int>::max()),
637 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700638
639 frame_width /= 2;
640 frame_height /= 2;
641 }
642
kthelgason876222f2016-11-29 01:44:11 -0800643 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700644 // lower resolution.
645 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
646 video_source_.IncomingCapturedFrame(CreateFrame(
647 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
648 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
649 vie_encoder_->TriggerCpuOveruse();
sprang84a37592017-02-10 07:04:27 -0800650 EXPECT_EQ(video_source_.sink_wants().target_pixel_count,
651 current_wants.target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700652 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
653 current_wants.max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700654
655 // Trigger CPU normal use.
656 vie_encoder_->TriggerCpuNormalUsage();
sprang84a37592017-02-10 07:04:27 -0800657 EXPECT_EQ(frame_width * frame_height * 5 / 3,
658 video_source_.sink_wants().target_pixel_count.value_or(0));
659 EXPECT_EQ(frame_width * frame_height * 4,
660 video_source_.sink_wants().max_pixel_count.value_or(0));
perkj803d97f2016-11-01 11:45:46 -0700661
662 vie_encoder_->Stop();
663}
664
665TEST_F(ViEEncoderTest,
666 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700667 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
668
sprang84a37592017-02-10 07:04:27 -0800669 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700670 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700671
672 int frame_width = 1280;
673 int frame_height = 720;
674
kthelgason5e13d412016-12-01 03:59:51 -0800675 video_source_.IncomingCapturedFrame(
676 CreateFrame(1, frame_width, frame_height));
677 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700678 // Trigger CPU overuse.
679 vie_encoder_->TriggerCpuOveruse();
680
681 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800682 CreateFrame(2, frame_width, frame_height));
683 sink_.WaitForEncodedFrame(2);
sprang84a37592017-02-10 07:04:27 -0800684 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700685 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
686 std::numeric_limits<int>::max()),
687 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700688
689 // Set new source.
690 test::FrameForwarder new_video_source;
691 vie_encoder_->SetSource(
692 &new_video_source,
693 VideoSendStream::DegradationPreference::kMaintainResolution);
694
sprang84a37592017-02-10 07:04:27 -0800695 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700696 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700697
698 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800699 CreateFrame(3, frame_width, frame_height));
700 sink_.WaitForEncodedFrame(3);
sprang84a37592017-02-10 07:04:27 -0800701 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700702 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700703
704 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
705 vie_encoder_->SetSource(&new_video_source,
706 VideoSendStream::DegradationPreference::kBalanced);
707 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
708 std::numeric_limits<int>::max()),
709 frame_width * frame_height);
sprang84a37592017-02-10 07:04:27 -0800710 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700711
712 vie_encoder_->Stop();
713}
714
715TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700716 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
717
718 int frame_width = 1280;
719 int frame_height = 720;
720
721 video_source_.IncomingCapturedFrame(
722 CreateFrame(1, frame_width, frame_height));
723 sink_.WaitForEncodedFrame(1);
724 VideoSendStream::Stats stats = stats_proxy_->GetStats();
725 EXPECT_FALSE(stats.cpu_limited_resolution);
726 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
727
728 // Trigger CPU overuse.
729 vie_encoder_->TriggerCpuOveruse();
730 video_source_.IncomingCapturedFrame(
731 CreateFrame(2, frame_width, frame_height));
732 sink_.WaitForEncodedFrame(2);
733
734 stats = stats_proxy_->GetStats();
735 EXPECT_TRUE(stats.cpu_limited_resolution);
736 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
737
738 // Trigger CPU normal use.
739 vie_encoder_->TriggerCpuNormalUsage();
740 video_source_.IncomingCapturedFrame(
741 CreateFrame(3, frame_width, frame_height));
742 sink_.WaitForEncodedFrame(3);
743
744 stats = stats_proxy_->GetStats();
745 EXPECT_FALSE(stats.cpu_limited_resolution);
746 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
747
748 vie_encoder_->Stop();
749}
750
kthelgason876222f2016-11-29 01:44:11 -0800751TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800752 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
753
754 int frame_width = 1280;
755 int frame_height = 720;
756 video_source_.IncomingCapturedFrame(
757 CreateFrame(1, frame_width, frame_height));
758 sink_.WaitForEncodedFrame(1);
759
760 VideoSendStream::Stats stats = stats_proxy_->GetStats();
761 EXPECT_FALSE(stats.cpu_limited_resolution);
762 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
763
764 vie_encoder_->TriggerCpuOveruse();
765
766 video_source_.IncomingCapturedFrame(
767 CreateFrame(2, frame_width, frame_height));
768 sink_.WaitForEncodedFrame(2);
769 stats = stats_proxy_->GetStats();
770 EXPECT_TRUE(stats.cpu_limited_resolution);
771 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
772
773 // Set new source with adaptation still enabled.
774 test::FrameForwarder new_video_source;
775 vie_encoder_->SetSource(&new_video_source,
776 VideoSendStream::DegradationPreference::kBalanced);
777
778 new_video_source.IncomingCapturedFrame(
779 CreateFrame(3, frame_width, frame_height));
780 sink_.WaitForEncodedFrame(3);
781 stats = stats_proxy_->GetStats();
782 EXPECT_TRUE(stats.cpu_limited_resolution);
783 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
784
785 // Set adaptation disabled.
786 vie_encoder_->SetSource(
787 &new_video_source,
788 VideoSendStream::DegradationPreference::kMaintainResolution);
789
790 new_video_source.IncomingCapturedFrame(
791 CreateFrame(4, frame_width, frame_height));
792 sink_.WaitForEncodedFrame(4);
793 stats = stats_proxy_->GetStats();
794 EXPECT_FALSE(stats.cpu_limited_resolution);
795 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
796
797 // Set adaptation back to enabled.
798 vie_encoder_->SetSource(&new_video_source,
799 VideoSendStream::DegradationPreference::kBalanced);
800
801 new_video_source.IncomingCapturedFrame(
802 CreateFrame(5, frame_width, frame_height));
803 sink_.WaitForEncodedFrame(5);
804 stats = stats_proxy_->GetStats();
805 EXPECT_TRUE(stats.cpu_limited_resolution);
806 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
807
808 vie_encoder_->TriggerCpuNormalUsage();
809
810 new_video_source.IncomingCapturedFrame(
811 CreateFrame(6, frame_width, frame_height));
812 sink_.WaitForEncodedFrame(6);
813 stats = stats_proxy_->GetStats();
814 EXPECT_FALSE(stats.cpu_limited_resolution);
815 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
816
817 vie_encoder_->Stop();
818}
819
820TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800821 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
822
823 int frame_width = 1280;
824 int frame_height = 720;
825 video_source_.IncomingCapturedFrame(
826 CreateFrame(1, frame_width, frame_height));
827 sink_.WaitForEncodedFrame(1);
828
829 VideoSendStream::Stats stats = stats_proxy_->GetStats();
830 EXPECT_FALSE(stats.cpu_limited_resolution);
831 EXPECT_FALSE(stats.bw_limited_resolution);
832 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
833
834 // Set new source with adaptation still enabled.
835 test::FrameForwarder new_video_source;
836 vie_encoder_->SetSource(&new_video_source,
837 VideoSendStream::DegradationPreference::kBalanced);
838
839 new_video_source.IncomingCapturedFrame(
840 CreateFrame(2, frame_width, frame_height));
841 sink_.WaitForEncodedFrame(2);
842 stats = stats_proxy_->GetStats();
843 EXPECT_FALSE(stats.cpu_limited_resolution);
844 EXPECT_FALSE(stats.bw_limited_resolution);
845 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
846
847 vie_encoder_->TriggerQualityLow();
848
849 new_video_source.IncomingCapturedFrame(
850 CreateFrame(3, frame_width, frame_height));
851 sink_.WaitForEncodedFrame(3);
852 stats = stats_proxy_->GetStats();
853 EXPECT_FALSE(stats.cpu_limited_resolution);
854 EXPECT_TRUE(stats.bw_limited_resolution);
855
856 vie_encoder_->SetSource(&new_video_source,
857 VideoSendStream::DegradationPreference::kBalanced);
858
859 new_video_source.IncomingCapturedFrame(
860 CreateFrame(4, frame_width, frame_height));
861 sink_.WaitForEncodedFrame(4);
862 stats = stats_proxy_->GetStats();
863 EXPECT_FALSE(stats.cpu_limited_resolution);
864 EXPECT_TRUE(stats.bw_limited_resolution);
865
866 // Set adaptation disabled.
867 vie_encoder_->SetSource(
868 &new_video_source,
869 VideoSendStream::DegradationPreference::kMaintainResolution);
870
871 new_video_source.IncomingCapturedFrame(
872 CreateFrame(5, frame_width, frame_height));
873 sink_.WaitForEncodedFrame(5);
874 stats = stats_proxy_->GetStats();
875 EXPECT_FALSE(stats.cpu_limited_resolution);
876 EXPECT_FALSE(stats.bw_limited_resolution);
877
878 vie_encoder_->Stop();
879}
880
perkj803d97f2016-11-01 11:45:46 -0700881TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700882 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
883
perkj803d97f2016-11-01 11:45:46 -0700884 int frame_width = 1280;
885 int frame_height = 720;
sprang84a37592017-02-10 07:04:27 -0800886 int sequence = 1;
perkj803d97f2016-11-01 11:45:46 -0700887
sprang84a37592017-02-10 07:04:27 -0800888 // Trigger CPU overuse, won't bite before first frame.
889 vie_encoder_->TriggerCpuOveruse();
perkj803d97f2016-11-01 11:45:46 -0700890 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800891 CreateFrame(sequence, frame_width, frame_height));
892 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700893
894 VideoSendStream::Stats stats = stats_proxy_->GetStats();
sprang84a37592017-02-10 07:04:27 -0800895 EXPECT_FALSE(stats.cpu_limited_resolution);
896 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
897
898 // Trigger CPU overuse again, should now adapt down.
899 vie_encoder_->TriggerCpuOveruse();
900 video_source_.IncomingCapturedFrame(
901 CreateFrame(sequence, frame_width, frame_height));
902 sink_.WaitForEncodedFrame(sequence++);
903
904 stats = stats_proxy_->GetStats();
perkj803d97f2016-11-01 11:45:46 -0700905 EXPECT_TRUE(stats.cpu_limited_resolution);
906 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
907
908 // Set new source with adaptation still enabled.
909 test::FrameForwarder new_video_source;
910 vie_encoder_->SetSource(&new_video_source,
911 VideoSendStream::DegradationPreference::kBalanced);
912
913 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800914 CreateFrame(sequence, frame_width, frame_height));
915 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700916 stats = stats_proxy_->GetStats();
917 EXPECT_TRUE(stats.cpu_limited_resolution);
918 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
919
920 // Set adaptation disabled.
921 vie_encoder_->SetSource(
922 &new_video_source,
923 VideoSendStream::DegradationPreference::kMaintainResolution);
924 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800925 CreateFrame(sequence, frame_width, frame_height));
926 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700927 stats = stats_proxy_->GetStats();
928 EXPECT_FALSE(stats.cpu_limited_resolution);
929 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
930
931 // Switch back the source with adaptation enabled.
932 vie_encoder_->SetSource(&video_source_,
933 VideoSendStream::DegradationPreference::kBalanced);
934 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800935 CreateFrame(sequence, frame_width, frame_height));
936 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700937 stats = stats_proxy_->GetStats();
938 EXPECT_TRUE(stats.cpu_limited_resolution);
939 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
940
941 // Trigger CPU normal usage.
942 vie_encoder_->TriggerCpuNormalUsage();
943 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800944 CreateFrame(sequence, frame_width, frame_height));
945 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700946 stats = stats_proxy_->GetStats();
947 EXPECT_FALSE(stats.cpu_limited_resolution);
948 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
949
950 vie_encoder_->Stop();
951}
952
Erik Språng08127a92016-11-16 16:41:30 +0100953TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100954 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
955
956 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
957 sink_.WaitForEncodedFrame(1);
958
959 VideoSendStream::Stats stats = stats_proxy_->GetStats();
960 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
961 stats.preferred_media_bitrate_bps);
962
963 vie_encoder_->Stop();
964}
965
kthelgason876222f2016-11-29 01:44:11 -0800966TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
kthelgason876222f2016-11-29 01:44:11 -0800967 int frame_width = 1280;
968 int frame_height = 720;
969 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
970
971 // Expect no scaling to begin with
sprang84a37592017-02-10 07:04:27 -0800972 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -0800973 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -0800974
kthelgason876222f2016-11-29 01:44:11 -0800975 video_source_.IncomingCapturedFrame(
976 CreateFrame(1, frame_width, frame_height));
977 sink_.WaitForEncodedFrame(1);
978
kthelgason5e13d412016-12-01 03:59:51 -0800979 // Trigger scale down
980 vie_encoder_->TriggerQualityLow();
981
982 video_source_.IncomingCapturedFrame(
983 CreateFrame(2, frame_width, frame_height));
984 sink_.WaitForEncodedFrame(2);
985
kthelgason876222f2016-11-29 01:44:11 -0800986 // Expect a scale down.
987 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
988 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
989 frame_width * frame_height);
990
991 // Set adaptation disabled.
992 test::FrameForwarder new_video_source;
993 vie_encoder_->SetSource(
994 &new_video_source,
995 VideoSendStream::DegradationPreference::kMaintainResolution);
996
997 // Trigger scale down
998 vie_encoder_->TriggerQualityLow();
999 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001000 CreateFrame(3, frame_width, frame_height));
1001 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -08001002
1003 // Expect no scaling
1004 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1005
1006 // Trigger scale up
1007 vie_encoder_->TriggerQualityHigh();
1008 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001009 CreateFrame(4, frame_width, frame_height));
1010 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -08001011
1012 // Expect nothing to change, still no scaling
1013 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1014
1015 vie_encoder_->Stop();
1016}
1017
kthelgason5e13d412016-12-01 03:59:51 -08001018TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
kthelgason5e13d412016-12-01 03:59:51 -08001019 int frame_width = 1280;
1020 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -08001021 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1022
1023 for (size_t i = 1; i <= 10; i++) {
1024 video_source_.IncomingCapturedFrame(
1025 CreateFrame(i, frame_width, frame_height));
1026 sink_.WaitForEncodedFrame(i);
1027 // Trigger scale down
1028 vie_encoder_->TriggerQualityLow();
1029 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
1030 }
1031
1032 vie_encoder_->Stop();
1033}
1034
perkj803d97f2016-11-01 11:45:46 -07001035TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -07001036 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1037
1038 int frame_width = 640;
1039 int frame_height = 360;
1040
1041 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1042 video_source_.IncomingCapturedFrame(
1043 CreateFrame(i, frame_width, frame_height));
1044 sink_.WaitForEncodedFrame(i);
1045 }
1046
1047 vie_encoder_->TriggerCpuOveruse();
1048 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1049 video_source_.IncomingCapturedFrame(
1050 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
1051 frame_width, frame_height));
1052 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
1053 i);
1054 }
1055
1056 vie_encoder_->Stop();
1057
1058 stats_proxy_.reset();
1059 EXPECT_EQ(1,
1060 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1061 EXPECT_EQ(
1062 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1063}
1064
sprang57c2fff2017-01-16 06:24:02 -08001065TEST_F(ViEEncoderTest, CallsBitrateObserver) {
1066 class MockBitrateObserver : public VideoBitrateAllocationObserver {
1067 public:
1068 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
1069 } bitrate_observer;
1070 vie_encoder_->SetBitrateObserver(&bitrate_observer);
1071
1072 const int kDefaultFps = 30;
1073 const BitrateAllocation expected_bitrate =
1074 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
kthelgason2bc68642017-02-07 07:02:22 -08001075 .GetAllocation(kLowTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -08001076
1077 // First called on bitrate updated, then again on first frame.
1078 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1079 .Times(2);
kthelgason2bc68642017-02-07 07:02:22 -08001080 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001081
1082 const int64_t kStartTimeMs = 1;
1083 video_source_.IncomingCapturedFrame(
1084 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1085 sink_.WaitForEncodedFrame(kStartTimeMs);
1086
1087 // Not called on second frame.
1088 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1089 .Times(0);
1090 video_source_.IncomingCapturedFrame(
1091 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1092 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1093
1094 // Called after a process interval.
1095 const int64_t kProcessIntervalMs =
1096 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1097 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1098 // Sleep for one processing interval plus one frame to avoid flakiness.
1099 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1100 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1101 .Times(1);
1102 video_source_.IncomingCapturedFrame(CreateFrame(
1103 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1104 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1105
1106 vie_encoder_->Stop();
1107}
1108
kthelgason2bc68642017-02-07 07:02:22 -08001109TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
1110 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1111 int frame_width = 640;
1112 int frame_height = 360;
1113
1114 video_source_.IncomingCapturedFrame(
1115 CreateFrame(1, frame_width, frame_height));
1116
1117 // Expect to drop this frame, the wait should time out.
1118 sink_.ExpectDroppedFrame();
1119
1120 // Expect the sink_wants to specify a scaled frame.
1121 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1122 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1123
1124 int last_pixel_count = *video_source_.sink_wants().max_pixel_count;
1125
1126 // Next frame is scaled
1127 video_source_.IncomingCapturedFrame(
1128 CreateFrame(2, frame_width * 3 / 4, frame_height * 3 / 4));
1129
1130 // Expect to drop this frame, the wait should time out.
1131 sink_.ExpectDroppedFrame();
1132
1133 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, last_pixel_count);
1134
1135 vie_encoder_->Stop();
1136}
1137
1138TEST_F(ViEEncoderTest, NrOfDroppedFramesLimited) {
1139 // 1kbps. This can never be achieved.
1140 vie_encoder_->OnBitrateUpdated(1000, 0, 0);
1141 int frame_width = 640;
1142 int frame_height = 360;
1143
1144 // We expect the n initial frames to get dropped.
1145 int i;
1146 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
1147 video_source_.IncomingCapturedFrame(
1148 CreateFrame(i, frame_width, frame_height));
1149 sink_.ExpectDroppedFrame();
1150 }
1151 // The n+1th frame should not be dropped, even though it's size is too large.
1152 video_source_.IncomingCapturedFrame(
1153 CreateFrame(i, frame_width, frame_height));
1154 sink_.WaitForEncodedFrame(i);
1155
1156 // Expect the sink_wants to specify a scaled frame.
1157 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1158 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1159
1160 vie_encoder_->Stop();
1161}
1162
1163TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
1164 int frame_width = 640;
1165 int frame_height = 360;
1166 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1167
1168 // Set degradation preference.
1169 vie_encoder_->SetSource(
1170 &video_source_,
1171 VideoSendStream::DegradationPreference::kMaintainResolution);
1172
1173 video_source_.IncomingCapturedFrame(
1174 CreateFrame(1, frame_width, frame_height));
1175 // Frame should not be dropped, even if it's too large.
1176 sink_.WaitForEncodedFrame(1);
1177
1178 vie_encoder_->Stop();
1179}
1180
sprangb1ca0732017-02-01 08:38:12 -08001181// TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
1182TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) {
1183 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1184
1185 const int kFrameWidth = 1280;
1186 const int kFrameHeight = 720;
1187 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
1188 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
1189 video_source_.set_adaptation_enabled(true);
1190
1191 video_source_.IncomingCapturedFrame(
1192 CreateFrame(1, kFrameWidth, kFrameHeight));
1193 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1194
1195 // Trigger CPU overuse, downscale by 3/4.
1196 vie_encoder_->TriggerCpuOveruse();
1197 video_source_.IncomingCapturedFrame(
1198 CreateFrame(2, kFrameWidth, kFrameHeight));
1199 sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
1200
1201 // Trigger CPU normal use, return to original resoluton;
1202 vie_encoder_->TriggerCpuNormalUsage();
1203 video_source_.IncomingCapturedFrame(
1204 CreateFrame(3, kFrameWidth, kFrameHeight));
1205 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1206
1207 vie_encoder_->Stop();
1208}
perkj26091b12016-09-01 01:17:40 -07001209} // namespace webrtc