Home | History | Annotate | Download | only in base
      1 // Copyright 2008 Google Inc.
      2 
      3 #include <stdio.h>
      4 #include <vector>
      5 
      6 #include "talk/base/gunit.h"
      7 #include "talk/base/logging.h"
      8 #include "talk/base/thread.h"
      9 #include "talk/media/base/fakemediaprocessor.h"
     10 #include "talk/media/base/fakevideocapturer.h"
     11 #include "talk/media/base/fakevideorenderer.h"
     12 #include "talk/media/base/testutils.h"
     13 #include "talk/media/base/videocapturer.h"
     14 #include "talk/media/base/videoprocessor.h"
     15 
     16 // If HAS_I420_FRAME is not defined the video capturer will not be able to
     17 // provide OnVideoFrame-callbacks since they require cricket::CapturedFrame to
     18 // be decoded as a cricket::VideoFrame (i.e. an I420 frame). This functionality
     19 // only exist if HAS_I420_FRAME is defined below. I420 frames are also a
     20 // requirement for the VideoProcessors so they will not be called either.
     21 #if defined(HAVE_WEBRTC_VIDEO)
     22 #define HAS_I420_FRAME
     23 #endif
     24 
     25 using cricket::FakeVideoCapturer;
     26 
     27 namespace {
     28 
     29 const int kMsCallbackWait = 500;
     30 // For HD only the height matters.
     31 const int kMinHdHeight = 720;
     32 const uint32 kTimeout = 5000U;
     33 
     34 }  // namespace
     35 
     36 // Sets the elapsed time in the video frame to 0.
     37 class VideoProcessor0 : public cricket::VideoProcessor {
     38  public:
     39   virtual void OnFrame(uint32 /*ssrc*/, cricket::VideoFrame* frame,
     40                        bool* drop_frame) {
     41     frame->SetElapsedTime(0u);
     42   }
     43 };
     44 
     45 // Adds one to the video frame's elapsed time. Note that VideoProcessor0 and
     46 // VideoProcessor1 are not commutative.
     47 class VideoProcessor1 : public cricket::VideoProcessor {
     48  public:
     49   virtual void OnFrame(uint32 /*ssrc*/, cricket::VideoFrame* frame,
     50                        bool* drop_frame) {
     51     int64 elapsed_time = frame->GetElapsedTime();
     52     frame->SetElapsedTime(elapsed_time + 1);
     53   }
     54 };
     55 
     56 class VideoCapturerTest
     57     : public sigslot::has_slots<>,
     58       public testing::Test {
     59  public:
     60   VideoCapturerTest()
     61       : capture_state_(cricket::CS_STOPPED),
     62         num_state_changes_(0),
     63         video_frames_received_(0),
     64         last_frame_elapsed_time_(0) {
     65     capturer_.SignalVideoFrame.connect(this, &VideoCapturerTest::OnVideoFrame);
     66     capturer_.SignalStateChange.connect(this,
     67                                         &VideoCapturerTest::OnStateChange);
     68   }
     69 
     70  protected:
     71   void OnVideoFrame(cricket::VideoCapturer*, const cricket::VideoFrame* frame) {
     72     ++video_frames_received_;
     73     last_frame_elapsed_time_ = frame->GetElapsedTime();
     74     renderer_.RenderFrame(frame);
     75   }
     76   void OnStateChange(cricket::VideoCapturer*,
     77                      cricket::CaptureState capture_state) {
     78     capture_state_ = capture_state;
     79     ++num_state_changes_;
     80   }
     81   cricket::CaptureState capture_state() { return capture_state_; }
     82   int num_state_changes() { return num_state_changes_; }
     83   int video_frames_received() const {
     84     return video_frames_received_;
     85   }
     86   int64 last_frame_elapsed_time() const { return last_frame_elapsed_time_; }
     87 
     88   cricket::FakeVideoCapturer capturer_;
     89   cricket::CaptureState capture_state_;
     90   int num_state_changes_;
     91   int video_frames_received_;
     92   int64 last_frame_elapsed_time_;
     93   cricket::FakeVideoRenderer renderer_;
     94 };
     95 
     96 TEST_F(VideoCapturerTest, CaptureState) {
     97   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
     98       640,
     99       480,
    100       cricket::VideoFormat::FpsToInterval(30),
    101       cricket::FOURCC_I420)));
    102   EXPECT_TRUE(capturer_.IsRunning());
    103   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    104   EXPECT_EQ(1, num_state_changes());
    105   capturer_.Stop();
    106   EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
    107   EXPECT_EQ(2, num_state_changes());
    108   capturer_.Stop();
    109   talk_base::Thread::Current()->ProcessMessages(100);
    110   EXPECT_EQ(2, num_state_changes());
    111 }
    112 
    113 TEST_F(VideoCapturerTest, TestRestart) {
    114   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    115       640,
    116       480,
    117       cricket::VideoFormat::FpsToInterval(30),
    118       cricket::FOURCC_I420)));
    119   EXPECT_TRUE(capturer_.IsRunning());
    120   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    121   EXPECT_EQ(1, num_state_changes());
    122   EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
    123       320,
    124       240,
    125       cricket::VideoFormat::FpsToInterval(30),
    126       cricket::FOURCC_I420)));
    127   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    128   EXPECT_TRUE(capturer_.IsRunning());
    129   EXPECT_GE(1, num_state_changes());
    130   capturer_.Stop();
    131   talk_base::Thread::Current()->ProcessMessages(100);
    132   EXPECT_FALSE(capturer_.IsRunning());
    133 }
    134 
    135 TEST_F(VideoCapturerTest, TestStartingWithRestart) {
    136   EXPECT_FALSE(capturer_.IsRunning());
    137   EXPECT_TRUE(capturer_.Restart(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 }
    145 
    146 TEST_F(VideoCapturerTest, TestRestartWithSameFormat) {
    147   cricket::VideoFormat format(640, 480,
    148                               cricket::VideoFormat::FpsToInterval(30),
    149                               cricket::FOURCC_I420);
    150   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format));
    151   EXPECT_TRUE(capturer_.IsRunning());
    152   EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
    153   EXPECT_EQ(1, num_state_changes());
    154   EXPECT_TRUE(capturer_.Restart(format));
    155   EXPECT_EQ(cricket::CS_RUNNING, capture_state());
    156   EXPECT_TRUE(capturer_.IsRunning());
    157   EXPECT_EQ(1, num_state_changes());
    158 }
    159 
    160 TEST_F(VideoCapturerTest, CameraOffOnMute) {
    161   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    162       640,
    163       480,
    164       cricket::VideoFormat::FpsToInterval(30),
    165       cricket::FOURCC_I420)));
    166   EXPECT_TRUE(capturer_.IsRunning());
    167   EXPECT_EQ(0, video_frames_received());
    168   EXPECT_TRUE(capturer_.CaptureFrame());
    169   EXPECT_EQ(1, video_frames_received());
    170   EXPECT_FALSE(capturer_.IsMuted());
    171 
    172   // Mute the camera and expect black output frame.
    173   capturer_.MuteToBlackThenPause(true);
    174   EXPECT_TRUE(capturer_.IsMuted());
    175   for (int i = 0; i < 31; ++i) {
    176     EXPECT_TRUE(capturer_.CaptureFrame());
    177     EXPECT_TRUE(renderer_.black_frame());
    178   }
    179   EXPECT_EQ(32, video_frames_received());
    180   EXPECT_EQ_WAIT(cricket::CS_PAUSED,
    181                  capturer_.capture_state(), kTimeout);
    182 
    183   // Verify that the camera is off.
    184   EXPECT_FALSE(capturer_.CaptureFrame());
    185   EXPECT_EQ(32, video_frames_received());
    186 
    187   // Unmute the camera and expect non-black output frame.
    188   capturer_.MuteToBlackThenPause(false);
    189   EXPECT_FALSE(capturer_.IsMuted());
    190   EXPECT_EQ_WAIT(cricket::CS_RUNNING,
    191                  capturer_.capture_state(), kTimeout);
    192   EXPECT_TRUE(capturer_.CaptureFrame());
    193   EXPECT_FALSE(renderer_.black_frame());
    194   EXPECT_EQ(33, video_frames_received());
    195 }
    196 
    197 TEST_F(VideoCapturerTest, TestFourccMatch) {
    198   cricket::VideoFormat desired(640, 480,
    199                                cricket::VideoFormat::FpsToInterval(30),
    200                                cricket::FOURCC_ANY);
    201   cricket::VideoFormat best;
    202   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    203   EXPECT_EQ(640, best.width);
    204   EXPECT_EQ(480, best.height);
    205   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    206 
    207   desired.fourcc = cricket::FOURCC_MJPG;
    208   EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
    209 
    210   desired.fourcc = cricket::FOURCC_I420;
    211   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    212 }
    213 
    214 TEST_F(VideoCapturerTest, TestResolutionMatch) {
    215   cricket::VideoFormat desired(1920, 1080,
    216                                cricket::VideoFormat::FpsToInterval(30),
    217                                cricket::FOURCC_ANY);
    218   cricket::VideoFormat best;
    219   // Ask for 1920x1080. Get HD 1280x720 which is the highest.
    220   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    221   EXPECT_EQ(1280, best.width);
    222   EXPECT_EQ(720, best.height);
    223   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    224 
    225   desired.width = 360;
    226   desired.height = 250;
    227   // Ask for a little higher than QVGA. Get QVGA.
    228   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    229   EXPECT_EQ(320, best.width);
    230   EXPECT_EQ(240, best.height);
    231   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    232 
    233   desired.width = 480;
    234   desired.height = 270;
    235   // Ask for HVGA. Get VGA.
    236   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    237   EXPECT_EQ(640, best.width);
    238   EXPECT_EQ(480, best.height);
    239   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    240 
    241   desired.width = 320;
    242   desired.height = 240;
    243   // Ask for QVGA. Get QVGA.
    244   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    245   EXPECT_EQ(320, best.width);
    246   EXPECT_EQ(240, best.height);
    247   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    248 
    249   desired.width = 80;
    250   desired.height = 60;
    251   // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
    252   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    253   EXPECT_EQ(160, best.width);
    254   EXPECT_EQ(120, best.height);
    255   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    256 }
    257 
    258 TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
    259   // Add some HD formats typical of a mediocre HD webcam.
    260   std::vector<cricket::VideoFormat> formats;
    261   formats.push_back(cricket::VideoFormat(320, 240,
    262       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    263   formats.push_back(cricket::VideoFormat(640, 480,
    264       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    265   formats.push_back(cricket::VideoFormat(960, 544,
    266       cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
    267   formats.push_back(cricket::VideoFormat(1280, 720,
    268       cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
    269   formats.push_back(cricket::VideoFormat(2592, 1944,
    270       cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
    271   capturer_.ResetSupportedFormats(formats);
    272 
    273   cricket::VideoFormat desired(960, 720,
    274                                cricket::VideoFormat::FpsToInterval(30),
    275                                cricket::FOURCC_ANY);
    276   cricket::VideoFormat best;
    277   // Ask for 960x720 30 fps. Get qHD 24 fps
    278   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    279   EXPECT_EQ(960, best.width);
    280   EXPECT_EQ(544, best.height);
    281   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
    282 
    283   desired.width = 960;
    284   desired.height = 544;
    285   desired.interval = cricket::VideoFormat::FpsToInterval(30);
    286   // Ask for qHD 30 fps. Get qHD 24 fps
    287   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    288   EXPECT_EQ(960, best.width);
    289   EXPECT_EQ(544, best.height);
    290   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
    291 
    292   desired.width = 360;
    293   desired.height = 250;
    294   desired.interval = cricket::VideoFormat::FpsToInterval(30);
    295   // Ask for a little higher than QVGA. Get QVGA.
    296   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    297   EXPECT_EQ(320, best.width);
    298   EXPECT_EQ(240, best.height);
    299   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    300 
    301   desired.width = 480;
    302   desired.height = 270;
    303   // Ask for HVGA. Get VGA.
    304   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    305   EXPECT_EQ(640, best.width);
    306   EXPECT_EQ(480, best.height);
    307   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    308 
    309   desired.width = 320;
    310   desired.height = 240;
    311   // Ask for QVGA. Get QVGA.
    312   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    313   EXPECT_EQ(320, best.width);
    314   EXPECT_EQ(240, best.height);
    315   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    316 
    317   desired.width = 160;
    318   desired.height = 120;
    319   // Ask for lower than QVGA. Get QVGA, which is the lowest.
    320   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    321   EXPECT_EQ(320, best.width);
    322   EXPECT_EQ(240, best.height);
    323   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    324 
    325   desired.width = 1280;
    326   desired.height = 720;
    327   // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
    328   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    329   EXPECT_EQ(640, best.width);
    330   EXPECT_EQ(480, best.height);
    331   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    332 
    333   desired.width = 1280;
    334   desired.height = 720;
    335   desired.interval = cricket::VideoFormat::FpsToInterval(15);
    336   // Ask for HD 15 fps. Fps matches. Get HD
    337   EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
    338   EXPECT_EQ(1280, best.width);
    339   EXPECT_EQ(720, best.height);
    340   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
    341 
    342   desired.width = 1920;
    343   desired.height = 1080;
    344   desired.interval = cricket::VideoFormat::FpsToInterval(30);
    345   // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
    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 
    352 // Some cameras support 320x240 and 320x640. Verify we choose 320x240.
    353 TEST_F(VideoCapturerTest, TestStrangeFormats) {
    354   std::vector<cricket::VideoFormat> supported_formats;
    355   supported_formats.push_back(cricket::VideoFormat(320, 240,
    356       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    357   supported_formats.push_back(cricket::VideoFormat(320, 640,
    358       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    359   capturer_.ResetSupportedFormats(supported_formats);
    360 
    361   std::vector<cricket::VideoFormat> required_formats;
    362   required_formats.push_back(cricket::VideoFormat(320, 240,
    363       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    364   required_formats.push_back(cricket::VideoFormat(320, 200,
    365       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    366   required_formats.push_back(cricket::VideoFormat(320, 180,
    367       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    368   cricket::VideoFormat best;
    369   for (size_t i = 0; i < required_formats.size(); ++i) {
    370     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    371     EXPECT_EQ(320, best.width);
    372     EXPECT_EQ(240, best.height);
    373   }
    374 
    375   supported_formats.clear();
    376   supported_formats.push_back(cricket::VideoFormat(320, 640,
    377       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    378   supported_formats.push_back(cricket::VideoFormat(320, 240,
    379       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    380   capturer_.ResetSupportedFormats(supported_formats);
    381 
    382   for (size_t i = 0; i < required_formats.size(); ++i) {
    383     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    384     EXPECT_EQ(320, best.width);
    385     EXPECT_EQ(240, best.height);
    386   }
    387 }
    388 
    389 // Some cameras only have very low fps. Verify we choose something sensible.
    390 TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
    391   // all formats are low framerate
    392   std::vector<cricket::VideoFormat> supported_formats;
    393   supported_formats.push_back(cricket::VideoFormat(320, 240,
    394       cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
    395   supported_formats.push_back(cricket::VideoFormat(640, 480,
    396       cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
    397   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    398       cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
    399   capturer_.ResetSupportedFormats(supported_formats);
    400 
    401   std::vector<cricket::VideoFormat> required_formats;
    402   required_formats.push_back(cricket::VideoFormat(320, 240,
    403       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    404   required_formats.push_back(cricket::VideoFormat(640, 480,
    405       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    406   cricket::VideoFormat best;
    407   for (size_t i = 0; i < required_formats.size(); ++i) {
    408     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    409     EXPECT_EQ(required_formats[i].width, best.width);
    410     EXPECT_EQ(required_formats[i].height, best.height);
    411   }
    412 
    413   // Increase framerate of 320x240. Expect low fps VGA avoided.
    414   supported_formats.clear();
    415   supported_formats.push_back(cricket::VideoFormat(320, 240,
    416       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    417   supported_formats.push_back(cricket::VideoFormat(640, 480,
    418       cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
    419   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    420       cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
    421   capturer_.ResetSupportedFormats(supported_formats);
    422 
    423   for (size_t i = 0; i < required_formats.size(); ++i) {
    424     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    425     EXPECT_EQ(320, best.width);
    426     EXPECT_EQ(240, best.height);
    427   }
    428 }
    429 
    430 // Some cameras support same size with different frame rates. Verify we choose
    431 // the frame rate properly.
    432 TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
    433   std::vector<cricket::VideoFormat> supported_formats;
    434   supported_formats.push_back(cricket::VideoFormat(320, 240,
    435       cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
    436   supported_formats.push_back(cricket::VideoFormat(320, 240,
    437       cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
    438   supported_formats.push_back(cricket::VideoFormat(320, 240,
    439       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    440   capturer_.ResetSupportedFormats(supported_formats);
    441 
    442   std::vector<cricket::VideoFormat> required_formats = supported_formats;
    443   cricket::VideoFormat best;
    444   for (size_t i = 0; i < required_formats.size(); ++i) {
    445     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    446     EXPECT_EQ(320, best.width);
    447     EXPECT_EQ(240, best.height);
    448     EXPECT_EQ(required_formats[i].interval, best.interval);
    449   }
    450 }
    451 
    452 // Some cameras support the correct resolution but at a lower fps than
    453 // we'd like. This tests we get the expected resolution and fps.
    454 TEST_F(VideoCapturerTest, TestFpsFormats) {
    455   // We have VGA but low fps. Choose VGA, not HD
    456   std::vector<cricket::VideoFormat> supported_formats;
    457   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    458       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    459   supported_formats.push_back(cricket::VideoFormat(640, 480,
    460       cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
    461   supported_formats.push_back(cricket::VideoFormat(640, 400,
    462       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    463   supported_formats.push_back(cricket::VideoFormat(640, 360,
    464       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    465   capturer_.ResetSupportedFormats(supported_formats);
    466 
    467   std::vector<cricket::VideoFormat> required_formats;
    468   required_formats.push_back(cricket::VideoFormat(640, 480,
    469       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
    470   required_formats.push_back(cricket::VideoFormat(640, 480,
    471       cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
    472   required_formats.push_back(cricket::VideoFormat(640, 480,
    473       cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
    474   cricket::VideoFormat best;
    475 
    476   // expect 30 fps to choose 30 fps format
    477   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
    478   EXPECT_EQ(640, best.width);
    479   EXPECT_EQ(400, best.height);
    480   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    481 
    482   // expect 20 fps to choose 20 fps format
    483   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
    484   EXPECT_EQ(640, best.width);
    485   EXPECT_EQ(400, best.height);
    486   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
    487 
    488   // expect 10 fps to choose 15 fps format but set fps to 10
    489   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
    490   EXPECT_EQ(640, best.width);
    491   EXPECT_EQ(480, best.height);
    492   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
    493 
    494   // We have VGA 60 fps and 15 fps. Choose best fps.
    495   supported_formats.clear();
    496   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    497       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    498   supported_formats.push_back(cricket::VideoFormat(640, 480,
    499       cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
    500   supported_formats.push_back(cricket::VideoFormat(640, 480,
    501       cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
    502   supported_formats.push_back(cricket::VideoFormat(640, 400,
    503       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    504   supported_formats.push_back(cricket::VideoFormat(640, 360,
    505       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    506   capturer_.ResetSupportedFormats(supported_formats);
    507 
    508   // expect 30 fps to choose 60 fps format, but will set best fps to 30
    509   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
    510   EXPECT_EQ(640, best.width);
    511   EXPECT_EQ(480, best.height);
    512   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
    513 
    514   // expect 20 fps to choose 60 fps format, but will set best fps to 20
    515   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
    516   EXPECT_EQ(640, best.width);
    517   EXPECT_EQ(480, best.height);
    518   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
    519 
    520   // expect 10 fps to choose 10 fps
    521   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
    522   EXPECT_EQ(640, best.width);
    523   EXPECT_EQ(480, best.height);
    524   EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
    525 }
    526 
    527 TEST_F(VideoCapturerTest, TestRequest16x10_9) {
    528   std::vector<cricket::VideoFormat> supported_formats;
    529   // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
    530   supported_formats.push_back(cricket::VideoFormat(640, 480,
    531       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    532   supported_formats.push_back(cricket::VideoFormat(640, 400,
    533       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    534   supported_formats.push_back(cricket::VideoFormat(640, 360,
    535       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    536   capturer_.ResetSupportedFormats(supported_formats);
    537 
    538   std::vector<cricket::VideoFormat> required_formats = supported_formats;
    539   cricket::VideoFormat best;
    540   // Expect 4x3, 16x10, and 16x9 requests are respected.
    541   for (size_t i = 0; i < required_formats.size(); ++i) {
    542     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    543     EXPECT_EQ(required_formats[i].width, best.width);
    544     EXPECT_EQ(required_formats[i].height, best.height);
    545   }
    546 
    547   // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
    548   supported_formats.clear();
    549   supported_formats.push_back(cricket::VideoFormat(960, 720,
    550       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    551   supported_formats.push_back(cricket::VideoFormat(640, 480,
    552       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    553   supported_formats.push_back(cricket::VideoFormat(640, 400,
    554       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    555   supported_formats.push_back(cricket::VideoFormat(640, 360,
    556       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    557   capturer_.ResetSupportedFormats(supported_formats);
    558 
    559   // Expect 4x3, 16x10, and 16x9 requests are respected.
    560   for (size_t i = 0; i < required_formats.size(); ++i) {
    561     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    562     EXPECT_EQ(required_formats[i].width, best.width);
    563     EXPECT_EQ(required_formats[i].height, best.height);
    564   }
    565 
    566   // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
    567   supported_formats.clear();
    568   supported_formats.push_back(cricket::VideoFormat(1280, 720,
    569       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    570   supported_formats.push_back(cricket::VideoFormat(640, 480,
    571       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    572   supported_formats.push_back(cricket::VideoFormat(640, 400,
    573       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    574   supported_formats.push_back(cricket::VideoFormat(640, 360,
    575       cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
    576   capturer_.ResetSupportedFormats(supported_formats);
    577 
    578   // Expect 4x3 for 4x3 and 16x10 requests.
    579   for (size_t i = 0; i < required_formats.size() - 1; ++i) {
    580     EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
    581     EXPECT_EQ(required_formats[i].width, best.width);
    582     EXPECT_EQ(required_formats[i].height, best.height);
    583   }
    584 
    585   // Expect 16x9 for 16x9 request.
    586   EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
    587   EXPECT_EQ(640, best.width);
    588   EXPECT_EQ(360, best.height);
    589 }
    590 
    591 #if defined(HAS_I420_FRAME)
    592 TEST_F(VideoCapturerTest, VideoFrame) {
    593   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    594       640,
    595       480,
    596       cricket::VideoFormat::FpsToInterval(30),
    597       cricket::FOURCC_I420)));
    598   EXPECT_TRUE(capturer_.IsRunning());
    599   EXPECT_EQ(0, video_frames_received());
    600   EXPECT_TRUE(capturer_.CaptureFrame());
    601   EXPECT_EQ(1, video_frames_received());
    602 }
    603 
    604 TEST_F(VideoCapturerTest, ProcessorChainTest) {
    605   VideoProcessor0 processor0;
    606   VideoProcessor1 processor1;
    607   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    608       640,
    609       480,
    610       cricket::VideoFormat::FpsToInterval(30),
    611       cricket::FOURCC_I420)));
    612   EXPECT_TRUE(capturer_.IsRunning());
    613   EXPECT_EQ(0, video_frames_received());
    614   // First processor sets elapsed time to 0.
    615   capturer_.AddVideoProcessor(&processor0);
    616   // Second processor adds 1 to the elapsed time. I.e. a frames elapsed time
    617   // should now always be 1 (and not 0).
    618   capturer_.AddVideoProcessor(&processor1);
    619   EXPECT_TRUE(capturer_.CaptureFrame());
    620   EXPECT_EQ(1, video_frames_received());
    621   EXPECT_EQ(1u, last_frame_elapsed_time());
    622   capturer_.RemoveVideoProcessor(&processor1);
    623   EXPECT_TRUE(capturer_.CaptureFrame());
    624   // Since processor1 has been removed the elapsed time should now be 0.
    625   EXPECT_EQ(2, video_frames_received());
    626   EXPECT_EQ(0u, last_frame_elapsed_time());
    627 }
    628 
    629 TEST_F(VideoCapturerTest, ProcessorDropFrame) {
    630   cricket::FakeMediaProcessor dropping_processor_;
    631   dropping_processor_.set_drop_frames(true);
    632   EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
    633       640,
    634       480,
    635       cricket::VideoFormat::FpsToInterval(30),
    636       cricket::FOURCC_I420)));
    637   EXPECT_TRUE(capturer_.IsRunning());
    638   EXPECT_EQ(0, video_frames_received());
    639   // Install a processor that always drop frames.
    640   capturer_.AddVideoProcessor(&dropping_processor_);
    641   EXPECT_TRUE(capturer_.CaptureFrame());
    642   EXPECT_EQ(0, video_frames_received());
    643 }
    644 #endif  // HAS_I420_FRAME
    645 
    646 bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
    647   for (std::vector<cricket::VideoFormat>::const_iterator found =
    648            formats.begin(); found != formats.end(); ++found) {
    649     if (found->height >= kMinHdHeight) {
    650       return true;
    651     }
    652   }
    653   return false;
    654 }
    655 
    656 TEST_F(VideoCapturerTest, Whitelist) {
    657   // The definition of HD only applies to the height. Set the HD width to the
    658   // smallest legal number to document this fact in this test.
    659   const int kMinHdWidth = 1;
    660   cricket::VideoFormat hd_format(kMinHdWidth,
    661                                  kMinHdHeight,
    662                                  cricket::VideoFormat::FpsToInterval(30),
    663                                  cricket::FOURCC_I420);
    664   cricket::VideoFormat vga_format(640, 480,
    665                                   cricket::VideoFormat::FpsToInterval(30),
    666                                   cricket::FOURCC_I420);
    667   std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
    668   formats.push_back(hd_format);
    669 
    670   // Enable whitelist. Expect HD not in list.
    671   capturer_.set_enable_camera_list(true);
    672   capturer_.ResetSupportedFormats(formats);
    673   EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
    674   capturer_.ConstrainSupportedFormats(vga_format);
    675   EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
    676 
    677   // Disable whitelist. Expect HD in list.
    678   capturer_.set_enable_camera_list(false);
    679   capturer_.ResetSupportedFormats(formats);
    680   EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
    681   capturer_.ConstrainSupportedFormats(vga_format);
    682   EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
    683 }
    684