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