Home | History | Annotate | Download | only in media
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Unit test for VideoCaptureManager.
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/ref_counted.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/message_loop/message_loop.h"
     13 #include "content/browser/browser_thread_impl.h"
     14 #include "content/browser/renderer_host/media/media_stream_provider.h"
     15 #include "content/browser/renderer_host/media/video_capture_manager.h"
     16 #include "content/common/media/media_stream_options.h"
     17 #include "media/video/capture/video_capture_device.h"
     18 #include "testing/gmock/include/gmock/gmock.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 
     21 using ::testing::_;
     22 using ::testing::AnyNumber;
     23 using ::testing::InSequence;
     24 using testing::SaveArg;
     25 using ::testing::Return;
     26 
     27 namespace content {
     28 
     29 // Listener class used to track progress of VideoCaptureManager test.
     30 class MockMediaStreamProviderListener : public MediaStreamProviderListener {
     31  public:
     32   MockMediaStreamProviderListener() {}
     33   ~MockMediaStreamProviderListener() {}
     34 
     35   MOCK_METHOD2(Opened, void(MediaStreamType, int));
     36   MOCK_METHOD2(Closed, void(MediaStreamType, int));
     37   MOCK_METHOD2(DevicesEnumerated, void(MediaStreamType,
     38                                        const StreamDeviceInfoArray&));
     39   MOCK_METHOD3(Error, void(MediaStreamType, int,
     40                            MediaStreamProviderError));
     41 };  // class MockMediaStreamProviderListener
     42 
     43 // Needed as an input argument to Start().
     44 class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
     45  public:
     46   virtual scoped_refptr<media::VideoFrame> ReserveOutputBuffer() OVERRIDE {
     47     return NULL;
     48   }
     49   virtual void OnError() OVERRIDE {}
     50   virtual void OnFrameInfo(
     51       const media::VideoCaptureCapability& info) OVERRIDE {}
     52   virtual void OnIncomingCapturedFrame(const uint8* data,
     53                                        int length,
     54                                        base::Time timestamp,
     55                                        int rotation,
     56                                        bool flip_vert,
     57                                        bool flip_horiz) OVERRIDE {}
     58   virtual void OnIncomingCapturedVideoFrame(
     59       const scoped_refptr<media::VideoFrame>& frame,
     60       base::Time timestamp) OVERRIDE {}
     61 };
     62 
     63 // Test class
     64 class VideoCaptureManagerTest : public testing::Test {
     65  public:
     66   VideoCaptureManagerTest() {}
     67   virtual ~VideoCaptureManagerTest() {}
     68 
     69  protected:
     70   virtual void SetUp() OVERRIDE {
     71     listener_.reset(new MockMediaStreamProviderListener());
     72     message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
     73     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
     74                                            message_loop_.get()));
     75     vcm_ = new VideoCaptureManager();
     76     vcm_->UseFakeDevice();
     77     vcm_->Register(listener_.get(), message_loop_->message_loop_proxy().get());
     78     frame_observer_.reset(new MockFrameObserver());
     79   }
     80 
     81   virtual void TearDown() OVERRIDE {}
     82 
     83   scoped_refptr<VideoCaptureManager> vcm_;
     84   scoped_ptr<MockMediaStreamProviderListener> listener_;
     85   scoped_ptr<base::MessageLoop> message_loop_;
     86   scoped_ptr<BrowserThreadImpl> io_thread_;
     87   scoped_ptr<MockFrameObserver> frame_observer_;
     88 
     89  private:
     90   DISALLOW_COPY_AND_ASSIGN(VideoCaptureManagerTest);
     91 };
     92 
     93 // Test cases
     94 
     95 // Try to open, start, stop and close a device.
     96 TEST_F(VideoCaptureManagerTest, CreateAndClose) {
     97   StreamDeviceInfoArray devices;
     98 
     99   InSequence s;
    100   EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
    101       .Times(1).WillOnce(SaveArg<1>(&devices));
    102   EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
    103   EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
    104 
    105   vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
    106 
    107   // Wait to get device callback.
    108   message_loop_->RunUntilIdle();
    109 
    110   int video_session_id = vcm_->Open(devices.front());
    111 
    112   media::VideoCaptureParams capture_params;
    113   capture_params.session_id = video_session_id;
    114   capture_params.width = 320;
    115   capture_params.height = 240;
    116   capture_params.frame_per_second = 30;
    117   vcm_->Start(capture_params, frame_observer_.get());
    118 
    119   vcm_->Stop(video_session_id, base::Closure());
    120   vcm_->Close(video_session_id);
    121 
    122   // Wait to check callbacks before removing the listener.
    123   message_loop_->RunUntilIdle();
    124   vcm_->Unregister();
    125 }
    126 
    127 // Open the same device twice.
    128 TEST_F(VideoCaptureManagerTest, OpenTwice) {
    129   StreamDeviceInfoArray devices;
    130 
    131   InSequence s;
    132   EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
    133       .Times(1).WillOnce(SaveArg<1>(&devices));
    134   EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
    135   EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
    136 
    137   vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
    138 
    139   // Wait to get device callback.
    140   message_loop_->RunUntilIdle();
    141 
    142   int video_session_id_first = vcm_->Open(devices.front());
    143 
    144   // This should trigger an error callback with error code
    145   // 'kDeviceAlreadyInUse'.
    146   int video_session_id_second = vcm_->Open(devices.front());
    147   EXPECT_NE(video_session_id_first, video_session_id_second);
    148 
    149   vcm_->Close(video_session_id_first);
    150   vcm_->Close(video_session_id_second);
    151 
    152   // Wait to check callbacks before removing the listener.
    153   message_loop_->RunUntilIdle();
    154   vcm_->Unregister();
    155 }
    156 
    157 // Open two different devices.
    158 TEST_F(VideoCaptureManagerTest, OpenTwo) {
    159   StreamDeviceInfoArray devices;
    160 
    161   InSequence s;
    162   EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
    163       .Times(1).WillOnce(SaveArg<1>(&devices));
    164   EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
    165   EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(2);
    166 
    167   vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
    168 
    169   // Wait to get device callback.
    170   message_loop_->RunUntilIdle();
    171 
    172   StreamDeviceInfoArray::iterator it = devices.begin();
    173 
    174   int video_session_id_first = vcm_->Open(*it);
    175   ++it;
    176   int video_session_id_second = vcm_->Open(*it);
    177 
    178   vcm_->Close(video_session_id_first);
    179   vcm_->Close(video_session_id_second);
    180 
    181   // Wait to check callbacks before removing the listener.
    182   message_loop_->RunUntilIdle();
    183   vcm_->Unregister();
    184 }
    185 
    186 // Try open a non-existing device.
    187 TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
    188   StreamDeviceInfoArray devices;
    189 
    190   InSequence s;
    191   EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
    192       .Times(1).WillOnce(SaveArg<1>(&devices));
    193   EXPECT_CALL(*listener_, Error(MEDIA_DEVICE_VIDEO_CAPTURE,
    194                                 _, kDeviceNotAvailable))
    195       .Times(1);
    196 
    197   vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
    198 
    199   // Wait to get device callback.
    200   message_loop_->RunUntilIdle();
    201 
    202   MediaStreamType stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
    203   std::string device_name("device_doesnt_exist");
    204   std::string device_id("id_doesnt_exist");
    205   StreamDeviceInfo dummy_device(stream_type, device_name, device_id, false);
    206 
    207   // This should fail with error code 'kDeviceNotAvailable'.
    208   vcm_->Open(dummy_device);
    209 
    210   // Wait to check callbacks before removing the listener.
    211   message_loop_->RunUntilIdle();
    212   vcm_->Unregister();
    213 }
    214 
    215 // Start a device using "magic" id, i.e. call Start without calling Open.
    216 TEST_F(VideoCaptureManagerTest, StartUsingId) {
    217   InSequence s;
    218   EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
    219   EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
    220 
    221   media::VideoCaptureParams capture_params;
    222   capture_params.session_id = VideoCaptureManager::kStartOpenSessionId;
    223   capture_params.width = 320;
    224   capture_params.height = 240;
    225   capture_params.frame_per_second = 30;
    226 
    227   // Start shall trigger the Open callback.
    228   vcm_->Start(capture_params, frame_observer_.get());
    229 
    230   // Stop shall trigger the Close callback
    231   vcm_->Stop(VideoCaptureManager::kStartOpenSessionId, base::Closure());
    232 
    233   // Wait to check callbacks before removing the listener.
    234   message_loop_->RunUntilIdle();
    235   vcm_->Unregister();
    236 }
    237 
    238 // Open and start a device, close it before calling Stop.
    239 TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
    240   StreamDeviceInfoArray devices;
    241 
    242   InSequence s;
    243   EXPECT_CALL(*listener_, DevicesEnumerated(MEDIA_DEVICE_VIDEO_CAPTURE, _))
    244       .Times(1).WillOnce(SaveArg<1>(&devices));
    245   EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
    246   EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _)).Times(1);
    247 
    248   vcm_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
    249 
    250   // Wait to get device callback.
    251   message_loop_->RunUntilIdle();
    252 
    253   int video_session_id = vcm_->Open(devices.front());
    254 
    255   media::VideoCaptureParams capture_params;
    256   capture_params.session_id = video_session_id;
    257   capture_params.width = 320;
    258   capture_params.height = 240;
    259   capture_params.frame_per_second = 30;
    260   vcm_->Start(capture_params, frame_observer_.get());
    261 
    262   // Close will stop the running device, an assert will be triggered in
    263   // VideoCaptureManager destructor otherwise.
    264   vcm_->Close(video_session_id);
    265   vcm_->Stop(video_session_id, base::Closure());
    266 
    267   // Wait to check callbacks before removing the listener
    268   message_loop_->RunUntilIdle();
    269   vcm_->Unregister();
    270 }
    271 
    272 }  // namespace content
    273