Home | History | Annotate | Download | only in base
      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