Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(732)

Side by Side Diff: webrtc/video/vie_encoder_unittest.cc

Issue 2995433002: Rename ViEEncoder to VideoStreamEncoder. (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/video/vie_encoder.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
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
11 #include <algorithm>
12 #include <limits>
13 #include <utility>
14
15 #include "webrtc/api/video/i420_buffer.h"
16 #include "webrtc/media/base/videoadapter.h"
17 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
18 #include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
19 #include "webrtc/rtc_base/fakeclock.h"
20 #include "webrtc/rtc_base/logging.h"
21 #include "webrtc/system_wrappers/include/metrics_default.h"
22 #include "webrtc/system_wrappers/include/sleep.h"
23 #include "webrtc/test/encoder_settings.h"
24 #include "webrtc/test/fake_encoder.h"
25 #include "webrtc/test/frame_generator.h"
26 #include "webrtc/test/gmock.h"
27 #include "webrtc/test/gtest.h"
28 #include "webrtc/video/send_statistics_proxy.h"
29 #include "webrtc/video/vie_encoder.h"
30
31 namespace {
32 // TODO(kthelgason): Lower this limit when better testing
33 // on MediaCodec and fallback implementations are in place.
34 const int kMinPixelsPerFrame = 320 * 180;
35 const int kMinFramerateFps = 2;
36 const int64_t kFrameTimeoutMs = 100;
37 } // namespace
38
39 namespace webrtc {
40
41 using DegredationPreference = VideoSendStream::DegradationPreference;
42 using ScaleReason = AdaptationObserverInterface::AdaptReason;
43 using ::testing::_;
44 using ::testing::Return;
45
46 namespace {
47 const size_t kMaxPayloadLength = 1440;
48 const int kTargetBitrateBps = 1000000;
49 const int kLowTargetBitrateBps = kTargetBitrateBps / 10;
50 const int kMaxInitialFramedrop = 4;
51 const int kDefaultFramerate = 30;
52
53 class 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
67 class CpuOveruseDetectorProxy : public OveruseFrameDetector {
68 public:
69 CpuOveruseDetectorProxy(const CpuOveruseOptions& options,
70 AdaptationObserverInterface* overuse_observer,
71 EncodedFrameObserver* encoder_timing_,
72 CpuOveruseMetricsObserver* metrics_observer)
73 : OveruseFrameDetector(options,
74 overuse_observer,
75 encoder_timing_,
76 metrics_observer),
77 last_target_framerate_fps_(-1) {}
78 virtual ~CpuOveruseDetectorProxy() {}
79
80 void OnTargetFramerateUpdated(int framerate_fps) override {
81 rtc::CritScope cs(&lock_);
82 last_target_framerate_fps_ = framerate_fps;
83 OveruseFrameDetector::OnTargetFramerateUpdated(framerate_fps);
84 }
85
86 int GetLastTargetFramerate() {
87 rtc::CritScope cs(&lock_);
88 return last_target_framerate_fps_;
89 }
90
91 private:
92 rtc::CriticalSection lock_;
93 int last_target_framerate_fps_ GUARDED_BY(lock_);
94 };
95
96 class ViEEncoderUnderTest : public ViEEncoder {
97 public:
98 ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
99 const VideoSendStream::Config::EncoderSettings& settings)
100 : ViEEncoder(1 /* number_of_cores */,
101 stats_proxy,
102 settings,
103 nullptr /* pre_encode_callback */,
104 nullptr /* encoder_timing */,
105 std::unique_ptr<OveruseFrameDetector>(
106 overuse_detector_proxy_ = new CpuOveruseDetectorProxy(
107 GetCpuOveruseOptions(settings.full_overuse_time),
108 this,
109 nullptr,
110 stats_proxy))) {}
111
112 void PostTaskAndWait(bool down, AdaptReason reason) {
113 rtc::Event event(false, false);
114 encoder_queue()->PostTask([this, &event, reason, down] {
115 down ? AdaptDown(reason) : AdaptUp(reason);
116 event.Set();
117 });
118 ASSERT_TRUE(event.Wait(5000));
119 }
120
121 // This is used as a synchronisation mechanism, to make sure that the
122 // encoder queue is not blocked before we start sending it frames.
123 void WaitUntilTaskQueueIsIdle() {
124 rtc::Event event(false, false);
125 encoder_queue()->PostTask([&event] {
126 event.Set();
127 });
128 ASSERT_TRUE(event.Wait(5000));
129 }
130
131 void TriggerCpuOveruse() { PostTaskAndWait(true, AdaptReason::kCpu); }
132
133 void TriggerCpuNormalUsage() { PostTaskAndWait(false, AdaptReason::kCpu); }
134
135 void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); }
136
137 void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); }
138
139 CpuOveruseDetectorProxy* overuse_detector_proxy_;
140 };
141
142 class VideoStreamFactory
143 : public VideoEncoderConfig::VideoStreamFactoryInterface {
144 public:
145 explicit VideoStreamFactory(size_t num_temporal_layers, int framerate)
146 : num_temporal_layers_(num_temporal_layers), framerate_(framerate) {
147 EXPECT_GT(num_temporal_layers, 0u);
148 EXPECT_GT(framerate, 0);
149 }
150
151 private:
152 std::vector<VideoStream> CreateEncoderStreams(
153 int width,
154 int height,
155 const VideoEncoderConfig& encoder_config) override {
156 std::vector<VideoStream> streams =
157 test::CreateVideoStreams(width, height, encoder_config);
158 for (VideoStream& stream : streams) {
159 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
160 stream.max_framerate = framerate_;
161 }
162 return streams;
163 }
164
165 const size_t num_temporal_layers_;
166 const int framerate_;
167 };
168
169
170 class AdaptingFrameForwarder : public test::FrameForwarder {
171 public:
172 AdaptingFrameForwarder() : adaptation_enabled_(false) {}
173 ~AdaptingFrameForwarder() override {}
174
175 void set_adaptation_enabled(bool enabled) {
176 rtc::CritScope cs(&crit_);
177 adaptation_enabled_ = enabled;
178 }
179
180 bool adaption_enabled() const {
181 rtc::CritScope cs(&crit_);
182 return adaptation_enabled_;
183 }
184
185 rtc::VideoSinkWants last_wants() const {
186 rtc::CritScope cs(&crit_);
187 return last_wants_;
188 }
189
190 void IncomingCapturedFrame(const VideoFrame& video_frame) override {
191 int cropped_width = 0;
192 int cropped_height = 0;
193 int out_width = 0;
194 int out_height = 0;
195 if (adaption_enabled()) {
196 if (adapter_.AdaptFrameResolution(
197 video_frame.width(), video_frame.height(),
198 video_frame.timestamp_us() * 1000, &cropped_width,
199 &cropped_height, &out_width, &out_height)) {
200 VideoFrame adapted_frame(new rtc::RefCountedObject<TestBuffer>(
201 nullptr, out_width, out_height),
202 99, 99, kVideoRotation_0);
203 adapted_frame.set_ntp_time_ms(video_frame.ntp_time_ms());
204 test::FrameForwarder::IncomingCapturedFrame(adapted_frame);
205 }
206 } else {
207 test::FrameForwarder::IncomingCapturedFrame(video_frame);
208 }
209 }
210
211 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
212 const rtc::VideoSinkWants& wants) override {
213 rtc::CritScope cs(&crit_);
214 last_wants_ = sink_wants();
215 adapter_.OnResolutionFramerateRequest(wants.target_pixel_count,
216 wants.max_pixel_count,
217 wants.max_framerate_fps);
218 test::FrameForwarder::AddOrUpdateSink(sink, wants);
219 }
220 cricket::VideoAdapter adapter_;
221 bool adaptation_enabled_ GUARDED_BY(crit_);
222 rtc::VideoSinkWants last_wants_ GUARDED_BY(crit_);
223 };
224
225 class MockableSendStatisticsProxy : public SendStatisticsProxy {
226 public:
227 MockableSendStatisticsProxy(Clock* clock,
228 const VideoSendStream::Config& config,
229 VideoEncoderConfig::ContentType content_type)
230 : SendStatisticsProxy(clock, config, content_type) {}
231
232 VideoSendStream::Stats GetStats() override {
233 rtc::CritScope cs(&lock_);
234 if (mock_stats_)
235 return *mock_stats_;
236 return SendStatisticsProxy::GetStats();
237 }
238
239 void SetMockStats(const VideoSendStream::Stats& stats) {
240 rtc::CritScope cs(&lock_);
241 mock_stats_.emplace(stats);
242 }
243
244 void ResetMockStats() {
245 rtc::CritScope cs(&lock_);
246 mock_stats_.reset();
247 }
248
249 private:
250 rtc::CriticalSection lock_;
251 rtc::Optional<VideoSendStream::Stats> mock_stats_ GUARDED_BY(lock_);
252 };
253
254 class MockBitrateObserver : public VideoBitrateAllocationObserver {
255 public:
256 MOCK_METHOD1(OnBitrateAllocationUpdated, void(const BitrateAllocation&));
257 };
258
259 } // namespace
260
261 class ViEEncoderTest : public ::testing::Test {
262 public:
263 static const int kDefaultTimeoutMs = 30 * 1000;
264
265 ViEEncoderTest()
266 : video_send_config_(VideoSendStream::Config(nullptr)),
267 codec_width_(320),
268 codec_height_(240),
269 max_framerate_(30),
270 fake_encoder_(),
271 stats_proxy_(new MockableSendStatisticsProxy(
272 Clock::GetRealTimeClock(),
273 video_send_config_,
274 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo)),
275 sink_(&fake_encoder_) {}
276
277 void SetUp() override {
278 metrics::Reset();
279 video_send_config_ = VideoSendStream::Config(nullptr);
280 video_send_config_.encoder_settings.encoder = &fake_encoder_;
281 video_send_config_.encoder_settings.payload_name = "FAKE";
282 video_send_config_.encoder_settings.payload_type = 125;
283
284 VideoEncoderConfig video_encoder_config;
285 test::FillEncoderConfiguration(1, &video_encoder_config);
286 video_encoder_config.video_stream_factory =
287 new rtc::RefCountedObject<VideoStreamFactory>(1, max_framerate_);
288 video_encoder_config_ = video_encoder_config.Copy();
289
290 // Framerate limit is specified by the VideoStreamFactory.
291 std::vector<VideoStream> streams =
292 video_encoder_config.video_stream_factory->CreateEncoderStreams(
293 codec_width_, codec_height_, video_encoder_config);
294 max_framerate_ = streams[0].max_framerate;
295 fake_clock_.SetTimeMicros(1234);
296
297 ConfigureEncoder(std::move(video_encoder_config), true /* nack_enabled */);
298 }
299
300 void ConfigureEncoder(VideoEncoderConfig video_encoder_config,
301 bool nack_enabled) {
302 if (vie_encoder_)
303 vie_encoder_->Stop();
304 vie_encoder_.reset(new ViEEncoderUnderTest(
305 stats_proxy_.get(), video_send_config_.encoder_settings));
306 vie_encoder_->SetSink(&sink_, false /* rotation_applied */);
307 vie_encoder_->SetSource(
308 &video_source_,
309 VideoSendStream::DegradationPreference::kMaintainFramerate);
310 vie_encoder_->SetStartBitrate(kTargetBitrateBps);
311 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
312 kMaxPayloadLength, nack_enabled);
313 vie_encoder_->WaitUntilTaskQueueIsIdle();
314 }
315
316 void ResetEncoder(const std::string& payload_name,
317 size_t num_streams,
318 size_t num_temporal_layers,
319 bool nack_enabled,
320 bool screenshare) {
321 video_send_config_.encoder_settings.payload_name = payload_name;
322
323 VideoEncoderConfig video_encoder_config;
324 video_encoder_config.number_of_streams = num_streams;
325 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
326 video_encoder_config.video_stream_factory =
327 new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers,
328 kDefaultFramerate);
329 video_encoder_config.content_type =
330 screenshare ? VideoEncoderConfig::ContentType::kScreen
331 : VideoEncoderConfig::ContentType::kRealtimeVideo;
332 ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
333 }
334
335 VideoFrame CreateFrame(int64_t ntp_time_ms,
336 rtc::Event* destruction_event) const {
337 VideoFrame frame(new rtc::RefCountedObject<TestBuffer>(
338 destruction_event, codec_width_, codec_height_),
339 99, 99, kVideoRotation_0);
340 frame.set_ntp_time_ms(ntp_time_ms);
341 return frame;
342 }
343
344 VideoFrame CreateFrame(int64_t ntp_time_ms, int width, int height) const {
345 VideoFrame frame(
346 new rtc::RefCountedObject<TestBuffer>(nullptr, width, height), 99, 99,
347 kVideoRotation_0);
348 frame.set_ntp_time_ms(ntp_time_ms);
349 frame.set_timestamp_us(ntp_time_ms * 1000);
350 return frame;
351 }
352
353 void VerifyNoLimitation(const rtc::VideoSinkWants& wants) {
354 EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_framerate_fps);
355 EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count);
356 EXPECT_FALSE(wants.target_pixel_count);
357 }
358
359 void VerifyFpsEqResolutionEq(const rtc::VideoSinkWants& wants1,
360 const rtc::VideoSinkWants& wants2) {
361 EXPECT_EQ(wants1.max_framerate_fps, wants2.max_framerate_fps);
362 EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count);
363 }
364
365 void VerifyFpsMaxResolutionLt(const rtc::VideoSinkWants& wants1,
366 const rtc::VideoSinkWants& wants2) {
367 EXPECT_EQ(std::numeric_limits<int>::max(), wants1.max_framerate_fps);
368 EXPECT_LT(wants1.max_pixel_count, wants2.max_pixel_count);
369 EXPECT_GT(wants1.max_pixel_count, 0);
370 }
371
372 void VerifyFpsMaxResolutionGt(const rtc::VideoSinkWants& wants1,
373 const rtc::VideoSinkWants& wants2) {
374 EXPECT_EQ(std::numeric_limits<int>::max(), wants1.max_framerate_fps);
375 EXPECT_GT(wants1.max_pixel_count, wants2.max_pixel_count);
376 }
377
378 void VerifyFpsMaxResolutionEq(const rtc::VideoSinkWants& wants1,
379 const rtc::VideoSinkWants& wants2) {
380 EXPECT_EQ(std::numeric_limits<int>::max(), wants1.max_framerate_fps);
381 EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count);
382 }
383
384 void VerifyFpsLtResolutionEq(const rtc::VideoSinkWants& wants1,
385 const rtc::VideoSinkWants& wants2) {
386 EXPECT_LT(wants1.max_framerate_fps, wants2.max_framerate_fps);
387 EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count);
388 }
389
390 void VerifyFpsGtResolutionEq(const rtc::VideoSinkWants& wants1,
391 const rtc::VideoSinkWants& wants2) {
392 EXPECT_GT(wants1.max_framerate_fps, wants2.max_framerate_fps);
393 EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count);
394 }
395
396 void VerifyFpsEqResolutionLt(const rtc::VideoSinkWants& wants1,
397 const rtc::VideoSinkWants& wants2) {
398 EXPECT_EQ(wants1.max_framerate_fps, wants2.max_framerate_fps);
399 EXPECT_LT(wants1.max_pixel_count, wants2.max_pixel_count);
400 EXPECT_GT(wants1.max_pixel_count, 0);
401 }
402
403 void VerifyFpsEqResolutionGt(const rtc::VideoSinkWants& wants1,
404 const rtc::VideoSinkWants& wants2) {
405 EXPECT_EQ(wants1.max_framerate_fps, wants2.max_framerate_fps);
406 EXPECT_GT(wants1.max_pixel_count, wants2.max_pixel_count);
407 }
408
409 void VerifyFpsMaxResolutionLt(const rtc::VideoSinkWants& wants,
410 int pixel_count) {
411 EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_framerate_fps);
412 EXPECT_LT(wants.max_pixel_count, pixel_count);
413 EXPECT_GT(wants.max_pixel_count, 0);
414 }
415
416 void VerifyFpsLtResolutionMax(const rtc::VideoSinkWants& wants, int fps) {
417 EXPECT_LT(wants.max_framerate_fps, fps);
418 EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count);
419 EXPECT_FALSE(wants.target_pixel_count);
420 }
421
422 void VerifyFpsEqResolutionMax(const rtc::VideoSinkWants& wants,
423 int expected_fps) {
424 EXPECT_EQ(expected_fps, wants.max_framerate_fps);
425 EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count);
426 EXPECT_FALSE(wants.target_pixel_count);
427 }
428
429 void WaitForEncodedFrame(int64_t expected_ntp_time) {
430 sink_.WaitForEncodedFrame(expected_ntp_time);
431 fake_clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec / max_framerate_);
432 }
433
434 bool TimedWaitForEncodedFrame(int64_t expected_ntp_time, int64_t timeout_ms) {
435 bool ok = sink_.TimedWaitForEncodedFrame(expected_ntp_time, timeout_ms);
436 fake_clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec / max_framerate_);
437 return ok;
438 }
439
440 void WaitForEncodedFrame(uint32_t expected_width, uint32_t expected_height) {
441 sink_.WaitForEncodedFrame(expected_width, expected_height);
442 fake_clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec / max_framerate_);
443 }
444
445 void ExpectDroppedFrame() {
446 sink_.ExpectDroppedFrame();
447 fake_clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec / max_framerate_);
448 }
449
450 bool WaitForFrame(int64_t timeout_ms) {
451 bool ok = sink_.WaitForFrame(timeout_ms);
452 fake_clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec / max_framerate_);
453 return ok;
454 }
455
456 class TestEncoder : public test::FakeEncoder {
457 public:
458 TestEncoder()
459 : FakeEncoder(Clock::GetRealTimeClock()),
460 continue_encode_event_(false, false) {}
461
462 VideoCodec codec_config() const {
463 rtc::CritScope lock(&crit_sect_);
464 return config_;
465 }
466
467 void BlockNextEncode() {
468 rtc::CritScope lock(&local_crit_sect_);
469 block_next_encode_ = true;
470 }
471
472 VideoEncoder::ScalingSettings GetScalingSettings() const override {
473 rtc::CritScope lock(&local_crit_sect_);
474 if (quality_scaling_)
475 return VideoEncoder::ScalingSettings(true, 1, 2);
476 return VideoEncoder::ScalingSettings(false);
477 }
478
479 void ContinueEncode() { continue_encode_event_.Set(); }
480
481 void CheckLastTimeStampsMatch(int64_t ntp_time_ms,
482 uint32_t timestamp) const {
483 rtc::CritScope lock(&local_crit_sect_);
484 EXPECT_EQ(timestamp_, timestamp);
485 EXPECT_EQ(ntp_time_ms_, ntp_time_ms);
486 }
487
488 void SetQualityScaling(bool b) {
489 rtc::CritScope lock(&local_crit_sect_);
490 quality_scaling_ = b;
491 }
492
493 void ForceInitEncodeFailure(bool force_failure) {
494 rtc::CritScope lock(&local_crit_sect_);
495 force_init_encode_failed_ = force_failure;
496 }
497
498 private:
499 int32_t Encode(const VideoFrame& input_image,
500 const CodecSpecificInfo* codec_specific_info,
501 const std::vector<FrameType>* frame_types) override {
502 bool block_encode;
503 {
504 rtc::CritScope lock(&local_crit_sect_);
505 EXPECT_GT(input_image.timestamp(), timestamp_);
506 EXPECT_GT(input_image.ntp_time_ms(), ntp_time_ms_);
507 EXPECT_EQ(input_image.timestamp(), input_image.ntp_time_ms() * 90);
508
509 timestamp_ = input_image.timestamp();
510 ntp_time_ms_ = input_image.ntp_time_ms();
511 last_input_width_ = input_image.width();
512 last_input_height_ = input_image.height();
513 block_encode = block_next_encode_;
514 block_next_encode_ = false;
515 }
516 int32_t result =
517 FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
518 if (block_encode)
519 EXPECT_TRUE(continue_encode_event_.Wait(kDefaultTimeoutMs));
520 return result;
521 }
522
523 int32_t InitEncode(const VideoCodec* config,
524 int32_t number_of_cores,
525 size_t max_payload_size) override {
526 int res =
527 FakeEncoder::InitEncode(config, number_of_cores, max_payload_size);
528 rtc::CritScope lock(&local_crit_sect_);
529 if (config->codecType == kVideoCodecVP8 && config->VP8().tl_factory) {
530 // Simulate setting up temporal layers, in order to validate the life
531 // cycle of these objects.
532 int num_streams = std::max<int>(1, config->numberOfSimulcastStreams);
533 int num_temporal_layers =
534 std::max<int>(1, config->VP8().numberOfTemporalLayers);
535 for (int i = 0; i < num_streams; ++i) {
536 allocated_temporal_layers_.emplace_back(
537 config->VP8().tl_factory->Create(i, num_temporal_layers, 42));
538 }
539 }
540 if (force_init_encode_failed_)
541 return -1;
542 return res;
543 }
544
545 rtc::CriticalSection local_crit_sect_;
546 bool block_next_encode_ GUARDED_BY(local_crit_sect_) = false;
547 rtc::Event continue_encode_event_;
548 uint32_t timestamp_ GUARDED_BY(local_crit_sect_) = 0;
549 int64_t ntp_time_ms_ GUARDED_BY(local_crit_sect_) = 0;
550 int last_input_width_ GUARDED_BY(local_crit_sect_) = 0;
551 int last_input_height_ GUARDED_BY(local_crit_sect_) = 0;
552 bool quality_scaling_ GUARDED_BY(local_crit_sect_) = true;
553 std::vector<std::unique_ptr<TemporalLayers>> allocated_temporal_layers_
554 GUARDED_BY(local_crit_sect_);
555 bool force_init_encode_failed_ GUARDED_BY(local_crit_sect_) = false;
556 };
557
558 class TestSink : public ViEEncoder::EncoderSink {
559 public:
560 explicit TestSink(TestEncoder* test_encoder)
561 : test_encoder_(test_encoder), encoded_frame_event_(false, false) {}
562
563 void WaitForEncodedFrame(int64_t expected_ntp_time) {
564 EXPECT_TRUE(
565 TimedWaitForEncodedFrame(expected_ntp_time, kDefaultTimeoutMs));
566 }
567
568 bool TimedWaitForEncodedFrame(int64_t expected_ntp_time,
569 int64_t timeout_ms) {
570 uint32_t timestamp = 0;
571 if (!encoded_frame_event_.Wait(timeout_ms))
572 return false;
573 {
574 rtc::CritScope lock(&crit_);
575 timestamp = last_timestamp_;
576 }
577 test_encoder_->CheckLastTimeStampsMatch(expected_ntp_time, timestamp);
578 return true;
579 }
580
581 void WaitForEncodedFrame(uint32_t expected_width,
582 uint32_t expected_height) {
583 EXPECT_TRUE(encoded_frame_event_.Wait(kDefaultTimeoutMs));
584 CheckLastFrameSizeMathces(expected_width, expected_height);
585 }
586
587 void CheckLastFrameSizeMathces(uint32_t expected_width,
588 uint32_t expected_height) {
589 uint32_t width = 0;
590 uint32_t height = 0;
591 {
592 rtc::CritScope lock(&crit_);
593 width = last_width_;
594 height = last_height_;
595 }
596 EXPECT_EQ(expected_height, height);
597 EXPECT_EQ(expected_width, width);
598 }
599
600 void ExpectDroppedFrame() { EXPECT_FALSE(encoded_frame_event_.Wait(100)); }
601
602 bool WaitForFrame(int64_t timeout_ms) {
603 return encoded_frame_event_.Wait(timeout_ms);
604 }
605
606 void SetExpectNoFrames() {
607 rtc::CritScope lock(&crit_);
608 expect_frames_ = false;
609 }
610
611 int number_of_reconfigurations() const {
612 rtc::CritScope lock(&crit_);
613 return number_of_reconfigurations_;
614 }
615
616 int last_min_transmit_bitrate() const {
617 rtc::CritScope lock(&crit_);
618 return min_transmit_bitrate_bps_;
619 }
620
621 private:
622 Result OnEncodedImage(
623 const EncodedImage& encoded_image,
624 const CodecSpecificInfo* codec_specific_info,
625 const RTPFragmentationHeader* fragmentation) override {
626 rtc::CritScope lock(&crit_);
627 EXPECT_TRUE(expect_frames_);
628 last_timestamp_ = encoded_image._timeStamp;
629 last_width_ = encoded_image._encodedWidth;
630 last_height_ = encoded_image._encodedHeight;
631 encoded_frame_event_.Set();
632 return Result(Result::OK, last_timestamp_);
633 }
634
635 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
636 int min_transmit_bitrate_bps) override {
637 rtc::CriticalSection crit_;
638 ++number_of_reconfigurations_;
639 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps;
640 }
641
642 rtc::CriticalSection crit_;
643 TestEncoder* test_encoder_;
644 rtc::Event encoded_frame_event_;
645 uint32_t last_timestamp_ = 0;
646 uint32_t last_height_ = 0;
647 uint32_t last_width_ = 0;
648 bool expect_frames_ = true;
649 int number_of_reconfigurations_ = 0;
650 int min_transmit_bitrate_bps_ = 0;
651 };
652
653 VideoSendStream::Config video_send_config_;
654 VideoEncoderConfig video_encoder_config_;
655 int codec_width_;
656 int codec_height_;
657 int max_framerate_;
658 TestEncoder fake_encoder_;
659 std::unique_ptr<MockableSendStatisticsProxy> stats_proxy_;
660 TestSink sink_;
661 AdaptingFrameForwarder video_source_;
662 std::unique_ptr<ViEEncoderUnderTest> vie_encoder_;
663 rtc::ScopedFakeClock fake_clock_;
664 };
665
666 TEST_F(ViEEncoderTest, EncodeOneFrame) {
667 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
668 rtc::Event frame_destroyed_event(false, false);
669 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
670 WaitForEncodedFrame(1);
671 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
672 vie_encoder_->Stop();
673 }
674
675 TEST_F(ViEEncoderTest, DropsFramesBeforeFirstOnBitrateUpdated) {
676 // Dropped since no target bitrate has been set.
677 rtc::Event frame_destroyed_event(false, false);
678 video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
679 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
680
681 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
682
683 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
684 WaitForEncodedFrame(2);
685 vie_encoder_->Stop();
686 }
687
688 TEST_F(ViEEncoderTest, DropsFramesWhenRateSetToZero) {
689 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
690 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
691 WaitForEncodedFrame(1);
692
693 vie_encoder_->OnBitrateUpdated(0, 0, 0);
694 // Dropped since bitrate is zero.
695 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
696
697 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
698 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
699 WaitForEncodedFrame(3);
700 vie_encoder_->Stop();
701 }
702
703 TEST_F(ViEEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
704 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
705 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
706 WaitForEncodedFrame(1);
707
708 // This frame will be dropped since it has the same ntp timestamp.
709 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
710
711 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
712 WaitForEncodedFrame(2);
713 vie_encoder_->Stop();
714 }
715
716 TEST_F(ViEEncoderTest, DropsFrameAfterStop) {
717 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
718
719 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
720 WaitForEncodedFrame(1);
721
722 vie_encoder_->Stop();
723 sink_.SetExpectNoFrames();
724 rtc::Event frame_destroyed_event(false, false);
725 video_source_.IncomingCapturedFrame(CreateFrame(2, &frame_destroyed_event));
726 EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
727 }
728
729 TEST_F(ViEEncoderTest, DropsPendingFramesOnSlowEncode) {
730 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
731
732 fake_encoder_.BlockNextEncode();
733 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
734 WaitForEncodedFrame(1);
735 // Here, the encoder thread will be blocked in the TestEncoder waiting for a
736 // call to ContinueEncode.
737 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
738 video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
739 fake_encoder_.ContinueEncode();
740 WaitForEncodedFrame(3);
741
742 vie_encoder_->Stop();
743 }
744
745 TEST_F(ViEEncoderTest, ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
746 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
747 EXPECT_EQ(0, sink_.number_of_reconfigurations());
748
749 // Capture a frame and wait for it to synchronize with the encoder thread.
750 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
751 WaitForEncodedFrame(1);
752 // The encoder will have been configured once when the first frame is
753 // received.
754 EXPECT_EQ(1, sink_.number_of_reconfigurations());
755
756 VideoEncoderConfig video_encoder_config;
757 test::FillEncoderConfiguration(1, &video_encoder_config);
758 video_encoder_config.min_transmit_bitrate_bps = 9999;
759 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
760 kMaxPayloadLength, true /* nack_enabled */);
761
762 // Capture a frame and wait for it to synchronize with the encoder thread.
763 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
764 WaitForEncodedFrame(2);
765 EXPECT_EQ(2, sink_.number_of_reconfigurations());
766 EXPECT_EQ(9999, sink_.last_min_transmit_bitrate());
767
768 vie_encoder_->Stop();
769 }
770
771 TEST_F(ViEEncoderTest, FrameResolutionChangeReconfigureEncoder) {
772 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
773
774 // Capture a frame and wait for it to synchronize with the encoder thread.
775 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
776 WaitForEncodedFrame(1);
777 // The encoder will have been configured once.
778 EXPECT_EQ(1, sink_.number_of_reconfigurations());
779 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
780 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
781
782 codec_width_ *= 2;
783 codec_height_ *= 2;
784 // Capture a frame with a higher resolution and wait for it to synchronize
785 // with the encoder thread.
786 video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
787 WaitForEncodedFrame(2);
788 EXPECT_EQ(codec_width_, fake_encoder_.codec_config().width);
789 EXPECT_EQ(codec_height_, fake_encoder_.codec_config().height);
790 EXPECT_EQ(2, sink_.number_of_reconfigurations());
791
792 vie_encoder_->Stop();
793 }
794
795 TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor1S1TLWithNackEnabled) {
796 const bool kNackEnabled = true;
797 const size_t kNumStreams = 1;
798 const size_t kNumTl = 1;
799 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled, false);
800 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
801
802 // Capture a frame and wait for it to synchronize with the encoder thread.
803 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
804 WaitForEncodedFrame(1);
805 // The encoder have been configured once when the first frame is received.
806 EXPECT_EQ(1, sink_.number_of_reconfigurations());
807 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
808 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
809 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
810 // Resilience is off for no temporal layers with nack on.
811 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
812 vie_encoder_->Stop();
813 }
814
815 TEST_F(ViEEncoderTest, Vp8ResilienceIsOffFor2S1TlWithNackEnabled) {
816 const bool kNackEnabled = true;
817 const size_t kNumStreams = 2;
818 const size_t kNumTl = 1;
819 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled, false);
820 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
821
822 // Capture a frame and wait for it to synchronize with the encoder thread.
823 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
824 WaitForEncodedFrame(1);
825 // The encoder have been configured once when the first frame is received.
826 EXPECT_EQ(1, sink_.number_of_reconfigurations());
827 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
828 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
829 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
830 // Resilience is off for no temporal layers and >1 streams with nack on.
831 EXPECT_EQ(kResilienceOff, fake_encoder_.codec_config().VP8()->resilience);
832 vie_encoder_->Stop();
833 }
834
835 TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S1TLWithNackDisabled) {
836 const bool kNackEnabled = false;
837 const size_t kNumStreams = 1;
838 const size_t kNumTl = 1;
839 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled, false);
840 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
841
842 // Capture a frame and wait for it to synchronize with the encoder thread.
843 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
844 WaitForEncodedFrame(1);
845 // The encoder have been configured once when the first frame is received.
846 EXPECT_EQ(1, sink_.number_of_reconfigurations());
847 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
848 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
849 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
850 // Resilience is on for no temporal layers with nack off.
851 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
852 vie_encoder_->Stop();
853 }
854
855 TEST_F(ViEEncoderTest, Vp8ResilienceIsOnFor1S2TlWithNackEnabled) {
856 const bool kNackEnabled = true;
857 const size_t kNumStreams = 1;
858 const size_t kNumTl = 2;
859 ResetEncoder("VP8", kNumStreams, kNumTl, kNackEnabled, false);
860 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
861
862 // Capture a frame and wait for it to synchronize with the encoder thread.
863 video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
864 WaitForEncodedFrame(1);
865 // The encoder have been configured once when the first frame is received.
866 EXPECT_EQ(1, sink_.number_of_reconfigurations());
867 EXPECT_EQ(kVideoCodecVP8, fake_encoder_.codec_config().codecType);
868 EXPECT_EQ(kNumStreams, fake_encoder_.codec_config().numberOfSimulcastStreams);
869 EXPECT_EQ(kNumTl, fake_encoder_.codec_config().VP8()->numberOfTemporalLayers);
870 // Resilience is on for temporal layers.
871 EXPECT_EQ(kResilientStream, fake_encoder_.codec_config().VP8()->resilience);
872 vie_encoder_->Stop();
873 }
874
875 TEST_F(ViEEncoderTest, SwitchSourceDeregisterEncoderAsSink) {
876 EXPECT_TRUE(video_source_.has_sinks());
877 test::FrameForwarder new_video_source;
878 vie_encoder_->SetSource(
879 &new_video_source,
880 VideoSendStream::DegradationPreference::kMaintainFramerate);
881 EXPECT_FALSE(video_source_.has_sinks());
882 EXPECT_TRUE(new_video_source.has_sinks());
883
884 vie_encoder_->Stop();
885 }
886
887 TEST_F(ViEEncoderTest, SinkWantsRotationApplied) {
888 EXPECT_FALSE(video_source_.sink_wants().rotation_applied);
889 vie_encoder_->SetSink(&sink_, true /*rotation_applied*/);
890 EXPECT_TRUE(video_source_.sink_wants().rotation_applied);
891 vie_encoder_->Stop();
892 }
893
894 TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) {
895 const int kMaxDowngrades = ViEEncoder::kMaxCpuResolutionDowngrades;
896 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
897
898 VerifyNoLimitation(video_source_.sink_wants());
899
900 int frame_width = 1280;
901 int frame_height = 720;
902
903 // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should
904 // request lower resolution.
905 for (int i = 1; i <= kMaxDowngrades; ++i) {
906 video_source_.IncomingCapturedFrame(
907 CreateFrame(i, frame_width, frame_height));
908 WaitForEncodedFrame(i);
909
910 vie_encoder_->TriggerCpuOveruse();
911
912 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
913 EXPECT_LT(video_source_.sink_wants().max_pixel_count,
914 frame_width * frame_height);
915 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
916 EXPECT_EQ(i, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
917
918 frame_width /= 2;
919 frame_height /= 2;
920 }
921
922 // Trigger CPU overuse one more time. This should not trigger a request for
923 // lower resolution.
924 rtc::VideoSinkWants current_wants = video_source_.sink_wants();
925 video_source_.IncomingCapturedFrame(
926 CreateFrame(kMaxDowngrades + 1, frame_width, frame_height));
927 WaitForEncodedFrame(kMaxDowngrades + 1);
928 vie_encoder_->TriggerCpuOveruse();
929 EXPECT_EQ(video_source_.sink_wants().target_pixel_count,
930 current_wants.target_pixel_count);
931 EXPECT_EQ(video_source_.sink_wants().max_pixel_count,
932 current_wants.max_pixel_count);
933 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
934 EXPECT_EQ(kMaxDowngrades,
935 stats_proxy_->GetStats().number_of_cpu_adapt_changes);
936
937 // Trigger CPU normal use.
938 vie_encoder_->TriggerCpuNormalUsage();
939 EXPECT_EQ(frame_width * frame_height * 5 / 3,
940 video_source_.sink_wants().target_pixel_count.value_or(0));
941 EXPECT_EQ(frame_width * frame_height * 4,
942 video_source_.sink_wants().max_pixel_count);
943 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
944 EXPECT_EQ(kMaxDowngrades + 1,
945 stats_proxy_->GetStats().number_of_cpu_adapt_changes);
946
947 vie_encoder_->Stop();
948 }
949
950 TEST_F(ViEEncoderTest, TestMaxCpuResolutionDowngrades_BalancedMode_NoFpsLimit) {
951 const int kMaxDowngrades = ViEEncoder::kMaxCpuResolutionDowngrades;
952 const int kWidth = 1280;
953 const int kHeight = 720;
954 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
955
956 // Enable kBalanced preference, no initial limitation.
957 AdaptingFrameForwarder source;
958 source.set_adaptation_enabled(true);
959 vie_encoder_->SetSource(&source,
960 VideoSendStream::DegradationPreference::kBalanced);
961 VerifyNoLimitation(source.sink_wants());
962 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
963 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
964
965 // Trigger adapt down kMaxCpuDowngrades times.
966 int t = 1;
967 for (int i = 1; i <= kMaxDowngrades; ++i) {
968 source.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight));
969 sink_.WaitForEncodedFrame(t++);
970 vie_encoder_->TriggerCpuOveruse();
971 VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
972 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
973 EXPECT_EQ(i, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
974 }
975
976 // Trigger adapt down, max cpu downgrades reach, expect no change.
977 rtc::VideoSinkWants last_wants = source.sink_wants();
978 source.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight));
979 sink_.WaitForEncodedFrame(t++);
980 vie_encoder_->TriggerCpuOveruse();
981 VerifyFpsEqResolutionEq(source.sink_wants(), last_wants);
982 EXPECT_EQ(last_wants.max_pixel_count, source.sink_wants().max_pixel_count);
983 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
984 EXPECT_EQ(kMaxDowngrades,
985 stats_proxy_->GetStats().number_of_cpu_adapt_changes);
986
987 // Trigger adapt up kMaxCpuDowngrades times.
988 for (int i = 1; i <= kMaxDowngrades; ++i) {
989 source.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight));
990 sink_.WaitForEncodedFrame(t++);
991 vie_encoder_->TriggerCpuNormalUsage();
992 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
993 EXPECT_GT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
994 EXPECT_EQ(kMaxDowngrades + i,
995 stats_proxy_->GetStats().number_of_cpu_adapt_changes);
996 }
997
998 VerifyNoLimitation(source.sink_wants());
999 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1000
1001 vie_encoder_->Stop();
1002 }
1003 TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) {
1004 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1005 VerifyNoLimitation(video_source_.sink_wants());
1006
1007 const int kFrameWidth = 1280;
1008 const int kFrameHeight = 720;
1009 const int kFrameIntervalMs = 1000 / 30;
1010
1011 int frame_timestamp = 1;
1012
1013 video_source_.IncomingCapturedFrame(
1014 CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
1015 WaitForEncodedFrame(frame_timestamp);
1016 frame_timestamp += kFrameIntervalMs;
1017
1018 // Trigger CPU overuse.
1019 vie_encoder_->TriggerCpuOveruse();
1020 video_source_.IncomingCapturedFrame(
1021 CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
1022 WaitForEncodedFrame(frame_timestamp);
1023 frame_timestamp += kFrameIntervalMs;
1024
1025 // Default degradation preference is maintain-framerate, so will lower max
1026 // wanted resolution.
1027 EXPECT_FALSE(video_source_.sink_wants().target_pixel_count);
1028 EXPECT_LT(video_source_.sink_wants().max_pixel_count,
1029 kFrameWidth * kFrameHeight);
1030 EXPECT_EQ(std::numeric_limits<int>::max(),
1031 video_source_.sink_wants().max_framerate_fps);
1032
1033 // Set new source, switch to maintain-resolution.
1034 test::FrameForwarder new_video_source;
1035 vie_encoder_->SetSource(
1036 &new_video_source,
1037 VideoSendStream::DegradationPreference::kMaintainResolution);
1038
1039 // Initially no degradation registered.
1040 VerifyNoLimitation(new_video_source.sink_wants());
1041
1042 // Force an input frame rate to be available, or the adaptation call won't
1043 // know what framerate to adapt form.
1044 const int kInputFps = 30;
1045 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1046 stats.input_frame_rate = kInputFps;
1047 stats_proxy_->SetMockStats(stats);
1048
1049 vie_encoder_->TriggerCpuOveruse();
1050 new_video_source.IncomingCapturedFrame(
1051 CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
1052 WaitForEncodedFrame(frame_timestamp);
1053 frame_timestamp += kFrameIntervalMs;
1054
1055 // Some framerate constraint should be set.
1056 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
1057 EXPECT_EQ(std::numeric_limits<int>::max(),
1058 new_video_source.sink_wants().max_pixel_count);
1059 EXPECT_LT(new_video_source.sink_wants().max_framerate_fps, kInputFps);
1060
1061 // Turn off degradation completely.
1062 vie_encoder_->SetSource(
1063 &new_video_source,
1064 VideoSendStream::DegradationPreference::kDegradationDisabled);
1065 VerifyNoLimitation(new_video_source.sink_wants());
1066
1067 vie_encoder_->TriggerCpuOveruse();
1068 new_video_source.IncomingCapturedFrame(
1069 CreateFrame(frame_timestamp, kFrameWidth, kFrameHeight));
1070 WaitForEncodedFrame(frame_timestamp);
1071 frame_timestamp += kFrameIntervalMs;
1072
1073 // Still no degradation.
1074 VerifyNoLimitation(new_video_source.sink_wants());
1075
1076 // Calling SetSource with resolution scaling enabled apply the old SinkWants.
1077 vie_encoder_->SetSource(
1078 &new_video_source,
1079 VideoSendStream::DegradationPreference::kMaintainFramerate);
1080 EXPECT_LT(new_video_source.sink_wants().max_pixel_count,
1081 kFrameWidth * kFrameHeight);
1082 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
1083 EXPECT_EQ(std::numeric_limits<int>::max(),
1084 new_video_source.sink_wants().max_framerate_fps);
1085
1086 // Calling SetSource with framerate scaling enabled apply the old SinkWants.
1087 vie_encoder_->SetSource(
1088 &new_video_source,
1089 VideoSendStream::DegradationPreference::kMaintainResolution);
1090 EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count);
1091 EXPECT_EQ(std::numeric_limits<int>::max(),
1092 new_video_source.sink_wants().max_pixel_count);
1093 EXPECT_LT(new_video_source.sink_wants().max_framerate_fps, kInputFps);
1094
1095 vie_encoder_->Stop();
1096 }
1097
1098 TEST_F(ViEEncoderTest, StatsTracksQualityAdaptationStats) {
1099 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1100
1101 const int kWidth = 1280;
1102 const int kHeight = 720;
1103 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1104 WaitForEncodedFrame(1);
1105 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1106 EXPECT_FALSE(stats.bw_limited_resolution);
1107 EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
1108
1109 // Trigger adapt down.
1110 vie_encoder_->TriggerQualityLow();
1111 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1112 WaitForEncodedFrame(2);
1113
1114 stats = stats_proxy_->GetStats();
1115 EXPECT_TRUE(stats.bw_limited_resolution);
1116 EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
1117
1118 // Trigger adapt up.
1119 vie_encoder_->TriggerQualityHigh();
1120 video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1121 WaitForEncodedFrame(3);
1122
1123 stats = stats_proxy_->GetStats();
1124 EXPECT_FALSE(stats.bw_limited_resolution);
1125 EXPECT_EQ(2, stats.number_of_quality_adapt_changes);
1126 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
1127
1128 vie_encoder_->Stop();
1129 }
1130
1131 TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStats) {
1132 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1133
1134 const int kWidth = 1280;
1135 const int kHeight = 720;
1136 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1137 WaitForEncodedFrame(1);
1138 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1139 EXPECT_FALSE(stats.cpu_limited_resolution);
1140 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
1141
1142 // Trigger CPU overuse.
1143 vie_encoder_->TriggerCpuOveruse();
1144 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1145 WaitForEncodedFrame(2);
1146
1147 stats = stats_proxy_->GetStats();
1148 EXPECT_TRUE(stats.cpu_limited_resolution);
1149 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1150
1151 // Trigger CPU normal use.
1152 vie_encoder_->TriggerCpuNormalUsage();
1153 video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1154 WaitForEncodedFrame(3);
1155
1156 stats = stats_proxy_->GetStats();
1157 EXPECT_FALSE(stats.cpu_limited_resolution);
1158 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
1159 EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
1160
1161 vie_encoder_->Stop();
1162 }
1163
1164 TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
1165 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1166
1167 const int kWidth = 1280;
1168 const int kHeight = 720;
1169 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1170 WaitForEncodedFrame(1);
1171 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1172 EXPECT_FALSE(stats.bw_limited_resolution);
1173 EXPECT_FALSE(stats.cpu_limited_resolution);
1174 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
1175
1176 // Trigger CPU overuse.
1177 vie_encoder_->TriggerCpuOveruse();
1178 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1179 WaitForEncodedFrame(2);
1180 stats = stats_proxy_->GetStats();
1181 EXPECT_FALSE(stats.bw_limited_resolution);
1182 EXPECT_TRUE(stats.cpu_limited_resolution);
1183 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1184
1185 // Set new source with adaptation still enabled.
1186 test::FrameForwarder new_video_source;
1187 vie_encoder_->SetSource(
1188 &new_video_source,
1189 VideoSendStream::DegradationPreference::kMaintainFramerate);
1190
1191 new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1192 WaitForEncodedFrame(3);
1193 stats = stats_proxy_->GetStats();
1194 EXPECT_FALSE(stats.bw_limited_resolution);
1195 EXPECT_TRUE(stats.cpu_limited_resolution);
1196 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1197
1198 // Set adaptation disabled.
1199 vie_encoder_->SetSource(
1200 &new_video_source,
1201 VideoSendStream::DegradationPreference::kDegradationDisabled);
1202
1203 new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1204 WaitForEncodedFrame(4);
1205 stats = stats_proxy_->GetStats();
1206 EXPECT_FALSE(stats.bw_limited_resolution);
1207 EXPECT_FALSE(stats.cpu_limited_resolution);
1208 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1209
1210 // Set adaptation back to enabled.
1211 vie_encoder_->SetSource(
1212 &new_video_source,
1213 VideoSendStream::DegradationPreference::kMaintainFramerate);
1214
1215 new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
1216 WaitForEncodedFrame(5);
1217 stats = stats_proxy_->GetStats();
1218 EXPECT_FALSE(stats.bw_limited_resolution);
1219 EXPECT_TRUE(stats.cpu_limited_resolution);
1220 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1221
1222 // Trigger CPU normal use.
1223 vie_encoder_->TriggerCpuNormalUsage();
1224 new_video_source.IncomingCapturedFrame(CreateFrame(6, kWidth, kHeight));
1225 WaitForEncodedFrame(6);
1226 stats = stats_proxy_->GetStats();
1227 EXPECT_FALSE(stats.bw_limited_resolution);
1228 EXPECT_FALSE(stats.cpu_limited_resolution);
1229 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
1230 EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
1231
1232 vie_encoder_->Stop();
1233 }
1234
1235 TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
1236 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1237
1238 const int kWidth = 1280;
1239 const int kHeight = 720;
1240 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1241 WaitForEncodedFrame(1);
1242 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1243 EXPECT_FALSE(stats.bw_limited_resolution);
1244 EXPECT_FALSE(stats.bw_limited_framerate);
1245 EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
1246
1247 // Set new source with adaptation still enabled.
1248 test::FrameForwarder new_video_source;
1249 vie_encoder_->SetSource(&new_video_source,
1250 VideoSendStream::DegradationPreference::kBalanced);
1251
1252 new_video_source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1253 WaitForEncodedFrame(2);
1254 stats = stats_proxy_->GetStats();
1255 EXPECT_FALSE(stats.bw_limited_resolution);
1256 EXPECT_FALSE(stats.bw_limited_framerate);
1257 EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
1258
1259 // Trigger adapt down.
1260 vie_encoder_->TriggerQualityLow();
1261 new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1262 WaitForEncodedFrame(3);
1263 stats = stats_proxy_->GetStats();
1264 EXPECT_TRUE(stats.bw_limited_resolution);
1265 EXPECT_FALSE(stats.bw_limited_framerate);
1266 EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
1267
1268 // Set new source with adaptation still enabled.
1269 vie_encoder_->SetSource(&new_video_source,
1270 VideoSendStream::DegradationPreference::kBalanced);
1271
1272 new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1273 WaitForEncodedFrame(4);
1274 stats = stats_proxy_->GetStats();
1275 EXPECT_TRUE(stats.bw_limited_resolution);
1276 EXPECT_FALSE(stats.bw_limited_framerate);
1277 EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
1278
1279 // Disable resolution scaling.
1280 vie_encoder_->SetSource(
1281 &new_video_source,
1282 VideoSendStream::DegradationPreference::kMaintainResolution);
1283
1284 new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
1285 WaitForEncodedFrame(5);
1286 stats = stats_proxy_->GetStats();
1287 EXPECT_FALSE(stats.bw_limited_resolution);
1288 EXPECT_FALSE(stats.bw_limited_framerate);
1289 EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
1290 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
1291
1292 vie_encoder_->Stop();
1293 }
1294
1295 TEST_F(ViEEncoderTest, QualityAdaptationStatsAreResetWhenScalerIsDisabled) {
1296 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1297
1298 const int kWidth = 1280;
1299 const int kHeight = 720;
1300 video_source_.set_adaptation_enabled(true);
1301 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1302 WaitForEncodedFrame(1);
1303 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1304 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1305 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1306
1307 // Trigger adapt down.
1308 vie_encoder_->TriggerQualityLow();
1309 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1310 WaitForEncodedFrame(2);
1311 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1312 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1313 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1314
1315 // Trigger overuse.
1316 vie_encoder_->TriggerCpuOveruse();
1317 video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1318 WaitForEncodedFrame(3);
1319 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1320 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1321 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1322
1323 // Set source with adaptation still enabled but quality scaler is off.
1324 fake_encoder_.SetQualityScaling(false);
1325 vie_encoder_->SetSource(
1326 &video_source_,
1327 VideoSendStream::DegradationPreference::kMaintainFramerate);
1328
1329 video_source_.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1330 WaitForEncodedFrame(4);
1331 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1332 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1333 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1334
1335 vie_encoder_->Stop();
1336 }
1337
1338 TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
1339 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1340
1341 const int kWidth = 1280;
1342 const int kHeight = 720;
1343 int sequence = 1;
1344
1345 video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
1346 WaitForEncodedFrame(sequence++);
1347 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1348 EXPECT_FALSE(stats.cpu_limited_resolution);
1349 EXPECT_FALSE(stats.cpu_limited_framerate);
1350 EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
1351
1352 // Trigger CPU overuse, should now adapt down.
1353 vie_encoder_->TriggerCpuOveruse();
1354 video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
1355 WaitForEncodedFrame(sequence++);
1356 stats = stats_proxy_->GetStats();
1357 EXPECT_TRUE(stats.cpu_limited_resolution);
1358 EXPECT_FALSE(stats.cpu_limited_framerate);
1359 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1360
1361 // Set new source with adaptation still enabled.
1362 test::FrameForwarder new_video_source;
1363 vie_encoder_->SetSource(
1364 &new_video_source,
1365 VideoSendStream::DegradationPreference::kMaintainFramerate);
1366
1367 new_video_source.IncomingCapturedFrame(
1368 CreateFrame(sequence, kWidth, kHeight));
1369 WaitForEncodedFrame(sequence++);
1370 stats = stats_proxy_->GetStats();
1371 EXPECT_TRUE(stats.cpu_limited_resolution);
1372 EXPECT_FALSE(stats.cpu_limited_framerate);
1373 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1374
1375 // Set cpu adaptation by frame dropping.
1376 vie_encoder_->SetSource(
1377 &new_video_source,
1378 VideoSendStream::DegradationPreference::kMaintainResolution);
1379 new_video_source.IncomingCapturedFrame(
1380 CreateFrame(sequence, kWidth, kHeight));
1381 WaitForEncodedFrame(sequence++);
1382 stats = stats_proxy_->GetStats();
1383 // Not adapted at first.
1384 EXPECT_FALSE(stats.cpu_limited_resolution);
1385 EXPECT_FALSE(stats.cpu_limited_framerate);
1386 EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
1387
1388 // Force an input frame rate to be available, or the adaptation call won't
1389 // know what framerate to adapt from.
1390 VideoSendStream::Stats mock_stats = stats_proxy_->GetStats();
1391 mock_stats.input_frame_rate = 30;
1392 stats_proxy_->SetMockStats(mock_stats);
1393 vie_encoder_->TriggerCpuOveruse();
1394 stats_proxy_->ResetMockStats();
1395
1396 new_video_source.IncomingCapturedFrame(
1397 CreateFrame(sequence, kWidth, kHeight));
1398 WaitForEncodedFrame(sequence++);
1399
1400 // Framerate now adapted.
1401 stats = stats_proxy_->GetStats();
1402 EXPECT_FALSE(stats.cpu_limited_resolution);
1403 EXPECT_TRUE(stats.cpu_limited_framerate);
1404 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
1405
1406 // Disable CPU adaptation.
1407 vie_encoder_->SetSource(
1408 &new_video_source,
1409 VideoSendStream::DegradationPreference::kDegradationDisabled);
1410 new_video_source.IncomingCapturedFrame(
1411 CreateFrame(sequence, kWidth, kHeight));
1412 WaitForEncodedFrame(sequence++);
1413
1414 stats = stats_proxy_->GetStats();
1415 EXPECT_FALSE(stats.cpu_limited_resolution);
1416 EXPECT_FALSE(stats.cpu_limited_framerate);
1417 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
1418
1419 // Try to trigger overuse. Should not succeed.
1420 stats_proxy_->SetMockStats(mock_stats);
1421 vie_encoder_->TriggerCpuOveruse();
1422 stats_proxy_->ResetMockStats();
1423
1424 stats = stats_proxy_->GetStats();
1425 EXPECT_FALSE(stats.cpu_limited_resolution);
1426 EXPECT_FALSE(stats.cpu_limited_framerate);
1427 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
1428
1429 // Switch back the source with resolution adaptation enabled.
1430 vie_encoder_->SetSource(
1431 &video_source_,
1432 VideoSendStream::DegradationPreference::kMaintainFramerate);
1433 video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
1434 WaitForEncodedFrame(sequence++);
1435 stats = stats_proxy_->GetStats();
1436 EXPECT_TRUE(stats.cpu_limited_resolution);
1437 EXPECT_FALSE(stats.cpu_limited_framerate);
1438 EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
1439
1440 // Trigger CPU normal usage.
1441 vie_encoder_->TriggerCpuNormalUsage();
1442 video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight));
1443 WaitForEncodedFrame(sequence++);
1444 stats = stats_proxy_->GetStats();
1445 EXPECT_FALSE(stats.cpu_limited_resolution);
1446 EXPECT_FALSE(stats.cpu_limited_framerate);
1447 EXPECT_EQ(3, stats.number_of_cpu_adapt_changes);
1448
1449 // Back to the source with adaptation off, set it back to maintain-resolution.
1450 vie_encoder_->SetSource(
1451 &new_video_source,
1452 VideoSendStream::DegradationPreference::kMaintainResolution);
1453 new_video_source.IncomingCapturedFrame(
1454 CreateFrame(sequence, kWidth, kHeight));
1455 WaitForEncodedFrame(sequence++);
1456 stats = stats_proxy_->GetStats();
1457 // Disabled, since we previously switched the source to disabled.
1458 EXPECT_FALSE(stats.cpu_limited_resolution);
1459 EXPECT_TRUE(stats.cpu_limited_framerate);
1460 EXPECT_EQ(3, stats.number_of_cpu_adapt_changes);
1461
1462 // Trigger CPU normal usage.
1463 vie_encoder_->TriggerCpuNormalUsage();
1464 new_video_source.IncomingCapturedFrame(
1465 CreateFrame(sequence, kWidth, kHeight));
1466 WaitForEncodedFrame(sequence++);
1467 stats = stats_proxy_->GetStats();
1468 EXPECT_FALSE(stats.cpu_limited_resolution);
1469 EXPECT_FALSE(stats.cpu_limited_framerate);
1470 EXPECT_EQ(4, stats.number_of_cpu_adapt_changes);
1471 EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
1472
1473 vie_encoder_->Stop();
1474 }
1475
1476 TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) {
1477 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1478
1479 const int kWidth = 1280;
1480 const int kHeight = 720;
1481 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1482 WaitForEncodedFrame(1);
1483
1484 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1485 EXPECT_EQ(video_encoder_config_.max_bitrate_bps,
1486 stats.preferred_media_bitrate_bps);
1487
1488 vie_encoder_->Stop();
1489 }
1490
1491 TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) {
1492 const int kWidth = 1280;
1493 const int kHeight = 720;
1494 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1495
1496 // Expect no scaling to begin with.
1497 VerifyNoLimitation(video_source_.sink_wants());
1498
1499 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1500 WaitForEncodedFrame(1);
1501
1502 // Trigger scale down.
1503 vie_encoder_->TriggerQualityLow();
1504
1505 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1506 WaitForEncodedFrame(2);
1507
1508 // Expect a scale down.
1509 EXPECT_TRUE(video_source_.sink_wants().max_pixel_count);
1510 EXPECT_LT(video_source_.sink_wants().max_pixel_count, kWidth * kHeight);
1511
1512 // Set resolution scaling disabled.
1513 test::FrameForwarder new_video_source;
1514 vie_encoder_->SetSource(
1515 &new_video_source,
1516 VideoSendStream::DegradationPreference::kMaintainResolution);
1517
1518 // Trigger scale down.
1519 vie_encoder_->TriggerQualityLow();
1520 new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1521 WaitForEncodedFrame(3);
1522
1523 // Expect no scaling.
1524 EXPECT_EQ(std::numeric_limits<int>::max(),
1525 new_video_source.sink_wants().max_pixel_count);
1526
1527 // Trigger scale up.
1528 vie_encoder_->TriggerQualityHigh();
1529 new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1530 WaitForEncodedFrame(4);
1531
1532 // Expect nothing to change, still no scaling.
1533 EXPECT_EQ(std::numeric_limits<int>::max(),
1534 new_video_source.sink_wants().max_pixel_count);
1535
1536 vie_encoder_->Stop();
1537 }
1538
1539 TEST_F(ViEEncoderTest, SkipsSameAdaptDownRequest_MaintainFramerateMode) {
1540 const int kWidth = 1280;
1541 const int kHeight = 720;
1542 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1543
1544 // Enable kMaintainFramerate preference, no initial limitation.
1545 test::FrameForwarder source;
1546 vie_encoder_->SetSource(
1547 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
1548
1549 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1550 WaitForEncodedFrame(1);
1551 VerifyNoLimitation(source.sink_wants());
1552 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1553 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1554
1555 // Trigger adapt down, expect scaled down resolution.
1556 vie_encoder_->TriggerCpuOveruse();
1557 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1558 const int kLastMaxPixelCount = source.sink_wants().max_pixel_count;
1559 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1560 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1561
1562 // Trigger adapt down for same input resolution, expect no change.
1563 vie_encoder_->TriggerCpuOveruse();
1564 EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count);
1565 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1566 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1567
1568 vie_encoder_->Stop();
1569 }
1570
1571 TEST_F(ViEEncoderTest, SkipsSameOrLargerAdaptDownRequest_BalancedMode) {
1572 const int kWidth = 1280;
1573 const int kHeight = 720;
1574 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1575
1576 // Enable kBalanced preference, no initial limitation.
1577 test::FrameForwarder source;
1578 vie_encoder_->SetSource(&source,
1579 VideoSendStream::DegradationPreference::kBalanced);
1580 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1581 sink_.WaitForEncodedFrame(1);
1582 VerifyNoLimitation(source.sink_wants());
1583
1584 // Trigger adapt down, expect scaled down resolution.
1585 vie_encoder_->TriggerQualityLow();
1586 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1587 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1588 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1589 const int kLastMaxPixelCount = source.sink_wants().max_pixel_count;
1590
1591 // Trigger adapt down for same input resolution, expect no change.
1592 source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1593 sink_.WaitForEncodedFrame(2);
1594 vie_encoder_->TriggerQualityLow();
1595 EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count);
1596 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1597 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1598
1599 // Trigger adapt down for larger input resolution, expect no change.
1600 source.IncomingCapturedFrame(CreateFrame(3, kWidth + 1, kHeight + 1));
1601 sink_.WaitForEncodedFrame(3);
1602 vie_encoder_->TriggerQualityLow();
1603 EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count);
1604 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1605 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1606
1607 vie_encoder_->Stop();
1608 }
1609
1610 TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainFramerateMode) {
1611 const int kWidth = 1280;
1612 const int kHeight = 720;
1613 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1614
1615 // Enable kMaintainFramerate preference, no initial limitation.
1616 test::FrameForwarder source;
1617 vie_encoder_->SetSource(
1618 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
1619
1620 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1621 WaitForEncodedFrame(kWidth, kHeight);
1622 VerifyNoLimitation(source.sink_wants());
1623 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1624 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1625
1626 // Trigger adapt up, expect no change.
1627 vie_encoder_->TriggerCpuNormalUsage();
1628 VerifyNoLimitation(source.sink_wants());
1629 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1630 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1631
1632 vie_encoder_->Stop();
1633 }
1634
1635 TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainResolutionMode) {
1636 const int kWidth = 1280;
1637 const int kHeight = 720;
1638 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1639
1640 // Enable kMaintainResolution preference, no initial limitation.
1641 test::FrameForwarder source;
1642 vie_encoder_->SetSource(
1643 &source, VideoSendStream::DegradationPreference::kMaintainResolution);
1644
1645 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1646 WaitForEncodedFrame(kWidth, kHeight);
1647 VerifyNoLimitation(source.sink_wants());
1648 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
1649 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1650
1651 // Trigger adapt up, expect no change.
1652 vie_encoder_->TriggerCpuNormalUsage();
1653 VerifyNoLimitation(source.sink_wants());
1654 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
1655 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1656
1657 vie_encoder_->Stop();
1658 }
1659
1660 TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_BalancedMode) {
1661 const int kWidth = 1280;
1662 const int kHeight = 720;
1663 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1664
1665 // Enable kBalanced preference, no initial limitation.
1666 test::FrameForwarder source;
1667 vie_encoder_->SetSource(&source,
1668 VideoSendStream::DegradationPreference::kBalanced);
1669
1670 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1671 sink_.WaitForEncodedFrame(kWidth, kHeight);
1672 VerifyNoLimitation(source.sink_wants());
1673 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1674 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
1675 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1676
1677 // Trigger adapt up, expect no change.
1678 vie_encoder_->TriggerQualityHigh();
1679 VerifyNoLimitation(source.sink_wants());
1680 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1681 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
1682 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1683
1684 vie_encoder_->Stop();
1685 }
1686
1687 TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_DisabledMode) {
1688 const int kWidth = 1280;
1689 const int kHeight = 720;
1690 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1691
1692 // Enable kDegradationDisabled preference, no initial limitation.
1693 test::FrameForwarder source;
1694 vie_encoder_->SetSource(
1695 &source, VideoSendStream::DegradationPreference::kDegradationDisabled);
1696
1697 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1698 sink_.WaitForEncodedFrame(kWidth, kHeight);
1699 VerifyNoLimitation(source.sink_wants());
1700 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1701 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
1702 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1703
1704 // Trigger adapt up, expect no change.
1705 vie_encoder_->TriggerQualityHigh();
1706 VerifyNoLimitation(source.sink_wants());
1707 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1708 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
1709 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1710
1711 vie_encoder_->Stop();
1712 }
1713
1714 TEST_F(ViEEncoderTest, AdaptsResolutionForLowQuality_MaintainFramerateMode) {
1715 const int kWidth = 1280;
1716 const int kHeight = 720;
1717 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1718
1719 // Enable kMaintainFramerate preference, no initial limitation.
1720 AdaptingFrameForwarder source;
1721 source.set_adaptation_enabled(true);
1722 vie_encoder_->SetSource(
1723 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
1724
1725 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1726 WaitForEncodedFrame(1);
1727 VerifyNoLimitation(source.sink_wants());
1728 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1729 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1730
1731 // Trigger adapt down, expect scaled down resolution.
1732 vie_encoder_->TriggerQualityLow();
1733 source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1734 WaitForEncodedFrame(2);
1735 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1736 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1737 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1738
1739 // Trigger adapt up, expect no restriction.
1740 vie_encoder_->TriggerQualityHigh();
1741 VerifyNoLimitation(source.sink_wants());
1742 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1743 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1744 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1745
1746 vie_encoder_->Stop();
1747 }
1748
1749 TEST_F(ViEEncoderTest, AdaptsFramerateForLowQuality_MaintainResolutionMode) {
1750 const int kWidth = 1280;
1751 const int kHeight = 720;
1752 const int kInputFps = 30;
1753 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1754
1755 VideoSendStream::Stats stats = stats_proxy_->GetStats();
1756 stats.input_frame_rate = kInputFps;
1757 stats_proxy_->SetMockStats(stats);
1758
1759 // Expect no scaling to begin with (preference: kMaintainFramerate).
1760 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1761 sink_.WaitForEncodedFrame(1);
1762 VerifyNoLimitation(video_source_.sink_wants());
1763
1764 // Trigger adapt down, expect scaled down resolution.
1765 vie_encoder_->TriggerQualityLow();
1766 video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1767 sink_.WaitForEncodedFrame(2);
1768 VerifyFpsMaxResolutionLt(video_source_.sink_wants(), kWidth * kHeight);
1769
1770 // Enable kMaintainResolution preference.
1771 test::FrameForwarder new_video_source;
1772 vie_encoder_->SetSource(
1773 &new_video_source,
1774 VideoSendStream::DegradationPreference::kMaintainResolution);
1775 VerifyNoLimitation(new_video_source.sink_wants());
1776
1777 // Trigger adapt down, expect reduced framerate.
1778 vie_encoder_->TriggerQualityLow();
1779 new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1780 sink_.WaitForEncodedFrame(3);
1781 VerifyFpsLtResolutionMax(new_video_source.sink_wants(), kInputFps);
1782
1783 // Trigger adapt up, expect no restriction.
1784 vie_encoder_->TriggerQualityHigh();
1785 VerifyNoLimitation(new_video_source.sink_wants());
1786
1787 vie_encoder_->Stop();
1788 }
1789
1790 TEST_F(ViEEncoderTest, DoesNotScaleBelowSetResolutionLimit) {
1791 const int kWidth = 1280;
1792 const int kHeight = 720;
1793 const size_t kNumFrames = 10;
1794
1795 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1796
1797 // Enable adapter, expected input resolutions when downscaling:
1798 // 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (min resolution limit)
1799 video_source_.set_adaptation_enabled(true);
1800
1801 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1802 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1803
1804 int downscales = 0;
1805 for (size_t i = 1; i <= kNumFrames; i++) {
1806 video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
1807 WaitForEncodedFrame(i);
1808
1809 // Trigger scale down.
1810 rtc::VideoSinkWants last_wants = video_source_.sink_wants();
1811 vie_encoder_->TriggerQualityLow();
1812 EXPECT_GE(video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame);
1813
1814 if (video_source_.sink_wants().max_pixel_count < last_wants.max_pixel_count)
1815 ++downscales;
1816
1817 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1818 EXPECT_EQ(downscales,
1819 stats_proxy_->GetStats().number_of_quality_adapt_changes);
1820 EXPECT_GT(downscales, 0);
1821 }
1822 vie_encoder_->Stop();
1823 }
1824
1825 TEST_F(ViEEncoderTest,
1826 AdaptsResolutionUpAndDownTwiceOnOveruse_MaintainFramerateMode) {
1827 const int kWidth = 1280;
1828 const int kHeight = 720;
1829 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1830
1831 // Enable kMaintainFramerate preference, no initial limitation.
1832 AdaptingFrameForwarder source;
1833 source.set_adaptation_enabled(true);
1834 vie_encoder_->SetSource(
1835 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
1836
1837 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1838 WaitForEncodedFrame(kWidth, kHeight);
1839 VerifyNoLimitation(source.sink_wants());
1840 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1841 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1842
1843 // Trigger adapt down, expect scaled down resolution.
1844 vie_encoder_->TriggerCpuOveruse();
1845 source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1846 WaitForEncodedFrame(2);
1847 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1848 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1849 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1850
1851 // Trigger adapt up, expect no restriction.
1852 vie_encoder_->TriggerCpuNormalUsage();
1853 source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1854 WaitForEncodedFrame(kWidth, kHeight);
1855 VerifyNoLimitation(source.sink_wants());
1856 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1857 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1858
1859 // Trigger adapt down, expect scaled down resolution.
1860 vie_encoder_->TriggerCpuOveruse();
1861 source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1862 WaitForEncodedFrame(4);
1863 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1864 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1865 EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1866
1867 // Trigger adapt up, expect no restriction.
1868 vie_encoder_->TriggerCpuNormalUsage();
1869 source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
1870 sink_.WaitForEncodedFrame(kWidth, kHeight);
1871 VerifyNoLimitation(source.sink_wants());
1872 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1873 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1874
1875 vie_encoder_->Stop();
1876 }
1877
1878 TEST_F(ViEEncoderTest,
1879 AdaptsResolutionUpAndDownTwiceForLowQuality_BalancedMode_NoFpsLimit) {
1880 const int kWidth = 1280;
1881 const int kHeight = 720;
1882 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1883
1884 // Enable kBalanced preference, no initial limitation.
1885 AdaptingFrameForwarder source;
1886 source.set_adaptation_enabled(true);
1887 vie_encoder_->SetSource(&source,
1888 VideoSendStream::DegradationPreference::kBalanced);
1889
1890 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1891 sink_.WaitForEncodedFrame(kWidth, kHeight);
1892 VerifyNoLimitation(source.sink_wants());
1893 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1894 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1895
1896 // Trigger adapt down, expect scaled down resolution.
1897 vie_encoder_->TriggerQualityLow();
1898 source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1899 sink_.WaitForEncodedFrame(2);
1900 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1901 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1902 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1903
1904 // Trigger adapt up, expect no restriction.
1905 vie_encoder_->TriggerQualityHigh();
1906 source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1907 sink_.WaitForEncodedFrame(kWidth, kHeight);
1908 VerifyNoLimitation(source.sink_wants());
1909 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1910 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1911
1912 // Trigger adapt down, expect scaled down resolution.
1913 vie_encoder_->TriggerQualityLow();
1914 source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1915 sink_.WaitForEncodedFrame(4);
1916 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1917 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1918 EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1919
1920 // Trigger adapt up, expect no restriction.
1921 vie_encoder_->TriggerQualityHigh();
1922 source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
1923 sink_.WaitForEncodedFrame(kWidth, kHeight);
1924 VerifyNoLimitation(source.sink_wants());
1925 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1926 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1927
1928 vie_encoder_->Stop();
1929 }
1930
1931 TEST_F(ViEEncoderTest,
1932 AdaptsResolutionOnOveruseAndLowQuality_MaintainFramerateMode) {
1933 const int kWidth = 1280;
1934 const int kHeight = 720;
1935 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
1936
1937 // Enable kMaintainFramerate preference, no initial limitation.
1938 AdaptingFrameForwarder source;
1939 source.set_adaptation_enabled(true);
1940 vie_encoder_->SetSource(
1941 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
1942
1943 source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
1944 WaitForEncodedFrame(kWidth, kHeight);
1945 VerifyNoLimitation(source.sink_wants());
1946 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
1947 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1948 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1949 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1950
1951 // Trigger cpu adapt down, expect scaled down resolution (960x540).
1952 vie_encoder_->TriggerCpuOveruse();
1953 source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
1954 WaitForEncodedFrame(2);
1955 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
1956 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1957 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1958 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1959 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1960
1961 // Trigger cpu adapt down, expect scaled down resolution (640x360).
1962 vie_encoder_->TriggerCpuOveruse();
1963 source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
1964 WaitForEncodedFrame(3);
1965 VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
1966 rtc::VideoSinkWants last_wants = source.sink_wants();
1967 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1968 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1969 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1970 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1971
1972 // Trigger cpu adapt down, max cpu downgrades reached, expect no change.
1973 vie_encoder_->TriggerCpuOveruse();
1974 source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
1975 WaitForEncodedFrame(4);
1976 VerifyFpsEqResolutionEq(source.sink_wants(), last_wants);
1977 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1978 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
1979 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1980 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1981
1982 // Trigger quality adapt down, expect scaled down resolution (480x270).
1983 vie_encoder_->TriggerQualityLow();
1984 source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
1985 WaitForEncodedFrame(5);
1986 VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
1987 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1988 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1989 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
1990 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
1991
1992 // Trigger cpu adapt up, expect upscaled resolution (640x360).
1993 vie_encoder_->TriggerCpuNormalUsage();
1994 source.IncomingCapturedFrame(CreateFrame(6, kWidth, kHeight));
1995 WaitForEncodedFrame(6);
1996 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
1997 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
1998 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
1999 EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2000 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2001
2002 // Trigger cpu adapt up, expect upscaled resolution (960x540).
2003 vie_encoder_->TriggerCpuNormalUsage();
2004 source.IncomingCapturedFrame(CreateFrame(7, kWidth, kHeight));
2005 WaitForEncodedFrame(7);
2006 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
2007 last_wants = source.sink_wants();
2008 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2009 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2010 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2011 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2012
2013 // Trigger cpu adapt up, no cpu downgrades, expect no change (960x540).
2014 vie_encoder_->TriggerCpuNormalUsage();
2015 source.IncomingCapturedFrame(CreateFrame(8, kWidth, kHeight));
2016 WaitForEncodedFrame(8);
2017 VerifyFpsEqResolutionEq(source.sink_wants(), last_wants);
2018 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2019 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2020 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2021 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2022
2023 // Trigger quality adapt up, expect no restriction (1280x720).
2024 vie_encoder_->TriggerQualityHigh();
2025 source.IncomingCapturedFrame(CreateFrame(9, kWidth, kHeight));
2026 WaitForEncodedFrame(kWidth, kHeight);
2027 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
2028 VerifyNoLimitation(source.sink_wants());
2029 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2030 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2031 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2032 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2033
2034 vie_encoder_->Stop();
2035 }
2036
2037 TEST_F(ViEEncoderTest, CpuLimitedHistogramIsReported) {
2038 const int kWidth = 640;
2039 const int kHeight = 360;
2040
2041 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2042
2043 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
2044 video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
2045 WaitForEncodedFrame(i);
2046 }
2047
2048 vie_encoder_->TriggerCpuOveruse();
2049 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
2050 video_source_.IncomingCapturedFrame(CreateFrame(
2051 SendStatisticsProxy::kMinRequiredMetricsSamples + i, kWidth, kHeight));
2052 WaitForEncodedFrame(SendStatisticsProxy::kMinRequiredMetricsSamples + i);
2053 }
2054
2055 vie_encoder_->Stop();
2056 vie_encoder_.reset();
2057 stats_proxy_.reset();
2058
2059 EXPECT_EQ(1,
2060 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
2061 EXPECT_EQ(
2062 1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
2063 }
2064
2065 TEST_F(ViEEncoderTest, CpuLimitedHistogramIsNotReportedForDisabledDegradation) {
2066 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2067 const int kWidth = 640;
2068 const int kHeight = 360;
2069
2070 vie_encoder_->SetSource(
2071 &video_source_,
2072 VideoSendStream::DegradationPreference::kDegradationDisabled);
2073
2074 for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
2075 video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
2076 WaitForEncodedFrame(i);
2077 }
2078
2079 vie_encoder_->Stop();
2080 vie_encoder_.reset();
2081 stats_proxy_.reset();
2082
2083 EXPECT_EQ(0,
2084 metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
2085 }
2086
2087 TEST_F(ViEEncoderTest, CallsBitrateObserver) {
2088 MockBitrateObserver bitrate_observer;
2089 vie_encoder_->SetBitrateObserver(&bitrate_observer);
2090
2091 const int kDefaultFps = 30;
2092 const BitrateAllocation expected_bitrate =
2093 DefaultVideoBitrateAllocator(fake_encoder_.codec_config())
2094 .GetAllocation(kLowTargetBitrateBps, kDefaultFps);
2095
2096 // First called on bitrate updated, then again on first frame.
2097 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
2098 .Times(2);
2099 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
2100
2101 const int64_t kStartTimeMs = 1;
2102 video_source_.IncomingCapturedFrame(
2103 CreateFrame(kStartTimeMs, codec_width_, codec_height_));
2104 WaitForEncodedFrame(kStartTimeMs);
2105
2106 // Not called on second frame.
2107 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
2108 .Times(0);
2109 video_source_.IncomingCapturedFrame(
2110 CreateFrame(kStartTimeMs + 1, codec_width_, codec_height_));
2111 WaitForEncodedFrame(kStartTimeMs + 1);
2112
2113 // Called after a process interval.
2114 const int64_t kProcessIntervalMs =
2115 vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
2116 fake_clock_.AdvanceTimeMicros(rtc::kNumMicrosecsPerMillisec *
2117 (kProcessIntervalMs + (1000 / kDefaultFps)));
2118 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
2119 .Times(1);
2120 video_source_.IncomingCapturedFrame(CreateFrame(
2121 kStartTimeMs + kProcessIntervalMs, codec_width_, codec_height_));
2122 WaitForEncodedFrame(kStartTimeMs + kProcessIntervalMs);
2123
2124 vie_encoder_->Stop();
2125 }
2126
2127 TEST_F(ViEEncoderTest, OveruseDetectorUpdatedOnReconfigureAndAdaption) {
2128 const int kFrameWidth = 1280;
2129 const int kFrameHeight = 720;
2130 const int kFramerate = 24;
2131
2132 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2133 test::FrameForwarder source;
2134 vie_encoder_->SetSource(
2135 &source, VideoSendStream::DegradationPreference::kMaintainResolution);
2136
2137 // Insert a single frame, triggering initial configuration.
2138 source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
2139 vie_encoder_->WaitUntilTaskQueueIsIdle();
2140
2141 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2142 kDefaultFramerate);
2143
2144 // Trigger reconfigure encoder (without resetting the entire instance).
2145 VideoEncoderConfig video_encoder_config;
2146 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
2147 video_encoder_config.number_of_streams = 1;
2148 video_encoder_config.video_stream_factory =
2149 new rtc::RefCountedObject<VideoStreamFactory>(1, kFramerate);
2150 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
2151 kMaxPayloadLength, false);
2152 vie_encoder_->WaitUntilTaskQueueIsIdle();
2153
2154 // Detector should be updated with fps limit from codec config.
2155 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2156 kFramerate);
2157
2158 // Trigger overuse, max framerate should be reduced.
2159 VideoSendStream::Stats stats = stats_proxy_->GetStats();
2160 stats.input_frame_rate = kFramerate;
2161 stats_proxy_->SetMockStats(stats);
2162 vie_encoder_->TriggerCpuOveruse();
2163 vie_encoder_->WaitUntilTaskQueueIsIdle();
2164 int adapted_framerate =
2165 vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
2166 EXPECT_LT(adapted_framerate, kFramerate);
2167
2168 // Trigger underuse, max framerate should go back to codec configured fps.
2169 // Set extra low fps, to make sure it's actually reset, not just incremented.
2170 stats = stats_proxy_->GetStats();
2171 stats.input_frame_rate = adapted_framerate / 2;
2172 stats_proxy_->SetMockStats(stats);
2173 vie_encoder_->TriggerCpuNormalUsage();
2174 vie_encoder_->WaitUntilTaskQueueIsIdle();
2175 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2176 kFramerate);
2177
2178 vie_encoder_->Stop();
2179 }
2180
2181 TEST_F(ViEEncoderTest, OveruseDetectorUpdatedRespectsFramerateAfterUnderuse) {
2182 const int kFrameWidth = 1280;
2183 const int kFrameHeight = 720;
2184 const int kLowFramerate = 15;
2185 const int kHighFramerate = 25;
2186
2187 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2188 test::FrameForwarder source;
2189 vie_encoder_->SetSource(
2190 &source, VideoSendStream::DegradationPreference::kMaintainResolution);
2191
2192 // Trigger initial configuration.
2193 VideoEncoderConfig video_encoder_config;
2194 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
2195 video_encoder_config.number_of_streams = 1;
2196 video_encoder_config.video_stream_factory =
2197 new rtc::RefCountedObject<VideoStreamFactory>(1, kLowFramerate);
2198 source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
2199 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
2200 kMaxPayloadLength, false);
2201 vie_encoder_->WaitUntilTaskQueueIsIdle();
2202
2203 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2204 kLowFramerate);
2205
2206 // Trigger overuse, max framerate should be reduced.
2207 VideoSendStream::Stats stats = stats_proxy_->GetStats();
2208 stats.input_frame_rate = kLowFramerate;
2209 stats_proxy_->SetMockStats(stats);
2210 vie_encoder_->TriggerCpuOveruse();
2211 vie_encoder_->WaitUntilTaskQueueIsIdle();
2212 int adapted_framerate =
2213 vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
2214 EXPECT_LT(adapted_framerate, kLowFramerate);
2215
2216 // Reconfigure the encoder with a new (higher max framerate), max fps should
2217 // still respect the adaptation.
2218 video_encoder_config.video_stream_factory =
2219 new rtc::RefCountedObject<VideoStreamFactory>(1, kHighFramerate);
2220 source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
2221 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
2222 kMaxPayloadLength, false);
2223 vie_encoder_->WaitUntilTaskQueueIsIdle();
2224
2225 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2226 adapted_framerate);
2227
2228 // Trigger underuse, max framerate should go back to codec configured fps.
2229 stats = stats_proxy_->GetStats();
2230 stats.input_frame_rate = adapted_framerate;
2231 stats_proxy_->SetMockStats(stats);
2232 vie_encoder_->TriggerCpuNormalUsage();
2233 vie_encoder_->WaitUntilTaskQueueIsIdle();
2234 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2235 kHighFramerate);
2236
2237 vie_encoder_->Stop();
2238 }
2239
2240 TEST_F(ViEEncoderTest, OveruseDetectorUpdatedOnDegradationPreferenceChange) {
2241 const int kFrameWidth = 1280;
2242 const int kFrameHeight = 720;
2243 const int kFramerate = 24;
2244
2245 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2246 test::FrameForwarder source;
2247 vie_encoder_->SetSource(
2248 &source, VideoSendStream::DegradationPreference::kMaintainResolution);
2249
2250 // Trigger initial configuration.
2251 VideoEncoderConfig video_encoder_config;
2252 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
2253 video_encoder_config.number_of_streams = 1;
2254 video_encoder_config.video_stream_factory =
2255 new rtc::RefCountedObject<VideoStreamFactory>(1, kFramerate);
2256 source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
2257 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
2258 kMaxPayloadLength, false);
2259 vie_encoder_->WaitUntilTaskQueueIsIdle();
2260
2261 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2262 kFramerate);
2263
2264 // Trigger overuse, max framerate should be reduced.
2265 VideoSendStream::Stats stats = stats_proxy_->GetStats();
2266 stats.input_frame_rate = kFramerate;
2267 stats_proxy_->SetMockStats(stats);
2268 vie_encoder_->TriggerCpuOveruse();
2269 vie_encoder_->WaitUntilTaskQueueIsIdle();
2270 int adapted_framerate =
2271 vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
2272 EXPECT_LT(adapted_framerate, kFramerate);
2273
2274 // Change degradation preference to not enable framerate scaling. Target
2275 // framerate should be changed to codec defined limit.
2276 vie_encoder_->SetSource(
2277 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
2278 vie_encoder_->WaitUntilTaskQueueIsIdle();
2279 EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
2280 kFramerate);
2281
2282 vie_encoder_->Stop();
2283 }
2284
2285 TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
2286 const int kTooLowBitrateForFrameSizeBps = 10000;
2287 vie_encoder_->OnBitrateUpdated(kTooLowBitrateForFrameSizeBps, 0, 0);
2288 const int kWidth = 640;
2289 const int kHeight = 360;
2290
2291 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
2292
2293 // Expect to drop this frame, the wait should time out.
2294 ExpectDroppedFrame();
2295
2296 // Expect the sink_wants to specify a scaled frame.
2297 EXPECT_LT(video_source_.sink_wants().max_pixel_count, kWidth * kHeight);
2298
2299 int last_pixel_count = video_source_.sink_wants().max_pixel_count;
2300
2301 // Next frame is scaled.
2302 video_source_.IncomingCapturedFrame(
2303 CreateFrame(2, kWidth * 3 / 4, kHeight * 3 / 4));
2304
2305 // Expect to drop this frame, the wait should time out.
2306 ExpectDroppedFrame();
2307
2308 EXPECT_LT(video_source_.sink_wants().max_pixel_count, last_pixel_count);
2309
2310 vie_encoder_->Stop();
2311 }
2312
2313 TEST_F(ViEEncoderTest, NumberOfDroppedFramesLimitedWhenBitrateIsTooLow) {
2314 const int kTooLowBitrateForFrameSizeBps = 10000;
2315 vie_encoder_->OnBitrateUpdated(kTooLowBitrateForFrameSizeBps, 0, 0);
2316 const int kWidth = 640;
2317 const int kHeight = 360;
2318
2319 // We expect the n initial frames to get dropped.
2320 int i;
2321 for (i = 1; i <= kMaxInitialFramedrop; ++i) {
2322 video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
2323 ExpectDroppedFrame();
2324 }
2325 // The n+1th frame should not be dropped, even though it's size is too large.
2326 video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
2327 WaitForEncodedFrame(i);
2328
2329 // Expect the sink_wants to specify a scaled frame.
2330 EXPECT_LT(video_source_.sink_wants().max_pixel_count, kWidth * kHeight);
2331
2332 vie_encoder_->Stop();
2333 }
2334
2335 TEST_F(ViEEncoderTest, InitialFrameDropOffWithMaintainResolutionPreference) {
2336 const int kWidth = 640;
2337 const int kHeight = 360;
2338 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
2339
2340 // Set degradation preference.
2341 vie_encoder_->SetSource(
2342 &video_source_,
2343 VideoSendStream::DegradationPreference::kMaintainResolution);
2344
2345 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
2346 // Frame should not be dropped, even if it's too large.
2347 WaitForEncodedFrame(1);
2348
2349 vie_encoder_->Stop();
2350 }
2351
2352 TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
2353 const int kWidth = 640;
2354 const int kHeight = 360;
2355 fake_encoder_.SetQualityScaling(false);
2356 vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
2357
2358 // Force quality scaler reconfiguration by resetting the source.
2359 vie_encoder_->SetSource(&video_source_,
2360 VideoSendStream::DegradationPreference::kBalanced);
2361
2362 video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
2363 // Frame should not be dropped, even if it's too large.
2364 WaitForEncodedFrame(1);
2365
2366 vie_encoder_->Stop();
2367 fake_encoder_.SetQualityScaling(true);
2368 }
2369
2370 TEST_F(ViEEncoderTest,
2371 ResolutionNotAdaptedForTooSmallFrame_MaintainFramerateMode) {
2372 const int kTooSmallWidth = 10;
2373 const int kTooSmallHeight = 10;
2374 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2375
2376 // Enable kMaintainFramerate preference, no initial limitation.
2377 test::FrameForwarder source;
2378 vie_encoder_->SetSource(
2379 &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
2380 VerifyNoLimitation(source.sink_wants());
2381 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2382
2383 // Trigger adapt down, too small frame, expect no change.
2384 source.IncomingCapturedFrame(CreateFrame(1, kTooSmallWidth, kTooSmallHeight));
2385 WaitForEncodedFrame(1);
2386 vie_encoder_->TriggerCpuOveruse();
2387 VerifyNoLimitation(source.sink_wants());
2388 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2389 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2390
2391 vie_encoder_->Stop();
2392 }
2393
2394 TEST_F(ViEEncoderTest, ResolutionNotAdaptedForTooSmallFrame_BalancedMode) {
2395 const int kTooSmallWidth = 10;
2396 const int kTooSmallHeight = 10;
2397 const int kFpsLimit = 7;
2398 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2399
2400 // Enable kBalanced preference, no initial limitation.
2401 test::FrameForwarder source;
2402 vie_encoder_->SetSource(&source,
2403 VideoSendStream::DegradationPreference::kBalanced);
2404 VerifyNoLimitation(source.sink_wants());
2405 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2406 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2407
2408 // Trigger adapt down, expect limited framerate.
2409 source.IncomingCapturedFrame(CreateFrame(1, kTooSmallWidth, kTooSmallHeight));
2410 WaitForEncodedFrame(1);
2411 vie_encoder_->TriggerQualityLow();
2412 VerifyFpsEqResolutionMax(source.sink_wants(), kFpsLimit);
2413 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2414 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2415 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2416
2417 // Trigger adapt down, too small frame, expect no change.
2418 source.IncomingCapturedFrame(CreateFrame(2, kTooSmallWidth, kTooSmallHeight));
2419 WaitForEncodedFrame(2);
2420 vie_encoder_->TriggerQualityLow();
2421 VerifyFpsEqResolutionMax(source.sink_wants(), kFpsLimit);
2422 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2423 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2424 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2425
2426 vie_encoder_->Stop();
2427 }
2428
2429 TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) {
2430 fake_encoder_.ForceInitEncodeFailure(true);
2431 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2432 ResetEncoder("VP8", 2, 1, true, false);
2433 const int kFrameWidth = 1280;
2434 const int kFrameHeight = 720;
2435 video_source_.IncomingCapturedFrame(
2436 CreateFrame(1, kFrameWidth, kFrameHeight));
2437 ExpectDroppedFrame();
2438 vie_encoder_->Stop();
2439 }
2440
2441 // TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
2442 TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse_MaintainFramerateMode) {
2443 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2444
2445 const int kFrameWidth = 1280;
2446 const int kFrameHeight = 720;
2447 // Enabled default VideoAdapter downscaling. First step is 3/4, not 3/5 as
2448 // requested by ViEEncoder::VideoSourceProxy::RequestResolutionLowerThan().
2449 video_source_.set_adaptation_enabled(true);
2450
2451 video_source_.IncomingCapturedFrame(
2452 CreateFrame(1, kFrameWidth, kFrameHeight));
2453 WaitForEncodedFrame(kFrameWidth, kFrameHeight);
2454
2455 // Trigger CPU overuse, downscale by 3/4.
2456 vie_encoder_->TriggerCpuOveruse();
2457 video_source_.IncomingCapturedFrame(
2458 CreateFrame(2, kFrameWidth, kFrameHeight));
2459 WaitForEncodedFrame((kFrameWidth * 3) / 4, (kFrameHeight * 3) / 4);
2460
2461 // Trigger CPU normal use, return to original resolution.
2462 vie_encoder_->TriggerCpuNormalUsage();
2463 video_source_.IncomingCapturedFrame(
2464 CreateFrame(3, kFrameWidth, kFrameHeight));
2465 WaitForEncodedFrame(kFrameWidth, kFrameHeight);
2466
2467 vie_encoder_->Stop();
2468 }
2469
2470 TEST_F(ViEEncoderTest, AdaptsFramerateOnOveruse_MaintainResolutionMode) {
2471 const int kFrameWidth = 1280;
2472 const int kFrameHeight = 720;
2473 int kFrameIntervalMs = rtc::kNumMillisecsPerSec / max_framerate_;
2474
2475 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2476 vie_encoder_->SetSource(
2477 &video_source_,
2478 VideoSendStream::DegradationPreference::kMaintainResolution);
2479 video_source_.set_adaptation_enabled(true);
2480
2481 int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
2482
2483 video_source_.IncomingCapturedFrame(
2484 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2485 WaitForEncodedFrame(timestamp_ms);
2486
2487 // Try to trigger overuse. No fps estimate available => no effect.
2488 vie_encoder_->TriggerCpuOveruse();
2489
2490 // Insert frames for one second to get a stable estimate.
2491 for (int i = 0; i < max_framerate_; ++i) {
2492 timestamp_ms += kFrameIntervalMs;
2493 video_source_.IncomingCapturedFrame(
2494 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2495 WaitForEncodedFrame(timestamp_ms);
2496 }
2497
2498 // Trigger CPU overuse, reduce framerate by 2/3.
2499 vie_encoder_->TriggerCpuOveruse();
2500 int num_frames_dropped = 0;
2501 for (int i = 0; i < max_framerate_; ++i) {
2502 timestamp_ms += kFrameIntervalMs;
2503 video_source_.IncomingCapturedFrame(
2504 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2505 if (!WaitForFrame(kFrameTimeoutMs)) {
2506 ++num_frames_dropped;
2507 } else {
2508 sink_.CheckLastFrameSizeMathces(kFrameWidth, kFrameHeight);
2509 }
2510 }
2511
2512 // Add some slack to account for frames dropped by the frame dropper.
2513 const int kErrorMargin = 1;
2514 EXPECT_NEAR(num_frames_dropped, max_framerate_ - (max_framerate_ * 2 / 3),
2515 kErrorMargin);
2516
2517 // Trigger CPU overuse, reduce framerate by 2/3 again.
2518 vie_encoder_->TriggerCpuOveruse();
2519 num_frames_dropped = 0;
2520 for (int i = 0; i < max_framerate_; ++i) {
2521 timestamp_ms += kFrameIntervalMs;
2522 video_source_.IncomingCapturedFrame(
2523 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2524 if (!WaitForFrame(kFrameTimeoutMs)) {
2525 ++num_frames_dropped;
2526 } else {
2527 sink_.CheckLastFrameSizeMathces(kFrameWidth, kFrameHeight);
2528 }
2529 }
2530 EXPECT_NEAR(num_frames_dropped, max_framerate_ - (max_framerate_ * 4 / 9),
2531 kErrorMargin);
2532
2533 // Go back up one step.
2534 vie_encoder_->TriggerCpuNormalUsage();
2535 num_frames_dropped = 0;
2536 for (int i = 0; i < max_framerate_; ++i) {
2537 timestamp_ms += kFrameIntervalMs;
2538 video_source_.IncomingCapturedFrame(
2539 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2540 if (!WaitForFrame(kFrameTimeoutMs)) {
2541 ++num_frames_dropped;
2542 } else {
2543 sink_.CheckLastFrameSizeMathces(kFrameWidth, kFrameHeight);
2544 }
2545 }
2546 EXPECT_NEAR(num_frames_dropped, max_framerate_ - (max_framerate_ * 2 / 3),
2547 kErrorMargin);
2548
2549 // Go back up to original mode.
2550 vie_encoder_->TriggerCpuNormalUsage();
2551 num_frames_dropped = 0;
2552 for (int i = 0; i < max_framerate_; ++i) {
2553 timestamp_ms += kFrameIntervalMs;
2554 video_source_.IncomingCapturedFrame(
2555 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2556 if (!WaitForFrame(kFrameTimeoutMs)) {
2557 ++num_frames_dropped;
2558 } else {
2559 sink_.CheckLastFrameSizeMathces(kFrameWidth, kFrameHeight);
2560 }
2561 }
2562 EXPECT_NEAR(num_frames_dropped, 0, kErrorMargin);
2563
2564 vie_encoder_->Stop();
2565 }
2566
2567 TEST_F(ViEEncoderTest, DoesntAdaptDownPastMinFramerate) {
2568 const int kFramerateFps = 5;
2569 const int kFrameIntervalMs = rtc::kNumMillisecsPerSec / kFramerateFps;
2570 const int kMinFpsFrameInterval = rtc::kNumMillisecsPerSec / kMinFramerateFps;
2571 const int kFrameWidth = 1280;
2572 const int kFrameHeight = 720;
2573
2574 // Reconfigure encoder with two temporal layers and screensharing, which will
2575 // disable frame dropping and make testing easier.
2576 ResetEncoder("VP8", 1, 2, true, true);
2577
2578 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2579 vie_encoder_->SetSource(
2580 &video_source_,
2581 VideoSendStream::DegradationPreference::kMaintainResolution);
2582 video_source_.set_adaptation_enabled(true);
2583
2584 int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
2585
2586 // Trigger overuse as much as we can.
2587 for (int i = 0; i < ViEEncoder::kMaxCpuResolutionDowngrades; ++i) {
2588 // Insert frames to get a new fps estimate...
2589 for (int j = 0; j < kFramerateFps; ++j) {
2590 video_source_.IncomingCapturedFrame(
2591 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2592 timestamp_ms += kFrameIntervalMs;
2593 }
2594 // ...and then try to adapt again.
2595 vie_encoder_->TriggerCpuOveruse();
2596 }
2597
2598 // Drain any frame in the pipeline.
2599 WaitForFrame(kDefaultTimeoutMs);
2600
2601 // Insert frames at min fps, all should go through.
2602 for (int i = 0; i < 10; ++i) {
2603 timestamp_ms += kMinFpsFrameInterval;
2604 video_source_.IncomingCapturedFrame(
2605 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
2606 WaitForEncodedFrame(timestamp_ms);
2607 }
2608
2609 vie_encoder_->Stop();
2610 }
2611
2612 TEST_F(ViEEncoderTest, AdaptsResolutionAndFramerateForLowQuality_BalancedMode) {
2613 const int kWidth = 1280;
2614 const int kHeight = 720;
2615 const int64_t kFrameIntervalMs = 150;
2616 int64_t timestamp_ms = kFrameIntervalMs;
2617 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2618
2619 // Enable kBalanced preference, no initial limitation.
2620 AdaptingFrameForwarder source;
2621 source.set_adaptation_enabled(true);
2622 vie_encoder_->SetSource(&source,
2623 VideoSendStream::DegradationPreference::kBalanced);
2624 timestamp_ms += kFrameIntervalMs;
2625 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2626 WaitForEncodedFrame(kWidth, kHeight);
2627 VerifyNoLimitation(source.sink_wants());
2628 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2629 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2630 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2631
2632 // Trigger adapt down, expect scaled down resolution (960x540@30fps).
2633 vie_encoder_->TriggerQualityLow();
2634 timestamp_ms += kFrameIntervalMs;
2635 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2636 WaitForEncodedFrame(timestamp_ms);
2637 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
2638 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2639 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2640 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2641
2642 // Trigger adapt down, expect scaled down resolution (640x360@30fps).
2643 vie_encoder_->TriggerQualityLow();
2644 timestamp_ms += kFrameIntervalMs;
2645 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2646 WaitForEncodedFrame(timestamp_ms);
2647 VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
2648 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2649 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2650 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2651
2652 // Trigger adapt down, expect reduced fps (640x360@15fps).
2653 vie_encoder_->TriggerQualityLow();
2654 timestamp_ms += kFrameIntervalMs;
2655 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2656 WaitForEncodedFrame(timestamp_ms);
2657 VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants());
2658 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2659 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2660 EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2661
2662 // Trigger adapt down, expect scaled down resolution (480x270@15fps).
2663 vie_encoder_->TriggerQualityLow();
2664 timestamp_ms += kFrameIntervalMs;
2665 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2666 WaitForEncodedFrame(timestamp_ms);
2667 VerifyFpsEqResolutionLt(source.sink_wants(), source.last_wants());
2668 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2669 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2670 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2671
2672 // Restrict bitrate, trigger adapt down, expect reduced fps (480x270@10fps).
2673 vie_encoder_->TriggerQualityLow();
2674 timestamp_ms += kFrameIntervalMs;
2675 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2676 WaitForEncodedFrame(timestamp_ms);
2677 VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants());
2678 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2679 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2680 EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2681
2682 // Trigger adapt down, expect scaled down resolution (320x180@10fps).
2683 vie_encoder_->TriggerQualityLow();
2684 timestamp_ms += kFrameIntervalMs;
2685 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2686 WaitForEncodedFrame(timestamp_ms);
2687 VerifyFpsEqResolutionLt(source.sink_wants(), source.last_wants());
2688 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2689 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2690 EXPECT_EQ(6, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2691
2692 // Trigger adapt down, expect reduced fps (320x180@7fps).
2693 vie_encoder_->TriggerQualityLow();
2694 timestamp_ms += kFrameIntervalMs;
2695 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2696 WaitForEncodedFrame(timestamp_ms);
2697 VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants());
2698 rtc::VideoSinkWants last_wants = source.sink_wants();
2699 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2700 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2701 EXPECT_EQ(7, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2702
2703 // Trigger adapt down, min resolution reached, expect no change.
2704 vie_encoder_->TriggerQualityLow();
2705 timestamp_ms += kFrameIntervalMs;
2706 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2707 WaitForEncodedFrame(timestamp_ms);
2708 VerifyFpsEqResolutionEq(source.sink_wants(), last_wants);
2709 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2710 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2711 EXPECT_EQ(7, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2712
2713 // Trigger adapt down, expect expect increased fps (320x180@10fps).
2714 vie_encoder_->TriggerQualityHigh();
2715 timestamp_ms += kFrameIntervalMs;
2716 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2717 WaitForEncodedFrame(timestamp_ms);
2718 VerifyFpsGtResolutionEq(source.sink_wants(), source.last_wants());
2719 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2720 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2721 EXPECT_EQ(8, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2722
2723 // Trigger adapt up, expect upscaled resolution (480x270@10fps).
2724 vie_encoder_->TriggerQualityHigh();
2725 timestamp_ms += kFrameIntervalMs;
2726 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2727 WaitForEncodedFrame(timestamp_ms);
2728 VerifyFpsEqResolutionGt(source.sink_wants(), source.last_wants());
2729 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2730 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2731 EXPECT_EQ(9, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2732
2733 // Increase bitrate, trigger adapt up, expect increased fps (480x270@15fps).
2734 vie_encoder_->TriggerQualityHigh();
2735 timestamp_ms += kFrameIntervalMs;
2736 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2737 WaitForEncodedFrame(timestamp_ms);
2738 VerifyFpsGtResolutionEq(source.sink_wants(), source.last_wants());
2739 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2740 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2741 EXPECT_EQ(10, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2742
2743 // Trigger adapt up, expect upscaled resolution (640x360@15fps).
2744 vie_encoder_->TriggerQualityHigh();
2745 timestamp_ms += kFrameIntervalMs;
2746 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2747 WaitForEncodedFrame(timestamp_ms);
2748 VerifyFpsEqResolutionGt(source.sink_wants(), source.last_wants());
2749 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2750 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2751 EXPECT_EQ(11, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2752
2753 // Trigger adapt up, expect increased fps (640x360@30fps).
2754 vie_encoder_->TriggerQualityHigh();
2755 timestamp_ms += kFrameIntervalMs;
2756 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2757 WaitForEncodedFrame(timestamp_ms);
2758 VerifyFpsMaxResolutionEq(source.sink_wants(), source.last_wants());
2759 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2760 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2761 EXPECT_EQ(12, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2762
2763 // Trigger adapt up, expect upscaled resolution (960x540@30fps).
2764 vie_encoder_->TriggerQualityHigh();
2765 timestamp_ms += kFrameIntervalMs;
2766 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2767 WaitForEncodedFrame(timestamp_ms);
2768 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
2769 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2770 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2771 EXPECT_EQ(13, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2772
2773 // Trigger adapt up, expect no restriction (1280x720fps@30fps).
2774 vie_encoder_->TriggerQualityHigh();
2775 timestamp_ms += kFrameIntervalMs;
2776 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2777 WaitForEncodedFrame(kWidth, kHeight);
2778 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
2779 VerifyNoLimitation(source.sink_wants());
2780 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2781 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2782 EXPECT_EQ(14, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2783
2784 // Trigger adapt up, expect no change.
2785 vie_encoder_->TriggerQualityHigh();
2786 VerifyNoLimitation(source.sink_wants());
2787 EXPECT_EQ(14, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2788
2789 vie_encoder_->Stop();
2790 }
2791
2792 TEST_F(ViEEncoderTest, AdaptWithTwoReasonsAndDifferentOrder_Framerate) {
2793 const int kWidth = 1280;
2794 const int kHeight = 720;
2795 const int64_t kFrameIntervalMs = 150;
2796 int64_t timestamp_ms = kFrameIntervalMs;
2797 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2798
2799 // Enable kBalanced preference, no initial limitation.
2800 AdaptingFrameForwarder source;
2801 source.set_adaptation_enabled(true);
2802 vie_encoder_->SetSource(&source,
2803 VideoSendStream::DegradationPreference::kBalanced);
2804 timestamp_ms += kFrameIntervalMs;
2805 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2806 WaitForEncodedFrame(kWidth, kHeight);
2807 VerifyNoLimitation(source.sink_wants());
2808 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2809 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2810 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2811 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2812 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2813 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2814
2815 // Trigger cpu adapt down, expect scaled down resolution (960x540@30fps).
2816 vie_encoder_->TriggerCpuOveruse();
2817 timestamp_ms += kFrameIntervalMs;
2818 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2819 WaitForEncodedFrame(timestamp_ms);
2820 VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
2821 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2822 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2823 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
2824 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2825 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2826 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2827
2828 // Trigger cpu adapt down, expect scaled down resolution (640x360@30fps).
2829 vie_encoder_->TriggerCpuOveruse();
2830 timestamp_ms += kFrameIntervalMs;
2831 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2832 WaitForEncodedFrame(timestamp_ms);
2833 VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
2834 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2835 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2836 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
2837 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2838 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2839 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2840
2841 // Trigger quality adapt down, expect reduced fps (640x360@15fps).
2842 vie_encoder_->TriggerQualityLow();
2843 timestamp_ms += kFrameIntervalMs;
2844 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2845 WaitForEncodedFrame(timestamp_ms);
2846 VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants());
2847 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2848 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2849 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
2850 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2851 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2852 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2853
2854 // Trigger cpu adapt up, expect increased fps (640x360@30fps).
2855 vie_encoder_->TriggerCpuNormalUsage();
2856 timestamp_ms += kFrameIntervalMs;
2857 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2858 WaitForEncodedFrame(timestamp_ms);
2859 VerifyFpsMaxResolutionEq(source.sink_wants(), source.last_wants());
2860 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2861 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2862 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
2863 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2864 EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2865 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2866
2867 // Trigger quality adapt up, expect upscaled resolution (960x540@30fps).
2868 vie_encoder_->TriggerQualityHigh();
2869 timestamp_ms += kFrameIntervalMs;
2870 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2871 WaitForEncodedFrame(timestamp_ms);
2872 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
2873 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2874 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2875 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
2876 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2877 EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2878 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2879
2880 // Trigger cpu adapt up, expect no restriction (1280x720fps@30fps).
2881 vie_encoder_->TriggerCpuNormalUsage();
2882 timestamp_ms += kFrameIntervalMs;
2883 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2884 WaitForEncodedFrame(kWidth, kHeight);
2885 VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
2886 VerifyNoLimitation(source.sink_wants());
2887 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2888 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2889 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2890 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2891 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2892 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2893
2894 // Trigger adapt up, expect no change.
2895 vie_encoder_->TriggerQualityHigh();
2896 VerifyNoLimitation(source.sink_wants());
2897 EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2898 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2899
2900 vie_encoder_->Stop();
2901 }
2902
2903 TEST_F(ViEEncoderTest, AdaptWithTwoReasonsAndDifferentOrder_Resolution) {
2904 const int kWidth = 640;
2905 const int kHeight = 360;
2906 const int kFpsLimit = 15;
2907 const int64_t kFrameIntervalMs = 150;
2908 int64_t timestamp_ms = kFrameIntervalMs;
2909 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
2910
2911 // Enable kBalanced preference, no initial limitation.
2912 AdaptingFrameForwarder source;
2913 source.set_adaptation_enabled(true);
2914 vie_encoder_->SetSource(&source,
2915 VideoSendStream::DegradationPreference::kBalanced);
2916 timestamp_ms += kFrameIntervalMs;
2917 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2918 WaitForEncodedFrame(kWidth, kHeight);
2919 VerifyNoLimitation(source.sink_wants());
2920 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2921 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2922 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2923 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2924 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2925 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2926
2927 // Trigger cpu adapt down, expect scaled down framerate (640x360@15fps).
2928 vie_encoder_->TriggerCpuOveruse();
2929 timestamp_ms += kFrameIntervalMs;
2930 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2931 WaitForEncodedFrame(timestamp_ms);
2932 VerifyFpsEqResolutionMax(source.sink_wants(), kFpsLimit);
2933 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2934 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2935 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2936 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
2937 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2938 EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2939
2940 // Trigger quality adapt down, expect scaled down resolution (480x270@15fps).
2941 vie_encoder_->TriggerQualityLow();
2942 timestamp_ms += kFrameIntervalMs;
2943 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2944 WaitForEncodedFrame(timestamp_ms);
2945 VerifyFpsEqResolutionLt(source.sink_wants(), source.last_wants());
2946 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
2947 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2948 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2949 EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate);
2950 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2951 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2952
2953 // Trigger cpu adapt up, expect upscaled resolution (640x360@15fps).
2954 vie_encoder_->TriggerCpuNormalUsage();
2955 timestamp_ms += kFrameIntervalMs;
2956 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2957 WaitForEncodedFrame(timestamp_ms);
2958 VerifyFpsEqResolutionGt(source.sink_wants(), source.last_wants());
2959 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2960 EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate);
2961 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2962 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2963 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2964 EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2965
2966 // Trigger quality adapt up, expect increased fps (640x360@30fps).
2967 vie_encoder_->TriggerQualityHigh();
2968 timestamp_ms += kFrameIntervalMs;
2969 source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight));
2970 WaitForEncodedFrame(timestamp_ms);
2971 VerifyNoLimitation(source.sink_wants());
2972 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
2973 EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate);
2974 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
2975 EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
2976 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2977 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2978
2979 // Trigger adapt up, expect no change.
2980 vie_encoder_->TriggerQualityHigh();
2981 VerifyNoLimitation(source.sink_wants());
2982 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
2983 EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes);
2984
2985 vie_encoder_->Stop();
2986 }
2987
2988 TEST_F(ViEEncoderTest, AcceptsFullHdAdaptedDownSimulcastFrames) {
2989 // Simulates simulcast behavior and makes highest stream resolutions divisible
2990 // by 4.
2991 class CroppingVideoStreamFactory
2992 : public VideoEncoderConfig::VideoStreamFactoryInterface {
2993 public:
2994 explicit CroppingVideoStreamFactory(size_t num_temporal_layers,
2995 int framerate)
2996 : num_temporal_layers_(num_temporal_layers), framerate_(framerate) {
2997 EXPECT_GT(num_temporal_layers, 0u);
2998 EXPECT_GT(framerate, 0);
2999 }
3000
3001 private:
3002 std::vector<VideoStream> CreateEncoderStreams(
3003 int width,
3004 int height,
3005 const VideoEncoderConfig& encoder_config) override {
3006 std::vector<VideoStream> streams =
3007 test::CreateVideoStreams(width - width % 4, height - height % 4,
3008 encoder_config);
3009 for (VideoStream& stream : streams) {
3010 stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
3011 stream.max_framerate = framerate_;
3012 }
3013 return streams;
3014 }
3015
3016 const size_t num_temporal_layers_;
3017 const int framerate_;
3018 };
3019
3020 const int kFrameWidth = 1920;
3021 const int kFrameHeight = 1080;
3022 // 3/4 of 1920.
3023 const int kAdaptedFrameWidth = 1440;
3024 // 3/4 of 1080 rounded down to multiple of 4.
3025 const int kAdaptedFrameHeight = 808;
3026 const int kFramerate = 24;
3027
3028 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
3029 // Trigger reconfigure encoder (without resetting the entire instance).
3030 VideoEncoderConfig video_encoder_config;
3031 video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
3032 video_encoder_config.number_of_streams = 1;
3033 video_encoder_config.video_stream_factory =
3034 new rtc::RefCountedObject<CroppingVideoStreamFactory>(1, kFramerate);
3035 vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
3036 kMaxPayloadLength, false);
3037 vie_encoder_->WaitUntilTaskQueueIsIdle();
3038
3039 video_source_.set_adaptation_enabled(true);
3040
3041 video_source_.IncomingCapturedFrame(
3042 CreateFrame(1, kFrameWidth, kFrameHeight));
3043 WaitForEncodedFrame(kFrameWidth, kFrameHeight);
3044
3045 // Trigger CPU overuse, downscale by 3/4.
3046 vie_encoder_->TriggerCpuOveruse();
3047 video_source_.IncomingCapturedFrame(
3048 CreateFrame(2, kFrameWidth, kFrameHeight));
3049 WaitForEncodedFrame(kAdaptedFrameWidth, kAdaptedFrameHeight);
3050
3051 vie_encoder_->Stop();
3052 }
3053
3054 TEST_F(ViEEncoderTest, PeriodicallyUpdatesChannelParameters) {
3055 const int kFrameWidth = 1280;
3056 const int kFrameHeight = 720;
3057 const int kLowFps = 2;
3058 const int kHighFps = 30;
3059
3060 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
3061
3062 int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
3063 max_framerate_ = kLowFps;
3064
3065 // Insert 2 seconds of 2fps video.
3066 for (int i = 0; i < kLowFps * 2; ++i) {
3067 video_source_.IncomingCapturedFrame(
3068 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
3069 WaitForEncodedFrame(timestamp_ms);
3070 timestamp_ms += 1000 / kLowFps;
3071 }
3072
3073 // Make sure encoder is updated with new target.
3074 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
3075 video_source_.IncomingCapturedFrame(
3076 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
3077 WaitForEncodedFrame(timestamp_ms);
3078 timestamp_ms += 1000 / kLowFps;
3079
3080 EXPECT_EQ(kLowFps, fake_encoder_.GetConfiguredInputFramerate());
3081
3082 // Insert 30fps frames for just a little more than the forced update period.
3083 const int kVcmTimerIntervalFrames =
3084 (vcm::VCMProcessTimer::kDefaultProcessIntervalMs * kHighFps) / 1000;
3085 const int kFrameIntervalMs = 1000 / kHighFps;
3086 max_framerate_ = kHighFps;
3087 for (int i = 0; i < kVcmTimerIntervalFrames + 2; ++i) {
3088 video_source_.IncomingCapturedFrame(
3089 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
3090 // Wait for encoded frame, but skip ahead if it doesn't arrive as it might
3091 // be dropped if the encoder hans't been updated with the new higher target
3092 // framerate yet, causing it to overshoot the target bitrate and then
3093 // suffering the wrath of the media optimizer.
3094 TimedWaitForEncodedFrame(timestamp_ms, 2 * kFrameIntervalMs);
3095 timestamp_ms += kFrameIntervalMs;
3096 }
3097
3098 // Don expect correct measurement just yet, but it should be higher than
3099 // before.
3100 EXPECT_GT(fake_encoder_.GetConfiguredInputFramerate(), kLowFps);
3101
3102 vie_encoder_->Stop();
3103 }
3104
3105 TEST_F(ViEEncoderTest, DoesNotUpdateBitrateAllocationWhenSuspended) {
3106 const int kFrameWidth = 1280;
3107 const int kFrameHeight = 720;
3108 const int kTargetBitrateBps = 1000000;
3109
3110 MockBitrateObserver bitrate_observer;
3111 vie_encoder_->SetBitrateObserver(&bitrate_observer);
3112
3113 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(_)).Times(1);
3114 // Initial bitrate update.
3115 vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
3116 vie_encoder_->WaitUntilTaskQueueIsIdle();
3117
3118 // Insert a first video frame, causes another bitrate update.
3119 int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
3120 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(_)).Times(1);
3121 video_source_.IncomingCapturedFrame(
3122 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
3123 WaitForEncodedFrame(timestamp_ms);
3124
3125 // Next, simulate video suspension due to pacer queue overrun.
3126 vie_encoder_->OnBitrateUpdated(0, 0, 1);
3127
3128 // Skip ahead until a new periodic parameter update should have occured.
3129 timestamp_ms += vcm::VCMProcessTimer::kDefaultProcessIntervalMs;
3130 fake_clock_.AdvanceTimeMicros(
3131 vcm::VCMProcessTimer::kDefaultProcessIntervalMs *
3132 rtc::kNumMicrosecsPerMillisec);
3133
3134 // Bitrate observer should not be called.
3135 EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(_)).Times(0);
3136 video_source_.IncomingCapturedFrame(
3137 CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
3138 ExpectDroppedFrame();
3139
3140 vie_encoder_->Stop();
3141 }
3142
3143 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/vie_encoder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698