blob: 8d1552390a25fbd0f14258bdf360475d8925039d [file] [log] [blame]
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001/*
2 * libjingle
3 * Copyright 2010 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
Magnus Jedvert1ecfd552015-03-30 11:24:46 +020028// If we don't have a WebRtcVideoFrame, just skip all of these tests.
29#if defined(HAVE_WEBRTC_VIDEO)
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000030#include <limits.h> // For INT_MAX
31#include <string>
32#include <vector>
33
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000034#include "talk/media/base/mediachannel.h"
35#include "talk/media/base/testutils.h"
36#include "talk/media/base/videoadapter.h"
37#include "talk/media/devices/filevideocapturer.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000038#include "webrtc/base/gunit.h"
39#include "webrtc/base/logging.h"
40#include "webrtc/base/sigslot.h"
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000041
42namespace cricket {
43
44namespace {
45 static const uint32 kWaitTimeout = 3000U; // 3 seconds.
46 static const uint32 kShortWaitTimeout = 1000U; // 1 second.
47 void UpdateCpuLoad(CoordinatedVideoAdapter* adapter,
48 int current_cpus, int max_cpus, float process_load, float system_load) {
49 adapter->set_cpu_load_min_samples(1);
50 adapter->OnCpuLoadUpdated(current_cpus, max_cpus,
51 process_load, system_load);
52 }
53}
54
55class VideoAdapterTest : public testing::Test {
56 public:
57 virtual void SetUp() {
58 capturer_.reset(new FileVideoCapturer);
59 EXPECT_TRUE(capturer_->Init(GetTestFilePath(
60 "captured-320x240-2s-48.frames")));
61 capture_format_ = capturer_->GetSupportedFormats()->at(0);
62 capture_format_.interval = VideoFormat::FpsToInterval(50);
63 adapter_.reset(new VideoAdapter());
64 adapter_->SetInputFormat(capture_format_);
65
66 listener_.reset(new VideoCapturerListener(adapter_.get()));
67 capturer_->SignalFrameCaptured.connect(
68 listener_.get(), &VideoCapturerListener::OnFrameCaptured);
69 }
70
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000071 virtual void TearDown() {
72 // Explicitly disconnect the VideoCapturer before to avoid data races
73 // (frames delivered to VideoCapturerListener while it's being destructed).
74 capturer_->SignalFrameCaptured.disconnect_all();
75 }
76
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000077 protected:
78 class VideoCapturerListener: public sigslot::has_slots<> {
79 public:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000080 struct Stats {
81 int captured_frames;
82 int dropped_frames;
83 bool last_adapt_was_no_op;
84
85 int adapted_width;
86 int adapted_height;
87 };
88
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000089 explicit VideoCapturerListener(VideoAdapter* adapter)
90 : video_adapter_(adapter),
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000091 captured_frames_(0),
92 dropped_frames_(0),
93 last_adapt_was_no_op_(false) {
94 }
95
96 void OnFrameCaptured(VideoCapturer* capturer,
97 const CapturedFrame* captured_frame) {
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000098 rtc::CritScope lock(&crit_);
Magnus Jedvertac27e202015-03-24 15:18:39 +010099 const int in_width = captured_frame->width;
100 const int in_height = abs(captured_frame->height);
101 const VideoFormat adapted_format =
102 video_adapter_->AdaptFrameResolution(in_width, in_height);
103 if (!adapted_format.IsSize0x0()) {
104 adapted_format_ = adapted_format;
105 last_adapt_was_no_op_ = (in_width == adapted_format.width &&
106 in_height == adapted_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000107 } else {
108 ++dropped_frames_;
109 }
110 ++captured_frames_;
111 }
112
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000113 Stats GetStats() {
114 rtc::CritScope lock(&crit_);
115 Stats stats;
116 stats.captured_frames = captured_frames_;
117 stats.dropped_frames = dropped_frames_;
118 stats.last_adapt_was_no_op = last_adapt_was_no_op_;
Magnus Jedvertac27e202015-03-24 15:18:39 +0100119 if (!adapted_format_.IsSize0x0()) {
120 stats.adapted_width = adapted_format_.width;
121 stats.adapted_height = adapted_format_.height;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000122 } else {
123 stats.adapted_width = stats.adapted_height = -1;
124 }
125
126 return stats;
127 }
128
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000129 private:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000130 rtc::CriticalSection crit_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000131 VideoAdapter* video_adapter_;
Magnus Jedvertac27e202015-03-24 15:18:39 +0100132 VideoFormat adapted_format_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000133 int captured_frames_;
134 int dropped_frames_;
135 bool last_adapt_was_no_op_;
136 };
137
138 class CpuAdapterListener: public sigslot::has_slots<> {
139 public:
140 CpuAdapterListener() : received_cpu_signal_(false) {}
141 void OnCpuAdaptationSignalled() { received_cpu_signal_ = true; }
142 bool received_cpu_signal() { return received_cpu_signal_; }
143 private:
144 bool received_cpu_signal_;
145 };
146
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000147 void VerifyAdaptedResolution(const VideoCapturerListener::Stats& stats,
148 int width,
149 int height) {
150 EXPECT_EQ(width, stats.adapted_width);
151 EXPECT_EQ(height, stats.adapted_height);
152 }
153
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000154 rtc::scoped_ptr<FileVideoCapturer> capturer_;
155 rtc::scoped_ptr<VideoAdapter> adapter_;
156 rtc::scoped_ptr<VideoCapturerListener> listener_;
157 VideoFormat capture_format_;
158};
159
160
161// Test adapter remembers exact pixel count
162TEST_F(VideoAdapterTest, AdaptNumPixels) {
163 adapter_->SetOutputNumPixels(123456);
164 EXPECT_EQ(123456, adapter_->GetOutputNumPixels());
165}
166
167// Test adapter is constructed but not activated. Expect no frame drop and no
168// resolution change.
169TEST_F(VideoAdapterTest, AdaptInactive) {
170 // Output resolution is not set.
171 EXPECT_EQ(INT_MAX, adapter_->GetOutputNumPixels());
172
173 // Call Adapter with some frames.
174 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
175 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000176 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000177
178 // Verify no frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000179 VideoCapturerListener::Stats stats = listener_->GetStats();
180 EXPECT_GE(stats.captured_frames, 10);
181 EXPECT_EQ(0, stats.dropped_frames);
182 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000183}
184
185// Do not adapt the frame rate or the resolution. Expect no frame drop and no
186// resolution change.
187TEST_F(VideoAdapterTest, AdaptNothing) {
188 adapter_->SetOutputFormat(capture_format_);
189 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
190 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000191 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000192
193 // Verify no frame drop and no resolution change.
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);
198 EXPECT_TRUE(stats.last_adapt_was_no_op);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000199}
200
201TEST_F(VideoAdapterTest, AdaptZeroInterval) {
202 VideoFormat format = capturer_->GetSupportedFormats()->at(0);
203 format.interval = 0;
204 adapter_->SetInputFormat(format);
205 adapter_->SetOutputFormat(format);
206 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
207 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000208 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000209
210 // Verify no crash and that frames aren't dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000211 VideoCapturerListener::Stats stats = listener_->GetStats();
212 EXPECT_GE(stats.captured_frames, 10);
213 EXPECT_EQ(0, 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, AdaptFramerate) {
220 VideoFormat request_format = capture_format_;
221 request_format.interval *= 2;
222 adapter_->SetOutputFormat(request_format);
223 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
224 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000225 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
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, 10);
230 EXPECT_EQ(stats.captured_frames / 2, stats.dropped_frames);
231 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000232}
233
234// Adapt the frame rate to be half of the capture rate at the beginning. Expect
235// the number of dropped frames to be half of the number the captured frames.
236TEST_F(VideoAdapterTest, AdaptFramerateVariable) {
237 VideoFormat request_format = capture_format_;
238 request_format.interval = request_format.interval * 3 / 2;
239 adapter_->SetOutputFormat(request_format);
240 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
241 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000242 listener_->GetStats().captured_frames >= 30, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000243
244 // Verify frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000245 VideoCapturerListener::Stats stats = listener_->GetStats();
246 EXPECT_GE(stats.captured_frames, 30);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000247 // Verify 2 / 3 kept (20) and 1 / 3 dropped (10).
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000248 EXPECT_EQ(stats.captured_frames * 1 / 3, stats.dropped_frames);
249 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000250}
251
252// Adapt the frame rate to be half of the capture rate after capturing no less
253// than 10 frames. Expect no frame dropped before adaptation and frame dropped
254// after adaptation.
255TEST_F(VideoAdapterTest, AdaptFramerateOntheFly) {
256 VideoFormat request_format = capture_format_;
257 adapter_->SetOutputFormat(request_format);
258 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
259 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000260 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000261
262 // Verify no frame drop before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000263 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000264
265 // Adapat the frame rate.
266 request_format.interval *= 2;
267 adapter_->SetOutputFormat(request_format);
268
269 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000270 listener_->GetStats().captured_frames >= 20, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000271
272 // Verify frame drop after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000273 EXPECT_GT(listener_->GetStats().dropped_frames, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000274}
275
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000276// Set a very high output pixel resolution. Expect no resolution change.
277TEST_F(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
278 adapter_->SetOutputNumPixels(INT_MAX);
279 VideoFormat adapted_format = adapter_->AdaptFrameResolution(
280 capture_format_.width, capture_format_.height);
281 EXPECT_EQ(capture_format_.width, adapted_format.width);
282 EXPECT_EQ(capture_format_.height, adapted_format.height);
283
284 adapter_->SetOutputNumPixels(987654321);
285 adapted_format = capture_format_,
286 adapter_->AdaptFrameResolution(capture_format_.width, capture_format_.height);
287 EXPECT_EQ(capture_format_.width, adapted_format.width);
288 EXPECT_EQ(capture_format_.height, adapted_format.height);
289}
290
291// Adapt the frame resolution to be the same as capture resolution. Expect no
292// resolution change.
293TEST_F(VideoAdapterTest, AdaptFrameResolutionIdentical) {
294 adapter_->SetOutputFormat(capture_format_);
295 const VideoFormat adapted_format = adapter_->AdaptFrameResolution(
296 capture_format_.width, capture_format_.height);
297 EXPECT_EQ(capture_format_.width, adapted_format.width);
298 EXPECT_EQ(capture_format_.height, adapted_format.height);
299}
300
301// Adapt the frame resolution to be a quarter of the capture resolution. Expect
302// resolution change.
303TEST_F(VideoAdapterTest, AdaptFrameResolutionQuarter) {
304 VideoFormat request_format = capture_format_;
305 request_format.width /= 2;
306 request_format.height /= 2;
307 adapter_->SetOutputFormat(request_format);
308 const VideoFormat adapted_format = adapter_->AdaptFrameResolution(
309 request_format.width, request_format.height);
310 EXPECT_EQ(request_format.width, adapted_format.width);
311 EXPECT_EQ(request_format.height, adapted_format.height);
312}
313
314// Adapt the pixel resolution to 0. Expect frame drop.
315TEST_F(VideoAdapterTest, AdaptFrameResolutionDrop) {
316 adapter_->SetOutputNumPixels(0);
317 EXPECT_TRUE(
318 adapter_->AdaptFrameResolution(capture_format_.width,
319 capture_format_.height).IsSize0x0());
320}
321
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000322// Adapt the frame resolution to be a quarter of the capture resolution at the
323// beginning. Expect resolution change.
324TEST_F(VideoAdapterTest, AdaptResolution) {
325 VideoFormat request_format = capture_format_;
326 request_format.width /= 2;
327 request_format.height /= 2;
328 adapter_->SetOutputFormat(request_format);
329 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
330 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000331 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000332
333 // Verify no frame drop and resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000334 VideoCapturerListener::Stats stats = listener_->GetStats();
335 EXPECT_EQ(0, stats.dropped_frames);
336 VerifyAdaptedResolution(stats, request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000337}
338
339// Adapt the frame resolution to half width. Expect resolution change.
340TEST_F(VideoAdapterTest, AdaptResolutionNarrow) {
341 VideoFormat request_format = capture_format_;
342 request_format.width /= 2;
343 adapter_->set_scale_third(true);
344 adapter_->SetOutputFormat(request_format);
345 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
346 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000347 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000348
349 // Verify resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000350 VerifyAdaptedResolution(listener_->GetStats(), 213, 160);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000351}
352
353// Adapt the frame resolution to half height. Expect resolution change.
354TEST_F(VideoAdapterTest, AdaptResolutionWide) {
355 VideoFormat request_format = capture_format_;
356 request_format.height /= 2;
357 adapter_->set_scale_third(true);
358 adapter_->SetOutputFormat(request_format);
359 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
360 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000361 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000362
363 // Verify resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000364 VerifyAdaptedResolution(listener_->GetStats(), 213, 160);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000365}
366
367// Adapt the frame resolution to be a quarter of the capture resolution after
368// capturing no less than 10 frames. Expect no resolution change before
369// adaptation and resolution change after adaptation.
370TEST_F(VideoAdapterTest, AdaptResolutionOnTheFly) {
371 VideoFormat request_format = capture_format_;
372 adapter_->SetOutputFormat(request_format);
373 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
374 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000375 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000376
377 // Verify no resolution change before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000378 VerifyAdaptedResolution(
379 listener_->GetStats(), request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000380
381 // Adapt the frame resolution.
382 request_format.width /= 2;
383 request_format.height /= 2;
384 adapter_->SetOutputFormat(request_format);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000385 int captured_frames = listener_->GetStats().captured_frames;
386 EXPECT_TRUE_WAIT(
387 !capturer_->IsRunning() ||
388 listener_->GetStats().captured_frames >= captured_frames + 10,
389 kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000390
391 // Verify resolution change after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000392 VerifyAdaptedResolution(
393 listener_->GetStats(), request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000394}
395
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000396// Drop all frames.
397TEST_F(VideoAdapterTest, DropAllFrames) {
398 VideoFormat format; // with resolution 0x0.
399 adapter_->SetOutputFormat(format);
400 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
401 EXPECT_TRUE_WAIT(!capturer_->IsRunning() ||
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000402 listener_->GetStats().captured_frames >= 10, kWaitTimeout);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000403
404 // Verify all frames are dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000405 VideoCapturerListener::Stats stats = listener_->GetStats();
406 EXPECT_GE(stats.captured_frames, 10);
407 EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000408}
409
410TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithoutCpuAdaptation) {
411 CoordinatedVideoAdapter adapter;
412 adapter.set_cpu_adaptation(false);
413
414 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
415 adapter.SetInputFormat(format);
416 adapter.set_scale_third(true);
417 EXPECT_EQ(format, adapter.input_format());
418 EXPECT_TRUE(adapter.output_format().IsSize0x0());
419
420 // Server format request 640x400.
421 format.height = 400;
422 adapter.OnOutputFormatRequest(format);
423 EXPECT_EQ(640, adapter.output_format().width);
424 EXPECT_EQ(400, adapter.output_format().height);
425
426 // Server format request 1280x720, higher than input. Adapt nothing.
427 format.width = 1280;
428 format.height = 720;
429 adapter.OnOutputFormatRequest(format);
430 EXPECT_EQ(640, adapter.output_format().width);
431 EXPECT_EQ(400, adapter.output_format().height);
432
433 // Cpu load is high, but cpu adaptation is disabled. Adapt nothing.
434 adapter.OnCpuLoadUpdated(1, 1, 0.99f, 0.99f);
435 EXPECT_EQ(640, adapter.output_format().width);
436 EXPECT_EQ(400, adapter.output_format().height);
437
438 // Encoder resolution request: downgrade with different size. Adapt nothing.
439 adapter.OnEncoderResolutionRequest(320, 200,
440 CoordinatedVideoAdapter::DOWNGRADE);
441 EXPECT_EQ(640, adapter.output_format().width);
442 EXPECT_EQ(400, adapter.output_format().height);
443
444 // Encoder resolution request: downgrade.
445 adapter.OnEncoderResolutionRequest(640, 400,
446 CoordinatedVideoAdapter::DOWNGRADE);
447 EXPECT_EQ(480, adapter.output_format().width);
448 EXPECT_EQ(300, adapter.output_format().height);
449
450 // Encoder resolution request: downgrade. But GD off. Adapt nothing.
451 adapter.set_gd_adaptation(false);
452 adapter.OnEncoderResolutionRequest(480, 300,
453 CoordinatedVideoAdapter::DOWNGRADE);
454 EXPECT_EQ(480, adapter.output_format().width);
455 EXPECT_EQ(300, adapter.output_format().height);
456 adapter.set_gd_adaptation(true);
457
458 // Encoder resolution request: downgrade.
459 adapter.OnEncoderResolutionRequest(480, 300,
460 CoordinatedVideoAdapter::DOWNGRADE);
461 EXPECT_EQ(320, adapter.output_format().width);
462 EXPECT_EQ(200, adapter.output_format().height);
463
464 // Encoder resolution request: keep. Adapt nothing.
465 adapter.OnEncoderResolutionRequest(320, 200,
466 CoordinatedVideoAdapter::KEEP);
467 EXPECT_EQ(320, adapter.output_format().width);
468 EXPECT_EQ(200, adapter.output_format().height);
469
470 // Encoder resolution request: upgrade.
471 adapter.OnEncoderResolutionRequest(320, 200,
472 CoordinatedVideoAdapter::UPGRADE);
473 EXPECT_EQ(480, adapter.output_format().width);
474 EXPECT_EQ(300, adapter.output_format().height);
475
476 // Server format request 0x0.
477 format.width = 0;
478 format.height = 0;
479 adapter.OnOutputFormatRequest(format);
480 EXPECT_TRUE(adapter.output_format().IsSize0x0());
481
482 // Server format request 320x200.
483 format.width = 320;
484 format.height = 200;
485 adapter.OnOutputFormatRequest(format);
486 EXPECT_EQ(320, adapter.output_format().width);
487 EXPECT_EQ(200, adapter.output_format().height);
488
489 // Server format request 160x100. But view disabled. Adapt nothing.
490 adapter.set_view_adaptation(false);
491 format.width = 160;
492 format.height = 100;
493 adapter.OnOutputFormatRequest(format);
494 EXPECT_EQ(320, adapter.output_format().width);
495 EXPECT_EQ(200, adapter.output_format().height);
496 adapter.set_view_adaptation(true);
497
498 // Enable View Switch. Expect adapt down.
499 adapter.set_view_switch(true);
500 format.width = 160;
501 format.height = 100;
502 adapter.OnOutputFormatRequest(format);
503 EXPECT_EQ(160, adapter.output_format().width);
504 EXPECT_EQ(100, adapter.output_format().height);
505
506 // Encoder resolution request: upgrade. Adapt nothing.
507 adapter.OnEncoderResolutionRequest(160, 100,
508 CoordinatedVideoAdapter::UPGRADE);
509 EXPECT_EQ(160, adapter.output_format().width);
510 EXPECT_EQ(100, adapter.output_format().height);
511
512 // Request View of 2 / 3. Expect adapt down.
513 adapter.set_view_switch(true);
514 format.width = (640 * 2 + 1) / 3;
515 format.height = (400 * 2 + 1) / 3;
516 adapter.OnOutputFormatRequest(format);
517 EXPECT_EQ((640 * 2 + 1) / 3, adapter.output_format().width);
518 EXPECT_EQ((400 * 2 + 1) / 3, adapter.output_format().height);
519
520
521 // Request View of 3 / 8. Expect adapt down.
522 adapter.set_view_switch(true);
523 format.width = 640 * 3 / 8;
524 format.height = 400 * 3 / 8;
525 adapter.OnOutputFormatRequest(format);
526 EXPECT_EQ(640 * 3 / 8, adapter.output_format().width);
527 EXPECT_EQ(400 * 3 / 8, adapter.output_format().height);
528
529 // View Switch back up. Expect adapt.
530 format.width = 320;
531 format.height = 200;
532 adapter.OnOutputFormatRequest(format);
533 EXPECT_EQ(320, adapter.output_format().width);
534 EXPECT_EQ(200, adapter.output_format().height);
535
536 adapter.set_view_switch(false);
537
538 // Encoder resolution request: upgrade. Constrained by server request.
539 adapter.OnEncoderResolutionRequest(320, 200,
540 CoordinatedVideoAdapter::UPGRADE);
541 EXPECT_EQ(320, adapter.output_format().width);
542 EXPECT_EQ(200, adapter.output_format().height);
543
544 // Server format request 480x300.
545 format.width = 480;
546 format.height = 300;
547 adapter.OnOutputFormatRequest(format);
548 EXPECT_EQ(480, adapter.output_format().width);
549 EXPECT_EQ(300, adapter.output_format().height);
550}
551
552TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithCpuAdaptation) {
553 CoordinatedVideoAdapter adapter;
554 adapter.set_cpu_adaptation(true);
555 EXPECT_FALSE(adapter.cpu_smoothing());
556 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
557 adapter.SetInputFormat(format);
558
559 // Server format request 640x400.
560 format.height = 400;
561 adapter.OnOutputFormatRequest(format);
562 EXPECT_EQ(640, adapter.output_format().width);
563 EXPECT_EQ(400, 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(480, adapter.output_format().width);
568 EXPECT_EQ(300, adapter.output_format().height);
569
570 // CPU high, but cpu adaptation disabled. Adapt nothing.
571 adapter.set_cpu_adaptation(false);
572 adapter.OnCpuLoadUpdated(1, 1, 0.55f, 0.98f);
573 EXPECT_EQ(480, adapter.output_format().width);
574 EXPECT_EQ(300, adapter.output_format().height);
575 adapter.set_cpu_adaptation(true);
576
577 // System load is high, but time has not elaspsed. Adapt nothing.
578 adapter.set_cpu_load_min_samples(2);
579 adapter.OnCpuLoadUpdated(1, 1, 0.55f, 0.98f);
580 EXPECT_EQ(480, adapter.output_format().width);
581 EXPECT_EQ(300, adapter.output_format().height);
582
583 // Process load is medium, but system load is high. Downgrade.
584 UpdateCpuLoad(&adapter, 1, 1, 0.55f, 0.98f);
585 EXPECT_EQ(320, adapter.output_format().width);
586 EXPECT_EQ(200, adapter.output_format().height);
587
588 // Test reason for adapting is CPU.
589 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
590 adapter.adapt_reason());
591
592 // Server format request 320x200. Same as CPU. Do nothing.
593 format.width = 320;
594 format.height = 200;
595 adapter.OnOutputFormatRequest(format);
596 EXPECT_EQ(320, adapter.output_format().width);
597 EXPECT_EQ(200, adapter.output_format().height);
598
599 // Test reason for adapting is CPU and VIEW.
600 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
601 CoordinatedVideoAdapter::ADAPTREASON_VIEW,
602 adapter.adapt_reason());
603
604 // Process load and system load are normal. Adapt nothing.
605 UpdateCpuLoad(&adapter, 1, 1, 0.5f, 0.8f);
606 EXPECT_EQ(320, adapter.output_format().width);
607 EXPECT_EQ(200, adapter.output_format().height);
608
609 // Process load and system load are low, but view is still low. Adapt nothing.
610 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
611 EXPECT_EQ(320, adapter.output_format().width);
612 EXPECT_EQ(200, adapter.output_format().height);
613
614 // Test reason for adapting is VIEW.
615 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
616 adapter.adapt_reason());
617
618 // Server format request 640x400. Cpu is still low. Upgrade.
619 format.width = 640;
620 format.height = 400;
621 adapter.OnOutputFormatRequest(format);
622 EXPECT_EQ(480, adapter.output_format().width);
623 EXPECT_EQ(300, adapter.output_format().height);
624
625 // Test reason for adapting is CPU.
626 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
627 adapter.adapt_reason());
628
629 // Encoder resolution request: downgrade.
630 adapter.OnEncoderResolutionRequest(480, 300,
631 CoordinatedVideoAdapter::DOWNGRADE);
632 EXPECT_EQ(320, adapter.output_format().width);
633 EXPECT_EQ(200, adapter.output_format().height);
634
635 // Test reason for adapting is BANDWIDTH.
636 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
637 adapter.adapt_reason());
638
639 // Process load and system load are low. Constrained by GD. Adapt nothing
640 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
641 EXPECT_EQ(320, adapter.output_format().width);
642 EXPECT_EQ(200, adapter.output_format().height);
643
644 // Encoder resolution request: upgrade.
645 adapter.OnEncoderResolutionRequest(320, 200,
646 CoordinatedVideoAdapter::UPGRADE);
647 EXPECT_EQ(480, adapter.output_format().width);
648 EXPECT_EQ(300, adapter.output_format().height);
649
650 // Encoder resolution request: upgrade. Constrained by CPU.
651 adapter.OnEncoderResolutionRequest(480, 300,
652 CoordinatedVideoAdapter::UPGRADE);
653 EXPECT_EQ(480, adapter.output_format().width);
654 EXPECT_EQ(300, adapter.output_format().height);
655
656 // Server format request 640x400. Constrained by CPU.
657 format.width = 640;
658 format.height = 400;
659 adapter.OnOutputFormatRequest(format);
660 EXPECT_EQ(480, adapter.output_format().width);
661 EXPECT_EQ(300, adapter.output_format().height);
662}
663
664TEST(CoordinatedVideoAdapterTest, TestCoordinatedWithCpuRequest) {
665 CoordinatedVideoAdapter adapter;
666 adapter.set_cpu_adaptation(true);
667 EXPECT_FALSE(adapter.cpu_smoothing());
668 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
669 adapter.SetInputFormat(format);
670
671 // Server format request 640x400.
672 format.height = 400;
673 adapter.OnOutputFormatRequest(format);
674 EXPECT_EQ(640, adapter.output_format().width);
675 EXPECT_EQ(400, adapter.output_format().height);
676
677 // CPU resolution request: downgrade. Adapt down.
678 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
679 EXPECT_EQ(480, adapter.output_format().width);
680 EXPECT_EQ(300, adapter.output_format().height);
681
682 // CPU resolution request: keep. Do nothing.
683 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::KEEP);
684 EXPECT_EQ(480, adapter.output_format().width);
685 EXPECT_EQ(300, adapter.output_format().height);
686
687 // CPU resolution request: downgrade, but cpu adaptation disabled.
688 // Adapt nothing.
689 adapter.set_cpu_adaptation(false);
690 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
691 EXPECT_EQ(480, adapter.output_format().width);
692 EXPECT_EQ(300, adapter.output_format().height);
693
694 // CPU resolution request: downgrade. Adapt down.
695 adapter.set_cpu_adaptation(true);
696 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
697 EXPECT_EQ(320, adapter.output_format().width);
698 EXPECT_EQ(200, adapter.output_format().height);
699
700 // Test reason for adapting is CPU.
701 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
702 adapter.adapt_reason());
703
704 // CPU resolution request: downgrade, but already at minimum. Do nothing.
705 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::DOWNGRADE);
706 EXPECT_EQ(320, adapter.output_format().width);
707 EXPECT_EQ(200, adapter.output_format().height);
708
709 // Server format request 320x200. Same as CPU. Do nothing.
710 format.width = 320;
711 format.height = 200;
712 adapter.OnOutputFormatRequest(format);
713 EXPECT_EQ(320, adapter.output_format().width);
714 EXPECT_EQ(200, adapter.output_format().height);
715
716 // Test reason for adapting is CPU and VIEW.
717 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU +
718 CoordinatedVideoAdapter::ADAPTREASON_VIEW,
719 adapter.adapt_reason());
720
721 // CPU resolution request: upgrade, but view request still low. Do nothing.
722 adapter.OnCpuResolutionRequest(CoordinatedVideoAdapter::UPGRADE);
723 EXPECT_EQ(320, adapter.output_format().width);
724 EXPECT_EQ(200, adapter.output_format().height);
725
726 // Test reason for adapting is VIEW.
727 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
728 adapter.adapt_reason());
729
730 // Server format request 640x400. Cpu is still low. Upgrade.
731 format.width = 640;
732 format.height = 400;
733 adapter.OnOutputFormatRequest(format);
734 EXPECT_EQ(480, adapter.output_format().width);
735 EXPECT_EQ(300, adapter.output_format().height);
736
737 // Test reason for adapting is CPU.
738 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU,
739 adapter.adapt_reason());
740
741 // Encoder resolution request: downgrade.
742 adapter.OnEncoderResolutionRequest(480, 300,
743 CoordinatedVideoAdapter::DOWNGRADE);
744 EXPECT_EQ(320, adapter.output_format().width);
745 EXPECT_EQ(200, adapter.output_format().height);
746
747 // Test reason for adapting is BANDWIDTH.
748 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
749 adapter.adapt_reason());
750
751 // Process load and system load are low. Constrained by GD. Adapt nothing
752 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
753 EXPECT_EQ(320, adapter.output_format().width);
754 EXPECT_EQ(200, adapter.output_format().height);
755
756 // Encoder resolution request: upgrade.
757 adapter.OnEncoderResolutionRequest(320, 200,
758 CoordinatedVideoAdapter::UPGRADE);
759 EXPECT_EQ(480, adapter.output_format().width);
760 EXPECT_EQ(300, adapter.output_format().height);
761
762 // Encoder resolution request: upgrade. Constrained by CPU.
763 adapter.OnEncoderResolutionRequest(480, 300,
764 CoordinatedVideoAdapter::UPGRADE);
765 EXPECT_EQ(480, adapter.output_format().width);
766 EXPECT_EQ(300, adapter.output_format().height);
767
768 // Server format request 640x400. Constrained by CPU.
769 format.width = 640;
770 format.height = 400;
771 adapter.OnOutputFormatRequest(format);
772 EXPECT_EQ(480, adapter.output_format().width);
773 EXPECT_EQ(300, adapter.output_format().height);
774}
775
776TEST(CoordinatedVideoAdapterTest, TestViewRequestPlusCameraSwitch) {
777 CoordinatedVideoAdapter adapter;
778 adapter.set_view_switch(true);
779
780 // Start at HD.
781 VideoFormat format(1280, 720, VideoFormat::FpsToInterval(30), FOURCC_I420);
782 adapter.SetInputFormat(format);
783 EXPECT_EQ(format, adapter.input_format());
784 EXPECT_TRUE(adapter.output_format().IsSize0x0());
785
786 // View request for VGA.
787 format.width = 640;
788 format.height = 360;
789 adapter.OnOutputFormatRequest(format);
790 EXPECT_EQ(640, adapter.output_format().width);
791 EXPECT_EQ(360, adapter.output_format().height);
792 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW, adapter.adapt_reason());
793
794 // Now, the camera reopens at VGA.
795 // Both the frame and the output format should be 640x360.
Magnus Jedvertac27e202015-03-24 15:18:39 +0100796 const VideoFormat out_format = adapter.AdaptFrameResolution(640, 360);
797 EXPECT_EQ(640, out_format.width);
798 EXPECT_EQ(360, out_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000799 // At this point, the view is no longer adapted, since the input has resized
800 // small enough to fit the last view request.
801 EXPECT_EQ(0, adapter.adapt_reason());
802
803 // And another view request comes in for 640x360, which should have no
804 // real impact.
805 adapter.OnOutputFormatRequest(format);
806 EXPECT_EQ(640, adapter.output_format().width);
807 EXPECT_EQ(360, adapter.output_format().height);
808 EXPECT_EQ(0, adapter.adapt_reason());
809}
810
811TEST(CoordinatedVideoAdapterTest, TestVGAWidth) {
812 CoordinatedVideoAdapter adapter;
813 adapter.set_view_switch(true);
814
815 // Start at 640x480, for cameras that don't support 640x360.
816 VideoFormat format(640, 480, VideoFormat::FpsToInterval(30), FOURCC_I420);
817 adapter.SetInputFormat(format);
818 EXPECT_EQ(format, adapter.input_format());
819 EXPECT_TRUE(adapter.output_format().IsSize0x0());
820
821 // Output format is 640x360, though.
822 format.width = 640;
823 format.height = 360;
824 adapter.SetOutputFormat(format);
825
826 // And also a view request comes for 640x360.
827 adapter.OnOutputFormatRequest(format);
828 // At this point, we have to adapt down to something lower.
829 EXPECT_EQ(480, adapter.output_format().width);
830 EXPECT_EQ(360, adapter.output_format().height);
831
832 // But if frames come in at 640x360, we shouldn't adapt them down.
833 // Fake a 640x360 frame.
Magnus Jedvertac27e202015-03-24 15:18:39 +0100834 VideoFormat out_format = adapter.AdaptFrameResolution(640, 360);
835 EXPECT_EQ(640, out_format.width);
836 EXPECT_EQ(360, out_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000837
838 // Similarly, no-op adapt requests for other reasons shouldn't change
839 // adaptation state (before a previous bug, the previous EXPECTs would
840 // fail and the following would succeed, as the no-op CPU request would
841 // fix the adaptation state).
842 adapter.set_cpu_adaptation(true);
843 UpdateCpuLoad(&adapter, 1, 1, 0.7f, 0.7f);
Magnus Jedvertac27e202015-03-24 15:18:39 +0100844 out_format = adapter.AdaptFrameResolution(640, 360);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000845
Magnus Jedvertac27e202015-03-24 15:18:39 +0100846 EXPECT_EQ(640, out_format.width);
847 EXPECT_EQ(360, out_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000848}
849
850// When adapting resolution for CPU or GD, the quantity of pixels that the
851// request is based on is reduced to half or double, and then an actual
852// resolution is snapped to, rounding to the closest actual resolution.
853// This works well for some tolerance to 3/4, odd widths and aspect ratios
854// that dont exactly match, but is not best behavior for ViewRequests which
855// need to be be strictly respected to avoid going over the resolution budget
856// given to the codec - 854x480 total pixels.
857// ViewRequest must find a lower resolution.
858TEST(CoordinatedVideoAdapterTest, TestCoordinatedViewRequestDown) {
859 CoordinatedVideoAdapter adapter;
860 adapter.set_cpu_adaptation(false);
861
862 VideoFormat format(960, 540, VideoFormat::FpsToInterval(30), FOURCC_I420);
863 adapter.SetInputFormat(format);
864 adapter.set_scale_third(true);
865 EXPECT_EQ(format, adapter.input_format());
866 EXPECT_TRUE(adapter.output_format().IsSize0x0());
867
868 // Server format request 640x400. Expect HVGA.
869 format.width = 640;
870 format.height = 400;
871 adapter.OnOutputFormatRequest(format);
872 EXPECT_EQ(640, adapter.output_format().width);
873 EXPECT_EQ(360, adapter.output_format().height);
874
875 // Test reason for adapting is VIEW.
876 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW, adapter.adapt_reason());
877}
878
879// Test that we downgrade video for cpu up to two times.
880TEST(CoordinatedVideoAdapterTest, TestCpuDowngradeTimes) {
881 CoordinatedVideoAdapter adapter;
882 adapter.set_cpu_adaptation(true);
883 EXPECT_FALSE(adapter.cpu_smoothing());
884 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
885 adapter.SetInputFormat(format);
886
887 // Server format request 640x400.
888 format.height = 400;
889 adapter.OnOutputFormatRequest(format);
890 EXPECT_EQ(640, adapter.output_format().width);
891 EXPECT_EQ(400, adapter.output_format().height);
892
893 // Process load and system load are low. Do not change the cpu desired format
894 // and do not adapt.
895 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
896 EXPECT_EQ(640, adapter.output_format().width);
897 EXPECT_EQ(400, adapter.output_format().height);
898
899 // System load is high. Downgrade.
900 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
901 EXPECT_EQ(480, adapter.output_format().width);
902 EXPECT_EQ(300, adapter.output_format().height);
903
904 // System load is high. Downgrade again.
905 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
906 EXPECT_EQ(320, adapter.output_format().width);
907 EXPECT_EQ(200, adapter.output_format().height);
908
909 // System load is still high. Do not downgrade any more.
910 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
911 EXPECT_EQ(320, adapter.output_format().width);
912 EXPECT_EQ(200, adapter.output_format().height);
913
914 // Process load and system load are low. Upgrade.
915 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
916 EXPECT_EQ(480, adapter.output_format().width);
917 EXPECT_EQ(300, adapter.output_format().height);
918
919 // System load is high. Downgrade.
920 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
921 EXPECT_EQ(320, adapter.output_format().width);
922 EXPECT_EQ(200, adapter.output_format().height);
923
924 // System load is still high. Do not downgrade any more.
925 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
926 EXPECT_EQ(320, adapter.output_format().width);
927 EXPECT_EQ(200, adapter.output_format().height);
928}
929
930// Test that we respect CPU adapter threshold values.
931TEST(CoordinatedVideoAdapterTest, TestAdapterCpuThreshold) {
932 CoordinatedVideoAdapter adapter;
933 adapter.set_cpu_adaptation(true);
934 EXPECT_FALSE(adapter.cpu_smoothing());
935 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
936 adapter.SetInputFormat(format);
937
938 // Server format request 640x400.
939 format.height = 400;
940 adapter.OnOutputFormatRequest(format);
941 EXPECT_EQ(640, adapter.output_format().width);
942 EXPECT_EQ(400, adapter.output_format().height);
943
944 // Process load and system load are low. Do not change the cpu desired format
945 // and do not adapt.
946 adapter.OnCpuLoadUpdated(1, 1, 0.2f, 0.3f);
947 EXPECT_EQ(640, adapter.output_format().width);
948 EXPECT_EQ(400, adapter.output_format().height);
949
950 // System load is high. Downgrade.
951 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
952 EXPECT_EQ(480, adapter.output_format().width);
953 EXPECT_EQ(300, adapter.output_format().height);
954
955 // Test reason for adapting is CPU.
956 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_CPU, adapter.adapt_reason());
957
958 // System load is high. Normally downgrade but threshold is high. Do nothing.
959 adapter.set_high_system_threshold(0.98f); // Set threshold high.
960 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
961 EXPECT_EQ(480, adapter.output_format().width);
962 EXPECT_EQ(300, adapter.output_format().height);
963
964 // System load is medium. Normally do nothing, threshold is low. Adapt down.
965 adapter.set_high_system_threshold(0.75f); // Set threshold low.
966 UpdateCpuLoad(&adapter, 1, 1, 0.8f, 0.8f);
967 EXPECT_EQ(320, adapter.output_format().width);
968 EXPECT_EQ(200, adapter.output_format().height);
969}
970
971
972// Test that for an upgrade cpu request, we actually upgrade the desired format;
973// for a downgrade request, we downgrade from the output format.
974TEST(CoordinatedVideoAdapterTest, TestRealCpuUpgrade) {
975 CoordinatedVideoAdapter adapter;
976 adapter.set_cpu_adaptation(true);
977 adapter.set_cpu_smoothing(true);
978 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
979 adapter.SetInputFormat(format);
980
981 // Server format request 640x400.
982 format.width = 640;
983 format.height = 400;
984 adapter.OnOutputFormatRequest(format);
985 EXPECT_EQ(640, adapter.output_format().width);
986 EXPECT_EQ(400, adapter.output_format().height);
987
988 // Process load and system load are low. Do not change the cpu desired format
989 // and do not adapt.
990 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
991 EXPECT_EQ(640, adapter.output_format().width);
992 EXPECT_EQ(400, adapter.output_format().height);
993
994 // Server format request 320x200.
995 format.width = 320;
996 format.height = 200;
997 adapter.OnOutputFormatRequest(format);
998 EXPECT_EQ(320, adapter.output_format().width);
999 EXPECT_EQ(200, adapter.output_format().height);
1000
1001 // Process load and system load are low. Do not change the cpu desired format
1002 // and do not adapt.
1003 UpdateCpuLoad(&adapter, 1, 1, 0.2f, 0.3f);
1004 EXPECT_EQ(320, adapter.output_format().width);
1005 EXPECT_EQ(200, adapter.output_format().height);
1006
1007 // Server format request 640x400. Set to 640x400 immediately.
1008 format.width = 640;
1009 format.height = 400;
1010 adapter.OnOutputFormatRequest(format);
1011 EXPECT_EQ(640, adapter.output_format().width);
1012 EXPECT_EQ(400, adapter.output_format().height);
1013
1014 // Server format request 320x200.
1015 format.width = 320;
1016 format.height = 200;
1017 adapter.OnOutputFormatRequest(format);
1018 EXPECT_EQ(320, adapter.output_format().width);
1019 EXPECT_EQ(200, adapter.output_format().height);
1020
1021 // Process load is high, but system is not. Do not change the cpu desired
1022 // format and do not adapt.
1023 for (size_t i = 0; i < 10; ++i) {
1024 UpdateCpuLoad(&adapter, 1, 1, 0.75f, 0.8f);
1025 }
1026 EXPECT_EQ(320, adapter.output_format().width);
1027 EXPECT_EQ(200, adapter.output_format().height);
1028}
1029
1030// Test that for an upgrade encoder request, we actually upgrade the desired
1031// format; for a downgrade request, we downgrade from the output format.
1032TEST(CoordinatedVideoAdapterTest, TestRealEncoderUpgrade) {
1033 CoordinatedVideoAdapter adapter;
1034 adapter.set_cpu_adaptation(true);
1035 adapter.set_cpu_smoothing(true);
1036 VideoFormat format(640, 400, VideoFormat::FpsToInterval(30), FOURCC_I420);
1037 adapter.SetInputFormat(format);
1038
1039 // Server format request 640x400.
1040 format.width = 640;
1041 format.height = 400;
1042 adapter.OnOutputFormatRequest(format);
1043 EXPECT_EQ(640, adapter.output_format().width);
1044 EXPECT_EQ(400, adapter.output_format().height);
1045
1046 // Encoder resolution request. Do not change the encoder desired format and
1047 // do not adapt.
1048 adapter.OnEncoderResolutionRequest(640, 400,
1049 CoordinatedVideoAdapter::UPGRADE);
1050 EXPECT_EQ(640, adapter.output_format().width);
1051 EXPECT_EQ(400, adapter.output_format().height);
1052
1053 // Server format request 320x200.
1054 format.width = 320;
1055 format.height = 200;
1056 adapter.OnOutputFormatRequest(format);
1057 EXPECT_EQ(320, adapter.output_format().width);
1058 EXPECT_EQ(200, adapter.output_format().height);
1059
1060 // Encoder resolution request. Do not change the encoder desired format and
1061 // do not adapt.
1062 adapter.OnEncoderResolutionRequest(320, 200,
1063 CoordinatedVideoAdapter::UPGRADE);
1064 EXPECT_EQ(320, adapter.output_format().width);
1065 EXPECT_EQ(200, adapter.output_format().height);
1066
1067 // Server format request 640x400. Set to 640x400 immediately.
1068 format.width = 640;
1069 format.height = 400;
1070 adapter.OnOutputFormatRequest(format);
1071 EXPECT_EQ(480, adapter.output_format().width);
1072 EXPECT_EQ(300, adapter.output_format().height);
1073
1074 // Test reason for adapting is BANDWIDTH.
1075 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH,
1076 adapter.adapt_reason());
1077
1078 // Server format request 320x200.
1079 format.width = 320;
1080 format.height = 200;
1081 adapter.OnOutputFormatRequest(format);
1082 EXPECT_EQ(320, adapter.output_format().width);
1083 EXPECT_EQ(200, adapter.output_format().height);
1084
1085 // Encoder resolution request. Downgrade from 320x200.
1086 adapter.OnEncoderResolutionRequest(320, 200,
1087 CoordinatedVideoAdapter::DOWNGRADE);
1088 EXPECT_EQ(240, adapter.output_format().width);
1089 EXPECT_EQ(150, adapter.output_format().height);
1090}
1091
1092TEST(CoordinatedVideoAdapterTest, TestNormalizeOutputFormat) {
1093 CoordinatedVideoAdapter adapter;
1094 // The input format is 640x360 and the output is limited to 16:9.
1095 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1096 adapter.SetInputFormat(format);
1097
1098 format.width = 320;
1099 format.height = 180;
1100 format.interval = VideoFormat::FpsToInterval(15);
1101 adapter.OnOutputFormatRequest(format);
1102 EXPECT_EQ(320, adapter.output_format().width);
1103 EXPECT_EQ(180, adapter.output_format().height);
1104 EXPECT_EQ(VideoFormat::FpsToInterval(15), adapter.output_format().interval);
1105
1106 format.width = 320;
1107 format.height = 200;
1108 format.interval = VideoFormat::FpsToInterval(40);
1109 adapter.OnOutputFormatRequest(format);
1110 EXPECT_EQ(320, adapter.output_format().width);
1111 EXPECT_EQ(180, adapter.output_format().height);
1112 EXPECT_EQ(VideoFormat::FpsToInterval(30), adapter.output_format().interval);
1113
1114 // Test reason for adapting is VIEW. Should work even with normalization.
1115 EXPECT_EQ(CoordinatedVideoAdapter::ADAPTREASON_VIEW,
1116 adapter.adapt_reason());
1117
1118 format.width = 320;
1119 format.height = 240;
1120 adapter.OnOutputFormatRequest(format);
1121 EXPECT_EQ(320, adapter.output_format().width);
1122 EXPECT_EQ(180, adapter.output_format().height);
1123
1124 // The input format is 640x480 and the output will be 4:3.
1125 format.width = 640;
1126 format.height = 480;
1127 adapter.SetInputFormat(format);
1128 EXPECT_EQ(320, adapter.output_format().width);
1129 EXPECT_EQ(240, adapter.output_format().height);
1130
1131 format.width = 320;
1132 format.height = 240;
1133 adapter.OnOutputFormatRequest(format);
1134 EXPECT_EQ(320, adapter.output_format().width);
1135 EXPECT_EQ(240, adapter.output_format().height);
1136
1137 // The input format is initialized after the output. At that time, the output
1138 // height is adjusted.
1139 format.width = 0;
1140 format.height = 0;
1141 adapter.SetInputFormat(format);
1142
1143 format.width = 320;
1144 format.height = 240;
1145 format.interval = VideoFormat::FpsToInterval(30);
1146 adapter.OnOutputFormatRequest(format);
1147 EXPECT_EQ(320, adapter.output_format().width);
1148 EXPECT_EQ(240, adapter.output_format().height);
1149 EXPECT_EQ(VideoFormat::FpsToInterval(30), adapter.output_format().interval);
1150
1151 format.width = 640;
1152 format.height = 480;
1153 format.interval = VideoFormat::FpsToInterval(15);
1154 adapter.SetInputFormat(format);
1155 EXPECT_EQ(320, adapter.output_format().width);
1156 EXPECT_EQ(240, adapter.output_format().height);
1157 EXPECT_EQ(VideoFormat::FpsToInterval(15), adapter.output_format().interval);
1158}
1159
1160// Test that we downgrade video for cpu up to two times.
1161TEST_F(VideoAdapterTest, CpuDowngradeAndSignal) {
1162 CoordinatedVideoAdapter adapter;
1163 CpuAdapterListener cpu_listener;
1164 adapter.SignalCpuAdaptationUnable.connect(
1165 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1166
1167 adapter.set_cpu_adaptation(true);
1168 EXPECT_FALSE(adapter.cpu_smoothing());
1169 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1170 adapter.SetInputFormat(format);
1171 adapter.OnOutputFormatRequest(format);
1172
1173 // System load is high. Downgrade.
1174 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1175
1176 // System load is high. Downgrade again.
1177 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1178
1179 // System load is still high. Do not downgrade any more. Ensure we have not
1180 // signalled until after the cpu warning though.
1181 EXPECT_TRUE(!cpu_listener.received_cpu_signal());
1182 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1183 EXPECT_TRUE_WAIT(cpu_listener.received_cpu_signal(), kWaitTimeout);
1184}
1185
1186// Test that we downgrade video for cpu up to two times.
1187TEST_F(VideoAdapterTest, CpuDowngradeAndDontSignal) {
1188 CoordinatedVideoAdapter adapter;
1189 CpuAdapterListener cpu_listener;
1190 adapter.SignalCpuAdaptationUnable.connect(
1191 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1192
1193 adapter.set_cpu_adaptation(true);
1194 adapter.set_cpu_smoothing(true);
1195 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1196 adapter.SetInputFormat(format);
1197 adapter.OnOutputFormatRequest(format);
1198
1199 // System load is high. Downgrade.
1200 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1201
1202 // System load is high, process is not, Do not downgrade again.
1203 UpdateCpuLoad(&adapter, 1, 1, 0.25f, 0.95f);
1204
1205 // System load is high, process is not, Do not downgrade again and do not
1206 // signal.
1207 adapter.set_cpu_adaptation(false);
1208 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1209 rtc::Thread::Current()->ProcessMessages(kShortWaitTimeout);
1210 EXPECT_TRUE(!cpu_listener.received_cpu_signal());
1211 adapter.set_cpu_adaptation(true);
1212}
1213
1214// Test that we require enough time before we downgrade.
1215TEST_F(VideoAdapterTest, CpuMinTimeRequirement) {
1216 CoordinatedVideoAdapter adapter;
1217 CpuAdapterListener cpu_listener;
1218 adapter.SignalCpuAdaptationUnable.connect(
1219 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1220
1221 adapter.set_cpu_adaptation(true);
1222 adapter.set_cpu_smoothing(true);
1223 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1224 adapter.SetInputFormat(format);
1225 adapter.OnOutputFormatRequest(format);
1226
1227 EXPECT_EQ(3, adapter.cpu_load_min_samples());
1228 adapter.set_cpu_load_min_samples(5);
1229
1230 for (size_t i = 0; i < 4; ++i) {
1231 adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1232 EXPECT_EQ(640, adapter.output_format().width);
1233 EXPECT_EQ(360, adapter.output_format().height);
1234 }
1235 // The computed cpu load should now be around 93.5%, with the coefficient of
1236 // 0.4 and a seed value of 0.5. That should be high enough to adapt, but it
1237 // isn't enough samples, so we shouldn't have adapted on any of the previous
1238 // samples.
1239
1240 // One more sample is enough, though, once enough time has passed.
1241 adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1242 EXPECT_EQ(480, adapter.output_format().width);
1243 EXPECT_EQ(270, adapter.output_format().height);
1244
1245 // Now the cpu is lower, but we still need enough samples to upgrade.
1246 for (size_t i = 0; i < 4; ++i) {
1247 adapter.OnCpuLoadUpdated(1, 1, 0.1f, 0.1f);
1248 EXPECT_EQ(480, adapter.output_format().width);
1249 EXPECT_EQ(270, adapter.output_format().height);
1250 }
1251
1252 // One more sample is enough, once time has elapsed.
1253 adapter.OnCpuLoadUpdated(1, 1, 1.0f, 1.0f);
1254 EXPECT_EQ(640, adapter.output_format().width);
1255 EXPECT_EQ(360, adapter.output_format().height);
1256}
1257
1258TEST_F(VideoAdapterTest, CpuIgnoresSpikes) {
1259 CoordinatedVideoAdapter adapter;
1260 CpuAdapterListener cpu_listener;
1261 adapter.SignalCpuAdaptationUnable.connect(
1262 &cpu_listener, &CpuAdapterListener::OnCpuAdaptationSignalled);
1263
1264 adapter.set_cpu_adaptation(true);
1265 adapter.set_cpu_smoothing(true);
1266 VideoFormat format(640, 360, VideoFormat::FpsToInterval(30), FOURCC_I420);
1267 adapter.SetInputFormat(format);
1268 adapter.OnOutputFormatRequest(format);
1269
1270 // System load is high. Downgrade.
1271 for (size_t i = 0; i < 5; ++i) {
1272 UpdateCpuLoad(&adapter, 1, 1, 0.95f, 0.95f);
1273 }
1274 EXPECT_EQ(480, adapter.output_format().width);
1275 EXPECT_EQ(270, adapter.output_format().height);
1276
1277 // Now we're in a state where we could upgrade or downgrade, so get to a
1278 // steady state of about 75% cpu usage.
1279 for (size_t i = 0; i < 5; ++i) {
1280 UpdateCpuLoad(&adapter, 1, 1, 0.75f, 0.75f);
1281 EXPECT_EQ(480, adapter.output_format().width);
1282 EXPECT_EQ(270, adapter.output_format().height);
1283 }
1284
1285 // Now, the cpu spikes for two samples, but then goes back to
1286 // normal. This shouldn't cause adaptation.
1287 UpdateCpuLoad(&adapter, 1, 1, 0.90f, 0.90f);
1288 UpdateCpuLoad(&adapter, 1, 1, 0.90f, 0.90f);
1289 EXPECT_EQ(480, adapter.output_format().width);
1290 EXPECT_EQ(270, adapter.output_format().height);
1291 // Back to the steady state for awhile.
1292 for (size_t i = 0; i < 5; ++i) {
1293 UpdateCpuLoad(&adapter, 1, 1, 0.75, 0.75);
1294 EXPECT_EQ(480, adapter.output_format().width);
1295 EXPECT_EQ(270, adapter.output_format().height);
1296 }
1297
1298 // Now, system cpu usage is starting to drop down. But it takes a bit before
1299 // it gets all the way there.
1300 for (size_t i = 0; i < 10; ++i) {
1301 UpdateCpuLoad(&adapter, 1, 1, 0.5f, 0.5f);
1302 }
1303 EXPECT_EQ(640, adapter.output_format().width);
1304 EXPECT_EQ(360, adapter.output_format().height);
1305}
1306
1307} // namespace cricket
Magnus Jedvert1ecfd552015-03-30 11:24:46 +02001308#endif // HAVE_WEBRTC_VIDEO