tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

video_capture_unittest.cc (13707B)


      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 "modules/video_capture/video_capture.h"
     12 
     13 #include <cstdint>
     14 #include <cstdio>
     15 #include <map>
     16 #include <memory>
     17 #include <sstream>
     18 #include <string>
     19 #include <vector>
     20 
     21 #include "api/scoped_refptr.h"
     22 #include "api/test/rtc_error_matchers.h"
     23 #include "api/units/time_delta.h"
     24 #include "api/video/video_frame.h"
     25 #include "api/video/video_rotation.h"
     26 #include "api/video/video_sink_interface.h"
     27 #include "modules/video_capture/video_capture_defines.h"
     28 #include "modules/video_capture/video_capture_factory.h"
     29 #include "rtc_base/checks.h"
     30 #include "rtc_base/synchronization/mutex.h"
     31 #include "system_wrappers/include/clock.h"
     32 #include "test/frame_utils.h"
     33 #include "test/gmock.h"
     34 #include "test/gtest.h"
     35 #include "test/wait_until.h"
     36 
     37 namespace webrtc {
     38 namespace {
     39 
     40 using ::testing::Ge;
     41 
     42 static const int kTimeOut = 5000;
     43 #ifdef WEBRTC_MAC
     44 static const int kTestHeight = 288;
     45 static const int kTestWidth = 352;
     46 static const int kTestFramerate = 30;
     47 #endif
     48 
     49 class TestVideoCaptureCallback : public VideoSinkInterface<webrtc::VideoFrame> {
     50 public:
     51  explicit TestVideoCaptureCallback(Clock& clock)
     52      : clock_(clock),
     53        last_render_time_ms_(0),
     54        incoming_frames_(0),
     55        timing_warnings_(0),
     56        rotate_frame_(kVideoRotation_0) {}
     57 
     58  ~TestVideoCaptureCallback() override {
     59    if (timing_warnings_ > 0)
     60      printf("No of timing warnings %d\n", timing_warnings_);
     61  }
     62 
     63  void OnFrame(const VideoFrame& videoFrame) override {
     64    MutexLock lock(&capture_lock_);
     65    int height = videoFrame.height();
     66    int width = videoFrame.width();
     67 #if defined(WEBRTC_ANDROID) && WEBRTC_ANDROID
     68    // Android camera frames may be rotated depending on test device
     69    // orientation.
     70    EXPECT_TRUE(height == capability_.height || height == capability_.width);
     71    EXPECT_TRUE(width == capability_.width || width == capability_.height);
     72 #else
     73    EXPECT_EQ(height, capability_.height);
     74    EXPECT_EQ(width, capability_.width);
     75    EXPECT_EQ(rotate_frame_, videoFrame.rotation());
     76 #endif
     77    // RenderTimstamp should be the time now.
     78    EXPECT_TRUE(videoFrame.render_time_ms() >=
     79                    clock_.TimeInMilliseconds() - 30 &&
     80                videoFrame.render_time_ms() <= clock_.TimeInMilliseconds());
     81 
     82    if ((videoFrame.render_time_ms() >
     83             last_render_time_ms_ + (1000 * 1.1) / capability_.maxFPS &&
     84         last_render_time_ms_ > 0) ||
     85        (videoFrame.render_time_ms() <
     86             last_render_time_ms_ + (1000 * 0.9) / capability_.maxFPS &&
     87         last_render_time_ms_ > 0)) {
     88      timing_warnings_++;
     89    }
     90 
     91    incoming_frames_++;
     92    last_render_time_ms_ = videoFrame.render_time_ms();
     93    last_frame_ = videoFrame.video_frame_buffer();
     94  }
     95 
     96  void SetExpectedCapability(VideoCaptureCapability capability) {
     97    MutexLock lock(&capture_lock_);
     98    capability_ = capability;
     99    incoming_frames_ = 0;
    100    last_render_time_ms_ = 0;
    101  }
    102  int incoming_frames() {
    103    MutexLock lock(&capture_lock_);
    104    return incoming_frames_;
    105  }
    106 
    107  int timing_warnings() {
    108    MutexLock lock(&capture_lock_);
    109    return timing_warnings_;
    110  }
    111  VideoCaptureCapability capability() {
    112    MutexLock lock(&capture_lock_);
    113    return capability_;
    114  }
    115 
    116  bool CompareLastFrame(const VideoFrame& frame) {
    117    MutexLock lock(&capture_lock_);
    118    return test::FrameBufsEqual(last_frame_, frame.video_frame_buffer());
    119  }
    120 
    121  void SetExpectedCaptureRotation(VideoRotation rotation) {
    122    MutexLock lock(&capture_lock_);
    123    rotate_frame_ = rotation;
    124  }
    125 
    126 private:
    127  Mutex capture_lock_;
    128  VideoCaptureCapability capability_;
    129  Clock& clock_;
    130  int64_t last_render_time_ms_;
    131  int incoming_frames_;
    132  int timing_warnings_;
    133  scoped_refptr<webrtc::VideoFrameBuffer> last_frame_;
    134  VideoRotation rotate_frame_;
    135 };
    136 
    137 class VideoCaptureTest : public ::testing::Test {
    138 public:
    139  VideoCaptureTest()
    140      : clock_(*Clock::GetRealTimeClock()), number_of_devices_(0) {}
    141 
    142  void SetUp() override {
    143    device_info_.reset(VideoCaptureFactory::CreateDeviceInfo());
    144    RTC_DCHECK(device_info_.get());
    145    number_of_devices_ = device_info_->NumberOfDevices();
    146    ASSERT_GT(number_of_devices_, 0u);
    147  }
    148 
    149  scoped_refptr<VideoCaptureModule> OpenVideoCaptureDevice(
    150      unsigned int device,
    151      VideoSinkInterface<webrtc::VideoFrame>* callback) {
    152    char device_name[256];
    153    char unique_name[256];
    154 
    155    EXPECT_EQ(0, device_info_->GetDeviceName(device, device_name, 256,
    156                                             unique_name, 256));
    157 
    158    scoped_refptr<VideoCaptureModule> module(
    159        VideoCaptureFactory::Create(unique_name));
    160    if (module.get() == nullptr)
    161      return nullptr;
    162 
    163    EXPECT_FALSE(module->CaptureStarted());
    164 
    165    module->RegisterCaptureDataCallback(callback);
    166    return module;
    167  }
    168 
    169  void StartCapture(VideoCaptureModule* capture_module,
    170                    VideoCaptureCapability capability) {
    171    ASSERT_EQ(0, capture_module->StartCapture(capability));
    172    EXPECT_TRUE(capture_module->CaptureStarted());
    173 
    174    VideoCaptureCapability resulting_capability;
    175    EXPECT_EQ(0, capture_module->CaptureSettings(resulting_capability));
    176    EXPECT_EQ(capability.width, resulting_capability.width);
    177    EXPECT_EQ(capability.height, resulting_capability.height);
    178  }
    179 
    180  Clock& clock_;
    181  std::unique_ptr<VideoCaptureModule::DeviceInfo> device_info_;
    182  unsigned int number_of_devices_;
    183 };
    184 
    185 #ifdef WEBRTC_MAC
    186 // Currently fails on Mac 64-bit, see
    187 // https://bugs.chromium.org/p/webrtc/issues/detail?id=5406
    188 #define MAYBE_CreateDelete DISABLED_CreateDelete
    189 #else
    190 #define MAYBE_CreateDelete CreateDelete
    191 #endif
    192 TEST_F(VideoCaptureTest, MAYBE_CreateDelete) {
    193  for (int i = 0; i < 5; ++i) {
    194    int64_t start_time = clock_.TimeInMilliseconds();
    195    TestVideoCaptureCallback capture_observer(clock_);
    196    scoped_refptr<VideoCaptureModule> module(
    197        OpenVideoCaptureDevice(0, &capture_observer));
    198    ASSERT_TRUE(module.get() != nullptr);
    199 
    200    VideoCaptureCapability capability;
    201 #ifndef WEBRTC_MAC
    202    device_info_->GetCapability(module->CurrentDeviceName(), 0, capability);
    203 #else
    204    capability.width = kTestWidth;
    205    capability.height = kTestHeight;
    206    capability.maxFPS = kTestFramerate;
    207    capability.videoType = VideoType::kUnknown;
    208 #endif
    209    capture_observer.SetExpectedCapability(capability);
    210    ASSERT_NO_FATAL_FAILURE(StartCapture(module.get(), capability));
    211 
    212    // Less than 4s to start the camera.
    213    EXPECT_LE(clock_.TimeInMilliseconds() - start_time, 4000);
    214 
    215    // Make sure 5 frames are captured.
    216    EXPECT_THAT(WaitUntil([&] { return capture_observer.incoming_frames(); },
    217                          Ge(5), {.timeout = TimeDelta::Millis(kTimeOut)}),
    218                IsRtcOk());
    219 
    220    int64_t stop_time = clock_.TimeInMilliseconds();
    221    EXPECT_EQ(0, module->StopCapture());
    222    EXPECT_FALSE(module->CaptureStarted());
    223 
    224    // Less than 3s to stop the camera.
    225    EXPECT_LE(clock_.TimeInMilliseconds() - stop_time, 3000);
    226  }
    227 }
    228 
    229 #ifdef WEBRTC_MAC
    230 // Currently fails on Mac 64-bit, see
    231 // https://bugs.chromium.org/p/webrtc/issues/detail?id=5406
    232 #define MAYBE_Capabilities DISABLED_Capabilities
    233 #else
    234 #define MAYBE_Capabilities Capabilities
    235 #endif
    236 TEST_F(VideoCaptureTest, MAYBE_Capabilities) {
    237  TestVideoCaptureCallback capture_observer(clock_);
    238 
    239  scoped_refptr<VideoCaptureModule> module(
    240      OpenVideoCaptureDevice(0, &capture_observer));
    241  ASSERT_TRUE(module.get() != nullptr);
    242 
    243  int number_of_capabilities =
    244      device_info_->NumberOfCapabilities(module->CurrentDeviceName());
    245  EXPECT_GT(number_of_capabilities, 0);
    246  // Key is <width>x<height>, value is vector of maxFPS values at that
    247  // resolution.
    248  typedef std::map<std::string, std::vector<int> > FrameRatesByResolution;
    249  FrameRatesByResolution frame_rates_by_resolution;
    250  for (int i = 0; i < number_of_capabilities; ++i) {
    251    VideoCaptureCapability capability;
    252    EXPECT_EQ(0, device_info_->GetCapability(module->CurrentDeviceName(), i,
    253                                             capability));
    254    std::ostringstream resolutionStream;
    255    resolutionStream << capability.width << "x" << capability.height;
    256    resolutionStream.flush();
    257    std::string resolution = resolutionStream.str();
    258    frame_rates_by_resolution[resolution].push_back(capability.maxFPS);
    259 
    260    // Since Android presents so many resolution/FPS combinations and the test
    261    // runner imposes a timeout, we only actually start the capture and test
    262    // that a frame was captured for 2 frame-rates at each resolution.
    263    if (frame_rates_by_resolution[resolution].size() > 2)
    264      continue;
    265 
    266    capture_observer.SetExpectedCapability(capability);
    267    ASSERT_NO_FATAL_FAILURE(StartCapture(module.get(), capability));
    268    // Make sure at least one frame is captured.
    269    EXPECT_THAT(WaitUntil([&] { return capture_observer.incoming_frames(); },
    270                          Ge(1), {.timeout = TimeDelta::Millis(kTimeOut)}),
    271                IsRtcOk());
    272 
    273    EXPECT_EQ(0, module->StopCapture());
    274  }
    275 
    276 #if defined(WEBRTC_ANDROID) && WEBRTC_ANDROID
    277  // There's no reason for this to _necessarily_ be true, but in practice all
    278  // Android devices this test runs on in fact do support multiple capture
    279  // resolutions and multiple frame-rates per captured resolution, so we assert
    280  // this fact here as a regression-test against the time that we only noticed a
    281  // single frame-rate per resolution (bug 2974).  If this test starts being run
    282  // on devices for which this is untrue (e.g. Nexus4) then the following should
    283  // probably be wrapped in a base::android::BuildInfo::model()/device() check.
    284  EXPECT_GT(frame_rates_by_resolution.size(), 1U);
    285  for (FrameRatesByResolution::const_iterator it =
    286           frame_rates_by_resolution.begin();
    287       it != frame_rates_by_resolution.end(); ++it) {
    288    EXPECT_GT(it->second.size(), 1U) << it->first;
    289  }
    290 #endif  // WEBRTC_ANDROID
    291 }
    292 
    293 // NOTE: flaky, crashes sometimes.
    294 // http://code.google.com/p/webrtc/issues/detail?id=777
    295 TEST_F(VideoCaptureTest, DISABLED_TestTwoCameras) {
    296  if (number_of_devices_ < 2) {
    297    printf("There are not two cameras available. Aborting test. \n");
    298    return;
    299  }
    300 
    301  TestVideoCaptureCallback capture_observer1(clock_);
    302  scoped_refptr<VideoCaptureModule> module1(
    303      OpenVideoCaptureDevice(0, &capture_observer1));
    304  ASSERT_TRUE(module1.get() != nullptr);
    305  VideoCaptureCapability capability1;
    306 #ifndef WEBRTC_MAC
    307  device_info_->GetCapability(module1->CurrentDeviceName(), 0, capability1);
    308 #else
    309  capability1.width = kTestWidth;
    310  capability1.height = kTestHeight;
    311  capability1.maxFPS = kTestFramerate;
    312  capability1.videoType = VideoType::kUnknown;
    313 #endif
    314  capture_observer1.SetExpectedCapability(capability1);
    315 
    316  TestVideoCaptureCallback capture_observer2(clock_);
    317  scoped_refptr<VideoCaptureModule> module2(
    318      OpenVideoCaptureDevice(1, &capture_observer2));
    319  ASSERT_TRUE(module1.get() != nullptr);
    320 
    321  VideoCaptureCapability capability2;
    322 #ifndef WEBRTC_MAC
    323  device_info_->GetCapability(module2->CurrentDeviceName(), 0, capability2);
    324 #else
    325  capability2.width = kTestWidth;
    326  capability2.height = kTestHeight;
    327  capability2.maxFPS = kTestFramerate;
    328  capability2.videoType = VideoType::kUnknown;
    329 #endif
    330  capture_observer2.SetExpectedCapability(capability2);
    331 
    332  ASSERT_NO_FATAL_FAILURE(StartCapture(module1.get(), capability1));
    333  ASSERT_NO_FATAL_FAILURE(StartCapture(module2.get(), capability2));
    334  EXPECT_THAT(WaitUntil([&] { return capture_observer1.incoming_frames(); },
    335                        Ge(5), {.timeout = TimeDelta::Millis(kTimeOut)}),
    336              IsRtcOk());
    337  EXPECT_THAT(WaitUntil([&] { return capture_observer2.incoming_frames(); },
    338                        Ge(5), {.timeout = TimeDelta::Millis(kTimeOut)}),
    339              IsRtcOk());
    340  EXPECT_EQ(0, module2->StopCapture());
    341  EXPECT_EQ(0, module1->StopCapture());
    342 }
    343 
    344 #ifdef WEBRTC_MAC
    345 // No VideoCaptureImpl on Mac.
    346 #define MAYBE_ConcurrentAccess DISABLED_ConcurrentAccess
    347 #else
    348 #define MAYBE_ConcurrentAccess ConcurrentAccess
    349 #endif
    350 TEST_F(VideoCaptureTest, MAYBE_ConcurrentAccess) {
    351  TestVideoCaptureCallback capture_observer1(clock_);
    352  scoped_refptr<VideoCaptureModule> module1(
    353      OpenVideoCaptureDevice(0, &capture_observer1));
    354  ASSERT_TRUE(module1.get() != nullptr);
    355  VideoCaptureCapability capability;
    356  device_info_->GetCapability(module1->CurrentDeviceName(), 0, capability);
    357  capture_observer1.SetExpectedCapability(capability);
    358 
    359  TestVideoCaptureCallback capture_observer2(clock_);
    360  scoped_refptr<VideoCaptureModule> module2(
    361      OpenVideoCaptureDevice(0, &capture_observer2));
    362  ASSERT_TRUE(module2.get() != nullptr);
    363  capture_observer2.SetExpectedCapability(capability);
    364 
    365  // Starting module1 should work.
    366  ASSERT_NO_FATAL_FAILURE(StartCapture(module1.get(), capability));
    367  EXPECT_THAT(WaitUntil([&] { return capture_observer1.incoming_frames(); },
    368                        Ge(5), {.timeout = TimeDelta::Millis(kTimeOut)}),
    369              IsRtcOk());
    370 
    371  // When module1 is stopped, starting module2 for the same device should work.
    372  EXPECT_EQ(0, module1->StopCapture());
    373  ASSERT_NO_FATAL_FAILURE(StartCapture(module2.get(), capability));
    374  EXPECT_THAT(WaitUntil([&] { return capture_observer2.incoming_frames(); },
    375                        Ge(5), {.timeout = TimeDelta::Millis(kTimeOut)}),
    376              IsRtcOk());
    377 
    378  EXPECT_EQ(0, module2->StopCapture());
    379 }
    380 
    381 }  // namespace
    382 }  // namespace webrtc