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