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 1308