Index: media/video/capture/video_capture_device_unittest.cc |
diff --git a/media/video/capture/video_capture_device_unittest.cc b/media/video/capture/video_capture_device_unittest.cc |
index 5a19d272c93d3eef65707bf92b21173bcfc0b0e2..586060f169fdac71b838effc7e976607e8f528ae 100644 |
--- a/media/video/capture/video_capture_device_unittest.cc |
+++ b/media/video/capture/video_capture_device_unittest.cc |
@@ -2,8 +2,12 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
+#include "base/bind.h" |
+#include "base/bind_helpers.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/message_loop/message_loop_proxy.h" |
+#include "base/run_loop.h" |
#include "base/synchronization/waitable_event.h" |
#include "base/test/test_timeouts.h" |
#include "base/threading/thread.h" |
@@ -65,8 +69,10 @@ class MockFrameObserver : public media::VideoCaptureDevice::EventHandler { |
MOCK_METHOD1(OnFrameInfo, void(const VideoCaptureCapability&)); |
MOCK_METHOD1(OnFrameInfoChanged, void(const VideoCaptureCapability&)); |
- explicit MockFrameObserver(base::WaitableEvent* wait_event) |
- : wait_event_(wait_event) {} |
+ explicit MockFrameObserver( |
+ base::Closure frame_cb) |
+ : main_thread_(base::MessageLoopProxy::current()), |
+ frame_cb_(frame_cb) {} |
virtual void OnError() OVERRIDE { |
OnErr(); |
@@ -79,45 +85,40 @@ class MockFrameObserver : public media::VideoCaptureDevice::EventHandler { |
int rotation, |
bool flip_vert, |
bool flip_horiz) OVERRIDE { |
- wait_event_->Signal(); |
+ main_thread_->PostTask(FROM_HERE, frame_cb_); |
} |
virtual void OnIncomingCapturedVideoFrame( |
const scoped_refptr<media::VideoFrame>& frame, |
base::Time timestamp) OVERRIDE { |
- wait_event_->Signal(); |
+ main_thread_->PostTask(FROM_HERE, frame_cb_); |
} |
private: |
- base::WaitableEvent* wait_event_; |
+ scoped_refptr<base::MessageLoopProxy> main_thread_; |
+ base::Closure frame_cb_; |
}; |
class VideoCaptureDeviceTest : public testing::Test { |
- public: |
- VideoCaptureDeviceTest(): wait_event_(false, false) { } |
- |
- void PostQuitTask() { |
- loop_->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); |
- loop_->Run(); |
- } |
- |
protected: |
+ typedef media::VideoCaptureDevice::EventHandler EventHandler; |
+ |
virtual void SetUp() { |
- frame_observer_.reset(new MockFrameObserver(&wait_event_)); |
loop_.reset(new base::MessageLoopForUI()); |
+ frame_observer_.reset(new MockFrameObserver(loop_->QuitClosure())); |
#if defined(OS_ANDROID) |
media::VideoCaptureDeviceAndroid::RegisterVideoCaptureDevice( |
base::android::AttachCurrentThread()); |
#endif |
} |
- virtual void TearDown() { |
+ void WaitForCapturedFrame() { |
+ loop_->Run(); |
} |
#if defined(OS_WIN) |
base::win::ScopedCOMInitializer initialize_com_; |
#endif |
- base::WaitableEvent wait_event_; |
scoped_ptr<MockFrameObserver> frame_observer_; |
VideoCaptureDevice::Names names_; |
scoped_ptr<base::MessageLoop> loop_; |
@@ -163,15 +164,13 @@ TEST_F(VideoCaptureDeviceTest, CaptureVGA) { |
0, |
false, |
ConstantResolutionVideoCaptureDevice); |
- device->Allocate(capture_format, frame_observer_.get()); |
- device->Start(); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
// Get captured video frames. |
- PostQuitTask(); |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_max_timeout())); |
+ loop_->Run(); |
EXPECT_EQ(rx_capability.width, 640); |
EXPECT_EQ(rx_capability.height, 480); |
- device->Stop(); |
- device->DeAllocate(); |
+ device->StopAndDeAllocate(); |
} |
TEST_F(VideoCaptureDeviceTest, Capture720p) { |
@@ -201,13 +200,11 @@ TEST_F(VideoCaptureDeviceTest, Capture720p) { |
0, |
false, |
ConstantResolutionVideoCaptureDevice); |
- device->Allocate(capture_format, frame_observer_.get()); |
- device->Start(); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
// Get captured video frames. |
- PostQuitTask(); |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_max_timeout())); |
- device->Stop(); |
- device->DeAllocate(); |
+ WaitForCapturedFrame(); |
+ device->StopAndDeAllocate(); |
} |
TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) { |
@@ -235,8 +232,9 @@ TEST_F(VideoCaptureDeviceTest, MAYBE_AllocateBadSize) { |
0, |
false, |
ConstantResolutionVideoCaptureDevice); |
- device->Allocate(capture_format, frame_observer_.get()); |
- device->DeAllocate(); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
+ device->StopAndDeAllocate(); |
EXPECT_EQ(rx_capability.width, 640); |
EXPECT_EQ(rx_capability.height, 480); |
} |
@@ -247,58 +245,67 @@ TEST_F(VideoCaptureDeviceTest, ReAllocateCamera) { |
DVLOG(1) << "No camera available. Exiting test."; |
return; |
} |
+ |
+ // First, do a number of very fast device start/stops. |
+ for (int i = 0; i <= 5; i++) { |
+ scoped_ptr<MockFrameObserver> frame_observer( |
+ new MockFrameObserver(base::Bind(&base::DoNothing))); |
+ scoped_ptr<VideoCaptureDevice> device( |
+ VideoCaptureDevice::Create(names_.front())); |
+ gfx::Size resolution; |
+ if (i % 2) { |
+ resolution = gfx::Size(640, 480); |
+ } else { |
+ resolution = gfx::Size(1280, 1024); |
+ } |
+ VideoCaptureCapability requested_format( |
+ resolution.width(), |
+ resolution.height(), |
+ 30, |
+ PIXEL_FORMAT_I420, |
+ 0, |
+ false, |
+ ConstantResolutionVideoCaptureDevice); |
+ |
+ // The device (if it is an async implementation) may or may not get as far |
+ // as the OnFrameInfo() step; we're intentionally not going to wait for it |
+ // to get that far. |
+ ON_CALL(*frame_observer, OnFrameInfo(_)); |
+ device->AllocateAndStart(requested_format, |
+ frame_observer.PassAs<EventHandler>()); |
+ device->StopAndDeAllocate(); |
+ } |
+ |
+ // Finally, do a device start and wait for it to finish. |
+ gfx::Size resolution; |
+ VideoCaptureCapability requested_format( |
+ 320, |
+ 240, |
+ 30, |
+ PIXEL_FORMAT_I420, |
+ 0, |
+ false, |
+ ConstantResolutionVideoCaptureDevice); |
+ |
+ base::RunLoop run_loop; |
+ scoped_ptr<MockFrameObserver> frame_observer( |
+ new MockFrameObserver(base::Bind(run_loop.QuitClosure()))); |
scoped_ptr<VideoCaptureDevice> device( |
VideoCaptureDevice::Create(names_.front())); |
- ASSERT_TRUE(device.get() != NULL); |
- EXPECT_CALL(*frame_observer_, OnErr()) |
- .Times(0); |
- // Get info about the new resolution. |
- VideoCaptureCapability rx_capability_1; |
- VideoCaptureCapability rx_capability_2; |
- VideoCaptureCapability capture_format_1(640, |
- 480, |
- 30, |
- PIXEL_FORMAT_I420, |
- 0, |
- false, |
- ConstantResolutionVideoCaptureDevice); |
- VideoCaptureCapability capture_format_2(1280, |
- 1024, |
- 30, |
- PIXEL_FORMAT_I420, |
- 0, |
- false, |
- ConstantResolutionVideoCaptureDevice); |
- VideoCaptureCapability capture_format_3(320, |
- 240, |
- 30, |
- PIXEL_FORMAT_I420, |
- 0, |
- false, |
- ConstantResolutionVideoCaptureDevice); |
- EXPECT_CALL(*frame_observer_, OnFrameInfo(_)) |
- .WillOnce(SaveArg<0>(&rx_capability_1)); |
- device->Allocate(capture_format_1, frame_observer_.get()); |
- device->Start(); |
- // Nothing shall happen. |
- device->Allocate(capture_format_2, frame_observer_.get()); |
- device->DeAllocate(); |
- // Allocate new size 320, 240 |
- EXPECT_CALL(*frame_observer_, OnFrameInfo(_)) |
- .WillOnce(SaveArg<0>(&rx_capability_2)); |
- device->Allocate(capture_format_3, frame_observer_.get()); |
- |
- device->Start(); |
- // Get captured video frames. |
- PostQuitTask(); |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_max_timeout())); |
- EXPECT_EQ(rx_capability_1.width, 640); |
- EXPECT_EQ(rx_capability_1.height, 480); |
- EXPECT_EQ(rx_capability_2.width, 320); |
- EXPECT_EQ(rx_capability_2.height, 240); |
- device->Stop(); |
- device->DeAllocate(); |
+ // The device (if it is an async implementation) may or may not get as far |
+ // as the OnFrameInfo() step; we're intentionally not going to wait for it |
+ // to get that far. |
+ VideoCaptureCapability final_format; |
+ EXPECT_CALL(*frame_observer, OnFrameInfo(_)) |
+ .Times(1).WillOnce(SaveArg<0>(&final_format)); |
+ device->AllocateAndStart(requested_format, |
+ frame_observer.PassAs<EventHandler>()); |
+ run_loop.Run(); // Waits for a frame. |
+ device->StopAndDeAllocate(); |
+ device.reset(); |
+ EXPECT_EQ(final_format.width, 320); |
+ EXPECT_EQ(final_format.height, 240); |
} |
TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) { |
@@ -325,16 +332,14 @@ TEST_F(VideoCaptureDeviceTest, DeAllocateCameraWhileRunning) { |
0, |
false, |
ConstantResolutionVideoCaptureDevice); |
- device->Allocate(capture_format, frame_observer_.get()); |
- |
- device->Start(); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
// Get captured video frames. |
- PostQuitTask(); |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_max_timeout())); |
+ WaitForCapturedFrame(); |
EXPECT_EQ(rx_capability.width, 640); |
EXPECT_EQ(rx_capability.height, 480); |
EXPECT_EQ(rx_capability.frame_rate, 30); |
- device->DeAllocate(); |
+ device->StopAndDeAllocate(); |
} |
TEST_F(VideoCaptureDeviceTest, FakeCapture) { |
@@ -363,15 +368,13 @@ TEST_F(VideoCaptureDeviceTest, FakeCapture) { |
0, |
false, |
ConstantResolutionVideoCaptureDevice); |
- device->Allocate(capture_format, frame_observer_.get()); |
- |
- device->Start(); |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_max_timeout())); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
+ WaitForCapturedFrame(); |
EXPECT_EQ(rx_capability.width, 640); |
EXPECT_EQ(rx_capability.height, 480); |
EXPECT_EQ(rx_capability.frame_rate, 30); |
- device->Stop(); |
- device->DeAllocate(); |
+ device->StopAndDeAllocate(); |
} |
// Start the camera in 720p to capture MJPEG instead of a raw format. |
@@ -400,14 +403,12 @@ TEST_F(VideoCaptureDeviceTest, MAYBE_CaptureMjpeg) { |
0, |
false, |
ConstantResolutionVideoCaptureDevice); |
- device->Allocate(capture_format, frame_observer_.get()); |
- |
- device->Start(); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
// Get captured video frames. |
- PostQuitTask(); |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_max_timeout())); |
+ WaitForCapturedFrame(); |
EXPECT_EQ(rx_capability.color, PIXEL_FORMAT_MJPEG); |
- device->DeAllocate(); |
+ device->StopAndDeAllocate(); |
} |
TEST_F(VideoCaptureDeviceTest, FakeCaptureVariableResolution) { |
@@ -432,22 +433,21 @@ TEST_F(VideoCaptureDeviceTest, FakeCaptureVariableResolution) { |
EXPECT_CALL(*frame_observer_, OnErr()) |
.Times(0); |
+ int action_count = 200; |
+ EXPECT_CALL(*frame_observer_, OnFrameInfoChanged(_)) |
+ .Times(AtLeast(action_count / 30)); |
- device->Allocate(capture_format, frame_observer_.get()); |
+ device->AllocateAndStart(capture_format, |
+ frame_observer_.PassAs<EventHandler>()); |
// The amount of times the OnFrameInfoChanged gets called depends on how often |
// FakeDevice is supposed to change and what is its actual frame rate. |
// We set TimeWait to 200 action timeouts and this should be enough for at |
// least action_count/kFakeCaptureCapabilityChangePeriod calls. |
- int action_count = 200; |
- EXPECT_CALL(*frame_observer_, OnFrameInfoChanged(_)) |
- .Times(AtLeast(action_count / 30)); |
- device->Start(); |
for (int i = 0; i < action_count; ++i) { |
- EXPECT_TRUE(wait_event_.TimedWait(TestTimeouts::action_timeout())); |
+ WaitForCapturedFrame(); |
} |
- device->Stop(); |
- device->DeAllocate(); |
+ device->StopAndDeAllocate(); |
} |
}; // namespace media |