blob: eedf771ac6d907ee44fb836b4b429f5901461a2d [file] [log] [blame]
perkj26091b12016-09-01 01:17:40 -07001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
perkj803d97f2016-11-01 11:45:46 -070011#include <limits>
Per512ecb32016-09-23 15:52:06 +020012#include <utility>
13
nisseaf916892017-01-10 07:44:26 -080014#include "webrtc/api/video/i420_buffer.h"
perkj26091b12016-09-01 01:17:40 -070015#include "webrtc/base/logging.h"
sprangb1ca0732017-02-01 08:38:12 -080016#include "webrtc/media/base/videoadapter.h"
sprang57c2fff2017-01-16 06:24:02 -080017#include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
perkj803d97f2016-11-01 11:45:46 -070018#include "webrtc/system_wrappers/include/metrics_default.h"
sprang57c2fff2017-01-16 06:24:02 -080019#include "webrtc/system_wrappers/include/sleep.h"
perkj26091b12016-09-01 01:17:40 -070020#include "webrtc/test/encoder_settings.h"
21#include "webrtc/test/fake_encoder.h"
perkja49cbd32016-09-16 07:53:41 -070022#include "webrtc/test/frame_generator.h"
sprang57c2fff2017-01-16 06:24:02 -080023#include "webrtc/test/gmock.h"
kwibergac9f8762016-09-30 22:29:43 -070024#include "webrtc/test/gtest.h"
perkj26091b12016-09-01 01:17:40 -070025#include "webrtc/video/send_statistics_proxy.h"
26#include "webrtc/video/vie_encoder.h"
27
kthelgason33ce8892016-12-09 03:53:59 -080028namespace {
29#if defined(WEBRTC_ANDROID)
30// TODO(kthelgason): Lower this limit when better testing
31// on MediaCodec and fallback implementations are in place.
32const int kMinPixelsPerFrame = 320 * 180;
33#else
34const int kMinPixelsPerFrame = 120 * 90;
35#endif
36}
37
perkj26091b12016-09-01 01:17:40 -070038namespace webrtc {
39
kthelgason876222f2016-11-29 01:44:11 -080040using DegredationPreference = VideoSendStream::DegradationPreference;
sprangb1ca0732017-02-01 08:38:12 -080041using ScaleReason = AdaptationObserverInterface::AdaptReason;
sprang57c2fff2017-01-16 06:24:02 -080042using ::testing::_;
43using ::testing::Return;
kthelgason876222f2016-11-29 01:44:11 -080044
perkj803d97f2016-11-01 11:45:46 -070045namespace {
asapersson5f7226f2016-11-25 04:37:00 -080046const size_t kMaxPayloadLength = 1440;
kthelgason2bc68642017-02-07 07:02:22 -080047const int kTargetBitrateBps = 1000000;
48const int kLowTargetBitrateBps = kTargetBitrateBps / 10;
49const int kMaxInitialFramedrop = 4;
asapersson5f7226f2016-11-25 04:37:00 -080050
perkj803d97f2016-11-01 11:45:46 -070051class TestBuffer : public webrtc::I420Buffer {
52 public:
53 TestBuffer(rtc::Event* event, int width, int height)
54 : I420Buffer(width, height), event_(event) {}
55
56 private:
57 friend class rtc::RefCountedObject<TestBuffer>;
58 ~TestBuffer() override {
59 if (event_)
60 event_->Set();
61 }
62 rtc::Event* const event_;
63};
64
65class ViEEncoderUnderTest : public ViEEncoder {
66 public:
kthelgason876222f2016-11-29 01:44:11 -080067 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
68 const VideoSendStream::Config::EncoderSettings& settings)
perkj803d97f2016-11-01 11:45:46 -070069 : ViEEncoder(1 /* number_of_cores */,
70 stats_proxy,
71 settings,
72 nullptr /* pre_encode_callback */,
73 nullptr /* encoder_timing */) {}
74
sprangb1ca0732017-02-01 08:38:12 -080075 void PostTaskAndWait(bool down, AdaptReason reason) {
perkj803d97f2016-11-01 11:45:46 -070076 rtc::Event event(false, false);
kthelgason876222f2016-11-29 01:44:11 -080077 encoder_queue()->PostTask([this, &event, reason, down] {
sprangb1ca0732017-02-01 08:38:12 -080078 down ? AdaptDown(reason) : AdaptUp(reason);
perkj803d97f2016-11-01 11:45:46 -070079 event.Set();
80 });
perkj070ba852017-02-16 15:46:27 -080081 ASSERT_TRUE(event.Wait(5000));
perkj803d97f2016-11-01 11:45:46 -070082 }
83
kthelgason2fc52542017-03-03 00:24:41 -080084 // This is used as a synchronisation mechanism, to make sure that the
85 // encoder queue is not blocked before we start sending it frames.
86 void WaitUntilTaskQueueIsIdle() {
87 rtc::Event event(false, false);
88 encoder_queue()->PostTask([&event] {
89 event.Set();
90 });
91 ASSERT_TRUE(event.Wait(5000));
92 }
93
sprangb1ca0732017-02-01 08:38:12 -080094 void TriggerCpuOveruse() { PostTaskAndWait(true, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080095
sprangb1ca0732017-02-01 08:38:12 -080096 void TriggerCpuNormalUsage() { PostTaskAndWait(false, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080097
sprangb1ca0732017-02-01 08:38:12 -080098 void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); }
kthelgason876222f2016-11-29 01:44:11 -080099
sprangb1ca0732017-02-01 08:38:12 -0800100 void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); }
perkj803d97f2016-11-01 11:45:46 -0700101};
102
asapersson5f7226f2016-11-25 04:37:00 -0800103class VideoStreamFactory
104 : public VideoEncoderConfig::VideoStreamFactoryInterface {
105 public:
106 explicit VideoStreamFactory(size_t num_temporal_layers)
107 : num_temporal_layers_(num_temporal_layers) {
108 EXPECT_GT(num_temporal_layers, 0u);
109 }
110
111 private:
112 std::vector<VideoStream> CreateEncoderStreams(
113 int width,
114 int height,
115 const VideoEncoderConfig& encoder_config) override {
116 std::vector<VideoStream> streams =
117 test::CreateVideoStreams(width, height, encoder_config);
118 for (VideoStream& stream : streams) {
119 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
120 }
121 return streams;
122 }
123 const size_t num_temporal_layers_;
124};
125
sprangb1ca0732017-02-01 08:38:12 -0800126class AdaptingFrameForwarder : public test::FrameForwarder {
127 public:
128 AdaptingFrameForwarder() : adaptation_enabled_(false) {}
129 virtual ~AdaptingFrameForwarder() {}
130
131 void set_adaptation_enabled(bool enabled) {
132 rtc::CritScope cs(&crit_);
133 adaptation_enabled_ = enabled;
134 }
135
136 bool adaption_enabled() {
137 rtc::CritScope cs(&crit_);
138 return adaptation_enabled_;
139 }
140
141 void IncomingCapturedFrame(const VideoFrame& video_frame) override {
142 int cropped_width = 0;
143 int cropped_height = 0;
144 int out_width = 0;
145 int out_height = 0;
146 if (adaption_enabled() &&
147 adapter_.AdaptFrameResolution(video_frame.width(), video_frame.height(),
148 video_frame.timestamp_us() * 1000,
149 &cropped_width, &cropped_height,
150 &out_width, &out_height)) {
151 VideoFrame adapted_frame(
152 new rtc::RefCountedObject<TestBuffer>(nullptr, out_width, out_height),
153 99, 99, kVideoRotation_0);
154 adapted_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
155 test::FrameForwarder::IncomingCapturedFrame(adapted_frame);
156 } else {
157 test::FrameForwarder::IncomingCapturedFrame(video_frame);
158 }
159 }
160
161 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
162 const rtc::VideoSinkWants& wants) override {
163 rtc::CritScope cs(&crit_);
sprang84a37592017-02-10 07:04:27 -0800164 adapter_.OnResolutionRequest(wants.target_pixel_count,
165 wants.max_pixel_count);
sprangb1ca0732017-02-01 08:38:12 -0800166 test::FrameForwarder::AddOrUpdateSink(sink, wants);
167 }
168
169 cricket::VideoAdapter adapter_;
170 bool adaptation_enabled_ GUARDED_BY(crit_);
171};
perkj803d97f2016-11-01 11:45:46 -0700172} // namespace
173
perkj26091b12016-09-01 01:17:40 -0700174class ViEEncoderTest : public ::testing::Test {
175 public:
176 static const int kDefaultTimeoutMs = 30 * 1000;
177
178 ViEEncoderTest()
179 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -0700180 codec_width_(320),
181 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -0700182 fake_encoder_(),
perkj803d97f2016-11-01 11:45:46 -0700183 stats_proxy_(new SendStatisticsProxy(
184 Clock::GetRealTimeClock(),
185 video_send_config_,
186 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -0700187 sink_(&fake_encoder_) {}
188
189 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -0700190 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -0700191 video_send_config_ = VideoSendStream::Config(nullptr);
192 video_send_config_.encoder_settings.encoder = &fake_encoder_;
193 video_send_config_.encoder_settings.payload_name = "FAKE";
194 video_send_config_.encoder_settings.payload_type = 125;
195
Per512ecb32016-09-23 15:52:06 +0200196 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700197 test::FillEncoderConfiguration(1, &video_encoder_config);
Erik Språng08127a92016-11-16 16:41:30 +0100198 video_encoder_config_ = video_encoder_config.Copy();
asapersson5f7226f2016-11-25 04:37:00 -0800199 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
200 }
201
202 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
203 bool nack_enabled) {
204 if (vie_encoder_)
205 vie_encoder_->Stop();
perkj803d97f2016-11-01 11:45:46 -0700206 vie_encoder_.reset(new ViEEncoderUnderTest(
207 stats_proxy_.get(), video_send_config_.encoder_settings));
208 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
209 vie_encoder_->SetSource(&video_source_,
210 VideoSendStream::DegradationPreference::kBalanced);
kthelgason2bc68642017-02-07 07:02:22 -0800211 vie_encoder_->SetStartBitrate(kTargetBitrateBps);
asapersson5f7226f2016-11-25 04:37:00 -0800212 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
213 kMaxPayloadLength, nack_enabled);
kthelgason2fc52542017-03-03 00:24:41 -0800214 vie_encoder_->WaitUntilTaskQueueIsIdle();
asapersson5f7226f2016-11-25 04:37:00 -0800215 }
216
217 void ResetEncoder(const std::string& payload_name,
218 size_t num_streams,
219 size_t num_temporal_layers,
220 bool nack_enabled) {
221 video_send_config_.encoder_settings.payload_name = payload_name;
222
223 VideoEncoderConfig video_encoder_config;
224 video_encoder_config.number_of_streams = num_streams;
kthelgason2bc68642017-02-07 07:02:22 -0800225 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
asapersson5f7226f2016-11-25 04:37:00 -0800226 video_encoder_config.video_stream_factory =
227 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
228 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
perkj26091b12016-09-01 01:17:40 -0700229 }
230
sprang57c2fff2017-01-16 06:24:02 -0800231 VideoFrame CreateFrame(int64_t ntp_time_ms,
232 rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200233 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
234 destruction_event, codec_width_, codec_height_),
235 99, 99, kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800236 frame.set_ntp_time_ms(ntp_time_ms);
perkj26091b12016-09-01 01:17:40 -0700237 return frame;
238 }
239
sprang57c2fff2017-01-16 06:24:02 -0800240 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
perkj803d97f2016-11-01 11:45:46 -0700241 VideoFrame frame(
242 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
243 kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800244 frame.set_ntp_time_ms(ntp_time_ms);
perkj803d97f2016-11-01 11:45:46 -0700245 return frame;
246 }
247
perkj26091b12016-09-01 01:17:40 -0700248 class TestEncoder : public test::FakeEncoder {
249 public:
250 TestEncoder()
251 : FakeEncoder(Clock::GetRealTimeClock()),
252 continue_encode_event_(false, false) {}
253
perkjfa10b552016-10-02 23:45:26 -0700254 VideoCodec codec_config() {
brandtre78d2662017-01-16 05:57:16 -0800255 rtc::CritScope lock(&crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700256 return config_;
257 }
258
259 void BlockNextEncode() {
brandtre78d2662017-01-16 05:57:16 -0800260 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700261 block_next_encode_ = true;
262 }
263
kthelgason876222f2016-11-29 01:44:11 -0800264 VideoEncoder::ScalingSettings GetScalingSettings() const override {
kthelgason2fc52542017-03-03 00:24:41 -0800265 rtc::CritScope lock(&local_crit_sect_);
kthelgasonad9010c2017-02-14 00:46:51 -0800266 if (quality_scaling_)
267 return VideoEncoder::ScalingSettings(true, 1, 2);
268 return VideoEncoder::ScalingSettings(false);
kthelgason876222f2016-11-29 01:44:11 -0800269 }
270
perkjfa10b552016-10-02 23:45:26 -0700271 void ContinueEncode() { continue_encode_event_.Set(); }
272
273 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
274 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800275 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700276 EXPECT_EQ(timestamp_, timestamp);
277 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
278 }
279
kthelgason2fc52542017-03-03 00:24:41 -0800280 void SetQualityScaling(bool b) {
281 rtc::CritScope lock(&local_crit_sect_);
282 quality_scaling_ = b;
283 }
kthelgasonad9010c2017-02-14 00:46:51 -0800284
perkjfa10b552016-10-02 23:45:26 -0700285 private:
perkj26091b12016-09-01 01:17:40 -0700286 int32_t Encode(const VideoFrame& input_image,
287 const CodecSpecificInfo* codec_specific_info,
288 const std::vector<FrameType>* frame_types) override {
289 bool block_encode;
290 {
brandtre78d2662017-01-16 05:57:16 -0800291 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700292 EXPECT_GT(input_image.timestamp(), timestamp_);
293 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
294 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
295
296 timestamp_ = input_image.timestamp();
297 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700298 last_input_width_ = input_image.width();
299 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700300 block_encode = block_next_encode_;
301 block_next_encode_ = false;
302 }
303 int32_t result =
304 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
305 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700306 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700307 return result;
308 }
309
brandtre78d2662017-01-16 05:57:16 -0800310 rtc::CriticalSection local_crit_sect_;
perkj26091b12016-09-01 01:17:40 -0700311 bool block_next_encode_ = false;
312 rtc::Event continue_encode_event_;
313 uint32_t timestamp_ = 0;
314 int64_t ntp_time_ms_ = 0;
perkj803d97f2016-11-01 11:45:46 -0700315 int last_input_width_ = 0;
316 int last_input_height_ = 0;
kthelgasonad9010c2017-02-14 00:46:51 -0800317 bool quality_scaling_ = true;
perkj26091b12016-09-01 01:17:40 -0700318 };
319
Per512ecb32016-09-23 15:52:06 +0200320 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700321 public:
322 explicit TestSink(TestEncoder* test_encoder)
323 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
324
perkj26091b12016-09-01 01:17:40 -0700325 void WaitForEncodedFrame(int64_t expected_ntp_time) {
326 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700327 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700328 {
329 rtc::CritScope lock(&crit_);
sprangb1ca0732017-02-01 08:38:12 -0800330 timestamp = last_timestamp_;
perkj26091b12016-09-01 01:17:40 -0700331 }
332 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
333 }
334
sprangb1ca0732017-02-01 08:38:12 -0800335 void WaitForEncodedFrame(uint32_t expected_width,
336 uint32_t expected_height) {
337 uint32_t width = 0;
338 uint32_t height = 0;
339 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
340 {
341 rtc::CritScope lock(&crit_);
342 width = last_width_;
343 height = last_height_;
344 }
345 EXPECT_EQ(expected_height, height);
346 EXPECT_EQ(expected_width, width);
347 }
348
kthelgason2fc52542017-03-03 00:24:41 -0800349 void ExpectDroppedFrame() { EXPECT_FALSE(encoded_frame_event_.Wait(100)); }
kthelgason2bc68642017-02-07 07:02:22 -0800350
perkj26091b12016-09-01 01:17:40 -0700351 void SetExpectNoFrames() {
352 rtc::CritScope lock(&crit_);
353 expect_frames_ = false;
354 }
355
Per512ecb32016-09-23 15:52:06 +0200356 int number_of_reconfigurations() {
357 rtc::CritScope lock(&crit_);
358 return number_of_reconfigurations_;
359 }
360
361 int last_min_transmit_bitrate() {
362 rtc::CritScope lock(&crit_);
363 return min_transmit_bitrate_bps_;
364 }
365
perkj26091b12016-09-01 01:17:40 -0700366 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700367 Result OnEncodedImage(
368 const EncodedImage& encoded_image,
369 const CodecSpecificInfo* codec_specific_info,
370 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200371 rtc::CritScope lock(&crit_);
372 EXPECT_TRUE(expect_frames_);
sprangb1ca0732017-02-01 08:38:12 -0800373 last_timestamp_ = encoded_image._timeStamp;
374 last_width_ = encoded_image._encodedWidth;
375 last_height_ = encoded_image._encodedHeight;
Per512ecb32016-09-23 15:52:06 +0200376 encoded_frame_event_.Set();
sprangb1ca0732017-02-01 08:38:12 -0800377 return Result(Result::OK, last_timestamp_);
Per512ecb32016-09-23 15:52:06 +0200378 }
379
380 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
381 int min_transmit_bitrate_bps) override {
382 rtc::CriticalSection crit_;
383 ++number_of_reconfigurations_;
384 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
385 }
386
perkj26091b12016-09-01 01:17:40 -0700387 rtc::CriticalSection crit_;
388 TestEncoder* test_encoder_;
389 rtc::Event encoded_frame_event_;
sprangb1ca0732017-02-01 08:38:12 -0800390 uint32_t last_timestamp_ = 0;
391 uint32_t last_height_ = 0;
392 uint32_t last_width_ = 0;
perkj26091b12016-09-01 01:17:40 -0700393 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200394 int number_of_reconfigurations_ = 0;
395 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700396 };
397
398 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100399 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200400 int codec_width_;
401 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700402 TestEncoder fake_encoder_;
perkj803d97f2016-11-01 11:45:46 -0700403 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700404 TestSink sink_;
sprangb1ca0732017-02-01 08:38:12 -0800405 AdaptingFrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700406 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700407};
408
409TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700410 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
411 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700412 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700413 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700414 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700415 vie_encoder_->Stop();
416}
417
418TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
419 // Dropped since no target bitrate has been set.
420 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700421 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
422 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700423
perkj26091b12016-09-01 01:17:40 -0700424 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
425
perkja49cbd32016-09-16 07:53:41 -0700426 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700427 sink_.WaitForEncodedFrame(2);
428 vie_encoder_->Stop();
429}
430
431TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700432 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700433 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700434 sink_.WaitForEncodedFrame(1);
435
436 vie_encoder_->OnBitrateUpdated(0, 0, 0);
437 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700438 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700439
440 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700441 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700442 sink_.WaitForEncodedFrame(3);
443 vie_encoder_->Stop();
444}
445
446TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700447 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700448 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700449 sink_.WaitForEncodedFrame(1);
450
451 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700452 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700453
perkja49cbd32016-09-16 07:53:41 -0700454 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700455 sink_.WaitForEncodedFrame(2);
456 vie_encoder_->Stop();
457}
458
459TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700460 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
461
perkja49cbd32016-09-16 07:53:41 -0700462 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700463 sink_.WaitForEncodedFrame(1);
464
465 vie_encoder_->Stop();
466 sink_.SetExpectNoFrames();
467 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700468 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
469 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700470}
471
472TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700473 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
474
475 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700476 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700477 sink_.WaitForEncodedFrame(1);
478 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
479 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700480 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
481 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700482 fake_encoder_.ContinueEncode();
483 sink_.WaitForEncodedFrame(3);
484
485 vie_encoder_->Stop();
486}
487
Per512ecb32016-09-23 15:52:06 +0200488TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200489 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100490 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200491
492 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200493 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200494 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100495 // The encoder will have been configured once when the first frame is
496 // received.
497 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200498
499 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700500 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200501 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800502 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
503 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200504
505 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200506 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200507 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100508 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700509 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700510
511 vie_encoder_->Stop();
512}
513
perkjfa10b552016-10-02 23:45:26 -0700514TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700515 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
516
517 // Capture a frame and wait for it to synchronize with the encoder thread.
518 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
519 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100520 // The encoder will have been configured once.
521 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700522 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
523 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
524
525 codec_width_ *= 2;
526 codec_height_ *= 2;
527 // Capture a frame with a higher resolution and wait for it to synchronize
528 // with the encoder thread.
529 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
530 sink_.WaitForEncodedFrame(2);
531 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
532 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100533 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700534
535 vie_encoder_->Stop();
536}
537
asapersson5f7226f2016-11-25 04:37:00 -0800538TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
539 const bool kNackEnabled = true;
540 const size_t kNumStreams = 1;
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 with nack on.
554 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
555 vie_encoder_->Stop();
556}
557
558TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
559 const bool kNackEnabled = true;
560 const size_t kNumStreams = 2;
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 off for no temporal layers and >1 streams with nack on.
574 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
575 vie_encoder_->Stop();
576}
577
578TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
579 const bool kNackEnabled = false;
580 const size_t kNumStreams = 1;
581 const size_t kNumTl = 1;
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 no temporal layers with nack off.
594 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
595 vie_encoder_->Stop();
596}
597
598TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
599 const bool kNackEnabled = true;
600 const size_t kNumStreams = 1;
601 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800602 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800603 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
604
605 // Capture a frame and wait for it to synchronize with the encoder thread.
606 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
607 sink_.WaitForEncodedFrame(1);
608 // The encoder have been configured once when the first frame is received.
609 EXPECT_EQ(1, sink_.number_of_reconfigurations());
610 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
611 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
612 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
613 // Resilience is on for temporal layers.
614 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
615 vie_encoder_->Stop();
616}
617
perkj803d97f2016-11-01 11:45:46 -0700618TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
619 EXPECT_TRUE(video_source_.has_sinks());
620 test::FrameForwarder new_video_source;
621 vie_encoder_->SetSource(&new_video_source,
622 VideoSendStream::DegradationPreference::kBalanced);
623 EXPECT_FALSE(video_source_.has_sinks());
624 EXPECT_TRUE(new_video_source.has_sinks());
625
626 vie_encoder_->Stop();
627}
628
629TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
630 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
631 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
632 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
633 vie_encoder_->Stop();
634}
635
636TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700637 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
638
sprang84a37592017-02-10 07:04:27 -0800639 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700640 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700641
642 int frame_width = 1280;
643 int frame_height = 720;
644
645 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
646 // request lower resolution.
647 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
648 video_source_.IncomingCapturedFrame(
649 CreateFrame(i, frame_width, frame_height));
650 sink_.WaitForEncodedFrame(i);
651
652 vie_encoder_->TriggerCpuOveruse();
653
sprang84a37592017-02-10 07:04:27 -0800654 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700655 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
656 std::numeric_limits<int>::max()),
657 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700658
659 frame_width /= 2;
660 frame_height /= 2;
661 }
662
kthelgason876222f2016-11-29 01:44:11 -0800663 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700664 // lower resolution.
665 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
666 video_source_.IncomingCapturedFrame(CreateFrame(
667 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
668 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
669 vie_encoder_->TriggerCpuOveruse();
sprang84a37592017-02-10 07:04:27 -0800670 EXPECT_EQ(video_source_.sink_wants().target_pixel_count,
671 current_wants.target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700672 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
673 current_wants.max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700674
675 // Trigger CPU normal use.
676 vie_encoder_->TriggerCpuNormalUsage();
sprang84a37592017-02-10 07:04:27 -0800677 EXPECT_EQ(frame_width * frame_height * 5 / 3,
678 video_source_.sink_wants().target_pixel_count.value_or(0));
679 EXPECT_EQ(frame_width * frame_height * 4,
680 video_source_.sink_wants().max_pixel_count.value_or(0));
perkj803d97f2016-11-01 11:45:46 -0700681
682 vie_encoder_->Stop();
683}
684
685TEST_F(ViEEncoderTest,
686 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700687 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
688
sprang84a37592017-02-10 07:04:27 -0800689 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700690 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700691
692 int frame_width = 1280;
693 int frame_height = 720;
694
kthelgason5e13d412016-12-01 03:59:51 -0800695 video_source_.IncomingCapturedFrame(
696 CreateFrame(1, frame_width, frame_height));
697 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700698 // Trigger CPU overuse.
699 vie_encoder_->TriggerCpuOveruse();
700
701 video_source_.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800702 CreateFrame(2, frame_width, frame_height));
703 sink_.WaitForEncodedFrame(2);
sprang84a37592017-02-10 07:04:27 -0800704 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700705 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
706 std::numeric_limits<int>::max()),
707 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700708
709 // Set new source.
710 test::FrameForwarder new_video_source;
711 vie_encoder_->SetSource(
712 &new_video_source,
713 VideoSendStream::DegradationPreference::kMaintainResolution);
714
sprang84a37592017-02-10 07:04:27 -0800715 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700716 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700717
718 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -0800719 CreateFrame(3, frame_width, frame_height));
720 sink_.WaitForEncodedFrame(3);
sprang84a37592017-02-10 07:04:27 -0800721 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700722 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700723
724 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
725 vie_encoder_->SetSource(&new_video_source,
726 VideoSendStream::DegradationPreference::kBalanced);
727 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
728 std::numeric_limits<int>::max()),
729 frame_width * frame_height);
sprang84a37592017-02-10 07:04:27 -0800730 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700731
732 vie_encoder_->Stop();
733}
734
735TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700736 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
737
738 int frame_width = 1280;
739 int frame_height = 720;
740
741 video_source_.IncomingCapturedFrame(
742 CreateFrame(1, frame_width, frame_height));
743 sink_.WaitForEncodedFrame(1);
744 VideoSendStream::Stats stats = stats_proxy_->GetStats();
745 EXPECT_FALSE(stats.cpu_limited_resolution);
746 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
747
748 // Trigger CPU overuse.
749 vie_encoder_->TriggerCpuOveruse();
750 video_source_.IncomingCapturedFrame(
751 CreateFrame(2, frame_width, frame_height));
752 sink_.WaitForEncodedFrame(2);
753
754 stats = stats_proxy_->GetStats();
755 EXPECT_TRUE(stats.cpu_limited_resolution);
756 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
757
758 // Trigger CPU normal use.
759 vie_encoder_->TriggerCpuNormalUsage();
760 video_source_.IncomingCapturedFrame(
761 CreateFrame(3, frame_width, frame_height));
762 sink_.WaitForEncodedFrame(3);
763
764 stats = stats_proxy_->GetStats();
765 EXPECT_FALSE(stats.cpu_limited_resolution);
766 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
767
768 vie_encoder_->Stop();
769}
770
kthelgason876222f2016-11-29 01:44:11 -0800771TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800772 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
773
774 int frame_width = 1280;
775 int frame_height = 720;
776 video_source_.IncomingCapturedFrame(
777 CreateFrame(1, frame_width, frame_height));
778 sink_.WaitForEncodedFrame(1);
779
780 VideoSendStream::Stats stats = stats_proxy_->GetStats();
781 EXPECT_FALSE(stats.cpu_limited_resolution);
782 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
783
784 vie_encoder_->TriggerCpuOveruse();
785
786 video_source_.IncomingCapturedFrame(
787 CreateFrame(2, frame_width, frame_height));
788 sink_.WaitForEncodedFrame(2);
789 stats = stats_proxy_->GetStats();
790 EXPECT_TRUE(stats.cpu_limited_resolution);
791 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
792
793 // Set new source with adaptation still enabled.
794 test::FrameForwarder new_video_source;
795 vie_encoder_->SetSource(&new_video_source,
796 VideoSendStream::DegradationPreference::kBalanced);
797
798 new_video_source.IncomingCapturedFrame(
799 CreateFrame(3, frame_width, frame_height));
800 sink_.WaitForEncodedFrame(3);
801 stats = stats_proxy_->GetStats();
802 EXPECT_TRUE(stats.cpu_limited_resolution);
803 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
804
805 // Set adaptation disabled.
806 vie_encoder_->SetSource(
807 &new_video_source,
808 VideoSendStream::DegradationPreference::kMaintainResolution);
809
810 new_video_source.IncomingCapturedFrame(
811 CreateFrame(4, frame_width, frame_height));
812 sink_.WaitForEncodedFrame(4);
813 stats = stats_proxy_->GetStats();
814 EXPECT_FALSE(stats.cpu_limited_resolution);
815 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
816
817 // Set adaptation back to enabled.
818 vie_encoder_->SetSource(&new_video_source,
819 VideoSendStream::DegradationPreference::kBalanced);
820
821 new_video_source.IncomingCapturedFrame(
822 CreateFrame(5, frame_width, frame_height));
823 sink_.WaitForEncodedFrame(5);
824 stats = stats_proxy_->GetStats();
825 EXPECT_TRUE(stats.cpu_limited_resolution);
826 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
827
828 vie_encoder_->TriggerCpuNormalUsage();
829
830 new_video_source.IncomingCapturedFrame(
831 CreateFrame(6, frame_width, frame_height));
832 sink_.WaitForEncodedFrame(6);
833 stats = stats_proxy_->GetStats();
834 EXPECT_FALSE(stats.cpu_limited_resolution);
835 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
836
837 vie_encoder_->Stop();
838}
839
840TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800841 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
842
843 int frame_width = 1280;
844 int frame_height = 720;
845 video_source_.IncomingCapturedFrame(
846 CreateFrame(1, frame_width, frame_height));
847 sink_.WaitForEncodedFrame(1);
848
849 VideoSendStream::Stats stats = stats_proxy_->GetStats();
850 EXPECT_FALSE(stats.cpu_limited_resolution);
851 EXPECT_FALSE(stats.bw_limited_resolution);
852 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
853
854 // Set new source with adaptation still enabled.
855 test::FrameForwarder new_video_source;
856 vie_encoder_->SetSource(&new_video_source,
857 VideoSendStream::DegradationPreference::kBalanced);
858
859 new_video_source.IncomingCapturedFrame(
860 CreateFrame(2, frame_width, frame_height));
861 sink_.WaitForEncodedFrame(2);
862 stats = stats_proxy_->GetStats();
863 EXPECT_FALSE(stats.cpu_limited_resolution);
864 EXPECT_FALSE(stats.bw_limited_resolution);
865 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
866
867 vie_encoder_->TriggerQualityLow();
868
869 new_video_source.IncomingCapturedFrame(
870 CreateFrame(3, frame_width, frame_height));
871 sink_.WaitForEncodedFrame(3);
872 stats = stats_proxy_->GetStats();
873 EXPECT_FALSE(stats.cpu_limited_resolution);
874 EXPECT_TRUE(stats.bw_limited_resolution);
875
876 vie_encoder_->SetSource(&new_video_source,
877 VideoSendStream::DegradationPreference::kBalanced);
878
879 new_video_source.IncomingCapturedFrame(
880 CreateFrame(4, frame_width, frame_height));
881 sink_.WaitForEncodedFrame(4);
882 stats = stats_proxy_->GetStats();
883 EXPECT_FALSE(stats.cpu_limited_resolution);
884 EXPECT_TRUE(stats.bw_limited_resolution);
885
886 // Set adaptation disabled.
887 vie_encoder_->SetSource(
888 &new_video_source,
889 VideoSendStream::DegradationPreference::kMaintainResolution);
890
891 new_video_source.IncomingCapturedFrame(
892 CreateFrame(5, frame_width, frame_height));
893 sink_.WaitForEncodedFrame(5);
894 stats = stats_proxy_->GetStats();
895 EXPECT_FALSE(stats.cpu_limited_resolution);
896 EXPECT_FALSE(stats.bw_limited_resolution);
897
898 vie_encoder_->Stop();
899}
900
perkj803d97f2016-11-01 11:45:46 -0700901TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700902 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
903
perkj803d97f2016-11-01 11:45:46 -0700904 int frame_width = 1280;
905 int frame_height = 720;
sprang84a37592017-02-10 07:04:27 -0800906 int sequence = 1;
perkj803d97f2016-11-01 11:45:46 -0700907
908 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800909 CreateFrame(sequence, frame_width, frame_height));
910 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700911
912 VideoSendStream::Stats stats = stats_proxy_->GetStats();
sprang84a37592017-02-10 07:04:27 -0800913 EXPECT_FALSE(stats.cpu_limited_resolution);
914 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
915
916 // Trigger CPU overuse again, should now adapt down.
917 vie_encoder_->TriggerCpuOveruse();
918 video_source_.IncomingCapturedFrame(
919 CreateFrame(sequence, frame_width, frame_height));
920 sink_.WaitForEncodedFrame(sequence++);
921
922 stats = stats_proxy_->GetStats();
perkj803d97f2016-11-01 11:45:46 -0700923 EXPECT_TRUE(stats.cpu_limited_resolution);
924 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
925
926 // Set new source with adaptation still enabled.
927 test::FrameForwarder new_video_source;
928 vie_encoder_->SetSource(&new_video_source,
929 VideoSendStream::DegradationPreference::kBalanced);
930
931 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800932 CreateFrame(sequence, frame_width, frame_height));
933 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700934 stats = stats_proxy_->GetStats();
935 EXPECT_TRUE(stats.cpu_limited_resolution);
936 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
937
938 // Set adaptation disabled.
939 vie_encoder_->SetSource(
940 &new_video_source,
941 VideoSendStream::DegradationPreference::kMaintainResolution);
942 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800943 CreateFrame(sequence, frame_width, frame_height));
944 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700945 stats = stats_proxy_->GetStats();
946 EXPECT_FALSE(stats.cpu_limited_resolution);
947 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
948
949 // Switch back the source with adaptation enabled.
950 vie_encoder_->SetSource(&video_source_,
951 VideoSendStream::DegradationPreference::kBalanced);
952 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800953 CreateFrame(sequence, frame_width, frame_height));
954 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700955 stats = stats_proxy_->GetStats();
956 EXPECT_TRUE(stats.cpu_limited_resolution);
957 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
958
959 // Trigger CPU normal usage.
960 vie_encoder_->TriggerCpuNormalUsage();
961 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800962 CreateFrame(sequence, frame_width, frame_height));
963 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700964 stats = stats_proxy_->GetStats();
965 EXPECT_FALSE(stats.cpu_limited_resolution);
966 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
967
968 vie_encoder_->Stop();
969}
970
Erik Språng08127a92016-11-16 16:41:30 +0100971TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +0100972 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
973
974 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
975 sink_.WaitForEncodedFrame(1);
976
977 VideoSendStream::Stats stats = stats_proxy_->GetStats();
978 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
979 stats.preferred_media_bitrate_bps);
980
981 vie_encoder_->Stop();
982}
983
kthelgason876222f2016-11-29 01:44:11 -0800984TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
kthelgason876222f2016-11-29 01:44:11 -0800985 int frame_width = 1280;
986 int frame_height = 720;
987 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
988
989 // Expect no scaling to begin with
sprang84a37592017-02-10 07:04:27 -0800990 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -0800991 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -0800992
kthelgason876222f2016-11-29 01:44:11 -0800993 video_source_.IncomingCapturedFrame(
994 CreateFrame(1, frame_width, frame_height));
995 sink_.WaitForEncodedFrame(1);
996
kthelgason5e13d412016-12-01 03:59:51 -0800997 // Trigger scale down
998 vie_encoder_->TriggerQualityLow();
999
1000 video_source_.IncomingCapturedFrame(
1001 CreateFrame(2, frame_width, frame_height));
1002 sink_.WaitForEncodedFrame(2);
1003
kthelgason876222f2016-11-29 01:44:11 -08001004 // Expect a scale down.
1005 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1006 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
1007 frame_width * frame_height);
1008
1009 // Set adaptation disabled.
1010 test::FrameForwarder new_video_source;
1011 vie_encoder_->SetSource(
1012 &new_video_source,
1013 VideoSendStream::DegradationPreference::kMaintainResolution);
1014
1015 // Trigger scale down
1016 vie_encoder_->TriggerQualityLow();
1017 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001018 CreateFrame(3, frame_width, frame_height));
1019 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -08001020
1021 // Expect no scaling
1022 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1023
1024 // Trigger scale up
1025 vie_encoder_->TriggerQualityHigh();
1026 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001027 CreateFrame(4, frame_width, frame_height));
1028 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -08001029
1030 // Expect nothing to change, still no scaling
1031 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
1032
1033 vie_encoder_->Stop();
1034}
1035
kthelgason5e13d412016-12-01 03:59:51 -08001036TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
kthelgason5e13d412016-12-01 03:59:51 -08001037 int frame_width = 1280;
1038 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -08001039 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1040
1041 for (size_t i = 1; i <= 10; i++) {
1042 video_source_.IncomingCapturedFrame(
1043 CreateFrame(i, frame_width, frame_height));
1044 sink_.WaitForEncodedFrame(i);
1045 // Trigger scale down
1046 vie_encoder_->TriggerQualityLow();
1047 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
1048 }
1049
1050 vie_encoder_->Stop();
1051}
1052
perkj803d97f2016-11-01 11:45:46 -07001053TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -07001054 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1055
1056 int frame_width = 640;
1057 int frame_height = 360;
1058
1059 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1060 video_source_.IncomingCapturedFrame(
1061 CreateFrame(i, frame_width, frame_height));
1062 sink_.WaitForEncodedFrame(i);
1063 }
1064
1065 vie_encoder_->TriggerCpuOveruse();
1066 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1067 video_source_.IncomingCapturedFrame(
1068 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
1069 frame_width, frame_height));
1070 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
1071 i);
1072 }
1073
1074 vie_encoder_->Stop();
sprangf8ee65e2017-02-28 08:49:33 -08001075 vie_encoder_.reset();
perkj803d97f2016-11-01 11:45:46 -07001076 stats_proxy_.reset();
sprangf8ee65e2017-02-28 08:49:33 -08001077
perkj803d97f2016-11-01 11:45:46 -07001078 EXPECT_EQ(1,
1079 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1080 EXPECT_EQ(
1081 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1082}
1083
sprang57c2fff2017-01-16 06:24:02 -08001084TEST_F(ViEEncoderTest, CallsBitrateObserver) {
1085 class MockBitrateObserver : public VideoBitrateAllocationObserver {
1086 public:
1087 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
1088 } bitrate_observer;
1089 vie_encoder_->SetBitrateObserver(&bitrate_observer);
1090
1091 const int kDefaultFps = 30;
1092 const BitrateAllocation expected_bitrate =
1093 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
kthelgason2bc68642017-02-07 07:02:22 -08001094 .GetAllocation(kLowTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -08001095
1096 // First called on bitrate updated, then again on first frame.
1097 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1098 .Times(2);
kthelgason2bc68642017-02-07 07:02:22 -08001099 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001100
1101 const int64_t kStartTimeMs = 1;
1102 video_source_.IncomingCapturedFrame(
1103 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1104 sink_.WaitForEncodedFrame(kStartTimeMs);
1105
1106 // Not called on second frame.
1107 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1108 .Times(0);
1109 video_source_.IncomingCapturedFrame(
1110 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1111 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1112
1113 // Called after a process interval.
1114 const int64_t kProcessIntervalMs =
1115 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1116 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1117 // Sleep for one processing interval plus one frame to avoid flakiness.
1118 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1119 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1120 .Times(1);
1121 video_source_.IncomingCapturedFrame(CreateFrame(
1122 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1123 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1124
1125 vie_encoder_->Stop();
1126}
1127
kthelgason2bc68642017-02-07 07:02:22 -08001128TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
1129 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1130 int frame_width = 640;
1131 int frame_height = 360;
1132
1133 video_source_.IncomingCapturedFrame(
1134 CreateFrame(1, frame_width, frame_height));
1135
1136 // Expect to drop this frame, the wait should time out.
1137 sink_.ExpectDroppedFrame();
1138
1139 // Expect the sink_wants to specify a scaled frame.
1140 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1141 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1142
1143 int last_pixel_count = *video_source_.sink_wants().max_pixel_count;
1144
1145 // Next frame is scaled
1146 video_source_.IncomingCapturedFrame(
1147 CreateFrame(2, frame_width * 3 / 4, frame_height * 3 / 4));
1148
1149 // Expect to drop this frame, the wait should time out.
1150 sink_.ExpectDroppedFrame();
1151
1152 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, last_pixel_count);
1153
1154 vie_encoder_->Stop();
1155}
1156
kthelgason2fc52542017-03-03 00:24:41 -08001157TEST_F(ViEEncoderTest, NrOfDroppedFramesLimited) {
kthelgason2bc68642017-02-07 07:02:22 -08001158 // 1kbps. This can never be achieved.
1159 vie_encoder_->OnBitrateUpdated(1000, 0, 0);
1160 int frame_width = 640;
1161 int frame_height = 360;
1162
1163 // We expect the n initial frames to get dropped.
1164 int i;
1165 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
1166 video_source_.IncomingCapturedFrame(
1167 CreateFrame(i, frame_width, frame_height));
1168 sink_.ExpectDroppedFrame();
1169 }
1170 // The n+1th frame should not be dropped, even though it's size is too large.
1171 video_source_.IncomingCapturedFrame(
1172 CreateFrame(i, frame_width, frame_height));
1173 sink_.WaitForEncodedFrame(i);
1174
1175 // Expect the sink_wants to specify a scaled frame.
1176 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1177 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
1178
1179 vie_encoder_->Stop();
1180}
1181
1182TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
1183 int frame_width = 640;
1184 int frame_height = 360;
1185 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1186
1187 // Set degradation preference.
1188 vie_encoder_->SetSource(
1189 &video_source_,
1190 VideoSendStream::DegradationPreference::kMaintainResolution);
1191
1192 video_source_.IncomingCapturedFrame(
1193 CreateFrame(1, frame_width, frame_height));
1194 // Frame should not be dropped, even if it's too large.
1195 sink_.WaitForEncodedFrame(1);
1196
1197 vie_encoder_->Stop();
1198}
1199
kthelgason2fc52542017-03-03 00:24:41 -08001200TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
kthelgasonad9010c2017-02-14 00:46:51 -08001201 int frame_width = 640;
1202 int frame_height = 360;
1203 fake_encoder_.SetQualityScaling(false);
1204 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
kthelgasonb83797b2017-02-14 11:57:25 -08001205 // Force quality scaler reconfiguration by resetting the source.
1206 vie_encoder_->SetSource(&video_source_,
1207 VideoSendStream::DegradationPreference::kBalanced);
kthelgasonad9010c2017-02-14 00:46:51 -08001208
1209 video_source_.IncomingCapturedFrame(
1210 CreateFrame(1, frame_width, frame_height));
1211 // Frame should not be dropped, even if it's too large.
1212 sink_.WaitForEncodedFrame(1);
1213
1214 vie_encoder_->Stop();
1215 fake_encoder_.SetQualityScaling(true);
1216}
1217
sprangb1ca0732017-02-01 08:38:12 -08001218// TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
1219TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) {
1220 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1221
1222 const int kFrameWidth = 1280;
1223 const int kFrameHeight = 720;
1224 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
1225 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
1226 video_source_.set_adaptation_enabled(true);
1227
1228 video_source_.IncomingCapturedFrame(
1229 CreateFrame(1, kFrameWidth, kFrameHeight));
1230 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1231
1232 // Trigger CPU overuse, downscale by 3/4.
1233 vie_encoder_->TriggerCpuOveruse();
1234 video_source_.IncomingCapturedFrame(
1235 CreateFrame(2, kFrameWidth, kFrameHeight));
1236 sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
1237
1238 // Trigger CPU normal use, return to original resoluton;
1239 vie_encoder_->TriggerCpuNormalUsage();
1240 video_source_.IncomingCapturedFrame(
1241 CreateFrame(3, kFrameWidth, kFrameHeight));
1242 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1243
1244 vie_encoder_->Stop();
1245}
perkj26091b12016-09-01 01:17:40 -07001246} // namespace webrtc