Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2008 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 #include <stdio.h>
     29 #include <vector>
     30 
     31 #include "talk/media/base/fakevideocapturer.h"
     32 #include "talk/media/base/fakevideorenderer.h"
     33 #include "talk/media/base/testutils.h"
     34 #include "talk/media/base/videocapturer.h"
     35 #include "webrtc/base/gunit.h"
     36 #include "webrtc/base/logging.h"
     37 #include "webrtc/base/thread.h"
     38 
     39 using cricket::FakeVideoCapturer;
     40 
     41 namespace {
     42 
     43 const int kMsCallbackWait = 500;
     44 // For HD only the height matters.
     45 const int kMinHdHeight = 720;
     46 const uint32_t kTimeout = 5000U;
     47 
     48 }  // namespace
     49 
     50 class VideoCapturerTest
     51     : public sigslot::has_slots<>,
     52       public testing::Test {
     53  public:
     54   VideoCapturerTest()
     55       : capture_state_(cricket::CS_STOPPED),
     56         num_state_changes_(0),
     57         video_frames_received_(0),
     58         expects_rotation_applied_(true) {
     59     capturer_.SignalVideoFrame.connect(this, &VideoCapturerTest::OnVideoFrame);
     60     capturer_.SignalStateChange.connect(this,
     61                                         &VideoCapturerTest::OnStateChange);
     62   }
     63 
     64   void set_expected_compensation(bool compensation) {
     65     expects_rotation_applied_ = compensation;
     66   }
     67 
     68  protected:
     69   void OnVideoFrame(cricket::VideoCapturer*, const cricket::VideoFrame* frame) {
     70     ++video_frames_received_;
     71     if (expects_rotation_applied_) {
     72       EXPECT_EQ(webrtc::kVideoRotation_0, frame->GetRotation());
     73     } else {
     74       EXPECT_EQ(capturer_.GetRotation(), frame->GetRotation());
     75     }
     76     renderer_.RenderFrame(frame);
     77   }
     78   void OnStateChange(cricket::VideoCapturer*,
     79                      cricket::CaptureState capture_state) {
     80     capture_state_ = capture_state;
     81     ++num_state_changes_;
     82   }
     83   cricket::CaptureState capture_state() { return capture_state_; }
     84   int num_state_changes() { return num_state_changes_; }
     85   int video_frames_received() const {
     86     return video_frames_received_;
     87   }
     88 
     89   cricket::FakeVideoCapturer capturer_;
     90   cricket::CaptureState capture_state_;
     91   int num_state_changes_;
     92   int video_frames_received_;
     93   cricket::FakeVideoRenderer renderer_;
     94   bool expects_rotation_applied_;
     95 };
     96 
     97 TEST_F(VideoCapturerTest, CaptureState) {
     98   EXPECT_TRUE(capturer_.enable_video_adapter());
     99   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    100       640,
    101       480,
    102       cricket::VideoFormat::FpsToInterval(30),
    103       cricket::FOURCC_I420)));
    104   EXPECT_TRUE(capturer_.IsRunning());
    105   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    106   EXPECT_EQ(1, num_state_changes());
    107   capturer_.Stop();
    108   EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
    109   EXPECT_EQ(2, num_state_changes());
    110   capturer_.Stop();
    111   rtc::Thread::Current()->ProcessMessages(100);
    112   EXPECT_EQ(2, num_state_changes());
    113 }
    114 
    115 TEST_F(VideoCapturerTest, TestRestart) {
    116   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    117       640,
    118       480,
    119       cricket::VideoFormat::FpsToInterval(30),
    120       cricket::FOURCC_I420)));
    121   EXPECT_TRUE(capturer_.IsRunning());
    122   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    123   EXPECT_EQ(1, num_state_changes());
    124   EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
    125       320,
    126       240,
    127       cricket::VideoFormat::FpsToInterval(30),
    128       cricket::FOURCC_I420)));
    129   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    130   EXPECT_TRUE(capturer_.IsRunning());
    131   EXPECT_GE(1, num_state_changes());
    132   capturer_.Stop();
    133   rtc::Thread::Current()->ProcessMessages(100);
    134   EXPECT_FALSE(capturer_.IsRunning());
    135 }
    136 
    137 TEST_F(VideoCapturerTest, TestStartingWithRestart) {
    138   EXPECT_FALSE(capturer_.IsRunning());
    139   EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
    140       640,
    141       480,
    142       cricket::VideoFormat::FpsToInterval(30),
    143       cricket::FOURCC_I420)));
    144   EXPECT_TRUE(capturer_.IsRunning());
    145   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    146 }
    147 
    148 TEST_F(VideoCapturerTest, TestRestartWithSameFormat) {
    149   cricket::VideoFormat format(640, 480,
    150                               cricket::VideoFormat::FpsToInterval(30),
    151                               cricket::FOURCC_I420);
    152   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format));
    153   EXPECT_TRUE(capturer_.IsRunning());
    154   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    155   EXPECT_EQ(1, num_state_changes());
    156   EXPECT_TRUE(capturer_.Restart(format));
    157   EXPECT_EQ(cricket::CS_RUNNING, capture_state());
    158   EXPECT_TRUE(capturer_.IsRunning());
    159   EXPECT_EQ(1, num_state_changes());
    160 }
    161 
    162 TEST_F(VideoCapturerTest, CameraOffOnMute) {
    163   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    164       640,
    165       480,
    166       cricket::VideoFormat::FpsToInterval(30),
    167       cricket::FOURCC_I420)));
    168   EXPECT_TRUE(capturer_.IsRunning());
    169   EXPECT_EQ(0, video_frames_received());
    170   EXPECT_TRUE(capturer_.CaptureFrame());
    171   EXPECT_EQ(1, video_frames_received());
    172   EXPECT_FALSE(capturer_.IsMuted());
    173 
    174   // Mute the camera and expect black output frame.
    175   capturer_.MuteToBlackThenPause(true);
    176   EXPECT_TRUE(capturer_.IsMuted());
    177   for (int i = 0; i < 31; ++i) {
    178     EXPECT_TRUE(capturer_.CaptureFrame());
    179     EXPECT_TRUE(renderer_.black_frame());
    180   }
    181   EXPECT_EQ(32, video_frames_received());
    182   EXPECT_EQ_WAIT(cricket::CS_PAUSED,
    183                  capturer_.capture_state(), kTimeout);
    184 
    185   // Verify that the camera is off.
    186   EXPECT_FALSE(capturer_.CaptureFrame());
    187   EXPECT_EQ(32, video_frames_received());
    188 
    189   // Unmute the camera and expect non-black output frame.
    190   capturer_.MuteToBlackThenPause(false);
    191   EXPECT_FALSE(capturer_.IsMuted());
    192   EXPECT_EQ_WAIT(cricket::CS_RUNNING,
    193                  capturer_.capture_state(), kTimeout);
    194   EXPECT_TRUE(capturer_.CaptureFrame());
    195   EXPECT_FALSE(renderer_.black_frame());
    196   EXPECT_EQ(33, video_frames_received());
    197 }
    198 
    199 TEST_F(VideoCapturerTest, ScreencastScaledOddWidth) {
    200   capturer_.SetScreencast(true);
    201 
    202   int kWidth = 1281;
    203   int kHeight = 720;
    204 
    205   std::vector<cricket::VideoFormat> formats;
    206   formats.push_back(cricket::VideoFormat(kWidth, kHeight,
    207       cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
    208   capturer_.ResetSupportedFormats(formats);
    209 
    210   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    211       kWidth,
    212       kHeight,
    213       cricket::VideoFormat::FpsToInterval(30),
    214       cricket::FOURCC_ARGB)));
    215   EXPECT_TRUE(capturer_.IsRunning());
    216   EXPECT_EQ(0, renderer_.num_rendered_frames());
    217   renderer_.SetSize(kWidth, kHeight, 0);
    218   EXPECT_TRUE(capturer_.CaptureFrame());
    219   EXPECT_EQ(1, renderer_.num_rendered_frames());
    220 }
    221 
    222 TEST_F(VideoCapturerTest, TestRotationPending) {
    223   int kWidth = 800;
    224   int kHeight = 400;
    225   int frame_count = 0;
    226 
    227   std::vector<cricket::VideoFormat> formats;
    228   formats.push_back(cricket::VideoFormat(kWidth, kHeight,
    229                                          cricket::VideoFormat::FpsToInterval(5),
    230                                          cricket::FOURCC_I420));
    231 
    232   capturer_.ResetSupportedFormats(formats);
    233   // capturer_ should compensate rotation as default.
    234   capturer_.UpdateAspectRatio(400, 200);
    235 
    236   EXPECT_EQ(cricket::CS_RUNNING,
    237             capturer_.Start(cricket::VideoFormat(
    238                 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
    239                 cricket::FOURCC_I420)));
    240   EXPECT_TRUE(capturer_.IsRunning());
    241   EXPECT_EQ(0, renderer_.num_rendered_frames());
    242 
    243   // If the frame's rotation is compensated anywhere in the pipeline based on
    244   // the rotation information, the renderer should be given the right dimension
    245   // such that the frame could be rendered.
    246 
    247   // Swap the dimension for the next 2 frames which are rotated by 90 and 270
    248   // degree.
    249   renderer_.SetSize(kHeight, kWidth, 0);
    250 
    251   capturer_.SetRotation(webrtc::kVideoRotation_90);
    252   EXPECT_TRUE(capturer_.CaptureFrame());
    253   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    254 
    255   capturer_.SetRotation(webrtc::kVideoRotation_270);
    256   EXPECT_TRUE(capturer_.CaptureFrame());
    257   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    258 
    259   // Reset the renderer to have corresponding width and height.
    260   renderer_.SetSize(kWidth, kHeight, 0);
    261 
    262   capturer_.SetRotation(webrtc::kVideoRotation_180);
    263   EXPECT_TRUE(capturer_.CaptureFrame());
    264   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    265 }
    266 
    267 TEST_F(VideoCapturerTest, TestRotationApplied) {
    268   int kWidth = 800;
    269   int kHeight = 400;
    270 
    271   std::vector<cricket::VideoFormat> formats;
    272   formats.push_back(cricket::VideoFormat(kWidth, kHeight,
    273                                          cricket::VideoFormat::FpsToInterval(5),
    274                                          cricket::FOURCC_I420));
    275 
    276   capturer_.ResetSupportedFormats(formats);
    277   // capturer_ should not compensate rotation.
    278   capturer_.SetApplyRotation(false);
    279   capturer_.UpdateAspectRatio(400, 200);
    280   set_expected_compensation(false);
    281 
    282   EXPECT_EQ(cricket::CS_RUNNING,
    283             capturer_.Start(cricket::VideoFormat(
    284                 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
    285                 cricket::FOURCC_I420)));
    286   EXPECT_TRUE(capturer_.IsRunning());
    287   EXPECT_EQ(0, renderer_.num_rendered_frames());
    288 
    289   renderer_.SetSize(kWidth, kHeight, 0);
    290 
    291   // If the frame's rotation is compensated anywhere in the pipeline, the frame
    292   // won't have its original dimension out from capturer. Since the renderer
    293   // here has the same dimension as the capturer, it will skip that frame as the
    294   // resolution won't match anymore.
    295 
    296   int frame_count = 0;
    297   capturer_.SetRotation(webrtc::kVideoRotation_0);
    298   EXPECT_TRUE(capturer_.CaptureFrame());
    299   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    300 
    301   capturer_.SetRotation(webrtc::kVideoRotation_90);
    302   EXPECT_TRUE(capturer_.CaptureFrame());
    303   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    304 
    305   capturer_.SetRotation(webrtc::kVideoRotation_180);
    306   EXPECT_TRUE(capturer_.CaptureFrame());
    307   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    308 
    309   capturer_.SetRotation(webrtc::kVideoRotation_270);
    310   EXPECT_TRUE(capturer_.CaptureFrame());
    311   EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
    312 }
    313 
    314 TEST_F(VideoCapturerTest, ScreencastScaledSuperLarge) {
    315   capturer_.SetScreencast(true);
    316 
    317   const int kMaxWidth = 4096;
    318   const int kMaxHeight = 3072;
    319   int kWidth = kMaxWidth + 4;
    320   int kHeight = kMaxHeight + 4;
    321 
    322   std::vector<cricket::VideoFormat> formats;
    323   formats.push_back(cricket::VideoFormat(kWidth, kHeight,
    324       cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
    325   capturer_.ResetSupportedFormats(formats);
    326 
    327   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    328       kWidth,
    329       kHeight,
    330       cricket::VideoFormat::FpsToInterval(30),
    331       cricket::FOURCC_ARGB)));
    332   EXPECT_TRUE(capturer_.IsRunning());
    333   EXPECT_EQ(0, renderer_.num_rendered_frames());
    334   renderer_.SetSize(2050, 1538, 0);
    335   EXPECT_TRUE(capturer_.CaptureFrame());
    336   EXPECT_EQ(1, renderer_.num_rendered_frames());
    337 }
    338 
    339 TEST_F(VideoCapturerTest, TestFourccMatch) {
    340   cricket::VideoFormat desired(640, 480,
    341                                cricket::VideoFormat::FpsToInterval(30),
    342                                cricket::FOURCC_ANY);
    343   cricket::VideoFormat best;
    344   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    345   EXPECT_EQ(640, best.width);
    346   EXPECT_EQ(480, best.height);
    347   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    348 
    349   desired.fourcc = cricket::FOURCC_MJPG;
    350   EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
    351 
    352   desired.fourcc = cricket::FOURCC_I420;
    353   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    354 }
    355 
    356 TEST_F(VideoCapturerTest, TestResolutionMatch) {
    357   cricket::VideoFormat desired(1920, 1080,
    358                                cricket::VideoFormat::FpsToInterval(30),
    359                                cricket::FOURCC_ANY);
    360   cricket::VideoFormat best;
    361   // Ask for 1920x1080. Get HD 1280x720 which is the highest.
    362   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    363   EXPECT_EQ(1280, best.width);
    364   EXPECT_EQ(720, best.height);
    365   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    366 
    367   desired.width = 360;
    368   desired.height = 250;
    369   // Ask for a little higher than QVGA. Get QVGA.
    370   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    371   EXPECT_EQ(320, best.width);
    372   EXPECT_EQ(240, best.height);
    373   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    374 
    375   desired.width = 480;
    376   desired.height = 270;
    377   // Ask for HVGA. Get VGA.
    378   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    379   EXPECT_EQ(640, best.width);
    380   EXPECT_EQ(480, best.height);
    381   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    382 
    383   desired.width = 320;
    384   desired.height = 240;
    385   // Ask for QVGA. Get QVGA.
    386   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    387   EXPECT_EQ(320, best.width);
    388   EXPECT_EQ(240, best.height);
    389   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    390 
    391   desired.width = 80;
    392   desired.height = 60;
    393   // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
    394   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    395   EXPECT_EQ(160, best.width);
    396   EXPECT_EQ(120, best.height);
    397   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    398 }
    399 
    400 TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
    401   // Add some HD formats typical of a mediocre HD webcam.
    402   std::vector<cricket::VideoFormat> formats;
    403   formats.push_back(cricket::VideoFormat(320, 240,
    404       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    405   formats.push_back(cricket::VideoFormat(640, 480,
    406       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    407   formats.push_back(cricket::VideoFormat(960, 544,
    408       cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
    409   formats.push_back(cricket::VideoFormat(1280, 720,
    410       cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
    411   formats.push_back(cricket::VideoFormat(2592, 1944,
    412       cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
    413   capturer_.ResetSupportedFormats(formats);
    414 
    415   cricket::VideoFormat desired(960, 720,
    416                                cricket::VideoFormat::FpsToInterval(30),
    417                                cricket::FOURCC_ANY);
    418   cricket::VideoFormat best;
    419   // Ask for 960x720 30 fps. Get qHD 24 fps
    420   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    421   EXPECT_EQ(960, best.width);
    422   EXPECT_EQ(544, best.height);
    423   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
    424 
    425   desired.width = 960;
    426   desired.height = 544;
    427   desired.interval = cricket::VideoFormat::FpsToInterval(30);
    428   // Ask for qHD 30 fps. Get qHD 24 fps
    429   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    430   EXPECT_EQ(960, best.width);
    431   EXPECT_EQ(544, best.height);
    432   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
    433 
    434   desired.width = 360;
    435   desired.height = 250;
    436   desired.interval = cricket::VideoFormat::FpsToInterval(30);
    437   // Ask for a little higher than QVGA. Get QVGA.
    438   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    439   EXPECT_EQ(320, best.width);
    440   EXPECT_EQ(240, best.height);
    441   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    442 
    443   desired.width = 480;
    444   desired.height = 270;
    445   // Ask for HVGA. Get VGA.
    446   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    447   EXPECT_EQ(640, best.width);
    448   EXPECT_EQ(480, best.height);
    449   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    450 
    451   desired.width = 320;
    452   desired.height = 240;
    453   // Ask for QVGA. Get QVGA.
    454   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    455   EXPECT_EQ(320, best.width);
    456   EXPECT_EQ(240, best.height);
    457   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    458 
    459   desired.width = 160;
    460   desired.height = 120;
    461   // Ask for lower than QVGA. Get QVGA, which is the lowest.
    462   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    463   EXPECT_EQ(320, best.width);
    464   EXPECT_EQ(240, best.height);
    465   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    466 
    467   desired.width = 1280;
    468   desired.height = 720;
    469   // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
    470   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    471   EXPECT_EQ(640, best.width);
    472   EXPECT_EQ(480, best.height);
    473   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    474 
    475   desired.width = 1280;
    476   desired.height = 720;
    477   desired.interval = cricket::VideoFormat::FpsToInterval(15);
    478   // Ask for HD 15 fps. Fps matches. Get HD
    479   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    480   EXPECT_EQ(1280, best.width);
    481   EXPECT_EQ(720, best.height);
    482   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
    483 
    484   desired.width = 1920;
    485   desired.height = 1080;
    486   desired.interval = cricket::VideoFormat::FpsToInterval(30);
    487   // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
    488   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    489   EXPECT_EQ(640, best.width);
    490   EXPECT_EQ(480, best.height);
    491   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    492 }
    493 
    494 // Some cameras support 320x240 and 320x640. Verify we choose 320x240.
    495 TEST_F(VideoCapturerTest, TestStrangeFormats) {
    496   std::vector<cricket::VideoFormat> supported_formats;
    497   supported_formats.push_back(cricket::VideoFormat(320, 240,
    498       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    499   supported_formats.push_back(cricket::VideoFormat(320, 640,
    500       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    501   capturer_.ResetSupportedFormats(supported_formats);
    502 
    503   std::vector<cricket::VideoFormat> required_formats;
    504   required_formats.push_back(cricket::VideoFormat(320, 240,
    505       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    506   required_formats.push_back(cricket::VideoFormat(320, 200,
    507       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    508   required_formats.push_back(cricket::VideoFormat(320, 180,
    509       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    510   cricket::VideoFormat best;
    511   for (size_t i = 0; i < required_formats.size(); ++i) {
    512     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    513     EXPECT_EQ(320, best.width);
    514     EXPECT_EQ(240, best.height);
    515   }
    516 
    517   supported_formats.clear();
    518   supported_formats.push_back(cricket::VideoFormat(320, 640,
    519       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    520   supported_formats.push_back(cricket::VideoFormat(320, 240,
    521       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    522   capturer_.ResetSupportedFormats(supported_formats);
    523 
    524   for (size_t i = 0; i < required_formats.size(); ++i) {
    525     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    526     EXPECT_EQ(320, best.width);
    527     EXPECT_EQ(240, best.height);
    528   }
    529 }
    530 
    531 // Some cameras only have very low fps. Verify we choose something sensible.
    532 TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
    533   // all formats are low framerate
    534   std::vector<cricket::VideoFormat> supported_formats;
    535   supported_formats.push_back(cricket::VideoFormat(320, 240,
    536       cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
    537   supported_formats.push_back(cricket::VideoFormat(640, 480,
    538       cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
    539   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    540       cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
    541   capturer_.ResetSupportedFormats(supported_formats);
    542 
    543   std::vector<cricket::VideoFormat> required_formats;
    544   required_formats.push_back(cricket::VideoFormat(320, 240,
    545       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    546   required_formats.push_back(cricket::VideoFormat(640, 480,
    547       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    548   cricket::VideoFormat best;
    549   for (size_t i = 0; i < required_formats.size(); ++i) {
    550     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    551     EXPECT_EQ(required_formats[i].width, best.width);
    552     EXPECT_EQ(required_formats[i].height, best.height);
    553   }
    554 
    555   // Increase framerate of 320x240. Expect low fps VGA avoided.
    556   supported_formats.clear();
    557   supported_formats.push_back(cricket::VideoFormat(320, 240,
    558       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    559   supported_formats.push_back(cricket::VideoFormat(640, 480,
    560       cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
    561   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    562       cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
    563   capturer_.ResetSupportedFormats(supported_formats);
    564 
    565   for (size_t i = 0; i < required_formats.size(); ++i) {
    566     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    567     EXPECT_EQ(320, best.width);
    568     EXPECT_EQ(240, best.height);
    569   }
    570 }
    571 
    572 // Some cameras support same size with different frame rates. Verify we choose
    573 // the frame rate properly.
    574 TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
    575   std::vector<cricket::VideoFormat> supported_formats;
    576   supported_formats.push_back(cricket::VideoFormat(320, 240,
    577       cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
    578   supported_formats.push_back(cricket::VideoFormat(320, 240,
    579       cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
    580   supported_formats.push_back(cricket::VideoFormat(320, 240,
    581       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    582   capturer_.ResetSupportedFormats(supported_formats);
    583 
    584   std::vector<cricket::VideoFormat> required_formats = supported_formats;
    585   cricket::VideoFormat best;
    586   for (size_t i = 0; i < required_formats.size(); ++i) {
    587     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    588     EXPECT_EQ(320, best.width);
    589     EXPECT_EQ(240, best.height);
    590     EXPECT_EQ(required_formats[i].interval, best.interval);
    591   }
    592 }
    593 
    594 // Some cameras support the correct resolution but at a lower fps than
    595 // we'd like. This tests we get the expected resolution and fps.
    596 TEST_F(VideoCapturerTest, TestFpsFormats) {
    597   // We have VGA but low fps. Choose VGA, not HD
    598   std::vector<cricket::VideoFormat> supported_formats;
    599   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    600       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    601   supported_formats.push_back(cricket::VideoFormat(640, 480,
    602       cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
    603   supported_formats.push_back(cricket::VideoFormat(640, 400,
    604       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    605   supported_formats.push_back(cricket::VideoFormat(640, 360,
    606       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    607   capturer_.ResetSupportedFormats(supported_formats);
    608 
    609   std::vector<cricket::VideoFormat> required_formats;
    610   required_formats.push_back(cricket::VideoFormat(640, 480,
    611       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
    612   required_formats.push_back(cricket::VideoFormat(640, 480,
    613       cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
    614   required_formats.push_back(cricket::VideoFormat(640, 480,
    615       cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
    616   cricket::VideoFormat best;
    617 
    618   // Expect 30 fps to choose 30 fps format.
    619   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
    620   EXPECT_EQ(640, best.width);
    621   EXPECT_EQ(400, best.height);
    622   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    623 
    624   // Expect 20 fps to choose 30 fps format.
    625   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
    626   EXPECT_EQ(640, best.width);
    627   EXPECT_EQ(400, best.height);
    628   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    629 
    630   // Expect 10 fps to choose 15 fps format and set fps to 15.
    631   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
    632   EXPECT_EQ(640, best.width);
    633   EXPECT_EQ(480, best.height);
    634   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
    635 
    636   // We have VGA 60 fps and 15 fps. Choose best fps.
    637   supported_formats.clear();
    638   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    639       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    640   supported_formats.push_back(cricket::VideoFormat(640, 480,
    641       cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
    642   supported_formats.push_back(cricket::VideoFormat(640, 480,
    643       cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
    644   supported_formats.push_back(cricket::VideoFormat(640, 400,
    645       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    646   supported_formats.push_back(cricket::VideoFormat(640, 360,
    647       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    648   capturer_.ResetSupportedFormats(supported_formats);
    649 
    650   // Expect 30 fps to choose 60 fps format and will set best fps to 60.
    651   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
    652   EXPECT_EQ(640, best.width);
    653   EXPECT_EQ(480, best.height);
    654   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
    655 
    656   // Expect 20 fps to choose 60 fps format, and will set best fps to 60.
    657   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
    658   EXPECT_EQ(640, best.width);
    659   EXPECT_EQ(480, best.height);
    660   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
    661 
    662   // Expect 10 fps to choose 15 fps.
    663   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
    664   EXPECT_EQ(640, best.width);
    665   EXPECT_EQ(480, best.height);
    666   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
    667 }
    668 
    669 TEST_F(VideoCapturerTest, TestRequest16x10_9) {
    670   std::vector<cricket::VideoFormat> supported_formats;
    671   // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
    672   supported_formats.push_back(cricket::VideoFormat(640, 480,
    673       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    674   supported_formats.push_back(cricket::VideoFormat(640, 400,
    675       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    676   supported_formats.push_back(cricket::VideoFormat(640, 360,
    677       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    678   capturer_.ResetSupportedFormats(supported_formats);
    679 
    680   std::vector<cricket::VideoFormat> required_formats = supported_formats;
    681   cricket::VideoFormat best;
    682   // Expect 4x3, 16x10, and 16x9 requests are respected.
    683   for (size_t i = 0; i < required_formats.size(); ++i) {
    684     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    685     EXPECT_EQ(required_formats[i].width, best.width);
    686     EXPECT_EQ(required_formats[i].height, best.height);
    687   }
    688 
    689   // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
    690   supported_formats.clear();
    691   supported_formats.push_back(cricket::VideoFormat(960, 720,
    692       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    693   supported_formats.push_back(cricket::VideoFormat(640, 480,
    694       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    695   supported_formats.push_back(cricket::VideoFormat(640, 400,
    696       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    697   supported_formats.push_back(cricket::VideoFormat(640, 360,
    698       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    699   capturer_.ResetSupportedFormats(supported_formats);
    700 
    701   // Expect 4x3, 16x10, and 16x9 requests are respected.
    702   for (size_t i = 0; i < required_formats.size(); ++i) {
    703     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    704     EXPECT_EQ(required_formats[i].width, best.width);
    705     EXPECT_EQ(required_formats[i].height, best.height);
    706   }
    707 
    708   // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
    709   supported_formats.clear();
    710   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    711       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    712   supported_formats.push_back(cricket::VideoFormat(640, 480,
    713       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    714   supported_formats.push_back(cricket::VideoFormat(640, 400,
    715       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    716   supported_formats.push_back(cricket::VideoFormat(640, 360,
    717       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    718   capturer_.ResetSupportedFormats(supported_formats);
    719 
    720   // Expect 4x3 for 4x3 and 16x10 requests.
    721   for (size_t i = 0; i < required_formats.size() - 1; ++i) {
    722     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    723     EXPECT_EQ(required_formats[i].width, best.width);
    724     EXPECT_EQ(required_formats[i].height, best.height);
    725   }
    726 
    727   // Expect 16x9 for 16x9 request.
    728   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
    729   EXPECT_EQ(640, best.width);
    730   EXPECT_EQ(360, best.height);
    731 }
    732 
    733 // If HAVE_WEBRTC_VIDEO is not defined the video capturer will not be able to
    734 // provide OnVideoFrame-callbacks since they require cricket::CapturedFrame to
    735 // be decoded as a cricket::VideoFrame (i.e. an I420 frame). This functionality
    736 // only exist if HAVE_WEBRTC_VIDEO is defined below. I420 frames are also a
    737 // requirement for the VideoProcessors so they will not be called either.
    738 #if defined(HAVE_WEBRTC_VIDEO)
    739 TEST_F(VideoCapturerTest, VideoFrame) {
    740   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    741       640,
    742       480,
    743       cricket::VideoFormat::FpsToInterval(30),
    744       cricket::FOURCC_I420)));
    745   EXPECT_TRUE(capturer_.IsRunning());
    746   EXPECT_EQ(0, video_frames_received());
    747   EXPECT_TRUE(capturer_.CaptureFrame());
    748   EXPECT_EQ(1, video_frames_received());
    749 }
    750 #endif  // HAVE_WEBRTC_VIDEO
    751 
    752 bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
    753   for (std::vector<cricket::VideoFormat>::const_iterator found =
    754            formats.begin(); found != formats.end(); ++found) {
    755     if (found->height >= kMinHdHeight) {
    756       return true;
    757     }
    758   }
    759   return false;
    760 }
    761 
    762 TEST_F(VideoCapturerTest, Whitelist) {
    763   // The definition of HD only applies to the height. Set the HD width to the
    764   // smallest legal number to document this fact in this test.
    765   const int kMinHdWidth = 1;
    766   cricket::VideoFormat hd_format(kMinHdWidth,
    767                                  kMinHdHeight,
    768                                  cricket::VideoFormat::FpsToInterval(30),
    769                                  cricket::FOURCC_I420);
    770   cricket::VideoFormat vga_format(640, 480,
    771                                   cricket::VideoFormat::FpsToInterval(30),
    772                                   cricket::FOURCC_I420);
    773   std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
    774   formats.push_back(hd_format);
    775 
    776   // Enable whitelist. Expect HD not in list.
    777   capturer_.set_enable_camera_list(true);
    778   capturer_.ResetSupportedFormats(formats);
    779   EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
    780   capturer_.ConstrainSupportedFormats(vga_format);
    781   EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
    782 
    783   // Disable whitelist. Expect HD in list.
    784   capturer_.set_enable_camera_list(false);
    785   capturer_.ResetSupportedFormats(formats);
    786   EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
    787   capturer_.ConstrainSupportedFormats(vga_format);
    788   EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
    789 }
    790 
    791 TEST_F(VideoCapturerTest, BlacklistAllFormats) {
    792   cricket::VideoFormat vga_format(640, 480,
    793                                   cricket::VideoFormat::FpsToInterval(30),
    794                                   cricket::FOURCC_I420);
    795   std::vector<cricket::VideoFormat> supported_formats;
    796   // Mock a device that only supports HD formats.
    797   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    798       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    799   supported_formats.push_back(cricket::VideoFormat(1920, 1080,
    800       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    801   capturer_.ResetSupportedFormats(supported_formats);
    802   EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
    803   // Now, enable the list, which would exclude both formats. However, since
    804   // only HD formats are available, we refuse to filter at all, so we don't
    805   // break this camera.
    806   capturer_.set_enable_camera_list(true);
    807   capturer_.ConstrainSupportedFormats(vga_format);
    808   EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
    809   // To make sure it's not just the camera list being broken, add in VGA and
    810   // try again. This time, only the VGA format should be there.
    811   supported_formats.push_back(vga_format);
    812   capturer_.ResetSupportedFormats(supported_formats);
    813   ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size());
    814   EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height);
    815 }
    816