blob: f037600e7d88025615d9a2e48184f921d21b9da3 [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
sprangfe627f32017-03-29 08:24:59 -070011#include <algorithm>
perkj803d97f2016-11-01 11:45:46 -070012#include <limits>
Per512ecb32016-09-23 15:52:06 +020013#include <utility>
14
nisseaf916892017-01-10 07:44:26 -080015#include "webrtc/api/video/i420_buffer.h"
perkj26091b12016-09-01 01:17:40 -070016#include "webrtc/base/logging.h"
sprangb1ca0732017-02-01 08:38:12 -080017#include "webrtc/media/base/videoadapter.h"
sprangfe627f32017-03-29 08:24:59 -070018#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
sprang57c2fff2017-01-16 06:24:02 -080019#include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
perkj803d97f2016-11-01 11:45:46 -070020#include "webrtc/system_wrappers/include/metrics_default.h"
sprang57c2fff2017-01-16 06:24:02 -080021#include "webrtc/system_wrappers/include/sleep.h"
perkj26091b12016-09-01 01:17:40 -070022#include "webrtc/test/encoder_settings.h"
23#include "webrtc/test/fake_encoder.h"
perkja49cbd32016-09-16 07:53:41 -070024#include "webrtc/test/frame_generator.h"
sprang57c2fff2017-01-16 06:24:02 -080025#include "webrtc/test/gmock.h"
kwibergac9f8762016-09-30 22:29:43 -070026#include "webrtc/test/gtest.h"
perkj26091b12016-09-01 01:17:40 -070027#include "webrtc/video/send_statistics_proxy.h"
28#include "webrtc/video/vie_encoder.h"
29
kthelgason33ce8892016-12-09 03:53:59 -080030namespace {
31#if defined(WEBRTC_ANDROID)
32// TODO(kthelgason): Lower this limit when better testing
33// on MediaCodec and fallback implementations are in place.
34const int kMinPixelsPerFrame = 320 * 180;
35#else
36const int kMinPixelsPerFrame = 120 * 90;
37#endif
lliuuf9ed2352017-03-30 10:44:38 -070038}
kthelgason33ce8892016-12-09 03:53:59 -080039
perkj26091b12016-09-01 01:17:40 -070040namespace webrtc {
41
kthelgason876222f2016-11-29 01:44:11 -080042using DegredationPreference = VideoSendStream::DegradationPreference;
sprangb1ca0732017-02-01 08:38:12 -080043using ScaleReason = AdaptationObserverInterface::AdaptReason;
sprang57c2fff2017-01-16 06:24:02 -080044using ::testing::_;
45using ::testing::Return;
kthelgason876222f2016-11-29 01:44:11 -080046
perkj803d97f2016-11-01 11:45:46 -070047namespace {
asapersson5f7226f2016-11-25 04:37:00 -080048const size_t kMaxPayloadLength = 1440;
kthelgason2bc68642017-02-07 07:02:22 -080049const int kTargetBitrateBps = 1000000;
50const int kLowTargetBitrateBps = kTargetBitrateBps / 10;
51const int kMaxInitialFramedrop = 4;
asapersson5f7226f2016-11-25 04:37:00 -080052
perkj803d97f2016-11-01 11:45:46 -070053class TestBuffer : public webrtc::I420Buffer {
54 public:
55 TestBuffer(rtc::Event* event, int width, int height)
56 : I420Buffer(width, height), event_(event) {}
57
58 private:
59 friend class rtc::RefCountedObject<TestBuffer>;
60 ~TestBuffer() override {
61 if (event_)
62 event_->Set();
63 }
64 rtc::Event* const event_;
65};
66
67class ViEEncoderUnderTest : public ViEEncoder {
68 public:
kthelgason876222f2016-11-29 01:44:11 -080069 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
70 const VideoSendStream::Config::EncoderSettings& settings)
perkj803d97f2016-11-01 11:45:46 -070071 : ViEEncoder(1 /* number_of_cores */,
72 stats_proxy,
73 settings,
74 nullptr /* pre_encode_callback */,
75 nullptr /* encoder_timing */) {}
76
sprangb1ca0732017-02-01 08:38:12 -080077 void PostTaskAndWait(bool down, AdaptReason reason) {
perkj803d97f2016-11-01 11:45:46 -070078 rtc::Event event(false, false);
kthelgason876222f2016-11-29 01:44:11 -080079 encoder_queue()->PostTask([this, &event, reason, down] {
sprangb1ca0732017-02-01 08:38:12 -080080 down ? AdaptDown(reason) : AdaptUp(reason);
perkj803d97f2016-11-01 11:45:46 -070081 event.Set();
82 });
perkj070ba852017-02-16 15:46:27 -080083 ASSERT_TRUE(event.Wait(5000));
perkj803d97f2016-11-01 11:45:46 -070084 }
85
kthelgason2fc52542017-03-03 00:24:41 -080086 // This is used as a synchronisation mechanism, to make sure that the
87 // encoder queue is not blocked before we start sending it frames.
88 void WaitUntilTaskQueueIsIdle() {
89 rtc::Event event(false, false);
90 encoder_queue()->PostTask([&event] {
91 event.Set();
92 });
93 ASSERT_TRUE(event.Wait(5000));
94 }
95
sprangb1ca0732017-02-01 08:38:12 -080096 void TriggerCpuOveruse() { PostTaskAndWait(true, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080097
sprangb1ca0732017-02-01 08:38:12 -080098 void TriggerCpuNormalUsage() { PostTaskAndWait(false, AdaptReason::kCpu); }
kthelgason876222f2016-11-29 01:44:11 -080099
sprangb1ca0732017-02-01 08:38:12 -0800100 void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); }
kthelgason876222f2016-11-29 01:44:11 -0800101
sprangb1ca0732017-02-01 08:38:12 -0800102 void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); }
perkj803d97f2016-11-01 11:45:46 -0700103};
104
asapersson5f7226f2016-11-25 04:37:00 -0800105class VideoStreamFactory
106 : public VideoEncoderConfig::VideoStreamFactoryInterface {
107 public:
108 explicit VideoStreamFactory(size_t num_temporal_layers)
109 : num_temporal_layers_(num_temporal_layers) {
110 EXPECT_GT(num_temporal_layers, 0u);
111 }
112
113 private:
114 std::vector<VideoStream> CreateEncoderStreams(
115 int width,
116 int height,
117 const VideoEncoderConfig& encoder_config) override {
118 std::vector<VideoStream> streams =
119 test::CreateVideoStreams(width, height, encoder_config);
120 for (VideoStream& stream : streams) {
121 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
122 }
123 return streams;
124 }
125 const size_t num_temporal_layers_;
126};
127
sprangb1ca0732017-02-01 08:38:12 -0800128class AdaptingFrameForwarder : public test::FrameForwarder {
129 public:
130 AdaptingFrameForwarder() : adaptation_enabled_(false) {}
131 virtual ~AdaptingFrameForwarder() {}
132
133 void set_adaptation_enabled(bool enabled) {
134 rtc::CritScope cs(&crit_);
135 adaptation_enabled_ = enabled;
136 }
137
138 bool adaption_enabled() {
139 rtc::CritScope cs(&crit_);
140 return adaptation_enabled_;
141 }
142
143 void IncomingCapturedFrame(const VideoFrame& video_frame) override {
144 int cropped_width = 0;
145 int cropped_height = 0;
146 int out_width = 0;
147 int out_height = 0;
lliuuf9ed2352017-03-30 10:44:38 -0700148 if (adaption_enabled() &&
149 adapter_.AdaptFrameResolution(video_frame.width(), video_frame.height(),
150 video_frame.timestamp_us() * 1000,
151 &cropped_width, &cropped_height,
152 &out_width, &out_height)) {
153 VideoFrame adapted_frame(
154 new rtc::RefCountedObject<TestBuffer>(nullptr, out_width, out_height),
155 99, 99, kVideoRotation_0);
156 adapted_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
157 test::FrameForwarder::IncomingCapturedFrame(adapted_frame);
sprangb1ca0732017-02-01 08:38:12 -0800158 } else {
159 test::FrameForwarder::IncomingCapturedFrame(video_frame);
160 }
161 }
162
163 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
164 const rtc::VideoSinkWants& wants) override {
165 rtc::CritScope cs(&crit_);
lliuuf9ed2352017-03-30 10:44:38 -0700166 adapter_.OnResolutionRequest(wants.target_pixel_count,
167 wants.max_pixel_count);
sprangb1ca0732017-02-01 08:38:12 -0800168 test::FrameForwarder::AddOrUpdateSink(sink, wants);
169 }
170
171 cricket::VideoAdapter adapter_;
172 bool adaptation_enabled_ GUARDED_BY(crit_);
173};
perkj803d97f2016-11-01 11:45:46 -0700174} // namespace
175
perkj26091b12016-09-01 01:17:40 -0700176class ViEEncoderTest : public ::testing::Test {
177 public:
178 static const int kDefaultTimeoutMs = 30 * 1000;
179
180 ViEEncoderTest()
181 : video_send_config_(VideoSendStream::Config(nullptr)),
perkjfa10b552016-10-02 23:45:26 -0700182 codec_width_(320),
183 codec_height_(240),
perkj26091b12016-09-01 01:17:40 -0700184 fake_encoder_(),
lliuuf9ed2352017-03-30 10:44:38 -0700185 stats_proxy_(new SendStatisticsProxy(
perkj803d97f2016-11-01 11:45:46 -0700186 Clock::GetRealTimeClock(),
187 video_send_config_,
188 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
perkj26091b12016-09-01 01:17:40 -0700189 sink_(&fake_encoder_) {}
190
191 void SetUp() override {
perkj803d97f2016-11-01 11:45:46 -0700192 metrics::Reset();
perkj26091b12016-09-01 01:17:40 -0700193 video_send_config_ = VideoSendStream::Config(nullptr);
194 video_send_config_.encoder_settings.encoder = &fake_encoder_;
195 video_send_config_.encoder_settings.payload_name = "FAKE";
196 video_send_config_.encoder_settings.payload_type = 125;
197
Per512ecb32016-09-23 15:52:06 +0200198 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700199 test::FillEncoderConfiguration(1, &video_encoder_config);
Erik Språng08127a92016-11-16 16:41:30 +0100200 video_encoder_config_ = video_encoder_config.Copy();
asapersson5f7226f2016-11-25 04:37:00 -0800201 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
202 }
203
204 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
205 bool nack_enabled) {
206 if (vie_encoder_)
207 vie_encoder_->Stop();
perkj803d97f2016-11-01 11:45:46 -0700208 vie_encoder_.reset(new ViEEncoderUnderTest(
209 stats_proxy_.get(), video_send_config_.encoder_settings));
210 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
lliuuf9ed2352017-03-30 10:44:38 -0700211 vie_encoder_->SetSource(&video_source_,
212 VideoSendStream::DegradationPreference::kBalanced);
kthelgason2bc68642017-02-07 07:02:22 -0800213 vie_encoder_->SetStartBitrate(kTargetBitrateBps);
asapersson5f7226f2016-11-25 04:37:00 -0800214 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
215 kMaxPayloadLength, nack_enabled);
kthelgason2fc52542017-03-03 00:24:41 -0800216 vie_encoder_->WaitUntilTaskQueueIsIdle();
asapersson5f7226f2016-11-25 04:37:00 -0800217 }
218
219 void ResetEncoder(const std::string& payload_name,
220 size_t num_streams,
221 size_t num_temporal_layers,
222 bool nack_enabled) {
223 video_send_config_.encoder_settings.payload_name = payload_name;
224
225 VideoEncoderConfig video_encoder_config;
226 video_encoder_config.number_of_streams = num_streams;
kthelgason2bc68642017-02-07 07:02:22 -0800227 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
asapersson5f7226f2016-11-25 04:37:00 -0800228 video_encoder_config.video_stream_factory =
229 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
230 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
perkj26091b12016-09-01 01:17:40 -0700231 }
232
sprang57c2fff2017-01-16 06:24:02 -0800233 VideoFrame CreateFrame(int64_t ntp_time_ms,
234 rtc::Event* destruction_event) const {
Per512ecb32016-09-23 15:52:06 +0200235 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
236 destruction_event, codec_width_, codec_height_),
237 99, 99, kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800238 frame.set_ntp_time_ms(ntp_time_ms);
perkj26091b12016-09-01 01:17:40 -0700239 return frame;
240 }
241
sprang57c2fff2017-01-16 06:24:02 -0800242 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
perkj803d97f2016-11-01 11:45:46 -0700243 VideoFrame frame(
244 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
245 kVideoRotation_0);
sprang57c2fff2017-01-16 06:24:02 -0800246 frame.set_ntp_time_ms(ntp_time_ms);
perkj803d97f2016-11-01 11:45:46 -0700247 return frame;
248 }
249
perkj26091b12016-09-01 01:17:40 -0700250 class TestEncoder : public test::FakeEncoder {
251 public:
252 TestEncoder()
253 : FakeEncoder(Clock::GetRealTimeClock()),
254 continue_encode_event_(false, false) {}
255
perkjfa10b552016-10-02 23:45:26 -0700256 VideoCodec codec_config() {
brandtre78d2662017-01-16 05:57:16 -0800257 rtc::CritScope lock(&crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700258 return config_;
259 }
260
261 void BlockNextEncode() {
brandtre78d2662017-01-16 05:57:16 -0800262 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700263 block_next_encode_ = true;
264 }
265
kthelgason876222f2016-11-29 01:44:11 -0800266 VideoEncoder::ScalingSettings GetScalingSettings() const override {
kthelgason2fc52542017-03-03 00:24:41 -0800267 rtc::CritScope lock(&local_crit_sect_);
kthelgasonad9010c2017-02-14 00:46:51 -0800268 if (quality_scaling_)
269 return VideoEncoder::ScalingSettings(true, 1, 2);
270 return VideoEncoder::ScalingSettings(false);
kthelgason876222f2016-11-29 01:44:11 -0800271 }
272
perkjfa10b552016-10-02 23:45:26 -0700273 void ContinueEncode() { continue_encode_event_.Set(); }
274
275 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
276 uint32_t timestamp) const {
brandtre78d2662017-01-16 05:57:16 -0800277 rtc::CritScope lock(&local_crit_sect_);
perkjfa10b552016-10-02 23:45:26 -0700278 EXPECT_EQ(timestamp_, timestamp);
279 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
280 }
281
kthelgason2fc52542017-03-03 00:24:41 -0800282 void SetQualityScaling(bool b) {
283 rtc::CritScope lock(&local_crit_sect_);
284 quality_scaling_ = b;
285 }
kthelgasonad9010c2017-02-14 00:46:51 -0800286
sprangfe627f32017-03-29 08:24:59 -0700287 void ForceInitEncodeFailure(bool force_failure) {
288 rtc::CritScope lock(&local_crit_sect_);
289 force_init_encode_failed_ = force_failure;
290 }
291
perkjfa10b552016-10-02 23:45:26 -0700292 private:
perkj26091b12016-09-01 01:17:40 -0700293 int32_t Encode(const VideoFrame& input_image,
294 const CodecSpecificInfo* codec_specific_info,
295 const std::vector<FrameType>* frame_types) override {
296 bool block_encode;
297 {
brandtre78d2662017-01-16 05:57:16 -0800298 rtc::CritScope lock(&local_crit_sect_);
perkj26091b12016-09-01 01:17:40 -0700299 EXPECT_GT(input_image.timestamp(), timestamp_);
300 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
301 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
302
303 timestamp_ = input_image.timestamp();
304 ntp_time_ms_ = input_image.ntp_time_ms();
perkj803d97f2016-11-01 11:45:46 -0700305 last_input_width_ = input_image.width();
306 last_input_height_ = input_image.height();
perkj26091b12016-09-01 01:17:40 -0700307 block_encode = block_next_encode_;
308 block_next_encode_ = false;
309 }
310 int32_t result =
311 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
312 if (block_encode)
perkja49cbd32016-09-16 07:53:41 -0700313 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700314 return result;
315 }
316
sprangfe627f32017-03-29 08:24:59 -0700317 int32_t InitEncode(const VideoCodec* config,
318 int32_t number_of_cores,
319 size_t max_payload_size) override {
320 int res =
321 FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
322 rtc::CritScope lock(&local_crit_sect_);
323 if (config->codecType == kVideoCodecVP8 && config->VP8().tl_factory) {
324 // Simulate setting up temporal layers, in order to validate the life
325 // cycle of these objects.
326 int num_streams = std::max<int>(1, config->numberOfSimulcastStreams);
327 int num_temporal_layers =
328 std::max<int>(1, config->VP8().numberOfTemporalLayers);
329 for (int i = 0; i < num_streams; ++i) {
330 allocated_temporal_layers_.emplace_back(
331 config->VP8().tl_factory->Create(i, num_temporal_layers, 42));
332 }
333 }
334 if (force_init_encode_failed_)
335 return -1;
336 return res;
337 }
338
brandtre78d2662017-01-16 05:57:16 -0800339 rtc::CriticalSection local_crit_sect_;
sprangfe627f32017-03-29 08:24:59 -0700340 bool block_next_encode_ GUARDED_BY(local_crit_sect_) = false;
perkj26091b12016-09-01 01:17:40 -0700341 rtc::Event continue_encode_event_;
sprangfe627f32017-03-29 08:24:59 -0700342 uint32_t timestamp_ GUARDED_BY(local_crit_sect_) = 0;
343 int64_t ntp_time_ms_ GUARDED_BY(local_crit_sect_) = 0;
344 int last_input_width_ GUARDED_BY(local_crit_sect_) = 0;
345 int last_input_height_ GUARDED_BY(local_crit_sect_) = 0;
346 bool quality_scaling_ GUARDED_BY(local_crit_sect_) = true;
347 std::vector<std::unique_ptr<TemporalLayers>> allocated_temporal_layers_
348 GUARDED_BY(local_crit_sect_);
349 bool force_init_encode_failed_ GUARDED_BY(local_crit_sect_) = false;
perkj26091b12016-09-01 01:17:40 -0700350 };
351
Per512ecb32016-09-23 15:52:06 +0200352 class TestSink : public ViEEncoder::EncoderSink {
perkj26091b12016-09-01 01:17:40 -0700353 public:
354 explicit TestSink(TestEncoder* test_encoder)
355 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
356
perkj26091b12016-09-01 01:17:40 -0700357 void WaitForEncodedFrame(int64_t expected_ntp_time) {
358 uint32_t timestamp = 0;
perkja49cbd32016-09-16 07:53:41 -0700359 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700360 {
361 rtc::CritScope lock(&crit_);
sprangb1ca0732017-02-01 08:38:12 -0800362 timestamp = last_timestamp_;
perkj26091b12016-09-01 01:17:40 -0700363 }
364 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
365 }
366
sprangb1ca0732017-02-01 08:38:12 -0800367 void WaitForEncodedFrame(uint32_t expected_width,
368 uint32_t expected_height) {
369 uint32_t width = 0;
370 uint32_t height = 0;
lliuuf9ed2352017-03-30 10:44:38 -0700371 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
sprangb1ca0732017-02-01 08:38:12 -0800372 {
373 rtc::CritScope lock(&crit_);
374 width = last_width_;
375 height = last_height_;
376 }
377 EXPECT_EQ(expected_height, height);
378 EXPECT_EQ(expected_width, width);
379 }
380
kthelgason2fc52542017-03-03 00:24:41 -0800381 void ExpectDroppedFrame() { EXPECT_FALSE(encoded_frame_event_.Wait(100)); }
kthelgason2bc68642017-02-07 07:02:22 -0800382
perkj26091b12016-09-01 01:17:40 -0700383 void SetExpectNoFrames() {
384 rtc::CritScope lock(&crit_);
385 expect_frames_ = false;
386 }
387
Per512ecb32016-09-23 15:52:06 +0200388 int number_of_reconfigurations() {
389 rtc::CritScope lock(&crit_);
390 return number_of_reconfigurations_;
391 }
392
393 int last_min_transmit_bitrate() {
394 rtc::CritScope lock(&crit_);
395 return min_transmit_bitrate_bps_;
396 }
397
perkj26091b12016-09-01 01:17:40 -0700398 private:
sergeyu2cb155a2016-11-04 11:39:29 -0700399 Result OnEncodedImage(
400 const EncodedImage& encoded_image,
401 const CodecSpecificInfo* codec_specific_info,
402 const RTPFragmentationHeader* fragmentation) override {
Per512ecb32016-09-23 15:52:06 +0200403 rtc::CritScope lock(&crit_);
404 EXPECT_TRUE(expect_frames_);
sprangb1ca0732017-02-01 08:38:12 -0800405 last_timestamp_ = encoded_image._timeStamp;
406 last_width_ = encoded_image._encodedWidth;
407 last_height_ = encoded_image._encodedHeight;
Per512ecb32016-09-23 15:52:06 +0200408 encoded_frame_event_.Set();
sprangb1ca0732017-02-01 08:38:12 -0800409 return Result(Result::OK, last_timestamp_);
Per512ecb32016-09-23 15:52:06 +0200410 }
411
412 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
413 int min_transmit_bitrate_bps) override {
414 rtc::CriticalSection crit_;
415 ++number_of_reconfigurations_;
416 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
417 }
418
perkj26091b12016-09-01 01:17:40 -0700419 rtc::CriticalSection crit_;
420 TestEncoder* test_encoder_;
421 rtc::Event encoded_frame_event_;
sprangb1ca0732017-02-01 08:38:12 -0800422 uint32_t last_timestamp_ = 0;
423 uint32_t last_height_ = 0;
424 uint32_t last_width_ = 0;
perkj26091b12016-09-01 01:17:40 -0700425 bool expect_frames_ = true;
Per512ecb32016-09-23 15:52:06 +0200426 int number_of_reconfigurations_ = 0;
427 int min_transmit_bitrate_bps_ = 0;
perkj26091b12016-09-01 01:17:40 -0700428 };
429
430 VideoSendStream::Config video_send_config_;
Erik Språng08127a92016-11-16 16:41:30 +0100431 VideoEncoderConfig video_encoder_config_;
Per512ecb32016-09-23 15:52:06 +0200432 int codec_width_;
433 int codec_height_;
perkj26091b12016-09-01 01:17:40 -0700434 TestEncoder fake_encoder_;
lliuuf9ed2352017-03-30 10:44:38 -0700435 std::unique_ptr<SendStatisticsProxy> stats_proxy_;
perkj26091b12016-09-01 01:17:40 -0700436 TestSink sink_;
sprangb1ca0732017-02-01 08:38:12 -0800437 AdaptingFrameForwarder video_source_;
perkj803d97f2016-11-01 11:45:46 -0700438 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
perkj26091b12016-09-01 01:17:40 -0700439};
440
441TEST_F(ViEEncoderTest, EncodeOneFrame) {
perkj26091b12016-09-01 01:17:40 -0700442 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
443 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700444 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
perkj26091b12016-09-01 01:17:40 -0700445 sink_.WaitForEncodedFrame(1);
perkja49cbd32016-09-16 07:53:41 -0700446 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700447 vie_encoder_->Stop();
448}
449
450TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
451 // Dropped since no target bitrate has been set.
452 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700453 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
454 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700455
perkj26091b12016-09-01 01:17:40 -0700456 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
457
perkja49cbd32016-09-16 07:53:41 -0700458 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700459 sink_.WaitForEncodedFrame(2);
460 vie_encoder_->Stop();
461}
462
463TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
perkj26091b12016-09-01 01:17:40 -0700464 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700465 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700466 sink_.WaitForEncodedFrame(1);
467
468 vie_encoder_->OnBitrateUpdated(0, 0, 0);
469 // Dropped since bitrate is zero.
perkja49cbd32016-09-16 07:53:41 -0700470 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700471
472 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700473 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700474 sink_.WaitForEncodedFrame(3);
475 vie_encoder_->Stop();
476}
477
478TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
perkj26091b12016-09-01 01:17:40 -0700479 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
perkja49cbd32016-09-16 07:53:41 -0700480 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700481 sink_.WaitForEncodedFrame(1);
482
483 // This frame will be dropped since it has the same ntp timestamp.
perkja49cbd32016-09-16 07:53:41 -0700484 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700485
perkja49cbd32016-09-16 07:53:41 -0700486 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
perkj26091b12016-09-01 01:17:40 -0700487 sink_.WaitForEncodedFrame(2);
488 vie_encoder_->Stop();
489}
490
491TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
perkj26091b12016-09-01 01:17:40 -0700492 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
493
perkja49cbd32016-09-16 07:53:41 -0700494 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700495 sink_.WaitForEncodedFrame(1);
496
497 vie_encoder_->Stop();
498 sink_.SetExpectNoFrames();
499 rtc::Event frame_destroyed_event(false, false);
perkja49cbd32016-09-16 07:53:41 -0700500 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
501 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
perkj26091b12016-09-01 01:17:40 -0700502}
503
504TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
perkj26091b12016-09-01 01:17:40 -0700505 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
506
507 fake_encoder_.BlockNextEncode();
perkja49cbd32016-09-16 07:53:41 -0700508 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
perkj26091b12016-09-01 01:17:40 -0700509 sink_.WaitForEncodedFrame(1);
510 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
511 // call to ContinueEncode.
perkja49cbd32016-09-16 07:53:41 -0700512 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
513 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
perkj26091b12016-09-01 01:17:40 -0700514 fake_encoder_.ContinueEncode();
515 sink_.WaitForEncodedFrame(3);
516
517 vie_encoder_->Stop();
518}
519
Per512ecb32016-09-23 15:52:06 +0200520TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
Per512ecb32016-09-23 15:52:06 +0200521 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
Per21d45d22016-10-30 21:37:57 +0100522 EXPECT_EQ(0, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200523
524 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200525 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
Per512ecb32016-09-23 15:52:06 +0200526 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100527 // The encoder will have been configured once when the first frame is
528 // received.
529 EXPECT_EQ(1, sink_.number_of_reconfigurations());
Per512ecb32016-09-23 15:52:06 +0200530
531 VideoEncoderConfig video_encoder_config;
perkjfa10b552016-10-02 23:45:26 -0700532 test::FillEncoderConfiguration(1, &video_encoder_config);
Per512ecb32016-09-23 15:52:06 +0200533 video_encoder_config.min_transmit_bitrate_bps = 9999;
asapersson5f7226f2016-11-25 04:37:00 -0800534 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
535 kMaxPayloadLength, true /* nack_enabled */);
Per512ecb32016-09-23 15:52:06 +0200536
537 // Capture a frame and wait for it to synchronize with the encoder thread.
Perf8c5f2b2016-09-23 16:24:55 +0200538 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
Per512ecb32016-09-23 15:52:06 +0200539 sink_.WaitForEncodedFrame(2);
Per21d45d22016-10-30 21:37:57 +0100540 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkj3b703ed2016-09-29 23:25:40 -0700541 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
perkj26105b42016-09-29 22:39:10 -0700542
543 vie_encoder_->Stop();
544}
545
perkjfa10b552016-10-02 23:45:26 -0700546TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
perkjfa10b552016-10-02 23:45:26 -0700547 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
548
549 // Capture a frame and wait for it to synchronize with the encoder thread.
550 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
551 sink_.WaitForEncodedFrame(1);
Per21d45d22016-10-30 21:37:57 +0100552 // The encoder will have been configured once.
553 EXPECT_EQ(1, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700554 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
555 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
556
557 codec_width_ *= 2;
558 codec_height_ *= 2;
559 // Capture a frame with a higher resolution and wait for it to synchronize
560 // with the encoder thread.
561 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
562 sink_.WaitForEncodedFrame(2);
563 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
564 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
Per21d45d22016-10-30 21:37:57 +0100565 EXPECT_EQ(2, sink_.number_of_reconfigurations());
perkjfa10b552016-10-02 23:45:26 -0700566
567 vie_encoder_->Stop();
568}
569
asapersson5f7226f2016-11-25 04:37:00 -0800570TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
571 const bool kNackEnabled = true;
572 const size_t kNumStreams = 1;
573 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800574 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800575 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
576
577 // Capture a frame and wait for it to synchronize with the encoder thread.
578 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
579 sink_.WaitForEncodedFrame(1);
580 // The encoder have been configured once when the first frame is received.
581 EXPECT_EQ(1, sink_.number_of_reconfigurations());
582 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
583 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
584 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
585 // Resilience is off for no temporal layers with nack on.
586 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
587 vie_encoder_->Stop();
588}
589
590TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
591 const bool kNackEnabled = true;
592 const size_t kNumStreams = 2;
593 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800594 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800595 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
596
597 // Capture a frame and wait for it to synchronize with the encoder thread.
598 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
599 sink_.WaitForEncodedFrame(1);
600 // The encoder have been configured once when the first frame is received.
601 EXPECT_EQ(1, sink_.number_of_reconfigurations());
602 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
603 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
604 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
605 // Resilience is off for no temporal layers and >1 streams with nack on.
606 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
607 vie_encoder_->Stop();
608}
609
610TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
611 const bool kNackEnabled = false;
612 const size_t kNumStreams = 1;
613 const size_t kNumTl = 1;
asaperssona90799d2016-12-09 02:35:20 -0800614 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800615 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
616
617 // Capture a frame and wait for it to synchronize with the encoder thread.
618 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
619 sink_.WaitForEncodedFrame(1);
620 // The encoder have been configured once when the first frame is received.
621 EXPECT_EQ(1, sink_.number_of_reconfigurations());
622 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
623 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
624 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
625 // Resilience is on for no temporal layers with nack off.
626 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
627 vie_encoder_->Stop();
628}
629
630TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
631 const bool kNackEnabled = true;
632 const size_t kNumStreams = 1;
633 const size_t kNumTl = 2;
asaperssona90799d2016-12-09 02:35:20 -0800634 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled);
asapersson5f7226f2016-11-25 04:37:00 -0800635 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
636
637 // Capture a frame and wait for it to synchronize with the encoder thread.
638 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
639 sink_.WaitForEncodedFrame(1);
640 // The encoder have been configured once when the first frame is received.
641 EXPECT_EQ(1, sink_.number_of_reconfigurations());
642 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
643 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
644 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
645 // Resilience is on for temporal layers.
646 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
647 vie_encoder_->Stop();
648}
649
perkj803d97f2016-11-01 11:45:46 -0700650TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
651 EXPECT_TRUE(video_source_.has_sinks());
652 test::FrameForwarder new_video_source;
lliuuf9ed2352017-03-30 10:44:38 -0700653 vie_encoder_->SetSource(&new_video_source,
654 VideoSendStream::DegradationPreference::kBalanced);
perkj803d97f2016-11-01 11:45:46 -0700655 EXPECT_FALSE(video_source_.has_sinks());
656 EXPECT_TRUE(new_video_source.has_sinks());
657
658 vie_encoder_->Stop();
659}
660
661TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
662 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
663 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
664 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
665 vie_encoder_->Stop();
666}
667
668TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
perkj803d97f2016-11-01 11:45:46 -0700669 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
670
sprang84a37592017-02-10 07:04:27 -0800671 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -0700672 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700673
674 int frame_width = 1280;
675 int frame_height = 720;
676
677 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
678 // request lower resolution.
lliuuf9ed2352017-03-30 10:44:38 -0700679 for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) {
perkj803d97f2016-11-01 11:45:46 -0700680 video_source_.IncomingCapturedFrame(
681 CreateFrame(i, frame_width, frame_height));
682 sink_.WaitForEncodedFrame(i);
683
684 vie_encoder_->TriggerCpuOveruse();
685
sprang84a37592017-02-10 07:04:27 -0800686 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -0700687 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
688 std::numeric_limits<int>::max()),
perkj803d97f2016-11-01 11:45:46 -0700689 frame_width * frame_height);
perkj803d97f2016-11-01 11:45:46 -0700690
691 frame_width /= 2;
692 frame_height /= 2;
693 }
694
kthelgason876222f2016-11-29 01:44:11 -0800695 // Trigger CPU overuse one more time. This should not trigger a request for
perkj803d97f2016-11-01 11:45:46 -0700696 // lower resolution.
697 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
698 video_source_.IncomingCapturedFrame(CreateFrame(
lliuuf9ed2352017-03-30 10:44:38 -0700699 ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height));
700 sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1);
perkj803d97f2016-11-01 11:45:46 -0700701 vie_encoder_->TriggerCpuOveruse();
sprang84a37592017-02-10 07:04:27 -0800702 EXPECT_EQ(video_source_.sink_wants().target_pixel_count,
703 current_wants.target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700704 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
705 current_wants.max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700706
707 // Trigger CPU normal use.
708 vie_encoder_->TriggerCpuNormalUsage();
sprang84a37592017-02-10 07:04:27 -0800709 EXPECT_EQ(frame_width * frame_height * 5 / 3,
710 video_source_.sink_wants().target_pixel_count.value_or(0));
711 EXPECT_EQ(frame_width * frame_height * 4,
lliuuf9ed2352017-03-30 10:44:38 -0700712 video_source_.sink_wants().max_pixel_count.value_or(0));
perkj803d97f2016-11-01 11:45:46 -0700713
714 vie_encoder_->Stop();
715}
716
lliuuf9ed2352017-03-30 10:44:38 -0700717TEST_F(ViEEncoderTest,
718 ResolutionSinkWantsResetOnSetSourceWithDisabledResolutionScaling) {
perkj803d97f2016-11-01 11:45:46 -0700719 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
720
sprang84a37592017-02-10 07:04:27 -0800721 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -0700722 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700723
lliuuf9ed2352017-03-30 10:44:38 -0700724 int frame_width = 1280;
725 int frame_height = 720;
perkj803d97f2016-11-01 11:45:46 -0700726
kthelgason5e13d412016-12-01 03:59:51 -0800727 video_source_.IncomingCapturedFrame(
lliuuf9ed2352017-03-30 10:44:38 -0700728 CreateFrame(1, frame_width, frame_height));
729 sink_.WaitForEncodedFrame(1);
perkj803d97f2016-11-01 11:45:46 -0700730 // Trigger CPU overuse.
731 vie_encoder_->TriggerCpuOveruse();
lliuuf9ed2352017-03-30 10:44:38 -0700732
perkj803d97f2016-11-01 11:45:46 -0700733 video_source_.IncomingCapturedFrame(
lliuuf9ed2352017-03-30 10:44:38 -0700734 CreateFrame(2, frame_width, frame_height));
735 sink_.WaitForEncodedFrame(2);
sprang3ea3c772017-03-30 07:23:48 -0700736 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -0700737 EXPECT_LT(video_source_.sink_wants().max_pixel_count.value_or(
738 std::numeric_limits<int>::max()),
739 frame_width * frame_height);
sprang3ea3c772017-03-30 07:23:48 -0700740
lliuuf9ed2352017-03-30 10:44:38 -0700741 // Set new source.
perkj803d97f2016-11-01 11:45:46 -0700742 test::FrameForwarder new_video_source;
743 vie_encoder_->SetSource(
744 &new_video_source,
745 VideoSendStream::DegradationPreference::kMaintainResolution);
746
sprang84a37592017-02-10 07:04:27 -0800747 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -0700748 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700749
750 new_video_source.IncomingCapturedFrame(
lliuuf9ed2352017-03-30 10:44:38 -0700751 CreateFrame(3, frame_width, frame_height));
752 sink_.WaitForEncodedFrame(3);
sprang84a37592017-02-10 07:04:27 -0800753 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -0700754 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700755
756 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
lliuuf9ed2352017-03-30 10:44:38 -0700757 vie_encoder_->SetSource(&new_video_source,
758 VideoSendStream::DegradationPreference::kBalanced);
759 EXPECT_LT(new_video_source.sink_wants().max_pixel_count.value_or(
760 std::numeric_limits<int>::max()),
761 frame_width * frame_height);
sprang84a37592017-02-10 07:04:27 -0800762 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
perkj803d97f2016-11-01 11:45:46 -0700763
764 vie_encoder_->Stop();
765}
766
767TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) {
perkj803d97f2016-11-01 11:45:46 -0700768 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
769
770 int frame_width = 1280;
771 int frame_height = 720;
772
773 video_source_.IncomingCapturedFrame(
774 CreateFrame(1, frame_width, frame_height));
775 sink_.WaitForEncodedFrame(1);
776 VideoSendStream::Stats stats = stats_proxy_->GetStats();
777 EXPECT_FALSE(stats.cpu_limited_resolution);
778 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
779
780 // Trigger CPU overuse.
781 vie_encoder_->TriggerCpuOveruse();
782 video_source_.IncomingCapturedFrame(
783 CreateFrame(2, frame_width, frame_height));
784 sink_.WaitForEncodedFrame(2);
785
786 stats = stats_proxy_->GetStats();
787 EXPECT_TRUE(stats.cpu_limited_resolution);
788 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
789
790 // Trigger CPU normal use.
791 vie_encoder_->TriggerCpuNormalUsage();
792 video_source_.IncomingCapturedFrame(
793 CreateFrame(3, frame_width, frame_height));
794 sink_.WaitForEncodedFrame(3);
795
796 stats = stats_proxy_->GetStats();
797 EXPECT_FALSE(stats.cpu_limited_resolution);
798 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
799
800 vie_encoder_->Stop();
801}
802
kthelgason876222f2016-11-29 01:44:11 -0800803TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800804 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
805
806 int frame_width = 1280;
807 int frame_height = 720;
808 video_source_.IncomingCapturedFrame(
809 CreateFrame(1, frame_width, frame_height));
810 sink_.WaitForEncodedFrame(1);
811
812 VideoSendStream::Stats stats = stats_proxy_->GetStats();
813 EXPECT_FALSE(stats.cpu_limited_resolution);
814 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
815
816 vie_encoder_->TriggerCpuOveruse();
817
818 video_source_.IncomingCapturedFrame(
819 CreateFrame(2, frame_width, frame_height));
820 sink_.WaitForEncodedFrame(2);
821 stats = stats_proxy_->GetStats();
822 EXPECT_TRUE(stats.cpu_limited_resolution);
823 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
824
825 // Set new source with adaptation still enabled.
826 test::FrameForwarder new_video_source;
lliuuf9ed2352017-03-30 10:44:38 -0700827 vie_encoder_->SetSource(&new_video_source,
828 VideoSendStream::DegradationPreference::kBalanced);
kthelgason876222f2016-11-29 01:44:11 -0800829
830 new_video_source.IncomingCapturedFrame(
831 CreateFrame(3, frame_width, frame_height));
832 sink_.WaitForEncodedFrame(3);
833 stats = stats_proxy_->GetStats();
834 EXPECT_TRUE(stats.cpu_limited_resolution);
835 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
836
837 // Set adaptation disabled.
838 vie_encoder_->SetSource(
839 &new_video_source,
lliuuf9ed2352017-03-30 10:44:38 -0700840 VideoSendStream::DegradationPreference::kMaintainResolution);
kthelgason876222f2016-11-29 01:44:11 -0800841
842 new_video_source.IncomingCapturedFrame(
843 CreateFrame(4, frame_width, frame_height));
844 sink_.WaitForEncodedFrame(4);
845 stats = stats_proxy_->GetStats();
846 EXPECT_FALSE(stats.cpu_limited_resolution);
847 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
848
849 // Set adaptation back to enabled.
lliuuf9ed2352017-03-30 10:44:38 -0700850 vie_encoder_->SetSource(&new_video_source,
851 VideoSendStream::DegradationPreference::kBalanced);
kthelgason876222f2016-11-29 01:44:11 -0800852
853 new_video_source.IncomingCapturedFrame(
854 CreateFrame(5, frame_width, frame_height));
855 sink_.WaitForEncodedFrame(5);
856 stats = stats_proxy_->GetStats();
857 EXPECT_TRUE(stats.cpu_limited_resolution);
858 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
859
860 vie_encoder_->TriggerCpuNormalUsage();
861
862 new_video_source.IncomingCapturedFrame(
863 CreateFrame(6, frame_width, frame_height));
864 sink_.WaitForEncodedFrame(6);
865 stats = stats_proxy_->GetStats();
866 EXPECT_FALSE(stats.cpu_limited_resolution);
867 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
868
869 vie_encoder_->Stop();
870}
871
872TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
kthelgason876222f2016-11-29 01:44:11 -0800873 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
874
875 int frame_width = 1280;
876 int frame_height = 720;
877 video_source_.IncomingCapturedFrame(
878 CreateFrame(1, frame_width, frame_height));
879 sink_.WaitForEncodedFrame(1);
880
881 VideoSendStream::Stats stats = stats_proxy_->GetStats();
882 EXPECT_FALSE(stats.cpu_limited_resolution);
883 EXPECT_FALSE(stats.bw_limited_resolution);
884 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
885
886 // Set new source with adaptation still enabled.
887 test::FrameForwarder new_video_source;
888 vie_encoder_->SetSource(&new_video_source,
889 VideoSendStream::DegradationPreference::kBalanced);
890
891 new_video_source.IncomingCapturedFrame(
892 CreateFrame(2, frame_width, frame_height));
893 sink_.WaitForEncodedFrame(2);
894 stats = stats_proxy_->GetStats();
895 EXPECT_FALSE(stats.cpu_limited_resolution);
896 EXPECT_FALSE(stats.bw_limited_resolution);
897 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
898
899 vie_encoder_->TriggerQualityLow();
900
901 new_video_source.IncomingCapturedFrame(
902 CreateFrame(3, frame_width, frame_height));
903 sink_.WaitForEncodedFrame(3);
904 stats = stats_proxy_->GetStats();
905 EXPECT_FALSE(stats.cpu_limited_resolution);
906 EXPECT_TRUE(stats.bw_limited_resolution);
907
908 vie_encoder_->SetSource(&new_video_source,
909 VideoSendStream::DegradationPreference::kBalanced);
910
911 new_video_source.IncomingCapturedFrame(
912 CreateFrame(4, frame_width, frame_height));
913 sink_.WaitForEncodedFrame(4);
914 stats = stats_proxy_->GetStats();
915 EXPECT_FALSE(stats.cpu_limited_resolution);
916 EXPECT_TRUE(stats.bw_limited_resolution);
917
918 // Set adaptation disabled.
919 vie_encoder_->SetSource(
920 &new_video_source,
921 VideoSendStream::DegradationPreference::kMaintainResolution);
922
923 new_video_source.IncomingCapturedFrame(
924 CreateFrame(5, frame_width, frame_height));
925 sink_.WaitForEncodedFrame(5);
926 stats = stats_proxy_->GetStats();
927 EXPECT_FALSE(stats.cpu_limited_resolution);
928 EXPECT_FALSE(stats.bw_limited_resolution);
929
930 vie_encoder_->Stop();
931}
932
asapersson36e9eb42017-03-31 05:29:12 -0700933TEST_F(ViEEncoderTest, QualityAdaptationStatsAreResetWhenScalerIsDisabled) {
934 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
935
936 const int kWidth = 1280;
937 const int kHeight = 720;
938 video_source_.set_adaptation_enabled(true);
939 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
940 sink_.WaitForEncodedFrame(1);
941 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
942 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
943 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
944
945 // Trigger adapt down.
946 vie_encoder_->TriggerQualityLow();
947 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
948 sink_.WaitForEncodedFrame(2);
949 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
950 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
951 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
952
953 // Trigger overuse.
954 vie_encoder_->TriggerCpuOveruse();
955 video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
956 sink_.WaitForEncodedFrame(3);
957 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
958 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
959 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
960
961 // Set source with adaptation still enabled but quality scaler is off.
962 fake_encoder_.SetQualityScaling(false);
963 vie_encoder_->SetSource(&video_source_,
964 VideoSendStream::DegradationPreference::kBalanced);
965
966 video_source_.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
967 sink_.WaitForEncodedFrame(4);
968 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
969 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
970 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
971
972 vie_encoder_->Stop();
973}
974
perkj803d97f2016-11-01 11:45:46 -0700975TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) {
perkj803d97f2016-11-01 11:45:46 -0700976 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
977
perkj803d97f2016-11-01 11:45:46 -0700978 int frame_width = 1280;
979 int frame_height = 720;
sprang84a37592017-02-10 07:04:27 -0800980 int sequence = 1;
perkj803d97f2016-11-01 11:45:46 -0700981
982 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -0800983 CreateFrame(sequence, frame_width, frame_height));
984 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -0700985
986 VideoSendStream::Stats stats = stats_proxy_->GetStats();
sprang84a37592017-02-10 07:04:27 -0800987 EXPECT_FALSE(stats.cpu_limited_resolution);
988 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
989
990 // Trigger CPU overuse again, should now adapt down.
991 vie_encoder_->TriggerCpuOveruse();
992 video_source_.IncomingCapturedFrame(
993 CreateFrame(sequence, frame_width, frame_height));
994 sink_.WaitForEncodedFrame(sequence++);
995
996 stats = stats_proxy_->GetStats();
perkj803d97f2016-11-01 11:45:46 -0700997 EXPECT_TRUE(stats.cpu_limited_resolution);
998 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
999
1000 // Set new source with adaptation still enabled.
1001 test::FrameForwarder new_video_source;
lliuuf9ed2352017-03-30 10:44:38 -07001002 vie_encoder_->SetSource(&new_video_source,
1003 VideoSendStream::DegradationPreference::kBalanced);
perkj803d97f2016-11-01 11:45:46 -07001004
1005 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -08001006 CreateFrame(sequence, frame_width, frame_height));
1007 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -07001008 stats = stats_proxy_->GetStats();
1009 EXPECT_TRUE(stats.cpu_limited_resolution);
1010 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1011
lliuuf9ed2352017-03-30 10:44:38 -07001012 // Set adaptation disabled.
perkj803d97f2016-11-01 11:45:46 -07001013 vie_encoder_->SetSource(
1014 &new_video_source,
1015 VideoSendStream::DegradationPreference::kMaintainResolution);
1016 new_video_source.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -08001017 CreateFrame(sequence, frame_width, frame_height));
1018 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -07001019 stats = stats_proxy_->GetStats();
1020 EXPECT_FALSE(stats.cpu_limited_resolution);
1021 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1022
lliuuf9ed2352017-03-30 10:44:38 -07001023 // Switch back the source with adaptation enabled.
1024 vie_encoder_->SetSource(&video_source_,
1025 VideoSendStream::DegradationPreference::kBalanced);
perkj803d97f2016-11-01 11:45:46 -07001026 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -08001027 CreateFrame(sequence, frame_width, frame_height));
1028 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -07001029 stats = stats_proxy_->GetStats();
1030 EXPECT_TRUE(stats.cpu_limited_resolution);
lliuuf9ed2352017-03-30 10:44:38 -07001031 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
perkj803d97f2016-11-01 11:45:46 -07001032
1033 // Trigger CPU normal usage.
1034 vie_encoder_->TriggerCpuNormalUsage();
1035 video_source_.IncomingCapturedFrame(
sprang84a37592017-02-10 07:04:27 -08001036 CreateFrame(sequence, frame_width, frame_height));
1037 sink_.WaitForEncodedFrame(sequence++);
perkj803d97f2016-11-01 11:45:46 -07001038 stats = stats_proxy_->GetStats();
1039 EXPECT_FALSE(stats.cpu_limited_resolution);
lliuuf9ed2352017-03-30 10:44:38 -07001040 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
perkj803d97f2016-11-01 11:45:46 -07001041
1042 vie_encoder_->Stop();
1043}
1044
Erik Språng08127a92016-11-16 16:41:30 +01001045TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
Erik Språng08127a92016-11-16 16:41:30 +01001046 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1047
1048 video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
1049 sink_.WaitForEncodedFrame(1);
1050
1051 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1052 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
1053 stats.preferred_media_bitrate_bps);
1054
1055 vie_encoder_->Stop();
1056}
1057
kthelgason876222f2016-11-29 01:44:11 -08001058TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
kthelgason876222f2016-11-29 01:44:11 -08001059 int frame_width = 1280;
1060 int frame_height = 720;
1061 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1062
1063 // Expect no scaling to begin with
sprang84a37592017-02-10 07:04:27 -08001064 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -07001065 EXPECT_FALSE(video_source_.sink_wants().max_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -08001066
kthelgason876222f2016-11-29 01:44:11 -08001067 video_source_.IncomingCapturedFrame(
1068 CreateFrame(1, frame_width, frame_height));
1069 sink_.WaitForEncodedFrame(1);
1070
kthelgason5e13d412016-12-01 03:59:51 -08001071 // Trigger scale down
1072 vie_encoder_->TriggerQualityLow();
1073
1074 video_source_.IncomingCapturedFrame(
1075 CreateFrame(2, frame_width, frame_height));
1076 sink_.WaitForEncodedFrame(2);
1077
kthelgason876222f2016-11-29 01:44:11 -08001078 // Expect a scale down.
1079 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
lliuuf9ed2352017-03-30 10:44:38 -07001080 EXPECT_LT(*video_source_.sink_wants().max_pixel_count,
kthelgason876222f2016-11-29 01:44:11 -08001081 frame_width * frame_height);
1082
1083 // Set adaptation disabled.
1084 test::FrameForwarder new_video_source;
1085 vie_encoder_->SetSource(
1086 &new_video_source,
1087 VideoSendStream::DegradationPreference::kMaintainResolution);
1088
1089 // Trigger scale down
1090 vie_encoder_->TriggerQualityLow();
1091 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001092 CreateFrame(3, frame_width, frame_height));
1093 sink_.WaitForEncodedFrame(3);
kthelgason876222f2016-11-29 01:44:11 -08001094
1095 // Expect no scaling
lliuuf9ed2352017-03-30 10:44:38 -07001096 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -08001097
1098 // Trigger scale up
1099 vie_encoder_->TriggerQualityHigh();
1100 new_video_source.IncomingCapturedFrame(
kthelgason5e13d412016-12-01 03:59:51 -08001101 CreateFrame(4, frame_width, frame_height));
1102 sink_.WaitForEncodedFrame(4);
kthelgason876222f2016-11-29 01:44:11 -08001103
1104 // Expect nothing to change, still no scaling
lliuuf9ed2352017-03-30 10:44:38 -07001105 EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count);
kthelgason876222f2016-11-29 01:44:11 -08001106
1107 vie_encoder_->Stop();
1108}
1109
kthelgason5e13d412016-12-01 03:59:51 -08001110TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) {
kthelgason5e13d412016-12-01 03:59:51 -08001111 int frame_width = 1280;
1112 int frame_height = 720;
kthelgason5e13d412016-12-01 03:59:51 -08001113 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1114
1115 for (size_t i = 1; i <= 10; i++) {
1116 video_source_.IncomingCapturedFrame(
1117 CreateFrame(i, frame_width, frame_height));
1118 sink_.WaitForEncodedFrame(i);
1119 // Trigger scale down
1120 vie_encoder_->TriggerQualityLow();
lliuuf9ed2352017-03-30 10:44:38 -07001121 EXPECT_GE(*video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
kthelgason5e13d412016-12-01 03:59:51 -08001122 }
1123
1124 vie_encoder_->Stop();
1125}
1126
perkj803d97f2016-11-01 11:45:46 -07001127TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) {
perkj803d97f2016-11-01 11:45:46 -07001128 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1129
1130 int frame_width = 640;
1131 int frame_height = 360;
1132
1133 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1134 video_source_.IncomingCapturedFrame(
1135 CreateFrame(i, frame_width, frame_height));
1136 sink_.WaitForEncodedFrame(i);
1137 }
1138
1139 vie_encoder_->TriggerCpuOveruse();
1140 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1141 video_source_.IncomingCapturedFrame(
1142 CreateFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i,
1143 frame_width, frame_height));
1144 sink_.WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples +
1145 i);
1146 }
1147
1148 vie_encoder_->Stop();
sprangf8ee65e2017-02-28 08:49:33 -08001149 vie_encoder_.reset();
perkj803d97f2016-11-01 11:45:46 -07001150 stats_proxy_.reset();
sprangf8ee65e2017-02-28 08:49:33 -08001151
perkj803d97f2016-11-01 11:45:46 -07001152 EXPECT_EQ(1,
1153 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1154 EXPECT_EQ(
1155 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1156}
1157
sprang57c2fff2017-01-16 06:24:02 -08001158TEST_F(ViEEncoderTest, CallsBitrateObserver) {
1159 class MockBitrateObserver : public VideoBitrateAllocationObserver {
1160 public:
1161 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
1162 } bitrate_observer;
1163 vie_encoder_->SetBitrateObserver(&bitrate_observer);
1164
1165 const int kDefaultFps = 30;
1166 const BitrateAllocation expected_bitrate =
1167 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
kthelgason2bc68642017-02-07 07:02:22 -08001168 .GetAllocation(kLowTargetBitrateBps, kDefaultFps);
sprang57c2fff2017-01-16 06:24:02 -08001169
1170 // First called on bitrate updated, then again on first frame.
1171 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1172 .Times(2);
kthelgason2bc68642017-02-07 07:02:22 -08001173 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
sprang57c2fff2017-01-16 06:24:02 -08001174
1175 const int64_t kStartTimeMs = 1;
1176 video_source_.IncomingCapturedFrame(
1177 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
1178 sink_.WaitForEncodedFrame(kStartTimeMs);
1179
1180 // Not called on second frame.
1181 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1182 .Times(0);
1183 video_source_.IncomingCapturedFrame(
1184 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
1185 sink_.WaitForEncodedFrame(kStartTimeMs + 1);
1186
1187 // Called after a process interval.
1188 const int64_t kProcessIntervalMs =
1189 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
1190 // TODO(sprang): ViEEncoder should die and/or get injectable clock.
1191 // Sleep for one processing interval plus one frame to avoid flakiness.
1192 SleepMs(kProcessIntervalMs + 1000 / kDefaultFps);
1193 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
1194 .Times(1);
1195 video_source_.IncomingCapturedFrame(CreateFrame(
1196 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
1197 sink_.WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
1198
1199 vie_encoder_->Stop();
1200}
1201
kthelgason2bc68642017-02-07 07:02:22 -08001202TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
1203 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1204 int frame_width = 640;
1205 int frame_height = 360;
1206
1207 video_source_.IncomingCapturedFrame(
1208 CreateFrame(1, frame_width, frame_height));
1209
1210 // Expect to drop this frame, the wait should time out.
1211 sink_.ExpectDroppedFrame();
1212
1213 // Expect the sink_wants to specify a scaled frame.
lliuuf9ed2352017-03-30 10:44:38 -07001214 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1215 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
kthelgason2bc68642017-02-07 07:02:22 -08001216
lliuuf9ed2352017-03-30 10:44:38 -07001217 int last_pixel_count = *video_source_.sink_wants().max_pixel_count;
kthelgason2bc68642017-02-07 07:02:22 -08001218
1219 // Next frame is scaled
1220 video_source_.IncomingCapturedFrame(
1221 CreateFrame(2, frame_width * 3 / 4, frame_height * 3 / 4));
1222
1223 // Expect to drop this frame, the wait should time out.
1224 sink_.ExpectDroppedFrame();
1225
lliuuf9ed2352017-03-30 10:44:38 -07001226 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, last_pixel_count);
kthelgason2bc68642017-02-07 07:02:22 -08001227
1228 vie_encoder_->Stop();
1229}
1230
kthelgason2fc52542017-03-03 00:24:41 -08001231TEST_F(ViEEncoderTest, NrOfDroppedFramesLimited) {
kthelgason2bc68642017-02-07 07:02:22 -08001232 // 1kbps. This can never be achieved.
1233 vie_encoder_->OnBitrateUpdated(1000, 0, 0);
1234 int frame_width = 640;
1235 int frame_height = 360;
1236
1237 // We expect the n initial frames to get dropped.
1238 int i;
1239 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
1240 video_source_.IncomingCapturedFrame(
1241 CreateFrame(i, frame_width, frame_height));
1242 sink_.ExpectDroppedFrame();
1243 }
1244 // The n+1th frame should not be dropped, even though it's size is too large.
1245 video_source_.IncomingCapturedFrame(
1246 CreateFrame(i, frame_width, frame_height));
1247 sink_.WaitForEncodedFrame(i);
1248
1249 // Expect the sink_wants to specify a scaled frame.
lliuuf9ed2352017-03-30 10:44:38 -07001250 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1251 EXPECT_LT(*video_source_.sink_wants().max_pixel_count, 1000 * 1000);
kthelgason2bc68642017-02-07 07:02:22 -08001252
1253 vie_encoder_->Stop();
1254}
1255
1256TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
1257 int frame_width = 640;
1258 int frame_height = 360;
1259 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
1260
1261 // Set degradation preference.
1262 vie_encoder_->SetSource(
1263 &video_source_,
1264 VideoSendStream::DegradationPreference::kMaintainResolution);
1265
1266 video_source_.IncomingCapturedFrame(
1267 CreateFrame(1, frame_width, frame_height));
1268 // Frame should not be dropped, even if it's too large.
1269 sink_.WaitForEncodedFrame(1);
1270
1271 vie_encoder_->Stop();
1272}
1273
kthelgason2fc52542017-03-03 00:24:41 -08001274TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
kthelgasonad9010c2017-02-14 00:46:51 -08001275 int frame_width = 640;
1276 int frame_height = 360;
1277 fake_encoder_.SetQualityScaling(false);
1278 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
kthelgasonb83797b2017-02-14 11:57:25 -08001279 // Force quality scaler reconfiguration by resetting the source.
1280 vie_encoder_->SetSource(&video_source_,
1281 VideoSendStream::DegradationPreference::kBalanced);
kthelgasonad9010c2017-02-14 00:46:51 -08001282
1283 video_source_.IncomingCapturedFrame(
1284 CreateFrame(1, frame_width, frame_height));
1285 // Frame should not be dropped, even if it's too large.
1286 sink_.WaitForEncodedFrame(1);
1287
1288 vie_encoder_->Stop();
1289 fake_encoder_.SetQualityScaling(true);
1290}
1291
sprangb1ca0732017-02-01 08:38:12 -08001292// TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
1293TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) {
1294 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1295
1296 const int kFrameWidth = 1280;
1297 const int kFrameHeight = 720;
1298 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
1299 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
1300 video_source_.set_adaptation_enabled(true);
1301
1302 video_source_.IncomingCapturedFrame(
1303 CreateFrame(1, kFrameWidth, kFrameHeight));
1304 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1305
1306 // Trigger CPU overuse, downscale by 3/4.
1307 vie_encoder_->TriggerCpuOveruse();
1308 video_source_.IncomingCapturedFrame(
1309 CreateFrame(2, kFrameWidth, kFrameHeight));
1310 sink_.WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
1311
lliuuf9ed2352017-03-30 10:44:38 -07001312 // Trigger CPU normal use, return to original resoluton;
sprangb1ca0732017-02-01 08:38:12 -08001313 vie_encoder_->TriggerCpuNormalUsage();
1314 video_source_.IncomingCapturedFrame(
1315 CreateFrame(3, kFrameWidth, kFrameHeight));
1316 sink_.WaitForEncodedFrame(kFrameWidth, kFrameHeight);
1317
1318 vie_encoder_->Stop();
1319}
sprangfe627f32017-03-29 08:24:59 -07001320
1321TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) {
1322 fake_encoder_.ForceInitEncodeFailure(true);
1323 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1324 ResetEncoder("VP8", 2, 1, true);
1325 const int kFrameWidth = 1280;
1326 const int kFrameHeight = 720;
1327 video_source_.IncomingCapturedFrame(
1328 CreateFrame(1, kFrameWidth, kFrameHeight));
1329 sink_.ExpectDroppedFrame();
1330 vie_encoder_->Stop();
1331}
perkj26091b12016-09-01 01:17:40 -07001332} // namespace webrtc