| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/memory/shared_memory.h" |
| #include "base/process/process_handle.h" |
| #include "content/common/media/video_capture_messages.h" |
| #include "content/renderer/media/video_capture_message_filter.h" |
| #include "ipc/ipc_test_sink.h" |
| #include "media/base/video_capture_types.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using ::testing::_; |
| using ::testing::AnyNumber; |
| using ::testing::DoAll; |
| using ::testing::Invoke; |
| using ::testing::Mock; |
| using ::testing::Return; |
| using ::testing::SaveArg; |
| using ::testing::StrictMock; |
| using ::testing::WithArg; |
| |
| namespace content { |
| namespace { |
| |
| class MockVideoCaptureDelegate : public VideoCaptureMessageFilter::Delegate { |
| public: |
| MockVideoCaptureDelegate() : device_id_(0) {} |
| |
| // VideoCaptureMessageFilter::Delegate implementation. |
| MOCK_METHOD3(OnBufferCreated, |
| void(base::SharedMemoryHandle handle, |
| int length, |
| int buffer_id)); |
| MOCK_METHOD3(OnBufferCreated2, |
| void(const std::vector<gfx::GpuMemoryBufferHandle>& handles, |
| const gfx::Size& size, |
| int buffer_id)); |
| MOCK_METHOD1(OnBufferDestroyed, void(int buffer_id)); |
| MOCK_METHOD7(OnBufferReceived, |
| void(int buffer_id, |
| base::TimeTicks timestamp, |
| const base::DictionaryValue& metadata, |
| media::VideoPixelFormat pixel_format, |
| media::VideoFrame::StorageType storage_type, |
| const gfx::Size& coded_size, |
| const gfx::Rect& visible_rect)); |
| MOCK_METHOD1(OnStateChanged, void(VideoCaptureState state)); |
| MOCK_METHOD1(OnDeviceSupportedFormatsEnumerated, |
| void(const media::VideoCaptureFormats& formats)); |
| MOCK_METHOD1(OnDeviceFormatsInUseReceived, |
| void(const media::VideoCaptureFormats& formats_in_use)); |
| |
| void OnDelegateAdded(int32 device_id) override { |
| ASSERT_TRUE(device_id != 0); |
| ASSERT_TRUE(device_id_ == 0); |
| device_id_ = device_id; |
| } |
| |
| int device_id() { return device_id_; } |
| |
| private: |
| int device_id_; |
| }; |
| |
| void ExpectMetadataContainsFooBarBaz(const base::DictionaryValue& metadata) { |
| std::string value; |
| if (metadata.GetString("foo", &value)) |
| EXPECT_EQ(std::string("bar"), value); |
| else if (metadata.GetString("bar", &value)) |
| EXPECT_EQ(std::string("baz"), value); |
| else |
| FAIL() << "Missing key 'foo' or key 'bar'."; |
| } |
| |
| } // namespace |
| |
| TEST(VideoCaptureMessageFilterTest, Basic) { |
| scoped_refptr<VideoCaptureMessageFilter> filter( |
| new VideoCaptureMessageFilter()); |
| |
| IPC::TestSink channel; |
| filter->OnFilterAdded(&channel); |
| MockVideoCaptureDelegate delegate; |
| filter->AddDelegate(&delegate); |
| ASSERT_EQ(1, delegate.device_id()); |
| |
| // VideoCaptureMsg_StateChanged |
| EXPECT_CALL(delegate, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED)); |
| filter->OnMessageReceived( |
| VideoCaptureMsg_StateChanged(delegate.device_id(), |
| VIDEO_CAPTURE_STATE_STARTED)); |
| Mock::VerifyAndClearExpectations(&delegate); |
| |
| // VideoCaptureMsg_NewBuffer |
| const base::SharedMemoryHandle handle = |
| #if defined(OS_WIN) |
| base::SharedMemoryHandle(reinterpret_cast<HANDLE>(10), |
| base::GetCurrentProcId()); |
| #else |
| base::SharedMemoryHandle(10, true); |
| #endif |
| EXPECT_CALL(delegate, OnBufferCreated(handle, 100, 1)); |
| filter->OnMessageReceived(VideoCaptureMsg_NewBuffer( |
| delegate.device_id(), handle, 100, 1)); |
| Mock::VerifyAndClearExpectations(&delegate); |
| |
| // VideoCaptureMsg_BufferReady |
| VideoCaptureMsg_BufferReady_Params params; |
| params.device_id = delegate.device_id(); |
| params.buffer_id = 22; |
| params.timestamp = base::TimeTicks::FromInternalValue(1); |
| params.metadata.SetString("foo", "bar"); |
| params.pixel_format = media::PIXEL_FORMAT_I420; |
| params.storage_type = media::VideoFrame::STORAGE_SHMEM; |
| params.coded_size = gfx::Size(234, 512); |
| params.visible_rect = gfx::Rect(100, 200, 300, 400); |
| |
| EXPECT_CALL(delegate, |
| OnBufferReceived(params.buffer_id, params.timestamp, _, |
| media::PIXEL_FORMAT_I420, |
| media::VideoFrame::STORAGE_SHMEM, |
| params.coded_size, params.visible_rect)) |
| .WillRepeatedly(WithArg<2>(Invoke(&ExpectMetadataContainsFooBarBaz))); |
| filter->OnMessageReceived(VideoCaptureMsg_BufferReady(params)); |
| Mock::VerifyAndClearExpectations(&delegate); |
| |
| // VideoCaptureMsg_FreeBuffer |
| EXPECT_CALL(delegate, OnBufferDestroyed(params.buffer_id)); |
| filter->OnMessageReceived(VideoCaptureMsg_FreeBuffer( |
| delegate.device_id(), params.buffer_id)); |
| Mock::VerifyAndClearExpectations(&delegate); |
| } |
| |
| TEST(VideoCaptureMessageFilterTest, Delegates) { |
| scoped_refptr<VideoCaptureMessageFilter> filter( |
| new VideoCaptureMessageFilter()); |
| |
| IPC::TestSink channel; |
| filter->OnFilterAdded(&channel); |
| |
| StrictMock<MockVideoCaptureDelegate> delegate1; |
| StrictMock<MockVideoCaptureDelegate> delegate2; |
| |
| filter->AddDelegate(&delegate1); |
| filter->AddDelegate(&delegate2); |
| ASSERT_EQ(1, delegate1.device_id()); |
| ASSERT_EQ(2, delegate2.device_id()); |
| |
| // Send an IPC message. Make sure the correct delegate gets called. |
| EXPECT_CALL(delegate1, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED)); |
| filter->OnMessageReceived( |
| VideoCaptureMsg_StateChanged(delegate1.device_id(), |
| VIDEO_CAPTURE_STATE_STARTED)); |
| Mock::VerifyAndClearExpectations(&delegate1); |
| |
| EXPECT_CALL(delegate2, OnStateChanged(VIDEO_CAPTURE_STATE_STARTED)); |
| filter->OnMessageReceived( |
| VideoCaptureMsg_StateChanged(delegate2.device_id(), |
| VIDEO_CAPTURE_STATE_STARTED)); |
| Mock::VerifyAndClearExpectations(&delegate2); |
| |
| // Remove the delegates. Make sure they won't get called. |
| filter->RemoveDelegate(&delegate1); |
| filter->OnMessageReceived( |
| VideoCaptureMsg_StateChanged(delegate1.device_id(), |
| VIDEO_CAPTURE_STATE_ENDED)); |
| |
| filter->RemoveDelegate(&delegate2); |
| filter->OnMessageReceived( |
| VideoCaptureMsg_StateChanged(delegate2.device_id(), |
| VIDEO_CAPTURE_STATE_ENDED)); |
| } |
| |
| TEST(VideoCaptureMessageFilterTest, GetSomeDeviceSupportedFormats) { |
| scoped_refptr<VideoCaptureMessageFilter> filter( |
| new VideoCaptureMessageFilter()); |
| |
| IPC::TestSink channel; |
| filter->OnFilterAdded(&channel); |
| MockVideoCaptureDelegate delegate; |
| filter->AddDelegate(&delegate); |
| ASSERT_EQ(1, delegate.device_id()); |
| |
| EXPECT_CALL(delegate, OnDeviceSupportedFormatsEnumerated(_)); |
| media::VideoCaptureFormats supported_formats; |
| filter->OnMessageReceived(VideoCaptureMsg_DeviceSupportedFormatsEnumerated( |
| delegate.device_id(), supported_formats)); |
| } |
| |
| TEST(VideoCaptureMessageFilterTest, GetSomeDeviceFormatInUse) { |
| scoped_refptr<VideoCaptureMessageFilter> filter( |
| new VideoCaptureMessageFilter()); |
| |
| IPC::TestSink channel; |
| filter->OnFilterAdded(&channel); |
| MockVideoCaptureDelegate delegate; |
| filter->AddDelegate(&delegate); |
| ASSERT_EQ(1, delegate.device_id()); |
| |
| EXPECT_CALL(delegate, OnDeviceFormatsInUseReceived(_)); |
| media::VideoCaptureFormats formats_in_use; |
| filter->OnMessageReceived(VideoCaptureMsg_DeviceFormatsInUseReceived( |
| delegate.device_id(), formats_in_use)); |
| } |
| } // namespace content |