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