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