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