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