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