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 VideoCaptureController.
      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_controller.h"
     16 #include "content/browser/renderer_host/media/video_capture_manager.h"
     17 #include "content/common/media/media_stream_options.h"
     18 #include "media/video/capture/fake_video_capture_device.h"
     19 #include "media/video/capture/video_capture_device.h"
     20 #include "testing/gmock/include/gmock/gmock.h"
     21 #include "testing/gtest/include/gtest/gtest.h"
     22 
     23 using ::testing::_;
     24 using ::testing::AnyNumber;
     25 using ::testing::AtLeast;
     26 using ::testing::InSequence;
     27 using ::testing::Return;
     28 
     29 namespace content {
     30 
     31 enum { kDeviceId = 1 };
     32 
     33 ACTION_P4(StopCapture, controller, controller_id, controller_handler,
     34           message_loop) {
     35   message_loop->PostTask(FROM_HERE,
     36       base::Bind(&VideoCaptureController::StopCapture,
     37                  controller, controller_id, controller_handler));
     38   message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
     39 }
     40 
     41 ACTION_P3(StopSession, controller, session_id, message_loop) {
     42   message_loop->PostTask(FROM_HERE,
     43       base::Bind(&VideoCaptureController::StopSession,
     44                  controller, session_id));
     45   message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
     46 }
     47 
     48 class MockVideoCaptureControllerEventHandler
     49     : public VideoCaptureControllerEventHandler {
     50  public:
     51   MockVideoCaptureControllerEventHandler(VideoCaptureController* controller,
     52                                          base::MessageLoop* message_loop)
     53       : controller_(controller),
     54         message_loop_(message_loop),
     55         controller_id_(kDeviceId),
     56         process_handle_(base::kNullProcessHandle) {
     57   }
     58   virtual ~MockVideoCaptureControllerEventHandler() {}
     59 
     60   MOCK_METHOD1(DoBufferCreated, void(const VideoCaptureControllerID&));
     61   MOCK_METHOD1(DoBufferReady, void(const VideoCaptureControllerID&));
     62   MOCK_METHOD1(DoFrameInfo, void(const VideoCaptureControllerID&));
     63   MOCK_METHOD1(DoEnded, void(const VideoCaptureControllerID&));
     64 
     65   virtual void OnError(const VideoCaptureControllerID& id) OVERRIDE {}
     66   virtual void OnBufferCreated(const VideoCaptureControllerID& id,
     67                                base::SharedMemoryHandle handle,
     68                                int length, int buffer_id) OVERRIDE {
     69     EXPECT_EQ(id, controller_id_);
     70     DoBufferCreated(id);
     71   }
     72   virtual void OnBufferReady(const VideoCaptureControllerID& id,
     73                              int buffer_id,
     74                              base::Time timestamp) OVERRIDE {
     75     EXPECT_EQ(id, controller_id_);
     76     DoBufferReady(id);
     77     message_loop_->PostTask(FROM_HERE,
     78         base::Bind(&VideoCaptureController::ReturnBuffer,
     79                    controller_, controller_id_, this, buffer_id));
     80   }
     81   virtual void OnFrameInfo(
     82       const VideoCaptureControllerID& id,
     83       const media::VideoCaptureCapability& format) OVERRIDE {
     84     EXPECT_EQ(id, controller_id_);
     85     DoFrameInfo(id);
     86   }
     87   virtual void OnEnded(const VideoCaptureControllerID& id) OVERRIDE {
     88     EXPECT_EQ(id, controller_id_);
     89     DoEnded(id);
     90   }
     91 
     92   scoped_refptr<VideoCaptureController> controller_;
     93   base::MessageLoop* message_loop_;
     94   VideoCaptureControllerID controller_id_;
     95   base::ProcessHandle process_handle_;
     96 };
     97 
     98 class MockVideoCaptureManager : public VideoCaptureManager {
     99  public:
    100   MockVideoCaptureManager()
    101       : video_session_id_(kStartOpenSessionId),
    102         device_name_("fake_device_0", "/dev/video0") {}
    103 
    104   void Init() {
    105     video_capture_device_.reset(
    106         media::FakeVideoCaptureDevice::Create(device_name_));
    107     ASSERT_TRUE(video_capture_device_.get() != NULL);
    108   }
    109 
    110   MOCK_METHOD3(StartCapture, void(int, int,
    111       media::VideoCaptureDevice::EventHandler*));
    112   MOCK_METHOD1(StopCapture, void(const media::VideoCaptureSessionId&));
    113 
    114   void Start(const media::VideoCaptureParams& capture_params,
    115              media::VideoCaptureDevice::EventHandler* vc_receiver) OVERRIDE {
    116     StartCapture(capture_params.width, capture_params.height, vc_receiver);
    117     // TODO(mcasas): Add testing for variable resolution video capture devices,
    118     // supported by FakeVideoCaptureDevice. See crbug.com/261410, second part.
    119     media::VideoCaptureCapability capture_format(
    120         capture_params.width,
    121         capture_params.height,
    122         capture_params.frame_per_second,
    123         media::VideoCaptureCapability::kI420,
    124         0,
    125         false,
    126         media::ConstantResolutionVideoCaptureDevice);
    127     video_capture_device_->Allocate(capture_format, vc_receiver);
    128     video_capture_device_->Start();
    129   }
    130 
    131   void Stop(const media::VideoCaptureSessionId& capture_session_id,
    132             base::Closure stopped_cb) OVERRIDE {
    133     StopCapture(capture_session_id);
    134     video_capture_device_->Stop();
    135     video_capture_device_->DeAllocate();
    136   }
    137 
    138   int video_session_id_;
    139   media::VideoCaptureDevice::Name device_name_;
    140   scoped_ptr<media::VideoCaptureDevice> video_capture_device_;
    141 
    142  private:
    143   virtual ~MockVideoCaptureManager() {}
    144   DISALLOW_COPY_AND_ASSIGN(MockVideoCaptureManager);
    145 };
    146 
    147 // Test class.
    148 class VideoCaptureControllerTest : public testing::Test {
    149  public:
    150   VideoCaptureControllerTest() {}
    151   virtual ~VideoCaptureControllerTest() {}
    152 
    153  protected:
    154   virtual void SetUp() OVERRIDE {
    155     message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
    156     file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE,
    157                                              message_loop_.get()));
    158     io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
    159                                            message_loop_.get()));
    160 
    161     vcm_ = new MockVideoCaptureManager();
    162     vcm_->Init();
    163     controller_ = new VideoCaptureController(vcm_.get());
    164     controller_handler_.reset(new MockVideoCaptureControllerEventHandler(
    165         controller_.get(), message_loop_.get()));
    166   }
    167 
    168   virtual void TearDown() OVERRIDE {}
    169 
    170   scoped_ptr<base::MessageLoop> message_loop_;
    171   scoped_ptr<BrowserThreadImpl> file_thread_;
    172   scoped_ptr<BrowserThreadImpl> io_thread_;
    173   scoped_refptr<MockVideoCaptureManager> vcm_;
    174   scoped_ptr<MockVideoCaptureControllerEventHandler> controller_handler_;
    175   scoped_refptr<VideoCaptureController> controller_;
    176 
    177  private:
    178   DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
    179 };
    180 
    181 // Try to start and stop capture.
    182 TEST_F(VideoCaptureControllerTest, StartAndStop) {
    183   media::VideoCaptureParams capture_params;
    184   capture_params.session_id = vcm_->video_session_id_;
    185   capture_params.width = 320;
    186   capture_params.height = 240;
    187   capture_params.frame_per_second = 30;
    188 
    189   InSequence s;
    190   EXPECT_CALL(*vcm_.get(),
    191               StartCapture(capture_params.width,
    192                            capture_params.height,
    193                            controller_.get())).Times(1);
    194   EXPECT_CALL(*controller_handler_,
    195               DoFrameInfo(controller_handler_->controller_id_))
    196       .Times(AtLeast(1));
    197   EXPECT_CALL(*controller_handler_,
    198               DoBufferCreated(controller_handler_->controller_id_))
    199       .Times(AtLeast(1));
    200   EXPECT_CALL(*controller_handler_,
    201               DoBufferReady(controller_handler_->controller_id_))
    202       .Times(AtLeast(1))
    203       .WillOnce(StopCapture(controller_.get(),
    204                             controller_handler_->controller_id_,
    205                             controller_handler_.get(),
    206                             message_loop_.get()));
    207   EXPECT_CALL(*vcm_.get(), StopCapture(vcm_->video_session_id_)).Times(1);
    208 
    209   controller_->StartCapture(controller_handler_->controller_id_,
    210                             controller_handler_.get(),
    211                             controller_handler_->process_handle_,
    212                             capture_params);
    213   message_loop_->Run();
    214 }
    215 
    216 // Try to stop session before stopping capture.
    217 TEST_F(VideoCaptureControllerTest, StopSession) {
    218   media::VideoCaptureParams capture_params;
    219   capture_params.session_id = vcm_->video_session_id_;
    220   capture_params.width = 320;
    221   capture_params.height = 240;
    222   capture_params.frame_per_second = 30;
    223 
    224   InSequence s;
    225   EXPECT_CALL(*vcm_.get(),
    226               StartCapture(capture_params.width,
    227                            capture_params.height,
    228                            controller_.get())).Times(1);
    229   EXPECT_CALL(*controller_handler_,
    230               DoFrameInfo(controller_handler_->controller_id_))
    231       .Times(AtLeast(1));
    232   EXPECT_CALL(*controller_handler_,
    233               DoBufferCreated(controller_handler_->controller_id_))
    234       .Times(AtLeast(1));
    235   EXPECT_CALL(*controller_handler_,
    236               DoBufferReady(controller_handler_->controller_id_))
    237       .Times(AtLeast(1))
    238       .WillOnce(StopSession(controller_.get(),
    239                             vcm_->video_session_id_,
    240                             message_loop_.get()));
    241   EXPECT_CALL(*controller_handler_,
    242               DoEnded(controller_handler_->controller_id_))
    243       .Times(1);
    244 
    245   controller_->StartCapture(controller_handler_->controller_id_,
    246                             controller_handler_.get(),
    247                             controller_handler_->process_handle_,
    248                             capture_params);
    249   message_loop_->Run();
    250 
    251   // The session is stopped now. There should be no buffer coming from
    252   // controller.
    253   EXPECT_CALL(*controller_handler_,
    254               DoBufferReady(controller_handler_->controller_id_))
    255       .Times(0);
    256   message_loop_->PostDelayedTask(FROM_HERE,
    257       base::MessageLoop::QuitClosure(), base::TimeDelta::FromSeconds(1));
    258   message_loop_->Run();
    259 
    260   EXPECT_CALL(*vcm_.get(), StopCapture(vcm_->video_session_id_)).Times(1);
    261   controller_->StopCapture(controller_handler_->controller_id_,
    262                            controller_handler_.get());
    263 }
    264 
    265 }  // namespace content
    266