blob: 09d9a97d8c5d1d44ceb0fa432835fae6ebfb69a0 [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_);
154 adapter_.OnResolutionRequest(wants.max_pixel_count,
155 wants.max_pixel_count_step_up);
156 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
619 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
620 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
621
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
634 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
635 std::numeric_limits<int>::max()),
636 frame_width * frame_height);
637 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
638
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();
650 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
651 current_wants.max_pixel_count);
652 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up,
653 current_wants.max_pixel_count_step_up);
654
655 // Trigger CPU normal use.
656 vie_encoder_->TriggerCpuNormalUsage();
657 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
658 EXPECT_EQ(video_source_.sink_wants().max_pixel_count_step_up.value_or(0),
659 frame_width * frame_height);
660
661 vie_encoder_->Stop();
662}
663
664TEST_F(ViEEncoderTest,
665 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700666 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
667
668 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
669 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
670
671 int frame_width = 1280;
672 int frame_height = 720;
673
kthelgason5e13d412016-12-01 03:59:51 -0800674 video_source_.IncomingCapturedFrame(
675 CreateFrame(1, frame_width, frame_height));
676 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700677 // Trigger CPU overuse.
678 vie_encoder_->TriggerCpuOveruse();
679
680 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800681 CreateFrame(2, frame_width, frame_height));
682 sink_.WaitForEncodedFrame(2);
perkj803d97f2016-11-01 11:45:46 -0700683 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
684 std::numeric_limits<int>::max()),
685 frame_width * frame_height);
686 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
687
688 // Set new source.
689 test::FrameForwarder new_video_source;
690 vie_encoder_->SetSource(
691 &new_video_source,
692 VideoSendStream::DegradationPreference::kMaintainResolution);
693
694 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
695 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
696
697 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800698 CreateFrame(3, frame_width, frame_height));
699 sink_.WaitForEncodedFrame(3);
perkj803d97f2016-11-01 11:45:46 -0700700 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
701 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
702
703 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
704 vie_encoder_->SetSource(&new_video_source,
705 VideoSendStream::DegradationPreference::kBalanced);
706 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
707 std::numeric_limits<int>::max()),
708 frame_width * frame_height);
709 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count_step_up);
710
711 vie_encoder_->Stop();
712}
713
714TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700715 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
716
717 int frame_width = 1280;
718 int frame_height = 720;
719
720 video_source_.IncomingCapturedFrame(
721 CreateFrame(1, frame_width, frame_height));
722 sink_.WaitForEncodedFrame(1);
723 VideoSendStream::Stats stats = stats_proxy_->GetStats();
724 EXPECT_FALSE(stats.cpu_limited_resolution);
725 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
726
727 // Trigger CPU overuse.
728 vie_encoder_->TriggerCpuOveruse();
729 video_source_.IncomingCapturedFrame(
730 CreateFrame(2, frame_width, frame_height));
731 sink_.WaitForEncodedFrame(2);
732
733 stats = stats_proxy_->GetStats();
734 EXPECT_TRUE(stats.cpu_limited_resolution);
735 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
736
737 // Trigger CPU normal use.
738 vie_encoder_->TriggerCpuNormalUsage();
739 video_source_.IncomingCapturedFrame(
740 CreateFrame(3, frame_width, frame_height));
741 sink_.WaitForEncodedFrame(3);
742
743 stats = stats_proxy_->GetStats();
744 EXPECT_FALSE(stats.cpu_limited_resolution);
745 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
746
747 vie_encoder_->Stop();
748}
749
kthelgason876222f2016-11-29 01:44:11 -0800750TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800751 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
752
753 int frame_width = 1280;
754 int frame_height = 720;
755 video_source_.IncomingCapturedFrame(
756 CreateFrame(1, frame_width, frame_height));
757 sink_.WaitForEncodedFrame(1);
758
759 VideoSendStream::Stats stats = stats_proxy_->GetStats();
760 EXPECT_FALSE(stats.cpu_limited_resolution);
761 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
762
763 vie_encoder_->TriggerCpuOveruse();
764
765 video_source_.IncomingCapturedFrame(
766 CreateFrame(2, frame_width, frame_height));
767 sink_.WaitForEncodedFrame(2);
768 stats = stats_proxy_->GetStats();
769 EXPECT_TRUE(stats.cpu_limited_resolution);
770 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
771
772 // Set new source with adaptation still enabled.
773 test::FrameForwarder new_video_source;
774 vie_encoder_->SetSource(&new_video_source,
775 VideoSendStream::DegradationPreference::kBalanced);
776
777 new_video_source.IncomingCapturedFrame(
778 CreateFrame(3, frame_width, frame_height));
779 sink_.WaitForEncodedFrame(3);
780 stats = stats_proxy_->GetStats();
781 EXPECT_TRUE(stats.cpu_limited_resolution);
782 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
783
784 // Set adaptation disabled.
785 vie_encoder_->SetSource(
786 &new_video_source,
787 VideoSendStream::DegradationPreference::kMaintainResolution);
788
789 new_video_source.IncomingCapturedFrame(
790 CreateFrame(4, frame_width, frame_height));
791 sink_.WaitForEncodedFrame(4);
792 stats = stats_proxy_->GetStats();
793 EXPECT_FALSE(stats.cpu_limited_resolution);
794 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
795
796 // Set adaptation back to enabled.
797 vie_encoder_->SetSource(&new_video_source,
798 VideoSendStream::DegradationPreference::kBalanced);
799
800 new_video_source.IncomingCapturedFrame(
801 CreateFrame(5, frame_width, frame_height));
802 sink_.WaitForEncodedFrame(5);
803 stats = stats_proxy_->GetStats();
804 EXPECT_TRUE(stats.cpu_limited_resolution);
805 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
806
807 vie_encoder_->TriggerCpuNormalUsage();
808
809 new_video_source.IncomingCapturedFrame(
810 CreateFrame(6, frame_width, frame_height));
811 sink_.WaitForEncodedFrame(6);
812 stats = stats_proxy_->GetStats();
813 EXPECT_FALSE(stats.cpu_limited_resolution);
814 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
815
816 vie_encoder_->Stop();
817}
818
819TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800820 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
821
822 int frame_width = 1280;
823 int frame_height = 720;
824 video_source_.IncomingCapturedFrame(
825 CreateFrame(1, frame_width, frame_height));
826 sink_.WaitForEncodedFrame(1);
827
828 VideoSendStream::Stats stats = stats_proxy_->GetStats();
829 EXPECT_FALSE(stats.cpu_limited_resolution);
830 EXPECT_FALSE(stats.bw_limited_resolution);
831 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
832
833 // Set new source with adaptation still enabled.
834 test::FrameForwarder new_video_source;
835 vie_encoder_->SetSource(&new_video_source,
836 VideoSendStream::DegradationPreference::kBalanced);
837
838 new_video_source.IncomingCapturedFrame(
839 CreateFrame(2, frame_width, frame_height));
840 sink_.WaitForEncodedFrame(2);
841 stats = stats_proxy_->GetStats();
842 EXPECT_FALSE(stats.cpu_limited_resolution);
843 EXPECT_FALSE(stats.bw_limited_resolution);
844 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
845
846 vie_encoder_->TriggerQualityLow();
847
848 new_video_source.IncomingCapturedFrame(
849 CreateFrame(3, frame_width, frame_height));
850 sink_.WaitForEncodedFrame(3);
851 stats = stats_proxy_->GetStats();
852 EXPECT_FALSE(stats.cpu_limited_resolution);
853 EXPECT_TRUE(stats.bw_limited_resolution);
854
855 vie_encoder_->SetSource(&new_video_source,
856 VideoSendStream::DegradationPreference::kBalanced);
857
858 new_video_source.IncomingCapturedFrame(
859 CreateFrame(4, frame_width, frame_height));
860 sink_.WaitForEncodedFrame(4);
861 stats = stats_proxy_->GetStats();
862 EXPECT_FALSE(stats.cpu_limited_resolution);
863 EXPECT_TRUE(stats.bw_limited_resolution);
864
865 // Set adaptation disabled.
866 vie_encoder_->SetSource(
867 &new_video_source,
868 VideoSendStream::DegradationPreference::kMaintainResolution);
869
870 new_video_source.IncomingCapturedFrame(
871 CreateFrame(5, frame_width, frame_height));
872 sink_.WaitForEncodedFrame(5);
873 stats = stats_proxy_->GetStats();
874 EXPECT_FALSE(stats.cpu_limited_resolution);
875 EXPECT_FALSE(stats.bw_limited_resolution);
876
877 vie_encoder_->Stop();
878}
879
perkj803d97f2016-11-01 11:45:46 -0700880TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700881 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
882
883 // Trigger CPU overuse.
884 vie_encoder_->TriggerCpuOveruse();
885 int frame_width = 1280;
886 int frame_height = 720;
887
888 video_source_.IncomingCapturedFrame(
889 CreateFrame(1, frame_width, frame_height));
890 sink_.WaitForEncodedFrame(1);
891
892 VideoSendStream::Stats stats = stats_proxy_->GetStats();
893 EXPECT_TRUE(stats.cpu_limited_resolution);
894 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
895
896 // Set new source with adaptation still enabled.
897 test::FrameForwarder new_video_source;
898 vie_encoder_->SetSource(&new_video_source,
899 VideoSendStream::DegradationPreference::kBalanced);
900
901 new_video_source.IncomingCapturedFrame(
902 CreateFrame(2, frame_width, frame_height));
903 sink_.WaitForEncodedFrame(2);
904 stats = stats_proxy_->GetStats();
905 EXPECT_TRUE(stats.cpu_limited_resolution);
906 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
907
908 // Set adaptation disabled.
909 vie_encoder_->SetSource(
910 &new_video_source,
911 VideoSendStream::DegradationPreference::kMaintainResolution);
912 new_video_source.IncomingCapturedFrame(
913 CreateFrame(3, frame_width, frame_height));
914 sink_.WaitForEncodedFrame(3);
915 stats = stats_proxy_->GetStats();
916 EXPECT_FALSE(stats.cpu_limited_resolution);
917 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
918
919 // Switch back the source with adaptation enabled.
920 vie_encoder_->SetSource(&video_source_,
921 VideoSendStream::DegradationPreference::kBalanced);
922 video_source_.IncomingCapturedFrame(
923 CreateFrame(4, frame_width, frame_height));
924 sink_.WaitForEncodedFrame(4);
925 stats = stats_proxy_->GetStats();
926 EXPECT_TRUE(stats.cpu_limited_resolution);
927 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
928
929 // Trigger CPU normal usage.
930 vie_encoder_->TriggerCpuNormalUsage();
931 video_source_.IncomingCapturedFrame(
932 CreateFrame(5, frame_width, frame_height));
933 sink_.WaitForEncodedFrame(5);
934 stats = stats_proxy_->GetStats();
935 EXPECT_FALSE(stats.cpu_limited_resolution);
936 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
937
938 vie_encoder_->Stop();
939}
940
Erik Språng08127a92016-11-16 16:41:30 +0100941TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100942 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
943
944 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
945 sink_.WaitForEncodedFrame(1);
946
947 VideoSendStream::Stats stats = stats_proxy_->GetStats();
948 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
949 stats.preferred_media_bitrate_bps);
950
951 vie_encoder_->Stop();
952}
953
kthelgason876222f2016-11-29 01:44:11 -0800954TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
kthelgason876222f2016-11-29 01:44:11 -0800955 int frame_width = 1280;
956 int frame_height = 720;
957 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
958
959 // Expect no scaling to begin with
960 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
961 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up);
962
kthelgason876222f2016-11-29 01:44:11 -0800963 video_source_.IncomingCapturedFrame(
964 CreateFrame(1, frame_width, frame_height));
965 sink_.WaitForEncodedFrame(1);
966
kthelgason5e13d412016-12-01 03:59:51 -0800967 // Trigger scale down
968 vie_encoder_->TriggerQualityLow();
969
970 video_source_.IncomingCapturedFrame(
971 CreateFrame(2, frame_width, frame_height));
972 sink_.WaitForEncodedFrame(2);
973
kthelgason876222f2016-11-29 01:44:11 -0800974 // Expect a scale down.
975 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
976 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
977 frame_width * frame_height);
978
979 // Set adaptation disabled.
980 test::FrameForwarder new_video_source;
981 vie_encoder_->SetSource(
982 &new_video_source,
983 VideoSendStream::DegradationPreference::kMaintainResolution);
984
985 // Trigger scale down
986 vie_encoder_->TriggerQualityLow();
987 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800988 CreateFrame(3, frame_width, frame_height));
989 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -0800990
991 // Expect no scaling
992 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
993
994 // Trigger scale up
995 vie_encoder_->TriggerQualityHigh();
996 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800997 CreateFrame(4, frame_width, frame_height));
998 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -0800999
1000 // Expect nothing to change, still no scaling
1001 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1002
1003 vie_encoder_->Stop();
1004}
1005
kthelgason5e13d412016-12-01 03:59:51 -08001006TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
kthelgason5e13d412016-12-01 03:59:51 -08001007 int frame_width = 1280;
1008 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -08001009 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1010
1011 for (size_t i = 1; i <= 10; i++) {
1012 video_source_.IncomingCapturedFrame(
1013 CreateFrame(i, frame_width, frame_height));
1014 sink_.WaitForEncodedFrame(i);
1015 // Trigger scale down
1016 vie_encoder_->TriggerQualityLow();
1017 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
1018 }
1019
1020 vie_encoder_->Stop();
1021}
1022
perkj803d97f2016-11-01 11:45:46 -07001023TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -07001024 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1025
1026 int frame_width = 640;
1027 int frame_height = 360;
1028
1029 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1030 video_source_.IncomingCapturedFrame(
1031 CreateFrame(i, frame_width, frame_height));
1032 sink_.WaitForEncodedFrame(i);
1033 }
1034
1035 vie_encoder_->TriggerCpuOveruse();
1036 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1037 video_source_.IncomingCapturedFrame(
1038 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
1039 frame_width, frame_height));
1040 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
1041 i);
1042 }
1043
1044 vie_encoder_->Stop();
1045
1046 stats_proxy_.reset();
1047 EXPECT_EQ(1,
1048 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1049 EXPECT_EQ(
1050 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1051}
1052
sprang57c2fff2017-01-16 06:24:02 -08001053TEST_F(ViEEncoderTest, CallsBitrateObserver) {
1054 class MockBitrateObserver : public VideoBitrateAllocationObserver {
1055 public:
1056 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
1057 } bitrate_observer;
1058 vie_encoder_->SetBitrateObserver(&bitrate_observer);
1059
1060 const int kDefaultFps = 30;
1061 const BitrateAllocation expected_bitrate =
1062 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
kthelgason2bc68642017-02-07 07:02:22 -08001063 .GetAllocation(kLowTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -08001064
1065 // First called on bitrate updated, then again on first frame.
1066 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1067 .Times(2);
kthelgason2bc68642017-02-07 07:02:22 -08001068 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001069
1070 const int64_t kStartTimeMs = 1;
1071 video_source_.IncomingCapturedFrame(
1072 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1073 sink_.WaitForEncodedFrame(kStartTimeMs);
1074
1075 // Not called on second frame.
1076 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1077 .Times(0);
1078 video_source_.IncomingCapturedFrame(
1079 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1080 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1081
1082 // Called after a process interval.
1083 const int64_t kProcessIntervalMs =
1084 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1085 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1086 // Sleep for one processing interval plus one frame to avoid flakiness.
1087 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1088 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1089 .Times(1);
1090 video_source_.IncomingCapturedFrame(CreateFrame(
1091 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1092 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1093
1094 vie_encoder_->Stop();
1095}
1096
kthelgason2bc68642017-02-07 07:02:22 -08001097TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
1098 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1099 int frame_width = 640;
1100 int frame_height = 360;
1101
1102 video_source_.IncomingCapturedFrame(
1103 CreateFrame(1, frame_width, frame_height));
1104
1105 // Expect to drop this frame, the wait should time out.
1106 sink_.ExpectDroppedFrame();
1107
1108 // Expect the sink_wants to specify a scaled frame.
1109 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1110 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1111
1112 int last_pixel_count = *video_source_.sink_wants().max_pixel_count;
1113
1114 // Next frame is scaled
1115 video_source_.IncomingCapturedFrame(
1116 CreateFrame(2, frame_width * 3 / 4, frame_height * 3 / 4));
1117
1118 // Expect to drop this frame, the wait should time out.
1119 sink_.ExpectDroppedFrame();
1120
1121 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, last_pixel_count);
1122
1123 vie_encoder_->Stop();
1124}
1125
1126TEST_F(ViEEncoderTest, NrOfDroppedFramesLimited) {
1127 // 1kbps. This can never be achieved.
1128 vie_encoder_->OnBitrateUpdated(1000, 0, 0);
1129 int frame_width = 640;
1130 int frame_height = 360;
1131
1132 // We expect the n initial frames to get dropped.
1133 int i;
1134 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
1135 video_source_.IncomingCapturedFrame(
1136 CreateFrame(i, frame_width, frame_height));
1137 sink_.ExpectDroppedFrame();
1138 }
1139 // The n+1th frame should not be dropped, even though it's size is too large.
1140 video_source_.IncomingCapturedFrame(
1141 CreateFrame(i, frame_width, frame_height));
1142 sink_.WaitForEncodedFrame(i);
1143
1144 // Expect the sink_wants to specify a scaled frame.
1145 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1146 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1147
1148 vie_encoder_->Stop();
1149}
1150
1151TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
1152 int frame_width = 640;
1153 int frame_height = 360;
1154 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1155
1156 // Set degradation preference.
1157 vie_encoder_->SetSource(
1158 &video_source_,
1159 VideoSendStream::DegradationPreference::kMaintainResolution);
1160
1161 video_source_.IncomingCapturedFrame(
1162 CreateFrame(1, frame_width, frame_height));
1163 // Frame should not be dropped, even if it's too large.
1164 sink_.WaitForEncodedFrame(1);
1165
1166 vie_encoder_->Stop();
1167}
1168
sprangb1ca0732017-02-01 08:38:12 -08001169// TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
1170TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) {
1171 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1172
1173 const int kFrameWidth = 1280;
1174 const int kFrameHeight = 720;
1175 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
1176 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
1177 video_source_.set_adaptation_enabled(true);
1178
1179 video_source_.IncomingCapturedFrame(
1180 CreateFrame(1, kFrameWidth, kFrameHeight));
1181 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1182
1183 // Trigger CPU overuse, downscale by 3/4.
1184 vie_encoder_->TriggerCpuOveruse();
1185 video_source_.IncomingCapturedFrame(
1186 CreateFrame(2, kFrameWidth, kFrameHeight));
1187 sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
1188
1189 // Trigger CPU normal use, return to original resoluton;
1190 vie_encoder_->TriggerCpuNormalUsage();
1191 video_source_.IncomingCapturedFrame(
1192 CreateFrame(3, kFrameWidth, kFrameHeight));
1193 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1194
1195 vie_encoder_->Stop();
1196}
perkj26091b12016-09-01 01:17:40 -07001197} // namespace webrtc