Home | History | Annotate | Download | only in source
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "gflags/gflags.h"
     12 #include "webrtc/common_types.h"
     13 #include "webrtc/engine_configurations.h"
     14 #include "webrtc/modules/video_capture/include/video_capture_factory.h"
     15 #include "webrtc/system_wrappers/interface/tick_util.h"
     16 #include "webrtc/video_engine/include/vie_base.h"
     17 #include "webrtc/video_engine/include/vie_capture.h"
     18 #include "webrtc/video_engine/include/vie_codec.h"
     19 #include "webrtc/video_engine/include/vie_network.h"
     20 #include "webrtc/video_engine/include/vie_render.h"
     21 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
     22 #include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
     23 #include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
     24 #include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h"
     25 #include "webrtc/video_engine/test/libvietest/include/tb_video_channel.h"
     26 #include "webrtc/voice_engine/include/voe_base.h"
     27 
     28 DEFINE_bool(capture_test_ensure_resolution_alignment_in_capture_device, true,
     29             "If true, we will give resolutions slightly below a reasonable "
     30             "value to test the camera's ability to choose a good resolution. "
     31             "If false, we will provide reasonable resolutions instead.");
     32 
     33 class CaptureObserver : public webrtc::ViECaptureObserver {
     34  public:
     35   CaptureObserver()
     36       : brightness_(webrtc::Normal),
     37         alarm_(webrtc::AlarmCleared),
     38         frame_rate_(0) {}
     39 
     40   virtual void BrightnessAlarm(const int capture_id,
     41                                const webrtc::Brightness brightness) {
     42     brightness_ = brightness;
     43     switch (brightness) {
     44       case webrtc::Normal:
     45         ViETest::Log("  BrightnessAlarm Normal");
     46         break;
     47       case webrtc::Bright:
     48         ViETest::Log("  BrightnessAlarm Bright");
     49         break;
     50       case webrtc::Dark:
     51         ViETest::Log("  BrightnessAlarm Dark");
     52         break;
     53     }
     54   }
     55 
     56   virtual void CapturedFrameRate(const int capture_id,
     57                                  const unsigned char frame_rate) {
     58     ViETest::Log("  CapturedFrameRate %u", frame_rate);
     59     frame_rate_ = frame_rate;
     60   }
     61 
     62   virtual void NoPictureAlarm(const int capture_id,
     63                               const webrtc::CaptureAlarm alarm) {
     64     alarm_ = alarm;
     65     if (alarm == webrtc::AlarmRaised) {
     66       ViETest::Log("NoPictureAlarm CARaised.");
     67     } else {
     68       ViETest::Log("NoPictureAlarm CACleared.");
     69     }
     70   }
     71 
     72   webrtc::Brightness brightness_;
     73   webrtc::CaptureAlarm alarm_;
     74   unsigned char frame_rate_;
     75 };
     76 
     77 class CaptureEffectFilter : public webrtc::ViEEffectFilter {
     78  public:
     79   CaptureEffectFilter(unsigned int expected_width, unsigned int expected_height)
     80       : number_of_captured_frames_(0),
     81         expected_width_(expected_width),
     82         expected_height_(expected_height) {
     83   }
     84 
     85   // Implements video_engineEffectFilter.
     86   virtual int Transform(int size,
     87                         unsigned char* frame_buffer,
     88                         int64_t ntp_time_ms,
     89                         unsigned int timestamp,
     90                         unsigned int width,
     91                         unsigned int height) {
     92     EXPECT_TRUE(frame_buffer != NULL);
     93     EXPECT_EQ(expected_width_, width);
     94     EXPECT_EQ(expected_height_, height);
     95     ++number_of_captured_frames_;
     96     return 0;
     97   }
     98 
     99   int number_of_captured_frames_;
    100 
    101  protected:
    102   unsigned int expected_width_;
    103   unsigned int expected_height_;
    104 };
    105 
    106 void ViEAutoTest::ViECaptureStandardTest() {
    107   /// **************************************************************
    108   //  Begin create/initialize WebRTC Video Engine for testing
    109   /// **************************************************************
    110 
    111   /// **************************************************************
    112   //  Engine ready. Begin testing class
    113   /// **************************************************************
    114 
    115   TbInterfaces video_engine("video_engineCaptureStandardTest");
    116 
    117   webrtc::VideoCaptureModule::DeviceInfo* dev_info =
    118       webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
    119   ASSERT_TRUE(dev_info != NULL);
    120 
    121   int number_of_capture_devices = dev_info->NumberOfDevices();
    122   ViETest::Log("Number of capture devices %d",
    123                         number_of_capture_devices);
    124   ASSERT_GT(number_of_capture_devices, 0)
    125       << "This test requires a capture device (i.e. a webcam)";
    126 
    127 #if !defined(WEBRTC_MAC)
    128   int capture_device_id[10] = {0};
    129   webrtc::VideoCaptureModule* vcpms[10] = {0};
    130 #endif
    131 
    132   // Check capabilities
    133   for (int device_index = 0; device_index < number_of_capture_devices;
    134        ++device_index) {
    135     char device_name[128];
    136     char device_unique_name[512];
    137 
    138     EXPECT_EQ(0, dev_info->GetDeviceName(device_index,
    139                                          device_name,
    140                                          sizeof(device_name),
    141                                          device_unique_name,
    142                                          sizeof(device_unique_name)));
    143     ViETest::Log("Found capture device %s\nUnique name %s",
    144                           device_name, device_unique_name);
    145 
    146 #if !defined(WEBRTC_MAC)  // these functions will return -1
    147     int number_of_capabilities =
    148         dev_info->NumberOfCapabilities(device_unique_name);
    149     EXPECT_GT(number_of_capabilities, 0);
    150 
    151     for (int cap_index = 0; cap_index < number_of_capabilities; ++cap_index) {
    152       webrtc::VideoCaptureCapability capability;
    153       EXPECT_EQ(0, dev_info->GetCapability(device_unique_name, cap_index,
    154                                            capability));
    155       ViETest::Log("Capture capability %d (of %u)", cap_index + 1,
    156                    number_of_capabilities);
    157       ViETest::Log("width %d, height %d, frame rate %d",
    158                    capability.width, capability.height, capability.maxFPS);
    159       ViETest::Log("expected delay %d, color type %d, encoding %d",
    160                    capability.expectedCaptureDelay, capability.rawType,
    161                    capability.codecType);
    162       EXPECT_GT(capability.width, 0);
    163       EXPECT_GT(capability.height, 0);
    164       EXPECT_GT(capability.maxFPS, -1);  // >= 0
    165       EXPECT_GT(capability.expectedCaptureDelay, 0);
    166     }
    167 #endif
    168   }
    169   // Capture Capability Functions are not supported on WEBRTC_MAC.
    170 #if !defined(WEBRTC_MAC)
    171 
    172   // Check allocation. Try to allocate them all after each other.
    173   for (int device_index = 0; device_index < number_of_capture_devices;
    174        ++device_index) {
    175     char device_name[128];
    176     char device_unique_name[512];
    177     EXPECT_EQ(0, dev_info->GetDeviceName(device_index,
    178                                          device_name,
    179                                          sizeof(device_name),
    180                                          device_unique_name,
    181                                          sizeof(device_unique_name)));
    182     webrtc::VideoCaptureModule* vcpm =
    183         webrtc::VideoCaptureFactory::Create(device_index, device_unique_name);
    184     EXPECT_TRUE(vcpm != NULL);
    185     if (!vcpm)
    186       continue;
    187 
    188     vcpm->AddRef();
    189     vcpms[device_index] = vcpm;
    190 
    191     EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(
    192         *vcpm, capture_device_id[device_index]));
    193 
    194     webrtc::VideoCaptureCapability capability;
    195     EXPECT_EQ(0, dev_info->GetCapability(device_unique_name, 0, capability));
    196 
    197     // Test that the camera select the closest capability to the selected
    198     // width and height.
    199     CaptureEffectFilter filter(capability.width, capability.height);
    200     EXPECT_EQ(0, video_engine.image_process->RegisterCaptureEffectFilter(
    201         capture_device_id[device_index], filter));
    202 
    203     ViETest::Log("Testing Device %s capability width %d  height %d",
    204                  device_unique_name, capability.width, capability.height);
    205 
    206     if (FLAGS_capture_test_ensure_resolution_alignment_in_capture_device) {
    207       // This tests that the capture device properly aligns to a
    208       // multiple of 16 (or at least 8).
    209       capability.height = capability.height - 2;
    210       capability.width  = capability.width  - 2;
    211     }
    212 
    213     webrtc::CaptureCapability vie_capability;
    214     vie_capability.width = capability.width;
    215     vie_capability.height = capability.height;
    216     vie_capability.codecType = capability.codecType;
    217     vie_capability.maxFPS = capability.maxFPS;
    218     vie_capability.rawType = capability.rawType;
    219 
    220     EXPECT_EQ(0, video_engine.capture->StartCapture(
    221         capture_device_id[device_index], vie_capability));
    222     webrtc::TickTime start_time = webrtc::TickTime::Now();
    223 
    224     while (filter.number_of_captured_frames_ < 10 &&
    225            (webrtc::TickTime::Now() - start_time).Milliseconds() < 10000) {
    226       AutoTestSleep(100);
    227     }
    228 
    229     EXPECT_GT(filter.number_of_captured_frames_, 9)
    230         << "Should capture at least some frames";
    231 
    232     EXPECT_EQ(0, video_engine.image_process->DeregisterCaptureEffectFilter(
    233         capture_device_id[device_index]));
    234 
    235 #ifdef WEBRTC_ANDROID  // Can only allocate one camera at the time on Android.
    236     EXPECT_EQ(0, video_engine.capture->StopCapture(
    237         capture_device_id[device_index]));
    238     EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(
    239         capture_device_id[device_index]));
    240 #endif
    241   }
    242 
    243   /// **************************************************************
    244   //  Testing finished. Tear down Video Engine
    245   /// **************************************************************
    246   delete dev_info;
    247 
    248   // Stop all started capture devices.
    249   for (int device_index = 0; device_index < number_of_capture_devices;
    250        ++device_index) {
    251 #if !defined(WEBRTC_ANDROID)
    252     // Don't stop on Android since we can only allocate one camera.
    253     EXPECT_EQ(0, video_engine.capture->StopCapture(
    254         capture_device_id[device_index]));
    255     EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(
    256         capture_device_id[device_index]));
    257 #endif  // !WEBRTC_ANDROID
    258     if (vcpms[device_index])
    259       vcpms[device_index]->Release();
    260   }
    261 #endif  // !WEBRTC_MAC
    262 }
    263 
    264 void ViEAutoTest::ViECaptureExtendedTest() {
    265   ViECaptureExternalCaptureTest();
    266 }
    267 
    268 void ViEAutoTest::ViECaptureAPITest() {
    269   /// **************************************************************
    270   //  Begin create/initialize WebRTC Video Engine for testing
    271   /// **************************************************************
    272 
    273   /// **************************************************************
    274   //  Engine ready. Begin testing class
    275   /// **************************************************************
    276   TbInterfaces video_engine("video_engineCaptureAPITest");
    277 
    278   video_engine.capture->NumberOfCaptureDevices();
    279 
    280   char device_name[128];
    281   char device_unique_name[512];
    282   int capture_id = 0;
    283 
    284   webrtc::VideoCaptureModule::DeviceInfo* dev_info =
    285       webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
    286   ASSERT_TRUE(dev_info != NULL);
    287   ASSERT_GT(dev_info->NumberOfDevices(), 0u)
    288       << "This test requires a capture device (i.e. a webcam)";
    289 
    290   // Get the first capture device
    291   EXPECT_EQ(0, dev_info->GetDeviceName(0, device_name,
    292                                        sizeof(device_name),
    293                                        device_unique_name,
    294                                        sizeof(device_unique_name)));
    295 
    296   webrtc::VideoCaptureModule* vcpm =
    297       webrtc::VideoCaptureFactory::Create(0, device_unique_name);
    298   vcpm->AddRef();
    299   EXPECT_TRUE(vcpm != NULL);
    300 
    301   // Allocate capture device.
    302   EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
    303 
    304   // Start the capture device.
    305   EXPECT_EQ(0, video_engine.capture->StartCapture(capture_id));
    306 
    307   // Start again. Should fail.
    308   EXPECT_NE(0, video_engine.capture->StartCapture(capture_id));
    309   EXPECT_EQ(kViECaptureDeviceAlreadyStarted, video_engine.LastError());
    310 
    311   // Start invalid capture device.
    312   EXPECT_NE(0, video_engine.capture->StartCapture(capture_id + 1));
    313   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    314 
    315   // Stop invalid capture device.
    316   EXPECT_NE(0, video_engine.capture->StopCapture(capture_id + 1));
    317   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    318 
    319   // Stop the capture device.
    320   EXPECT_EQ(0, video_engine.capture->StopCapture(capture_id));
    321 
    322   // Stop the capture device again.
    323   EXPECT_NE(0, video_engine.capture->StopCapture(capture_id));
    324   EXPECT_EQ(kViECaptureDeviceNotStarted, video_engine.LastError());
    325 
    326   // Connect to invalid channel.
    327   EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id, 0));
    328   EXPECT_EQ(kViECaptureDeviceInvalidChannelId,
    329             video_engine.LastError());
    330 
    331   TbVideoChannel channel(video_engine);
    332 
    333   // Connect invalid capture_id.
    334   EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id + 1,
    335                                                  channel.videoChannel));
    336   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    337 
    338   // Connect the capture device to the channel.
    339   EXPECT_EQ(0, video_engine.capture->ConnectCaptureDevice(capture_id,
    340                                                  channel.videoChannel));
    341 
    342   // Connect the channel again.
    343   EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id,
    344                                                  channel.videoChannel));
    345   EXPECT_EQ(kViECaptureDeviceAlreadyConnected,
    346             video_engine.LastError());
    347 
    348   // Start the capture device.
    349   EXPECT_EQ(0, video_engine.capture->StartCapture(capture_id));
    350 
    351   // Release invalid capture device.
    352   EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id + 1));
    353   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    354 
    355   // Release the capture device.
    356   EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
    357 
    358   // Release the capture device again.
    359   EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
    360   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    361 
    362   // Test GetOrientation.
    363   webrtc::VideoCaptureRotation orientation;
    364   char dummy_name[5];
    365   EXPECT_NE(0, dev_info->GetOrientation(dummy_name, orientation));
    366 
    367   // Test SetRotation.
    368   EXPECT_NE(0, video_engine.capture->SetRotateCapturedFrames(
    369       capture_id, webrtc::RotateCapturedFrame_90));
    370   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    371 
    372   // Allocate capture device.
    373   EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
    374 
    375   EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
    376       capture_id, webrtc::RotateCapturedFrame_0));
    377   EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
    378       capture_id, webrtc::RotateCapturedFrame_90));
    379   EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
    380       capture_id, webrtc::RotateCapturedFrame_180));
    381   EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
    382       capture_id, webrtc::RotateCapturedFrame_270));
    383 
    384   // Release the capture device
    385   EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
    386 
    387   /// **************************************************************
    388   //  Testing finished. Tear down Video Engine
    389   /// **************************************************************
    390   delete dev_info;
    391   vcpm->Release();
    392 }
    393 
    394 void ViEAutoTest::ViECaptureExternalCaptureTest() {
    395   /// **************************************************************
    396   //  Begin create/initialize WebRTC Video Engine for testing
    397   /// **************************************************************
    398 
    399   TbInterfaces video_engine("video_engineCaptureExternalCaptureTest");
    400   TbVideoChannel channel(video_engine);
    401   channel.StartReceive();
    402   channel.StartSend();
    403 
    404   webrtc::VideoCaptureExternal* external_capture = NULL;
    405   int capture_id = 0;
    406 
    407   // Allocate the external capture device.
    408   webrtc::VideoCaptureModule* vcpm =
    409       webrtc::VideoCaptureFactory::Create(0, external_capture);
    410   EXPECT_TRUE(vcpm != NULL);
    411   EXPECT_TRUE(external_capture != NULL);
    412   vcpm->AddRef();
    413 
    414   EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
    415 
    416   // Connect the capture device to the channel.
    417   EXPECT_EQ(0, video_engine.capture->ConnectCaptureDevice(capture_id,
    418                                                  channel.videoChannel));
    419 
    420   // Render the local capture.
    421   EXPECT_EQ(0, video_engine.render->AddRenderer(capture_id, _window1, 1, 0.0,
    422                                                 0.0, 1.0, 1.0));
    423 
    424   // Render the remote capture.
    425   EXPECT_EQ(0, video_engine.render->AddRenderer(channel.videoChannel, _window2,
    426                                                 1, 0.0, 0.0, 1.0, 1.0));
    427   EXPECT_EQ(0, video_engine.render->StartRender(capture_id));
    428   EXPECT_EQ(0, video_engine.render->StartRender(channel.videoChannel));
    429 
    430   // Register observer.
    431   CaptureObserver observer;
    432   EXPECT_EQ(0, video_engine.capture->RegisterObserver(capture_id, observer));
    433 
    434   // Enable brightness alarm.
    435   EXPECT_EQ(0, video_engine.capture->EnableBrightnessAlarm(capture_id, true));
    436 
    437   CaptureEffectFilter effect_filter(176, 144);
    438   EXPECT_EQ(0, video_engine.image_process->RegisterCaptureEffectFilter(
    439       capture_id, effect_filter));
    440 
    441   // Call started.
    442   ViETest::Log("You should see local preview from external capture\n"
    443                "in window 1 and the remote video in window 2.\n");
    444 
    445   /// **************************************************************
    446   //  Engine ready. Begin testing class
    447   /// **************************************************************
    448   const unsigned int video_frame_length = (176 * 144 * 3) / 2;
    449   unsigned char* video_frame = new unsigned char[video_frame_length];
    450   memset(video_frame, 128, 176 * 144);
    451 
    452   int frame_count = 0;
    453   webrtc::VideoCaptureCapability capability;
    454   capability.width = 176;
    455   capability.height = 144;
    456   capability.rawType = webrtc::kVideoI420;
    457 
    458   ViETest::Log("Testing external capturing and frame rate callbacks.");
    459   // TODO(mflodman) Change when using a real file!
    460   // while (fread(video_frame, video_frame_length, 1, foreman) == 1)
    461   while (frame_count < 120) {
    462     external_capture->IncomingFrame(
    463         video_frame, video_frame_length, capability,
    464         webrtc::TickTime::MillisecondTimestamp());
    465     AutoTestSleep(33);
    466 
    467     if (effect_filter.number_of_captured_frames_ > 2) {
    468       EXPECT_EQ(webrtc::Normal, observer.brightness_) <<
    469           "Brightness or picture alarm should not have been called yet.";
    470       EXPECT_EQ(webrtc::AlarmCleared, observer.alarm_) <<
    471           "Brightness or picture alarm should not have been called yet.";
    472     }
    473     frame_count++;
    474   }
    475 
    476   // Test brightness alarm.
    477   // Test bright image.
    478   for (int i = 0; i < 176 * 144; ++i) {
    479     if (video_frame[i] <= 155)
    480       video_frame[i] = video_frame[i] + 100;
    481     else
    482       video_frame[i] = 255;
    483   }
    484   ViETest::Log("Testing Brighness alarm");
    485   for (int frame = 0; frame < 30; ++frame) {
    486     external_capture->IncomingFrame(
    487         video_frame, video_frame_length, capability,
    488         webrtc::TickTime::MillisecondTimestamp());
    489     AutoTestSleep(33);
    490   }
    491   EXPECT_EQ(webrtc::Bright, observer.brightness_) <<
    492       "Should be bright at this point since we are using a bright image.";
    493 
    494   // Test Dark image
    495   for (int i = 0; i < 176 * 144; ++i) {
    496     video_frame[i] = video_frame[i] > 200 ? video_frame[i] - 200 : 0;
    497   }
    498   for (int frame = 0; frame < 30; ++frame) {
    499     external_capture->IncomingFrame(
    500         video_frame, video_frame_length, capability,
    501         webrtc::TickTime::MillisecondTimestamp());
    502     AutoTestSleep(33);
    503   }
    504   EXPECT_EQ(webrtc::Dark, observer.brightness_) <<
    505       "Should be dark at this point since we are using a dark image.";
    506   EXPECT_GT(effect_filter.number_of_captured_frames_, 150) <<
    507       "Frames should have been played.";
    508 
    509   EXPECT_GE(observer.frame_rate_, 29) <<
    510       "Frame rate callback should be approximately correct.";
    511   EXPECT_LE(observer.frame_rate_, 30) <<
    512       "Frame rate callback should be approximately correct.";
    513 
    514   // Test no picture alarm
    515   ViETest::Log("Testing NoPictureAlarm.");
    516   AutoTestSleep(1050);
    517 
    518   EXPECT_EQ(webrtc::AlarmRaised, observer.alarm_) <<
    519       "No picture alarm should be raised.";
    520   for (int frame = 0; frame < 10; ++frame) {
    521     external_capture->IncomingFrame(
    522         video_frame, video_frame_length, capability,
    523         webrtc::TickTime::MillisecondTimestamp());
    524     AutoTestSleep(33);
    525   }
    526   EXPECT_EQ(webrtc::AlarmCleared, observer.alarm_) <<
    527   "Alarm should be cleared since ge just got some data.";
    528 
    529   delete video_frame;
    530 
    531   // Release the capture device
    532   EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
    533 
    534   // Release the capture device again
    535   EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
    536   EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
    537   vcpm->Release();
    538 
    539   /// **************************************************************
    540   //  Testing finished. Tear down Video Engine
    541   /// **************************************************************
    542 }
    543