summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-20 13:40:20 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-01-22 12:41:23 +0000
commit7961cea6d1041e3e454dae6a1da660b453efd238 (patch)
treec0eeb4a9ff9ba32986289c1653d9608e53ccb444 /chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
parentb7034d0803538058e5c9d904ef03cf5eab34f6ef (diff)
downloadqtwebengine-chromium-7961cea6d1041e3e454dae6a1da660b453efd238.tar.gz
BASELINE: Update Chromium to 78.0.3904.130
Change-Id: If185e0c0061b3437531c97c9c8c78f239352a68b Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc')
-rw-r--r--chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc526
1 files changed, 526 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
new file mode 100644
index 00000000000..7a99f544a53
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/video_capture/video_capture_impl_test.cc
@@ -0,0 +1,526 @@
+// 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 <stddef.h>
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/read_only_shared_memory_region.h"
+#include "base/memory/unsafe_shared_memory_region.h"
+#include "base/test/task_environment.h"
+#include "media/capture/mojom/video_capture.mojom-blink.h"
+#include "media/capture/mojom/video_capture_types.mojom-blink.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
+#include "third_party/blink/renderer/platform/video_capture/video_capture_impl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::InvokeWithoutArgs;
+using ::testing::SaveArg;
+using ::testing::WithArgs;
+
+namespace blink {
+
+void RunEmptyFormatsCallback(
+ media::mojom::blink::VideoCaptureHost::GetDeviceSupportedFormatsCallback&
+ callback) {
+ Vector<media::VideoCaptureFormat> formats;
+ std::move(callback).Run(formats);
+}
+
+ACTION(DoNothing) {}
+
+// Mock implementation of the Mojo Host service.
+class MockMojoVideoCaptureHost : public media::mojom::blink::VideoCaptureHost {
+ public:
+ MockMojoVideoCaptureHost() : released_buffer_count_(0) {
+ ON_CALL(*this, GetDeviceSupportedFormatsMock(_, _, _))
+ .WillByDefault(WithArgs<2>(Invoke(RunEmptyFormatsCallback)));
+ ON_CALL(*this, GetDeviceFormatsInUseMock(_, _, _))
+ .WillByDefault(WithArgs<2>(Invoke(RunEmptyFormatsCallback)));
+ ON_CALL(*this, ReleaseBuffer(_, _, _))
+ .WillByDefault(InvokeWithoutArgs(
+ this, &MockMojoVideoCaptureHost::increase_released_buffer_count));
+ }
+
+ // Start() can't be mocked directly due to move-only |observer|.
+ void Start(const base::UnguessableToken& device_id,
+ const base::UnguessableToken& session_id,
+ const media::VideoCaptureParams& params,
+ media::mojom::blink::VideoCaptureObserverPtr observer) override {
+ DoStart(device_id, session_id, params);
+ }
+ MOCK_METHOD3(DoStart,
+ void(const base::UnguessableToken&,
+ const base::UnguessableToken&,
+ const media::VideoCaptureParams&));
+ MOCK_METHOD1(Stop, void(const base::UnguessableToken&));
+ MOCK_METHOD1(Pause, void(const base::UnguessableToken&));
+ MOCK_METHOD3(Resume,
+ void(const base::UnguessableToken&,
+ const base::UnguessableToken&,
+ const media::VideoCaptureParams&));
+ MOCK_METHOD1(RequestRefreshFrame, void(const base::UnguessableToken&));
+ MOCK_METHOD3(ReleaseBuffer,
+ void(const base::UnguessableToken&, int32_t, double));
+ MOCK_METHOD3(GetDeviceSupportedFormatsMock,
+ void(const base::UnguessableToken&,
+ const base::UnguessableToken&,
+ GetDeviceSupportedFormatsCallback&));
+ MOCK_METHOD3(GetDeviceFormatsInUseMock,
+ void(const base::UnguessableToken&,
+ const base::UnguessableToken&,
+ GetDeviceFormatsInUseCallback&));
+ MOCK_METHOD2(OnFrameDropped,
+ void(const base::UnguessableToken&,
+ media::VideoCaptureFrameDropReason));
+ MOCK_METHOD2(OnLog, void(const base::UnguessableToken&, const String&));
+
+ void GetDeviceSupportedFormats(
+ const base::UnguessableToken& arg1,
+ const base::UnguessableToken& arg2,
+ GetDeviceSupportedFormatsCallback arg3) override {
+ GetDeviceSupportedFormatsMock(arg1, arg2, arg3);
+ }
+
+ void GetDeviceFormatsInUse(const base::UnguessableToken& arg1,
+ const base::UnguessableToken& arg2,
+ GetDeviceFormatsInUseCallback arg3) override {
+ GetDeviceFormatsInUseMock(arg1, arg2, arg3);
+ }
+
+ int released_buffer_count() const { return released_buffer_count_; }
+ void increase_released_buffer_count() { released_buffer_count_++; }
+
+ private:
+ int released_buffer_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMojoVideoCaptureHost);
+};
+
+// This class encapsulates a VideoCaptureImpl under test and the necessary
+// accessory classes, namely:
+// - a MockMojoVideoCaptureHost, mimicking the RendererHost;
+// - a few callbacks that are bound when calling operations of VideoCaptureImpl
+// and on which we set expectations.
+class VideoCaptureImplTest : public ::testing::Test {
+ public:
+ VideoCaptureImplTest()
+ : video_capture_impl_(new VideoCaptureImpl(session_id_)) {
+ params_small_.requested_format = media::VideoCaptureFormat(
+ gfx::Size(176, 144), 30, media::PIXEL_FORMAT_I420);
+ params_large_.requested_format = media::VideoCaptureFormat(
+ gfx::Size(320, 240), 30, media::PIXEL_FORMAT_I420);
+
+ video_capture_impl_->SetVideoCaptureHostForTesting(
+ &mock_video_capture_host_);
+
+ ON_CALL(mock_video_capture_host_, DoStart(_, _, _))
+ .WillByDefault(InvokeWithoutArgs([this]() {
+ video_capture_impl_->OnStateChanged(
+ media::mojom::VideoCaptureState::STARTED);
+ }));
+ }
+
+ protected:
+ // These four mocks are used to create callbacks for the different oeprations.
+ MOCK_METHOD2(OnFrameReady,
+ void(scoped_refptr<media::VideoFrame>, base::TimeTicks));
+ MOCK_METHOD1(OnStateUpdate, void(VideoCaptureState));
+ MOCK_METHOD1(OnDeviceFormatsInUse,
+ void(const Vector<media::VideoCaptureFormat>&));
+ MOCK_METHOD1(OnDeviceSupportedFormats,
+ void(const Vector<media::VideoCaptureFormat>&));
+
+ void StartCapture(int client_id, const media::VideoCaptureParams& params) {
+ const auto state_update_callback = base::Bind(
+ &VideoCaptureImplTest::OnStateUpdate, base::Unretained(this));
+ const auto frame_ready_callback =
+ base::Bind(&VideoCaptureImplTest::OnFrameReady, base::Unretained(this));
+
+ video_capture_impl_->StartCapture(client_id, params, state_update_callback,
+ frame_ready_callback);
+ }
+
+ void StopCapture(int client_id) {
+ video_capture_impl_->StopCapture(client_id);
+ }
+
+ void SimulateOnBufferCreated(int buffer_id,
+ const base::UnsafeSharedMemoryRegion& region) {
+ video_capture_impl_->OnNewBuffer(
+ buffer_id,
+ media::mojom::blink::VideoBufferHandle::NewSharedBufferHandle(
+ mojo::WrapUnsafeSharedMemoryRegion(region.Duplicate())));
+ }
+
+ void SimulateReadOnlyBufferCreated(int buffer_id,
+ base::ReadOnlySharedMemoryRegion region) {
+ video_capture_impl_->OnNewBuffer(
+ buffer_id,
+ media::mojom::blink::VideoBufferHandle::NewReadOnlyShmemRegion(
+ std::move(region)));
+ }
+
+ void SimulateBufferReceived(int buffer_id, const gfx::Size& size) {
+ media::mojom::blink::VideoFrameInfoPtr info =
+ media::mojom::blink::VideoFrameInfo::New();
+
+ const base::TimeTicks now = base::TimeTicks::Now();
+ media::VideoFrameMetadata frame_metadata;
+ frame_metadata.SetTimeTicks(media::VideoFrameMetadata::REFERENCE_TIME, now);
+ info->metadata = frame_metadata.GetInternalValues().Clone();
+
+ info->timestamp = now - base::TimeTicks();
+ info->pixel_format = media::PIXEL_FORMAT_I420;
+ info->coded_size = WebSize(size);
+ info->visible_rect = WebRect(gfx::Rect(size));
+
+ video_capture_impl_->OnBufferReady(buffer_id, std::move(info));
+ }
+
+ void SimulateBufferDestroyed(int buffer_id) {
+ video_capture_impl_->OnBufferDestroyed(buffer_id);
+ }
+
+ void GetDeviceSupportedFormats() {
+ const base::Callback<void(const Vector<media::VideoCaptureFormat>&)>
+ callback = base::Bind(&VideoCaptureImplTest::OnDeviceSupportedFormats,
+ base::Unretained(this));
+ video_capture_impl_->GetDeviceSupportedFormats(callback);
+ }
+
+ void GetDeviceFormatsInUse() {
+ const base::Callback<void(const Vector<media::VideoCaptureFormat>&)>
+ callback = base::Bind(&VideoCaptureImplTest::OnDeviceFormatsInUse,
+ base::Unretained(this));
+ video_capture_impl_->GetDeviceFormatsInUse(callback);
+ }
+
+ void OnStateChanged(media::mojom::VideoCaptureState state) {
+ video_capture_impl_->OnStateChanged(state);
+ }
+
+ const base::UnguessableToken session_id_ = base::UnguessableToken::Create();
+ base::test::TaskEnvironment task_environment_;
+ ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
+ const std::unique_ptr<VideoCaptureImpl> video_capture_impl_;
+ MockMojoVideoCaptureHost mock_video_capture_host_;
+ media::VideoCaptureParams params_small_;
+ media::VideoCaptureParams params_large_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplTest);
+};
+
+TEST_F(VideoCaptureImplTest, Simple) {
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+
+ StartCapture(0, params_small_);
+ StopCapture(0);
+}
+
+TEST_F(VideoCaptureImplTest, TwoClientsInSequence) {
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED))
+ .Times(2);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+
+ StartCapture(0, params_small_);
+ StopCapture(0);
+ StartCapture(1, params_small_);
+ StopCapture(1);
+}
+
+TEST_F(VideoCaptureImplTest, LargeAndSmall) {
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED))
+ .Times(2);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_large_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+
+ StartCapture(0, params_large_);
+ StopCapture(0);
+ StartCapture(1, params_small_);
+ StopCapture(1);
+}
+
+TEST_F(VideoCaptureImplTest, SmallAndLarge) {
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED))
+ .Times(2);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+
+ StartCapture(0, params_small_);
+ StopCapture(0);
+ StartCapture(1, params_large_);
+ StopCapture(1);
+}
+
+// Checks that a request to GetDeviceSupportedFormats() ends up eventually in
+// the provided callback.
+TEST_F(VideoCaptureImplTest, GetDeviceFormats) {
+ EXPECT_CALL(*this, OnDeviceSupportedFormats(_));
+ EXPECT_CALL(mock_video_capture_host_,
+ GetDeviceSupportedFormatsMock(_, session_id_, _));
+
+ GetDeviceSupportedFormats();
+}
+
+// Checks that two requests to GetDeviceSupportedFormats() end up eventually
+// calling the provided callbacks.
+TEST_F(VideoCaptureImplTest, TwoClientsGetDeviceFormats) {
+ EXPECT_CALL(*this, OnDeviceSupportedFormats(_)).Times(2);
+ EXPECT_CALL(mock_video_capture_host_,
+ GetDeviceSupportedFormatsMock(_, session_id_, _))
+ .Times(2);
+
+ GetDeviceSupportedFormats();
+ GetDeviceSupportedFormats();
+}
+
+// Checks that a request to GetDeviceFormatsInUse() ends up eventually in the
+// provided callback.
+TEST_F(VideoCaptureImplTest, GetDeviceFormatsInUse) {
+ EXPECT_CALL(*this, OnDeviceFormatsInUse(_));
+ EXPECT_CALL(mock_video_capture_host_,
+ GetDeviceFormatsInUseMock(_, session_id_, _));
+
+ GetDeviceFormatsInUse();
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceived) {
+ const int kArbitraryBufferId = 11;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_small_.requested_format.frame_size);
+ base::UnsafeSharedMemoryRegion region =
+ base::UnsafeSharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(region.IsValid());
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kArbitraryBufferId, _))
+ .Times(0);
+
+ StartCapture(0, params_small_);
+ SimulateOnBufferCreated(kArbitraryBufferId, region);
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
+ StopCapture(0);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 0);
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceived_ReadOnlyShmemRegion) {
+ const int kArbitraryBufferId = 11;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_small_.requested_format.frame_size);
+ base::MappedReadOnlyRegion shm =
+ base::ReadOnlySharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(shm.IsValid());
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_, ReleaseBuffer(_, kArbitraryBufferId, _))
+ .Times(0);
+
+ StartCapture(0, params_small_);
+ SimulateReadOnlyBufferCreated(kArbitraryBufferId, std::move(shm.region));
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
+ StopCapture(0);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 0);
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop) {
+ const int kArbitraryBufferId = 12;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_large_.requested_format.frame_size);
+ base::UnsafeSharedMemoryRegion region =
+ base::UnsafeSharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(region.IsValid());
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _)).Times(0);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_large_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+
+ StartCapture(0, params_large_);
+ SimulateOnBufferCreated(kArbitraryBufferId, region);
+ StopCapture(0);
+ // A buffer received after StopCapture() triggers an instant ReleaseBuffer().
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_large_.requested_format.frame_size);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 1);
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceivedAfterStop_ReadOnlyShmemRegion) {
+ const int kArbitraryBufferId = 12;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_large_.requested_format.frame_size);
+ base::MappedReadOnlyRegion shm =
+ base::ReadOnlySharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(shm.IsValid());
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(*this, OnFrameReady(_, _)).Times(0);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_large_));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+
+ StartCapture(0, params_large_);
+ SimulateReadOnlyBufferCreated(kArbitraryBufferId, std::move(shm.region));
+ StopCapture(0);
+ // A buffer received after StopCapture() triggers an instant ReleaseBuffer().
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_large_.requested_format.frame_size);
+ SimulateBufferDestroyed(kArbitraryBufferId);
+
+ EXPECT_EQ(mock_video_capture_host_.released_buffer_count(), 1);
+}
+
+TEST_F(VideoCaptureImplTest, AlreadyStarted) {
+ media::VideoCaptureParams params = {};
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED))
+ .Times(2);
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_))
+ .WillOnce(DoAll(InvokeWithoutArgs([this]() {
+ video_capture_impl_->OnStateChanged(
+ media::mojom::VideoCaptureState::STARTED);
+ }),
+ SaveArg<2>(&params)));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+
+ StartCapture(0, params_small_);
+ StartCapture(1, params_large_);
+ StopCapture(0);
+ StopCapture(1);
+ DCHECK(params.requested_format == params_small_.requested_format);
+}
+
+TEST_F(VideoCaptureImplTest, EndedBeforeStop) {
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+
+ StartCapture(0, params_small_);
+
+ OnStateChanged(media::mojom::VideoCaptureState::ENDED);
+
+ StopCapture(0);
+}
+
+TEST_F(VideoCaptureImplTest, ErrorBeforeStop) {
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_ERROR));
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_));
+
+ StartCapture(0, params_small_);
+
+ OnStateChanged(media::mojom::VideoCaptureState::FAILED);
+
+ StopCapture(0);
+}
+
+TEST_F(VideoCaptureImplTest, BufferReceivedBeforeOnStarted) {
+ const int kArbitraryBufferId = 16;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_small_.requested_format.frame_size);
+ base::UnsafeSharedMemoryRegion region =
+ base::UnsafeSharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(region.IsValid());
+
+ InSequence s;
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_))
+ .WillOnce(DoNothing());
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+ StartCapture(0, params_small_);
+ SimulateOnBufferCreated(kArbitraryBufferId, region);
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+
+ // Additional STARTED will cause RequestRefreshFrame a second time.
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ StopCapture(0);
+}
+
+TEST_F(VideoCaptureImplTest,
+ BufferReceivedBeforeOnStarted_ReadOnlyShmemRegion) {
+ const int kArbitraryBufferId = 16;
+
+ const size_t frame_size = media::VideoFrame::AllocationSize(
+ media::PIXEL_FORMAT_I420, params_small_.requested_format.frame_size);
+ base::MappedReadOnlyRegion shm =
+ base::ReadOnlySharedMemoryRegion::Create(frame_size);
+ ASSERT_TRUE(shm.IsValid());
+
+ InSequence s;
+ EXPECT_CALL(mock_video_capture_host_, DoStart(_, session_id_, params_small_))
+ .WillOnce(DoNothing());
+ EXPECT_CALL(mock_video_capture_host_,
+ ReleaseBuffer(_, kArbitraryBufferId, _));
+ StartCapture(0, params_small_);
+ SimulateReadOnlyBufferCreated(kArbitraryBufferId, std::move(shm.region));
+ SimulateBufferReceived(kArbitraryBufferId,
+ params_small_.requested_format.frame_size);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+
+ // Additional STARTED will cause RequestRefreshFrame a second time.
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STARTED));
+ EXPECT_CALL(mock_video_capture_host_, RequestRefreshFrame(_));
+ video_capture_impl_->OnStateChanged(media::mojom::VideoCaptureState::STARTED);
+
+ EXPECT_CALL(*this, OnStateUpdate(blink::VIDEO_CAPTURE_STATE_STOPPED));
+ EXPECT_CALL(mock_video_capture_host_, Stop(_));
+ StopCapture(0);
+}
+
+} // namespace blink