blob: a1c910c5ca4c1610242c8107c5ae4bce04f66a38 [file] [log] [blame]
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00009 */
10
Magnus Jedvert1ecfd552015-03-30 11:24:46 +020011// If we don't have a WebRtcVideoFrame, just skip all of these tests.
12#if defined(HAVE_WEBRTC_VIDEO)
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000013#include <limits.h> // For INT_MAX
14#include <string>
15#include <vector>
16
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000017#include "webrtc/base/gunit.h"
18#include "webrtc/base/logging.h"
19#include "webrtc/base/sigslot.h"
kjellandera96e2d72016-02-04 23:52:28 -080020#include "webrtc/media/base/fakevideocapturer.h"
21#include "webrtc/media/base/mediachannel.h"
22#include "webrtc/media/base/testutils.h"
23#include "webrtc/media/base/videoadapter.h"
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000024
25namespace cricket {
26
27namespace {
Peter Boström0c4e06b2015-10-07 12:23:21 +020028static const uint32_t kWaitTimeout = 3000U; // 3 seconds.
29static const uint32_t kShortWaitTimeout = 1000U; // 1 second.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000030 void UpdateCpuLoad(CoordinatedVideoAdapter* adapter,
31 int current_cpus, int max_cpus, float process_load, float system_load) {
32 adapter->set_cpu_load_min_samples(1);
33 adapter->OnCpuLoadUpdated(current_cpus, max_cpus,
34 process_load, system_load);
35 }
36}
37
38class VideoAdapterTest : public testing::Test {
39 public:
40 virtual void SetUp() {
Magnus Jedvert01840572015-04-10 11:18:39 +020041 capturer_.reset(new FakeVideoCapturer);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000042 capture_format_ = capturer_->GetSupportedFormats()->at(0);
43 capture_format_.interval = VideoFormat::FpsToInterval(50);
44 adapter_.reset(new VideoAdapter());
45 adapter_->SetInputFormat(capture_format_);
46
47 listener_.reset(new VideoCapturerListener(adapter_.get()));
48 capturer_->SignalFrameCaptured.connect(
49 listener_.get(), &VideoCapturerListener::OnFrameCaptured);
50 }
51
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000052 virtual void TearDown() {
53 // Explicitly disconnect the VideoCapturer before to avoid data races
54 // (frames delivered to VideoCapturerListener while it's being destructed).
55 capturer_->SignalFrameCaptured.disconnect_all();
56 }
57
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000058 protected:
59 class VideoCapturerListener: public sigslot::has_slots<> {
60 public:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000061 struct Stats {
62 int captured_frames;
63 int dropped_frames;
64 bool last_adapt_was_no_op;
65
66 int adapted_width;
67 int adapted_height;
68 };
69
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000070 explicit VideoCapturerListener(VideoAdapter* adapter)
71 : video_adapter_(adapter),
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000072 captured_frames_(0),
73 dropped_frames_(0),
74 last_adapt_was_no_op_(false) {
75 }
76
77 void OnFrameCaptured(VideoCapturer* capturer,
78 const CapturedFrame* captured_frame) {
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000079 rtc::CritScope lock(&crit_);
Magnus Jedvertac27e202015-03-24 15:18:39 +010080 const int in_width = captured_frame->width;
81 const int in_height = abs(captured_frame->height);
82 const VideoFormat adapted_format =
83 video_adapter_->AdaptFrameResolution(in_width, in_height);
84 if (!adapted_format.IsSize0x0()) {
85 adapted_format_ = adapted_format;
86 last_adapt_was_no_op_ = (in_width == adapted_format.width &&
87 in_height == adapted_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000088 } else {
89 ++dropped_frames_;
90 }
91 ++captured_frames_;
92 }
93
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000094 Stats GetStats() {
95 rtc::CritScope lock(&crit_);
96 Stats stats;
97 stats.captured_frames = captured_frames_;
98 stats.dropped_frames = dropped_frames_;
99 stats.last_adapt_was_no_op = last_adapt_was_no_op_;
Magnus Jedvertac27e202015-03-24 15:18:39 +0100100 if (!adapted_format_.IsSize0x0()) {
101 stats.adapted_width = adapted_format_.width;
102 stats.adapted_height = adapted_format_.height;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000103 } else {
104 stats.adapted_width = stats.adapted_height = -1;
105 }
106
107 return stats;
108 }
109
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000110 private:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000111 rtc::CriticalSection crit_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000112 VideoAdapter* video_adapter_;
Magnus Jedvertac27e202015-03-24 15:18:39 +0100113 VideoFormat adapted_format_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000114 int captured_frames_;
115 int dropped_frames_;
116 bool last_adapt_was_no_op_;
117 };
118
119 class CpuAdapterListener: public sigslot::has_slots<> {
120 public:
121 CpuAdapterListener() : received_cpu_signal_(false) {}
122 void OnCpuAdaptationSignalled() { received_cpu_signal_ = true; }
123 bool received_cpu_signal() { return received_cpu_signal_; }
124 private:
125 bool received_cpu_signal_;
126 };
127
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000128 void VerifyAdaptedResolution(const VideoCapturerListener::Stats& stats,
129 int width,
130 int height) {
131 EXPECT_EQ(width, stats.adapted_width);
132 EXPECT_EQ(height, stats.adapted_height);
133 }
134
Magnus Jedvert01840572015-04-10 11:18:39 +0200135 rtc::scoped_ptr<FakeVideoCapturer> capturer_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000136 rtc::scoped_ptr<VideoAdapter> adapter_;
137 rtc::scoped_ptr<VideoCapturerListener> listener_;
138 VideoFormat capture_format_;
139};
140
141
142// Test adapter remembers exact pixel count
143TEST_F(VideoAdapterTest, AdaptNumPixels) {
144 adapter_->SetOutputNumPixels(123456);
145 EXPECT_EQ(123456, adapter_->GetOutputNumPixels());
146}
147
148// Test adapter is constructed but not activated. Expect no frame drop and no
149// resolution change.
150TEST_F(VideoAdapterTest, AdaptInactive) {
151 // Output resolution is not set.
152 EXPECT_EQ(INT_MAX, adapter_->GetOutputNumPixels());
153
154 // Call Adapter with some frames.
155 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200156 for (int i = 0; i < 10; ++i)
157 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000158
159 // Verify no frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000160 VideoCapturerListener::Stats stats = listener_->GetStats();
161 EXPECT_GE(stats.captured_frames, 10);
162 EXPECT_EQ(0, stats.dropped_frames);
163 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000164}
165
166// Do not adapt the frame rate or the resolution. Expect no frame drop and no
167// resolution change.
168TEST_F(VideoAdapterTest, AdaptNothing) {
169 adapter_->SetOutputFormat(capture_format_);
170 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200171 for (int i = 0; i < 10; ++i)
172 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000173
174 // Verify no frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000175 VideoCapturerListener::Stats stats = listener_->GetStats();
176 EXPECT_GE(stats.captured_frames, 10);
177 EXPECT_EQ(0, stats.dropped_frames);
178 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
179 EXPECT_TRUE(stats.last_adapt_was_no_op);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000180}
181
182TEST_F(VideoAdapterTest, AdaptZeroInterval) {
183 VideoFormat format = capturer_->GetSupportedFormats()->at(0);
184 format.interval = 0;
185 adapter_->SetInputFormat(format);
186 adapter_->SetOutputFormat(format);
187 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200188 for (int i = 0; i < 10; ++i)
189 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000190
191 // Verify no crash and that frames aren't dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000192 VideoCapturerListener::Stats stats = listener_->GetStats();
193 EXPECT_GE(stats.captured_frames, 10);
194 EXPECT_EQ(0, stats.dropped_frames);
195 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000196}
197
198// Adapt the frame rate to be half of the capture rate at the beginning. Expect
199// the number of dropped frames to be half of the number the captured frames.
200TEST_F(VideoAdapterTest, AdaptFramerate) {
201 VideoFormat request_format = capture_format_;
202 request_format.interval *= 2;
203 adapter_->SetOutputFormat(request_format);
204 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200205 for (int i = 0; i < 10; ++i)
206 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000207
208 // Verify frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000209 VideoCapturerListener::Stats stats = listener_->GetStats();
210 EXPECT_GE(stats.captured_frames, 10);
211 EXPECT_EQ(stats.captured_frames / 2, stats.dropped_frames);
212 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000213}
214
215// Adapt the frame rate to be half of the capture rate at the beginning. Expect
216// the number of dropped frames to be half of the number the captured frames.
217TEST_F(VideoAdapterTest, AdaptFramerateVariable) {
218 VideoFormat request_format = capture_format_;
219 request_format.interval = request_format.interval * 3 / 2;
220 adapter_->SetOutputFormat(request_format);
221 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200222 for (int i = 0; i < 30; ++i)
223 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000224
225 // Verify frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000226 VideoCapturerListener::Stats stats = listener_->GetStats();
227 EXPECT_GE(stats.captured_frames, 30);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000228 // Verify 2 / 3 kept (20) and 1 / 3 dropped (10).
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000229 EXPECT_EQ(stats.captured_frames * 1 / 3, stats.dropped_frames);
230 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000231}
232
233// Adapt the frame rate to be half of the capture rate after capturing no less
234// than 10 frames. Expect no frame dropped before adaptation and frame dropped
235// after adaptation.
236TEST_F(VideoAdapterTest, AdaptFramerateOntheFly) {
237 VideoFormat request_format = capture_format_;
238 adapter_->SetOutputFormat(request_format);
239 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200240 for (int i = 0; i < 10; ++i)
241 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000242
243 // Verify no frame drop before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000244 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000245
246 // Adapat the frame rate.
247 request_format.interval *= 2;
248 adapter_->SetOutputFormat(request_format);
249
Magnus Jedvert01840572015-04-10 11:18:39 +0200250 for (int i = 0; i < 20; ++i)
251 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000252
253 // Verify frame drop after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000254 EXPECT_GT(listener_->GetStats().dropped_frames, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000255}
256
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000257// Set a very high output pixel resolution. Expect no resolution change.
258TEST_F(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
259 adapter_->SetOutputNumPixels(INT_MAX);
260 VideoFormat adapted_format = adapter_->AdaptFrameResolution(
261 capture_format_.width, capture_format_.height);
262 EXPECT_EQ(capture_format_.width, adapted_format.width);
263 EXPECT_EQ(capture_format_.height, adapted_format.height);
264
265 adapter_->SetOutputNumPixels(987654321);
266 adapted_format = capture_format_,
267 adapter_->AdaptFrameResolution(capture_format_.width, capture_format_.height);
268 EXPECT_EQ(capture_format_.width, adapted_format.width);
269 EXPECT_EQ(capture_format_.height, adapted_format.height);
270}
271
272// Adapt the frame resolution to be the same as capture resolution. Expect no
273// resolution change.
274TEST_F(VideoAdapterTest, AdaptFrameResolutionIdentical) {
275 adapter_->SetOutputFormat(capture_format_);
276 const VideoFormat adapted_format = adapter_->AdaptFrameResolution(
277 capture_format_.width, capture_format_.height);
278 EXPECT_EQ(capture_format_.width, adapted_format.width);
279 EXPECT_EQ(capture_format_.height, adapted_format.height);
280}
281
282// Adapt the frame resolution to be a quarter of the capture resolution. Expect
283// resolution change.
284TEST_F(VideoAdapterTest, AdaptFrameResolutionQuarter) {
285 VideoFormat request_format = capture_format_;
286 request_format.width /= 2;
287 request_format.height /= 2;
288 adapter_->SetOutputFormat(request_format);
289 const VideoFormat adapted_format = adapter_->AdaptFrameResolution(
290 request_format.width, request_format.height);
291 EXPECT_EQ(request_format.width, adapted_format.width);
292 EXPECT_EQ(request_format.height, adapted_format.height);
293}
294
295// Adapt the pixel resolution to 0. Expect frame drop.
296TEST_F(VideoAdapterTest, AdaptFrameResolutionDrop) {
297 adapter_->SetOutputNumPixels(0);
298 EXPECT_TRUE(
299 adapter_->AdaptFrameResolution(capture_format_.width,
300 capture_format_.height).IsSize0x0());
301}
302
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000303// Adapt the frame resolution to be a quarter of the capture resolution at the
304// beginning. Expect resolution change.
305TEST_F(VideoAdapterTest, AdaptResolution) {
306 VideoFormat request_format = capture_format_;
307 request_format.width /= 2;
308 request_format.height /= 2;
309 adapter_->SetOutputFormat(request_format);
310 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200311 for (int i = 0; i < 10; ++i)
312 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000313
314 // Verify no frame drop and resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000315 VideoCapturerListener::Stats stats = listener_->GetStats();
316 EXPECT_EQ(0, stats.dropped_frames);
317 VerifyAdaptedResolution(stats, request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000318}
319
320// Adapt the frame resolution to half width. Expect resolution change.
321TEST_F(VideoAdapterTest, AdaptResolutionNarrow) {
322 VideoFormat request_format = capture_format_;
323 request_format.width /= 2;
324 adapter_->set_scale_third(true);
325 adapter_->SetOutputFormat(request_format);
326 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200327 for (int i = 0; i < 10; ++i)
328 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000329
330 // Verify resolution change.
Magnus Jedvert01840572015-04-10 11:18:39 +0200331 VerifyAdaptedResolution(listener_->GetStats(),
332 capture_format_.width * 2 / 3,
333 capture_format_.height * 2 / 3);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000334}
335
336// Adapt the frame resolution to half height. Expect resolution change.
337TEST_F(VideoAdapterTest, AdaptResolutionWide) {
338 VideoFormat request_format = capture_format_;
339 request_format.height /= 2;
340 adapter_->set_scale_third(true);
341 adapter_->SetOutputFormat(request_format);
342 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200343 for (int i = 0; i < 10; ++i)
344 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000345
346 // Verify resolution change.
Magnus Jedvert01840572015-04-10 11:18:39 +0200347 VerifyAdaptedResolution(listener_->GetStats(),
348 capture_format_.width * 2 / 3,
349 capture_format_.height * 2 / 3);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000350}
351
352// Adapt the frame resolution to be a quarter of the capture resolution after
353// capturing no less than 10 frames. Expect no resolution change before
354// adaptation and resolution change after adaptation.
355TEST_F(VideoAdapterTest, AdaptResolutionOnTheFly) {
356 VideoFormat request_format = capture_format_;
357 adapter_->SetOutputFormat(request_format);
358 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200359 for (int i = 0; i < 10; ++i)
360 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000361
362 // Verify no resolution change before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000363 VerifyAdaptedResolution(
364 listener_->GetStats(), request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000365
366 // Adapt the frame resolution.
367 request_format.width /= 2;
368 request_format.height /= 2;
369 adapter_->SetOutputFormat(request_format);
Magnus Jedvert01840572015-04-10 11:18:39 +0200370 for (int i = 0; i < 10; ++i)
371 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000372
373 // Verify resolution change after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000374 VerifyAdaptedResolution(
375 listener_->GetStats(), request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000376}
377
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000378// Drop all frames.
379TEST_F(VideoAdapterTest, DropAllFrames) {
380 VideoFormat format; // with resolution 0x0.
381 adapter_->SetOutputFormat(format);
382 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200383 for (int i = 0; i < 10; ++i)
384 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000385
386 // Verify all frames are dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000387 VideoCapturerListener::Stats stats = listener_->GetStats();
388 EXPECT_GE(stats.captured_frames, 10);
389 EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000390}
391
392TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithoutCpuAdaptation) {
393 CoordinatedVideoAdapter adapter;
394 adapter.set_cpu_adaptation(false);
395
396 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
397 adapter.SetInputFormat(format);
398 adapter.set_scale_third(true);
399 EXPECT_EQ(format, adapter.input_format());
400 EXPECT_TRUE(adapter.output_format().IsSize0x0());
401
402 // Server format request 640x400.
403 format.height = 400;
404 adapter.OnOutputFormatRequest(format);
405 EXPECT_EQ(640, adapter.output_format().width);
406 EXPECT_EQ(400, adapter.output_format().height);
407
408 // Server format request 1280x720, higher than input. Adapt nothing.
409 format.width = 1280;
410 format.height = 720;
411 adapter.OnOutputFormatRequest(format);
412 EXPECT_EQ(640, adapter.output_format().width);
413 EXPECT_EQ(400, adapter.output_format().height);
414
415 // Cpu load is high, but cpu adaptation is disabled. Adapt nothing.
416 adapter.OnCpuLoadUpdated(1, 1, 0.99f, 0.99f);
417 EXPECT_EQ(640, adapter.output_format().width);
418 EXPECT_EQ(400, adapter.output_format().height);
419
420 // Encoder resolution request: downgrade with different size. Adapt nothing.
421 adapter.OnEncoderResolutionRequest(320, 200,
422 CoordinatedVideoAdapter::DOWNGRADE);
423 EXPECT_EQ(640, adapter.output_format().width);
424 EXPECT_EQ(400, adapter.output_format().height);
425
426 // Encoder resolution request: downgrade.
427 adapter.OnEncoderResolutionRequest(640, 400,
428 CoordinatedVideoAdapter::DOWNGRADE);
429 EXPECT_EQ(480, adapter.output_format().width);
430 EXPECT_EQ(300, adapter.output_format().height);
431
432 // Encoder resolution request: downgrade. But GD off. Adapt nothing.
433 adapter.set_gd_adaptation(false);
434 adapter.OnEncoderResolutionRequest(480, 300,
435 CoordinatedVideoAdapter::DOWNGRADE);
436 EXPECT_EQ(480, adapter.output_format().width);
437 EXPECT_EQ(300, adapter.output_format().height);
438 adapter.set_gd_adaptation(true);
439
440 // Encoder resolution request: downgrade.
441 adapter.OnEncoderResolutionRequest(480, 300,
442 CoordinatedVideoAdapter::DOWNGRADE);
443 EXPECT_EQ(320, adapter.output_format().width);
444 EXPECT_EQ(200, adapter.output_format().height);
445
446 // Encoder resolution request: keep. Adapt nothing.
447 adapter.OnEncoderResolutionRequest(320, 200,
448 CoordinatedVideoAdapter::KEEP);
449 EXPECT_EQ(320, adapter.output_format().width);
450 EXPECT_EQ(200, adapter.output_format().height);
451
452 // Encoder resolution request: upgrade.
453 adapter.OnEncoderResolutionRequest(320, 200,
454 CoordinatedVideoAdapter::UPGRADE);
455 EXPECT_EQ(480, adapter.output_format().width);
456 EXPECT_EQ(300, adapter.output_format().height);
457
458 // Server format request 0x0.
459 format.width = 0;
460 format.height = 0;
461 adapter.OnOutputFormatRequest(format);
462 EXPECT_TRUE(adapter.output_format().IsSize0x0());
463
464 // Server format request 320x200.
465 format.width = 320;
466 format.height = 200;
467 adapter.OnOutputFormatRequest(format);
468 EXPECT_EQ(320, adapter.output_format().width);
469 EXPECT_EQ(200, adapter.output_format().height);
470
471 // Server format request 160x100. But view disabled. Adapt nothing.
472 adapter.set_view_adaptation(false);
473 format.width = 160;
474 format.height = 100;
475 adapter.OnOutputFormatRequest(format);
476 EXPECT_EQ(320, adapter.output_format().width);
477 EXPECT_EQ(200, adapter.output_format().height);
478 adapter.set_view_adaptation(true);
479
480 // Enable View Switch. Expect adapt down.
481 adapter.set_view_switch(true);
482 format.width = 160;
483 format.height = 100;
484 adapter.OnOutputFormatRequest(format);
485 EXPECT_EQ(160, adapter.output_format().width);
486 EXPECT_EQ(100, adapter.output_format().height);
487
488 // Encoder resolution request: upgrade. Adapt nothing.
489 adapter.OnEncoderResolutionRequest(160, 100,
490 CoordinatedVideoAdapter::UPGRADE);
491 EXPECT_EQ(160, adapter.output_format().width);
492 EXPECT_EQ(100, adapter.output_format().height);
493
494 // Request View of 2 / 3. Expect adapt down.
495 adapter.set_view_switch(true);
496 format.width = (640 * 2 + 1) / 3;
497 format.height = (400 * 2 + 1) / 3;
498 adapter.OnOutputFormatRequest(format);
499 EXPECT_EQ((640 * 2 + 1) / 3, adapter.output_format().width);
500 EXPECT_EQ((400 * 2 + 1) / 3, adapter.output_format().height);
501
502
503 // Request View of 3 / 8. Expect adapt down.
504 adapter.set_view_switch(true);
505 format.width = 640 * 3 / 8;
506 format.height = 400 * 3 / 8;
507 adapter.OnOutputFormatRequest(format);
508 EXPECT_EQ(640 * 3 / 8, adapter.output_format().width);
509 EXPECT_EQ(400 * 3 / 8, adapter.output_format().height);
510
511 // View Switch back up. Expect adapt.
512 format.width = 320;
513 format.height = 200;
514 adapter.OnOutputFormatRequest(format);
515 EXPECT_EQ(320, adapter.output_format().width);
516 EXPECT_EQ(200, adapter.output_format().height);
517
518 adapter.set_view_switch(false);
519
520 // Encoder resolution request: upgrade. Constrained by server request.
521 adapter.OnEncoderResolutionRequest(320, 200,
522 CoordinatedVideoAdapter::UPGRADE);
523 EXPECT_EQ(320, adapter.output_format().width);
524 EXPECT_EQ(200, adapter.output_format().height);
525
526 // Server format request 480x300.
527 format.width = 480;
528 format.height = 300;
529 adapter.OnOutputFormatRequest(format);
530 EXPECT_EQ(480, adapter.output_format().width);
531 EXPECT_EQ(300, adapter.output_format().height);
532}
533
534TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithCpuAdaptation) {
535 CoordinatedVideoAdapter adapter;
536 adapter.set_cpu_adaptation(true);
537 EXPECT_FALSE(adapter.cpu_smoothing());
538 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
539 adapter.SetInputFormat(format);
540
541 // Server format request 640x400.
542 format.height = 400;
543 adapter.OnOutputFormatRequest(format);
544 EXPECT_EQ(640, adapter.output_format().width);
545 EXPECT_EQ(400, adapter.output_format().height);
546
547 // Process load is medium, but system load is high. Downgrade.
548 UpdateCpuLoad(&adapter, 1, 1, 0.55f, 0.98f);
549 EXPECT_EQ(480, adapter.output_format().width);
550 EXPECT_EQ(300, adapter.output_format().height);
551
552 // CPU high, but cpu adaptation disabled. Adapt nothing.
553 adapter.set_cpu_adaptation(false);
554 adapter.OnCpuLoadUpdated(1, 1, 0.55f, 0.98f);
555 EXPECT_EQ(480, adapter.output_format().width);
556 EXPECT_EQ(300, adapter.output_format().height);
557 adapter.set_cpu_adaptation(true);
558
559 // System load is high, but time has not elaspsed. Adapt nothing.
560 adapter.set_cpu_load_min_samples(2);
561 adapter.OnCpuLoadUpdated(1, 1, 0.55f, 0.98f);
562 EXPECT_EQ(480, adapter.output_format().width);
563 EXPECT_EQ(300, adapter.output_format().height);
564
565 // Process load is medium, but system load is high. Downgrade.
566 UpdateCpuLoad(&adapter, 1, 1, 0.55f, 0.98f);
567 EXPECT_EQ(320, adapter.output_format().width);
568 EXPECT_EQ(200, adapter.output_format().height);
569
570 // Test reason for adapting is CPU.
571 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
572 adapter.adapt_reason());
573
574 // Server format request 320x200. Same as CPU. Do nothing.
575 format.width = 320;
576 format.height = 200;
577 adapter.OnOutputFormatRequest(format);
578 EXPECT_EQ(320, adapter.output_format().width);
579 EXPECT_EQ(200, adapter.output_format().height);
580
581 // Test reason for adapting is CPU and VIEW.
582 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
583 CoordinatedVideoAdapter::ADAPTREASON_VIEW,
584 adapter.adapt_reason());
585
586 // Process load and system load are normal. Adapt nothing.
587 UpdateCpuLoad(&adapter, 1, 1, 0.5f, 0.8f);
588 EXPECT_EQ(320, adapter.output_format().width);
589 EXPECT_EQ(200, adapter.output_format().height);
590
591 // Process load and system load are low, but view is still low. Adapt nothing.
592 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
593 EXPECT_EQ(320, adapter.output_format().width);
594 EXPECT_EQ(200, adapter.output_format().height);
595
596 // Test reason for adapting is VIEW.
597 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
598 adapter.adapt_reason());
599
600 // Server format request 640x400. Cpu is still low. Upgrade.
601 format.width = 640;
602 format.height = 400;
603 adapter.OnOutputFormatRequest(format);
604 EXPECT_EQ(480, adapter.output_format().width);
605 EXPECT_EQ(300, adapter.output_format().height);
606
607 // Test reason for adapting is CPU.
608 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
609 adapter.adapt_reason());
610
611 // Encoder resolution request: downgrade.
612 adapter.OnEncoderResolutionRequest(480, 300,
613 CoordinatedVideoAdapter::DOWNGRADE);
614 EXPECT_EQ(320, adapter.output_format().width);
615 EXPECT_EQ(200, adapter.output_format().height);
616
617 // Test reason for adapting is BANDWIDTH.
618 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
619 adapter.adapt_reason());
620
621 // Process load and system load are low. Constrained by GD. Adapt nothing
622 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
623 EXPECT_EQ(320, adapter.output_format().width);
624 EXPECT_EQ(200, adapter.output_format().height);
625
626 // Encoder resolution request: upgrade.
627 adapter.OnEncoderResolutionRequest(320, 200,
628 CoordinatedVideoAdapter::UPGRADE);
629 EXPECT_EQ(480, adapter.output_format().width);
630 EXPECT_EQ(300, adapter.output_format().height);
631
632 // Encoder resolution request: upgrade. Constrained by CPU.
633 adapter.OnEncoderResolutionRequest(480, 300,
634 CoordinatedVideoAdapter::UPGRADE);
635 EXPECT_EQ(480, adapter.output_format().width);
636 EXPECT_EQ(300, adapter.output_format().height);
637
638 // Server format request 640x400. Constrained by CPU.
639 format.width = 640;
640 format.height = 400;
641 adapter.OnOutputFormatRequest(format);
642 EXPECT_EQ(480, adapter.output_format().width);
643 EXPECT_EQ(300, adapter.output_format().height);
644}
645
646TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithCpuRequest) {
647 CoordinatedVideoAdapter adapter;
648 adapter.set_cpu_adaptation(true);
649 EXPECT_FALSE(adapter.cpu_smoothing());
650 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
651 adapter.SetInputFormat(format);
652
653 // Server format request 640x400.
654 format.height = 400;
655 adapter.OnOutputFormatRequest(format);
656 EXPECT_EQ(640, adapter.output_format().width);
657 EXPECT_EQ(400, adapter.output_format().height);
658
659 // CPU resolution request: downgrade. Adapt down.
660 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
661 EXPECT_EQ(480, adapter.output_format().width);
662 EXPECT_EQ(300, adapter.output_format().height);
663
664 // CPU resolution request: keep. Do nothing.
665 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::KEEP);
666 EXPECT_EQ(480, adapter.output_format().width);
667 EXPECT_EQ(300, adapter.output_format().height);
668
669 // CPU resolution request: downgrade, but cpu adaptation disabled.
670 // Adapt nothing.
671 adapter.set_cpu_adaptation(false);
672 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
673 EXPECT_EQ(480, adapter.output_format().width);
674 EXPECT_EQ(300, adapter.output_format().height);
675
676 // CPU resolution request: downgrade. Adapt down.
677 adapter.set_cpu_adaptation(true);
678 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
679 EXPECT_EQ(320, adapter.output_format().width);
680 EXPECT_EQ(200, adapter.output_format().height);
681
682 // Test reason for adapting is CPU.
683 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
684 adapter.adapt_reason());
685
686 // CPU resolution request: downgrade, but already at minimum. Do nothing.
687 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
688 EXPECT_EQ(320, adapter.output_format().width);
689 EXPECT_EQ(200, adapter.output_format().height);
690
691 // Server format request 320x200. Same as CPU. Do nothing.
692 format.width = 320;
693 format.height = 200;
694 adapter.OnOutputFormatRequest(format);
695 EXPECT_EQ(320, adapter.output_format().width);
696 EXPECT_EQ(200, adapter.output_format().height);
697
698 // Test reason for adapting is CPU and VIEW.
699 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
700 CoordinatedVideoAdapter::ADAPTREASON_VIEW,
701 adapter.adapt_reason());
702
703 // CPU resolution request: upgrade, but view request still low. Do nothing.
704 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE);
705 EXPECT_EQ(320, adapter.output_format().width);
706 EXPECT_EQ(200, adapter.output_format().height);
707
708 // Test reason for adapting is VIEW.
709 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
710 adapter.adapt_reason());
711
712 // Server format request 640x400. Cpu is still low. Upgrade.
713 format.width = 640;
714 format.height = 400;
715 adapter.OnOutputFormatRequest(format);
716 EXPECT_EQ(480, adapter.output_format().width);
717 EXPECT_EQ(300, adapter.output_format().height);
718
719 // Test reason for adapting is CPU.
720 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
721 adapter.adapt_reason());
722
723 // Encoder resolution request: downgrade.
724 adapter.OnEncoderResolutionRequest(480, 300,
725 CoordinatedVideoAdapter::DOWNGRADE);
726 EXPECT_EQ(320, adapter.output_format().width);
727 EXPECT_EQ(200, adapter.output_format().height);
728
729 // Test reason for adapting is BANDWIDTH.
730 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
731 adapter.adapt_reason());
732
733 // Process load and system load are low. Constrained by GD. Adapt nothing
734 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
735 EXPECT_EQ(320, adapter.output_format().width);
736 EXPECT_EQ(200, adapter.output_format().height);
737
738 // Encoder resolution request: upgrade.
739 adapter.OnEncoderResolutionRequest(320, 200,
740 CoordinatedVideoAdapter::UPGRADE);
741 EXPECT_EQ(480, adapter.output_format().width);
742 EXPECT_EQ(300, adapter.output_format().height);
743
744 // Encoder resolution request: upgrade. Constrained by CPU.
745 adapter.OnEncoderResolutionRequest(480, 300,
746 CoordinatedVideoAdapter::UPGRADE);
747 EXPECT_EQ(480, adapter.output_format().width);
748 EXPECT_EQ(300, adapter.output_format().height);
749
750 // Server format request 640x400. Constrained by CPU.
751 format.width = 640;
752 format.height = 400;
753 adapter.OnOutputFormatRequest(format);
754 EXPECT_EQ(480, adapter.output_format().width);
755 EXPECT_EQ(300, adapter.output_format().height);
756}
757
758TEST(CoordinatedVideoAdapterTest, TestViewRequestPlusCameraSwitch) {
759 CoordinatedVideoAdapter adapter;
760 adapter.set_view_switch(true);
761
762 // Start at HD.
763 VideoFormat format(1280, 720, VideoFormat::FpsToInterval(30), FOURCC_I420);
764 adapter.SetInputFormat(format);
765 EXPECT_EQ(format, adapter.input_format());
766 EXPECT_TRUE(adapter.output_format().IsSize0x0());
767
768 // View request for VGA.
769 format.width = 640;
770 format.height = 360;
771 adapter.OnOutputFormatRequest(format);
772 EXPECT_EQ(640, adapter.output_format().width);
773 EXPECT_EQ(360, adapter.output_format().height);
774 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW, adapter.adapt_reason());
775
776 // Now, the camera reopens at VGA.
777 // Both the frame and the output format should be 640x360.
Magnus Jedvertac27e202015-03-24 15:18:39 +0100778 const VideoFormat out_format = adapter.AdaptFrameResolution(640, 360);
779 EXPECT_EQ(640, out_format.width);
780 EXPECT_EQ(360, out_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000781 // At this point, the view is no longer adapted, since the input has resized
782 // small enough to fit the last view request.
783 EXPECT_EQ(0, adapter.adapt_reason());
784
785 // And another view request comes in for 640x360, which should have no
786 // real impact.
787 adapter.OnOutputFormatRequest(format);
788 EXPECT_EQ(640, adapter.output_format().width);
789 EXPECT_EQ(360, adapter.output_format().height);
790 EXPECT_EQ(0, adapter.adapt_reason());
791}
792
793TEST(CoordinatedVideoAdapterTest, TestVGAWidth) {
794 CoordinatedVideoAdapter adapter;
795 adapter.set_view_switch(true);
796
797 // Start at 640x480, for cameras that don't support 640x360.
798 VideoFormat format(640, 480, VideoFormat::FpsToInterval(30), FOURCC_I420);
799 adapter.SetInputFormat(format);
800 EXPECT_EQ(format, adapter.input_format());
801 EXPECT_TRUE(adapter.output_format().IsSize0x0());
802
803 // Output format is 640x360, though.
804 format.width = 640;
805 format.height = 360;
806 adapter.SetOutputFormat(format);
807
808 // And also a view request comes for 640x360.
809 adapter.OnOutputFormatRequest(format);
810 // At this point, we have to adapt down to something lower.
811 EXPECT_EQ(480, adapter.output_format().width);
812 EXPECT_EQ(360, adapter.output_format().height);
813
814 // But if frames come in at 640x360, we shouldn't adapt them down.
815 // Fake a 640x360 frame.
Magnus Jedvertac27e202015-03-24 15:18:39 +0100816 VideoFormat out_format = adapter.AdaptFrameResolution(640, 360);
817 EXPECT_EQ(640, out_format.width);
818 EXPECT_EQ(360, out_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000819
820 // Similarly, no-op adapt requests for other reasons shouldn't change
821 // adaptation state (before a previous bug, the previous EXPECTs would
822 // fail and the following would succeed, as the no-op CPU request would
823 // fix the adaptation state).
824 adapter.set_cpu_adaptation(true);
825 UpdateCpuLoad(&adapter, 1, 1, 0.7f, 0.7f);
Magnus Jedvertac27e202015-03-24 15:18:39 +0100826 out_format = adapter.AdaptFrameResolution(640, 360);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000827
Magnus Jedvertac27e202015-03-24 15:18:39 +0100828 EXPECT_EQ(640, out_format.width);
829 EXPECT_EQ(360, out_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000830}
831
832// When adapting resolution for CPU or GD, the quantity of pixels that the
833// request is based on is reduced to half or double, and then an actual
834// resolution is snapped to, rounding to the closest actual resolution.
835// This works well for some tolerance to 3/4, odd widths and aspect ratios
836// that dont exactly match, but is not best behavior for ViewRequests which
837// need to be be strictly respected to avoid going over the resolution budget
838// given to the codec - 854x480 total pixels.
839// ViewRequest must find a lower resolution.
840TEST(CoordinatedVideoAdapterTest, TestCoordinatedViewRequestDown) {
841 CoordinatedVideoAdapter adapter;
842 adapter.set_cpu_adaptation(false);
843
844 VideoFormat format(960, 540, VideoFormat::FpsToInterval(30), FOURCC_I420);
845 adapter.SetInputFormat(format);
846 adapter.set_scale_third(true);
847 EXPECT_EQ(format, adapter.input_format());
848 EXPECT_TRUE(adapter.output_format().IsSize0x0());
849
850 // Server format request 640x400. Expect HVGA.
851 format.width = 640;
852 format.height = 400;
853 adapter.OnOutputFormatRequest(format);
854 EXPECT_EQ(640, adapter.output_format().width);
855 EXPECT_EQ(360, adapter.output_format().height);
856
857 // Test reason for adapting is VIEW.
858 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW, adapter.adapt_reason());
859}
860
861// Test that we downgrade video for cpu up to two times.
862TEST(CoordinatedVideoAdapterTest, TestCpuDowngradeTimes) {
863 CoordinatedVideoAdapter adapter;
864 adapter.set_cpu_adaptation(true);
865 EXPECT_FALSE(adapter.cpu_smoothing());
866 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
867 adapter.SetInputFormat(format);
868
869 // Server format request 640x400.
870 format.height = 400;
871 adapter.OnOutputFormatRequest(format);
872 EXPECT_EQ(640, adapter.output_format().width);
873 EXPECT_EQ(400, adapter.output_format().height);
874
875 // Process load and system load are low. Do not change the cpu desired format
876 // and do not adapt.
877 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
878 EXPECT_EQ(640, adapter.output_format().width);
879 EXPECT_EQ(400, adapter.output_format().height);
880
881 // System load is high. Downgrade.
882 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
883 EXPECT_EQ(480, adapter.output_format().width);
884 EXPECT_EQ(300, adapter.output_format().height);
885
886 // System load is high. Downgrade again.
887 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
888 EXPECT_EQ(320, adapter.output_format().width);
889 EXPECT_EQ(200, adapter.output_format().height);
890
891 // System load is still high. Do not downgrade any more.
892 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
893 EXPECT_EQ(320, adapter.output_format().width);
894 EXPECT_EQ(200, adapter.output_format().height);
895
896 // Process load and system load are low. Upgrade.
897 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
898 EXPECT_EQ(480, adapter.output_format().width);
899 EXPECT_EQ(300, adapter.output_format().height);
900
901 // System load is high. Downgrade.
902 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
903 EXPECT_EQ(320, adapter.output_format().width);
904 EXPECT_EQ(200, adapter.output_format().height);
905
906 // System load is still high. Do not downgrade any more.
907 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
908 EXPECT_EQ(320, adapter.output_format().width);
909 EXPECT_EQ(200, adapter.output_format().height);
910}
911
912// Test that we respect CPU adapter threshold values.
913TEST(CoordinatedVideoAdapterTest, TestAdapterCpuThreshold) {
914 CoordinatedVideoAdapter adapter;
915 adapter.set_cpu_adaptation(true);
916 EXPECT_FALSE(adapter.cpu_smoothing());
917 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
918 adapter.SetInputFormat(format);
919
920 // Server format request 640x400.
921 format.height = 400;
922 adapter.OnOutputFormatRequest(format);
923 EXPECT_EQ(640, adapter.output_format().width);
924 EXPECT_EQ(400, adapter.output_format().height);
925
926 // Process load and system load are low. Do not change the cpu desired format
927 // and do not adapt.
928 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
929 EXPECT_EQ(640, adapter.output_format().width);
930 EXPECT_EQ(400, adapter.output_format().height);
931
932 // System load is high. Downgrade.
933 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
934 EXPECT_EQ(480, adapter.output_format().width);
935 EXPECT_EQ(300, adapter.output_format().height);
936
937 // Test reason for adapting is CPU.
938 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, adapter.adapt_reason());
939
940 // System load is high. Normally downgrade but threshold is high. Do nothing.
941 adapter.set_high_system_threshold(0.98f); // Set threshold high.
942 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
943 EXPECT_EQ(480, adapter.output_format().width);
944 EXPECT_EQ(300, adapter.output_format().height);
945
946 // System load is medium. Normally do nothing, threshold is low. Adapt down.
947 adapter.set_high_system_threshold(0.75f); // Set threshold low.
948 UpdateCpuLoad(&adapter, 1, 1, 0.8f, 0.8f);
949 EXPECT_EQ(320, adapter.output_format().width);
950 EXPECT_EQ(200, adapter.output_format().height);
951}
952
953
954// Test that for an upgrade cpu request, we actually upgrade the desired format;
955// for a downgrade request, we downgrade from the output format.
956TEST(CoordinatedVideoAdapterTest, TestRealCpuUpgrade) {
957 CoordinatedVideoAdapter adapter;
958 adapter.set_cpu_adaptation(true);
959 adapter.set_cpu_smoothing(true);
960 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
961 adapter.SetInputFormat(format);
962
963 // Server format request 640x400.
964 format.width = 640;
965 format.height = 400;
966 adapter.OnOutputFormatRequest(format);
967 EXPECT_EQ(640, adapter.output_format().width);
968 EXPECT_EQ(400, adapter.output_format().height);
969
970 // Process load and system load are low. Do not change the cpu desired format
971 // and do not adapt.
972 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
973 EXPECT_EQ(640, adapter.output_format().width);
974 EXPECT_EQ(400, adapter.output_format().height);
975
976 // Server format request 320x200.
977 format.width = 320;
978 format.height = 200;
979 adapter.OnOutputFormatRequest(format);
980 EXPECT_EQ(320, adapter.output_format().width);
981 EXPECT_EQ(200, adapter.output_format().height);
982
983 // Process load and system load are low. Do not change the cpu desired format
984 // and do not adapt.
985 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
986 EXPECT_EQ(320, adapter.output_format().width);
987 EXPECT_EQ(200, adapter.output_format().height);
988
989 // Server format request 640x400. Set to 640x400 immediately.
990 format.width = 640;
991 format.height = 400;
992 adapter.OnOutputFormatRequest(format);
993 EXPECT_EQ(640, adapter.output_format().width);
994 EXPECT_EQ(400, adapter.output_format().height);
995
996 // Server format request 320x200.
997 format.width = 320;
998 format.height = 200;
999 adapter.OnOutputFormatRequest(format);
1000 EXPECT_EQ(320, adapter.output_format().width);
1001 EXPECT_EQ(200, adapter.output_format().height);
1002
1003 // Process load is high, but system is not. Do not change the cpu desired
1004 // format and do not adapt.
1005 for (size_t i = 0; i < 10; ++i) {
1006 UpdateCpuLoad(&adapter, 1, 1, 0.75f, 0.8f);
1007 }
1008 EXPECT_EQ(320, adapter.output_format().width);
1009 EXPECT_EQ(200, adapter.output_format().height);
1010}
1011
1012// Test that for an upgrade encoder request, we actually upgrade the desired
1013// format; for a downgrade request, we downgrade from the output format.
1014TEST(CoordinatedVideoAdapterTest, TestRealEncoderUpgrade) {
1015 CoordinatedVideoAdapter adapter;
1016 adapter.set_cpu_adaptation(true);
1017 adapter.set_cpu_smoothing(true);
1018 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
1019 adapter.SetInputFormat(format);
1020
1021 // Server format request 640x400.
1022 format.width = 640;
1023 format.height = 400;
1024 adapter.OnOutputFormatRequest(format);
1025 EXPECT_EQ(640, adapter.output_format().width);
1026 EXPECT_EQ(400, adapter.output_format().height);
1027
1028 // Encoder resolution request. Do not change the encoder desired format and
1029 // do not adapt.
1030 adapter.OnEncoderResolutionRequest(640, 400,
1031 CoordinatedVideoAdapter::UPGRADE);
1032 EXPECT_EQ(640, adapter.output_format().width);
1033 EXPECT_EQ(400, adapter.output_format().height);
1034
1035 // Server format request 320x200.
1036 format.width = 320;
1037 format.height = 200;
1038 adapter.OnOutputFormatRequest(format);
1039 EXPECT_EQ(320, adapter.output_format().width);
1040 EXPECT_EQ(200, adapter.output_format().height);
1041
1042 // Encoder resolution request. Do not change the encoder desired format and
1043 // do not adapt.
1044 adapter.OnEncoderResolutionRequest(320, 200,
1045 CoordinatedVideoAdapter::UPGRADE);
1046 EXPECT_EQ(320, adapter.output_format().width);
1047 EXPECT_EQ(200, adapter.output_format().height);
1048
1049 // Server format request 640x400. Set to 640x400 immediately.
1050 format.width = 640;
1051 format.height = 400;
1052 adapter.OnOutputFormatRequest(format);
1053 EXPECT_EQ(480, adapter.output_format().width);
1054 EXPECT_EQ(300, adapter.output_format().height);
1055
1056 // Test reason for adapting is BANDWIDTH.
1057 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
1058 adapter.adapt_reason());
1059
1060 // Server format request 320x200.
1061 format.width = 320;
1062 format.height = 200;
1063 adapter.OnOutputFormatRequest(format);
1064 EXPECT_EQ(320, adapter.output_format().width);
1065 EXPECT_EQ(200, adapter.output_format().height);
1066
1067 // Encoder resolution request. Downgrade from 320x200.
1068 adapter.OnEncoderResolutionRequest(320, 200,
1069 CoordinatedVideoAdapter::DOWNGRADE);
1070 EXPECT_EQ(240, adapter.output_format().width);
1071 EXPECT_EQ(150, adapter.output_format().height);
1072}
1073
1074TEST(CoordinatedVideoAdapterTest, TestNormalizeOutputFormat) {
1075 CoordinatedVideoAdapter adapter;
1076 // The input format is 640x360 and the output is limited to 16:9.
1077 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1078 adapter.SetInputFormat(format);
1079
1080 format.width = 320;
1081 format.height = 180;
1082 format.interval = VideoFormat::FpsToInterval(15);
1083 adapter.OnOutputFormatRequest(format);
1084 EXPECT_EQ(320, adapter.output_format().width);
1085 EXPECT_EQ(180, adapter.output_format().height);
1086 EXPECT_EQ(VideoFormat::FpsToInterval(15), adapter.output_format().interval);
1087
1088 format.width = 320;
1089 format.height = 200;
1090 format.interval = VideoFormat::FpsToInterval(40);
1091 adapter.OnOutputFormatRequest(format);
1092 EXPECT_EQ(320, adapter.output_format().width);
1093 EXPECT_EQ(180, adapter.output_format().height);
1094 EXPECT_EQ(VideoFormat::FpsToInterval(30), adapter.output_format().interval);
1095
1096 // Test reason for adapting is VIEW. Should work even with normalization.
1097 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
1098 adapter.adapt_reason());
1099
1100 format.width = 320;
1101 format.height = 240;
1102 adapter.OnOutputFormatRequest(format);
1103 EXPECT_EQ(320, adapter.output_format().width);
1104 EXPECT_EQ(180, adapter.output_format().height);
1105
1106 // The input format is 640x480 and the output will be 4:3.
1107 format.width = 640;
1108 format.height = 480;
1109 adapter.SetInputFormat(format);
1110 EXPECT_EQ(320, adapter.output_format().width);
1111 EXPECT_EQ(240, adapter.output_format().height);
1112
1113 format.width = 320;
1114 format.height = 240;
1115 adapter.OnOutputFormatRequest(format);
1116 EXPECT_EQ(320, adapter.output_format().width);
1117 EXPECT_EQ(240, adapter.output_format().height);
1118
1119 // The input format is initialized after the output. At that time, the output
1120 // height is adjusted.
1121 format.width = 0;
1122 format.height = 0;
1123 adapter.SetInputFormat(format);
1124
1125 format.width = 320;
1126 format.height = 240;
1127 format.interval = VideoFormat::FpsToInterval(30);
1128 adapter.OnOutputFormatRequest(format);
1129 EXPECT_EQ(320, adapter.output_format().width);
1130 EXPECT_EQ(240, adapter.output_format().height);
1131 EXPECT_EQ(VideoFormat::FpsToInterval(30), adapter.output_format().interval);
1132
1133 format.width = 640;
1134 format.height = 480;
1135 format.interval = VideoFormat::FpsToInterval(15);
1136 adapter.SetInputFormat(format);
1137 EXPECT_EQ(320, adapter.output_format().width);
1138 EXPECT_EQ(240, adapter.output_format().height);
1139 EXPECT_EQ(VideoFormat::FpsToInterval(15), adapter.output_format().interval);
1140}
1141
1142// Test that we downgrade video for cpu up to two times.
1143TEST_F(VideoAdapterTest, CpuDowngradeAndSignal) {
1144 CoordinatedVideoAdapter adapter;
1145 CpuAdapterListener cpu_listener;
1146 adapter.SignalCpuAdaptationUnable.connect(
1147 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1148
1149 adapter.set_cpu_adaptation(true);
1150 EXPECT_FALSE(adapter.cpu_smoothing());
1151 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1152 adapter.SetInputFormat(format);
1153 adapter.OnOutputFormatRequest(format);
1154
1155 // System load is high. Downgrade.
1156 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1157
1158 // System load is high. Downgrade again.
1159 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1160
1161 // System load is still high. Do not downgrade any more. Ensure we have not
1162 // signalled until after the cpu warning though.
1163 EXPECT_TRUE(!cpu_listener.received_cpu_signal());
1164 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1165 EXPECT_TRUE_WAIT(cpu_listener.received_cpu_signal(), kWaitTimeout);
1166}
1167
1168// Test that we downgrade video for cpu up to two times.
1169TEST_F(VideoAdapterTest, CpuDowngradeAndDontSignal) {
1170 CoordinatedVideoAdapter adapter;
1171 CpuAdapterListener cpu_listener;
1172 adapter.SignalCpuAdaptationUnable.connect(
1173 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1174
1175 adapter.set_cpu_adaptation(true);
1176 adapter.set_cpu_smoothing(true);
1177 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1178 adapter.SetInputFormat(format);
1179 adapter.OnOutputFormatRequest(format);
1180
1181 // System load is high. Downgrade.
1182 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1183
1184 // System load is high, process is not, Do not downgrade again.
1185 UpdateCpuLoad(&adapter, 1, 1, 0.25f, 0.95f);
1186
1187 // System load is high, process is not, Do not downgrade again and do not
1188 // signal.
1189 adapter.set_cpu_adaptation(false);
1190 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1191 rtc::Thread::Current()->ProcessMessages(kShortWaitTimeout);
1192 EXPECT_TRUE(!cpu_listener.received_cpu_signal());
1193 adapter.set_cpu_adaptation(true);
1194}
1195
1196// Test that we require enough time before we downgrade.
1197TEST_F(VideoAdapterTest, CpuMinTimeRequirement) {
1198 CoordinatedVideoAdapter adapter;
1199 CpuAdapterListener cpu_listener;
1200 adapter.SignalCpuAdaptationUnable.connect(
1201 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1202
1203 adapter.set_cpu_adaptation(true);
1204 adapter.set_cpu_smoothing(true);
1205 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1206 adapter.SetInputFormat(format);
1207 adapter.OnOutputFormatRequest(format);
1208
1209 EXPECT_EQ(3, adapter.cpu_load_min_samples());
1210 adapter.set_cpu_load_min_samples(5);
1211
1212 for (size_t i = 0; i < 4; ++i) {
1213 adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1214 EXPECT_EQ(640, adapter.output_format().width);
1215 EXPECT_EQ(360, adapter.output_format().height);
1216 }
1217 // The computed cpu load should now be around 93.5%, with the coefficient of
1218 // 0.4 and a seed value of 0.5. That should be high enough to adapt, but it
1219 // isn't enough samples, so we shouldn't have adapted on any of the previous
1220 // samples.
1221
1222 // One more sample is enough, though, once enough time has passed.
1223 adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1224 EXPECT_EQ(480, adapter.output_format().width);
1225 EXPECT_EQ(270, adapter.output_format().height);
1226
1227 // Now the cpu is lower, but we still need enough samples to upgrade.
1228 for (size_t i = 0; i < 4; ++i) {
1229 adapter.OnCpuLoadUpdated(1, 1, 0.1f, 0.1f);
1230 EXPECT_EQ(480, adapter.output_format().width);
1231 EXPECT_EQ(270, adapter.output_format().height);
1232 }
1233
1234 // One more sample is enough, once time has elapsed.
1235 adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1236 EXPECT_EQ(640, adapter.output_format().width);
1237 EXPECT_EQ(360, adapter.output_format().height);
1238}
1239
1240TEST_F(VideoAdapterTest, CpuIgnoresSpikes) {
1241 CoordinatedVideoAdapter adapter;
1242 CpuAdapterListener cpu_listener;
1243 adapter.SignalCpuAdaptationUnable.connect(
1244 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1245
1246 adapter.set_cpu_adaptation(true);
1247 adapter.set_cpu_smoothing(true);
1248 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1249 adapter.SetInputFormat(format);
1250 adapter.OnOutputFormatRequest(format);
1251
1252 // System load is high. Downgrade.
1253 for (size_t i = 0; i < 5; ++i) {
1254 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1255 }
1256 EXPECT_EQ(480, adapter.output_format().width);
1257 EXPECT_EQ(270, adapter.output_format().height);
1258
1259 // Now we're in a state where we could upgrade or downgrade, so get to a
1260 // steady state of about 75% cpu usage.
1261 for (size_t i = 0; i < 5; ++i) {
1262 UpdateCpuLoad(&adapter, 1, 1, 0.75f, 0.75f);
1263 EXPECT_EQ(480, adapter.output_format().width);
1264 EXPECT_EQ(270, adapter.output_format().height);
1265 }
1266
1267 // Now, the cpu spikes for two samples, but then goes back to
1268 // normal. This shouldn't cause adaptation.
1269 UpdateCpuLoad(&adapter, 1, 1, 0.90f, 0.90f);
1270 UpdateCpuLoad(&adapter, 1, 1, 0.90f, 0.90f);
1271 EXPECT_EQ(480, adapter.output_format().width);
1272 EXPECT_EQ(270, adapter.output_format().height);
1273 // Back to the steady state for awhile.
1274 for (size_t i = 0; i < 5; ++i) {
1275 UpdateCpuLoad(&adapter, 1, 1, 0.75, 0.75);
1276 EXPECT_EQ(480, adapter.output_format().width);
1277 EXPECT_EQ(270, adapter.output_format().height);
1278 }
1279
1280 // Now, system cpu usage is starting to drop down. But it takes a bit before
1281 // it gets all the way there.
1282 for (size_t i = 0; i < 10; ++i) {
1283 UpdateCpuLoad(&adapter, 1, 1, 0.5f, 0.5f);
1284 }
1285 EXPECT_EQ(640, adapter.output_format().width);
1286 EXPECT_EQ(360, adapter.output_format().height);
1287}
1288
1289} // namespace cricket
Magnus Jedvert1ecfd552015-03-30 11:24:46 +02001290#endif // HAVE_WEBRTC_VIDEO