-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Video Capture Service] Allow buffer retired while still in use in Br…
…oadcastingReceiver In the recently added class BroadcastingReceiver for enabling multi-client access to video capture devices, see design doc [1], an assumption was made that producers never retire buffers while they are still in use. Even though this assumption may have held at some point during development, a test failure at a CL [2] that moves the service to the browser process on ChromeOS revealed that it no longer holds. This CL removes this assumption and adds correct handling of the case. [1] https://docs.google.com/document/d/1mYnsZfLBRmbsDpUtfb6C7dzhfw2Kcxg_-uiG_6MnWVQ/edit?usp=sharing [2] https://chromium-review.googlesource.com/c/chromium/src/+/1506604/1 test: services_unittests --gtest_filter=BroadcastingReceiverTest.* test: services_unittests --gtest_filter=MockVideoCaptureDeviceSharedAccessTest.* test: content_browsertests --gtest_filter=WebRtcVideoCaptureServiceBrowserTest.* Bug: 783442, 939587 Change-Id: I9d27c69386e76c2ea472f8549721fa5cf890ae61 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1509902 Reviewed-by: Robert Sesek <rsesek@chromium.org> Reviewed-by: Emircan Uysaler <emircan@chromium.org> Commit-Queue: Christian Fremerey <chfremer@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#639747}(cherry picked from commit ce0b05d2aa49a6b22c1033c4d1081a3d923248a7) Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1520348 Reviewed-by: Christian Fremerey <chfremer@chromium.org> Cr-Commit-Position: refs/branch-heads/3729@{#85} Cr-Branched-From: d4a8972-refs/heads/master@{#638880}
- Loading branch information
Christian Fremerey
committed
Mar 13, 2019
1 parent
f45c768
commit 97528db
Showing
6 changed files
with
206 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
services/video_capture/broadcasting_receiver_unittest.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// Copyright 2019 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 "services/video_capture/broadcasting_receiver.h" | ||
|
||
#include "base/run_loop.h" | ||
#include "base/test/scoped_task_environment.h" | ||
#include "media/capture/video/shared_memory_handle_provider.h" | ||
#include "mojo/public/cpp/bindings/strong_binding.h" | ||
#include "services/video_capture/public/cpp/mock_receiver.h" | ||
#include "testing/gmock/include/gmock/gmock.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
using testing::_; | ||
using testing::InvokeWithoutArgs; | ||
|
||
namespace video_capture { | ||
|
||
class FakeAccessPermission : public mojom::ScopedAccessPermission { | ||
public: | ||
FakeAccessPermission(base::OnceClosure destruction_cb) | ||
: destruction_cb_(std::move(destruction_cb)) {} | ||
~FakeAccessPermission() override { std::move(destruction_cb_).Run(); } | ||
|
||
private: | ||
base::OnceClosure destruction_cb_; | ||
}; | ||
|
||
class BroadcastingReceiverTest : public ::testing::Test { | ||
public: | ||
void SetUp() override { | ||
mojom::ReceiverPtr receiver_1; | ||
mojom::ReceiverPtr receiver_2; | ||
mock_receiver_1_ = | ||
std::make_unique<MockReceiver>(mojo::MakeRequest(&receiver_1)); | ||
mock_receiver_2_ = | ||
std::make_unique<MockReceiver>(mojo::MakeRequest(&receiver_2)); | ||
broadcaster_.AddClient(std::move(receiver_1), | ||
media::VideoCaptureBufferType::kSharedMemory); | ||
broadcaster_.AddClient(std::move(receiver_2), | ||
media::VideoCaptureBufferType::kSharedMemory); | ||
} | ||
|
||
protected: | ||
BroadcastingReceiver broadcaster_; | ||
std::unique_ptr<MockReceiver> mock_receiver_1_; | ||
std::unique_ptr<MockReceiver> mock_receiver_2_; | ||
base::test::ScopedTaskEnvironment task_environment_; | ||
}; | ||
|
||
TEST_F( | ||
BroadcastingReceiverTest, | ||
HoldsOnToAccessPermissionForRetiredBufferUntilLastClientFinishedConsuming) { | ||
media::SharedMemoryHandleProvider shm_provider; | ||
const size_t kArbitraryDummyBufferSize = 8u; | ||
ASSERT_TRUE(shm_provider.InitForSize(kArbitraryDummyBufferSize)); | ||
media::mojom::VideoBufferHandlePtr buffer_handle = | ||
media::mojom::VideoBufferHandle::New(); | ||
buffer_handle->set_shared_buffer_handle( | ||
shm_provider.GetHandleForInterProcessTransit(true /*read_only*/)); | ||
static const int kArbiraryBufferId = 123; | ||
static const int kArbiraryFrameFeedbackId = 456; | ||
broadcaster_.OnNewBuffer(kArbiraryBufferId, std::move(buffer_handle)); | ||
|
||
base::RunLoop frame_arrived_at_receiver_1; | ||
base::RunLoop frame_arrived_at_receiver_2; | ||
EXPECT_CALL(*mock_receiver_1_, DoOnFrameReadyInBuffer(_, _, _, _)) | ||
.WillOnce(InvokeWithoutArgs([&frame_arrived_at_receiver_1]() { | ||
frame_arrived_at_receiver_1.Quit(); | ||
})); | ||
EXPECT_CALL(*mock_receiver_2_, DoOnFrameReadyInBuffer(_, _, _, _)) | ||
.WillOnce(InvokeWithoutArgs([&frame_arrived_at_receiver_2]() { | ||
frame_arrived_at_receiver_2.Quit(); | ||
})); | ||
mock_receiver_2_->HoldAccessPermissions(); | ||
|
||
mojom::ScopedAccessPermissionPtr access_permission; | ||
bool access_permission_has_been_released = false; | ||
mojo::MakeStrongBinding(std::make_unique<FakeAccessPermission>(base::BindOnce( | ||
[](bool* access_permission_has_been_released) { | ||
*access_permission_has_been_released = true; | ||
}, | ||
&access_permission_has_been_released)), | ||
mojo::MakeRequest(&access_permission)); | ||
media::mojom::VideoFrameInfoPtr frame_info = | ||
media::mojom::VideoFrameInfo::New(); | ||
media::VideoFrameMetadata frame_metadata; | ||
frame_info->metadata = frame_metadata.GetInternalValues().Clone(); | ||
broadcaster_.OnFrameReadyInBuffer(kArbiraryBufferId, kArbiraryFrameFeedbackId, | ||
std::move(access_permission), | ||
std::move(frame_info)); | ||
|
||
// mock_receiver_1_ finishes consuming immediately. | ||
// mock_receiver_2_ continues consuming. | ||
frame_arrived_at_receiver_1.Run(); | ||
frame_arrived_at_receiver_2.Run(); | ||
|
||
base::RunLoop buffer_retired_arrived_at_receiver_1; | ||
base::RunLoop buffer_retired_arrived_at_receiver_2; | ||
EXPECT_CALL(*mock_receiver_1_, DoOnBufferRetired(_)) | ||
.WillOnce(InvokeWithoutArgs([&buffer_retired_arrived_at_receiver_1]() { | ||
buffer_retired_arrived_at_receiver_1.Quit(); | ||
})); | ||
EXPECT_CALL(*mock_receiver_2_, DoOnBufferRetired(_)) | ||
.WillOnce(InvokeWithoutArgs([&buffer_retired_arrived_at_receiver_2]() { | ||
buffer_retired_arrived_at_receiver_2.Quit(); | ||
})); | ||
|
||
// retire the buffer | ||
broadcaster_.OnBufferRetired(kArbiraryBufferId); | ||
|
||
// expect that both receivers get the retired event | ||
buffer_retired_arrived_at_receiver_1.Run(); | ||
buffer_retired_arrived_at_receiver_2.Run(); | ||
|
||
// expect that |access_permission| is still being held | ||
base::RunLoop().RunUntilIdle(); | ||
EXPECT_FALSE(access_permission_has_been_released); | ||
|
||
// mock_receiver_2_ finishes consuming | ||
mock_receiver_2_->ReleaseAccessPermissions(); | ||
|
||
// expect that |access_permission| is released | ||
base::RunLoop().RunUntilIdle(); | ||
EXPECT_TRUE(access_permission_has_been_released); | ||
} | ||
|
||
} // namespace video_capture |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters