broadcasting_receiver_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Copyright 2019 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. #include "services/video_capture/broadcasting_receiver.h"
  5. #include "base/memory/unsafe_shared_memory_region.h"
  6. #include "base/run_loop.h"
  7. #include "base/test/task_environment.h"
  8. #include "mojo/public/cpp/bindings/pending_remote.h"
  9. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  10. #include "services/video_capture/public/cpp/mock_video_frame_handler.h"
  11. #include "services/video_capture/public/mojom/video_frame_handler.mojom.h"
  12. #include "testing/gmock/include/gmock/gmock.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. using testing::_;
  15. using testing::InvokeWithoutArgs;
  16. namespace video_capture {
  17. static const size_t kArbitraryDummyBufferSize = 8u;
  18. static const int kArbitraryBufferId = 123;
  19. static const int kArbitraryFrameFeedbackId = 456;
  20. class BroadcastingReceiverTest : public ::testing::Test {
  21. public:
  22. void SetUp() override {
  23. mojo::PendingRemote<mojom::VideoFrameHandler> video_frame_handler_1;
  24. mojo::PendingRemote<mojom::VideoFrameHandler> video_frame_handler_2;
  25. mock_video_frame_handler_1_ = std::make_unique<MockVideoFrameHandler>(
  26. video_frame_handler_1.InitWithNewPipeAndPassReceiver());
  27. mock_video_frame_handler_2_ = std::make_unique<MockVideoFrameHandler>(
  28. video_frame_handler_2.InitWithNewPipeAndPassReceiver());
  29. client_id_1_ =
  30. broadcaster_.AddClient(std::move(video_frame_handler_1),
  31. media::VideoCaptureBufferType::kSharedMemory);
  32. client_id_2_ =
  33. broadcaster_.AddClient(std::move(video_frame_handler_2),
  34. media::VideoCaptureBufferType::kSharedMemory);
  35. shm_region_ =
  36. base::UnsafeSharedMemoryRegion::Create(kArbitraryDummyBufferSize);
  37. ASSERT_TRUE(shm_region_.IsValid());
  38. media::mojom::VideoBufferHandlePtr buffer_handle =
  39. media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  40. std::move(shm_region_));
  41. broadcaster_.OnNewBuffer(kArbitraryBufferId, std::move(buffer_handle));
  42. }
  43. FakeVideoFrameAccessHandler* CreateAndSendFakeVideoFrameAccessHandler() {
  44. mojo::PendingRemote<mojom::VideoFrameAccessHandler> pending_remote;
  45. auto frame_access_handler =
  46. mojo::MakeSelfOwnedReceiver<mojom::VideoFrameAccessHandler>(
  47. std::make_unique<FakeVideoFrameAccessHandler>(),
  48. pending_remote.InitWithNewPipeAndPassReceiver());
  49. broadcaster_.OnFrameAccessHandlerReady(std::move(pending_remote));
  50. return static_cast<FakeVideoFrameAccessHandler*>(
  51. frame_access_handler->impl());
  52. }
  53. protected:
  54. BroadcastingReceiver broadcaster_;
  55. std::unique_ptr<MockVideoFrameHandler> mock_video_frame_handler_1_;
  56. std::unique_ptr<MockVideoFrameHandler> mock_video_frame_handler_2_;
  57. int32_t client_id_1_;
  58. int32_t client_id_2_;
  59. base::UnsafeSharedMemoryRegion shm_region_;
  60. base::test::TaskEnvironment task_environment_;
  61. };
  62. TEST_F(
  63. BroadcastingReceiverTest,
  64. HoldsOnToAccessPermissionForRetiredBufferUntilLastClientFinishedConsuming) {
  65. FakeVideoFrameAccessHandler* frame_access_handler =
  66. CreateAndSendFakeVideoFrameAccessHandler();
  67. base::RunLoop frame_arrived_at_video_frame_handler_1;
  68. base::RunLoop frame_arrived_at_video_frame_handler_2;
  69. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnFrameReadyInBuffer(_, _, _))
  70. .WillOnce(InvokeWithoutArgs([&frame_arrived_at_video_frame_handler_1]() {
  71. frame_arrived_at_video_frame_handler_1.Quit();
  72. }));
  73. EXPECT_CALL(*mock_video_frame_handler_2_, DoOnFrameReadyInBuffer(_, _, _))
  74. .WillOnce(InvokeWithoutArgs([&frame_arrived_at_video_frame_handler_2]() {
  75. frame_arrived_at_video_frame_handler_2.Quit();
  76. }));
  77. mock_video_frame_handler_1_->HoldAccessPermissions();
  78. mock_video_frame_handler_2_->HoldAccessPermissions();
  79. media::mojom::VideoFrameInfoPtr frame_info =
  80. media::mojom::VideoFrameInfo::New();
  81. broadcaster_.OnFrameReadyInBuffer(
  82. mojom::ReadyFrameInBuffer::New(
  83. kArbitraryBufferId, kArbitraryFrameFeedbackId, std::move(frame_info)),
  84. {});
  85. // mock_video_frame_handler_1_ finishes consuming immediately.
  86. // mock_video_frame_handler_2_ continues consuming.
  87. frame_arrived_at_video_frame_handler_1.Run();
  88. frame_arrived_at_video_frame_handler_2.Run();
  89. base::RunLoop buffer_retired_arrived_at_video_frame_handler_1;
  90. base::RunLoop buffer_retired_arrived_at_video_frame_handler_2;
  91. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnBufferRetired(_))
  92. .WillOnce(InvokeWithoutArgs(
  93. [&buffer_retired_arrived_at_video_frame_handler_1]() {
  94. buffer_retired_arrived_at_video_frame_handler_1.Quit();
  95. }));
  96. EXPECT_CALL(*mock_video_frame_handler_2_, DoOnBufferRetired(_))
  97. .WillOnce(InvokeWithoutArgs(
  98. [&buffer_retired_arrived_at_video_frame_handler_2]() {
  99. buffer_retired_arrived_at_video_frame_handler_2.Quit();
  100. }));
  101. // Retiring the buffer results in both receivers getting the retired event.
  102. broadcaster_.OnBufferRetired(kArbitraryBufferId);
  103. buffer_retired_arrived_at_video_frame_handler_1.Run();
  104. buffer_retired_arrived_at_video_frame_handler_2.Run();
  105. base::RunLoop().RunUntilIdle();
  106. // Despite retiring, the access to the buffer is not released because it is
  107. // still in use by both handlers.
  108. EXPECT_TRUE(frame_access_handler->released_buffer_ids().empty());
  109. // mock_video_frame_handler_2_ finishes consuming. Access is still not
  110. // released because of mock_video_frame_handler_1_.
  111. mock_video_frame_handler_2_->ReleaseAccessedFrames();
  112. base::RunLoop().RunUntilIdle();
  113. EXPECT_TRUE(frame_access_handler->released_buffer_ids().empty());
  114. // mock_video_frame_handler_1_ finishes consuming. Now the buffer is finally
  115. // released.
  116. mock_video_frame_handler_1_->ReleaseAccessedFrames();
  117. base::RunLoop().RunUntilIdle();
  118. EXPECT_FALSE(frame_access_handler->released_buffer_ids().empty());
  119. }
  120. TEST_F(BroadcastingReceiverTest,
  121. DoesNotHoldOnToAccessPermissionWhenAllClientsAreSuspended) {
  122. FakeVideoFrameAccessHandler* frame_access_handler =
  123. CreateAndSendFakeVideoFrameAccessHandler();
  124. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnFrameReadyInBuffer(_, _, _))
  125. .Times(0);
  126. EXPECT_CALL(*mock_video_frame_handler_2_, DoOnFrameReadyInBuffer(_, _, _))
  127. .Times(0);
  128. mock_video_frame_handler_1_->HoldAccessPermissions();
  129. mock_video_frame_handler_2_->HoldAccessPermissions();
  130. broadcaster_.SuspendClient(client_id_1_);
  131. broadcaster_.SuspendClient(client_id_2_);
  132. broadcaster_.OnFrameReadyInBuffer(
  133. mojom::ReadyFrameInBuffer::New(kArbitraryBufferId,
  134. kArbitraryFrameFeedbackId,
  135. media::mojom::VideoFrameInfo::New()),
  136. {});
  137. // Because the clients are suspended, frames are automatically released.
  138. base::RunLoop().RunUntilIdle();
  139. EXPECT_FALSE(frame_access_handler->released_buffer_ids().empty());
  140. frame_access_handler->ClearReleasedBufferIds();
  141. // Resume one of the clients and pass another frame.
  142. broadcaster_.ResumeClient(client_id_2_);
  143. EXPECT_CALL(*mock_video_frame_handler_2_, DoOnFrameReadyInBuffer(_, _, _))
  144. .Times(1);
  145. broadcaster_.OnFrameReadyInBuffer(
  146. mojom::ReadyFrameInBuffer::New(kArbitraryBufferId,
  147. kArbitraryFrameFeedbackId,
  148. media::mojom::VideoFrameInfo::New()),
  149. {});
  150. // This time the buffer is not released automatically.
  151. base::RunLoop().RunUntilIdle();
  152. EXPECT_TRUE(frame_access_handler->released_buffer_ids().empty());
  153. // Releasing mock_video_frame_handler_2_'s frame is sufficient for the buffer
  154. // to be released since the frame was never delivered to
  155. // mock_video_frame_handler_1_.
  156. mock_video_frame_handler_2_->ReleaseAccessedFrames();
  157. base::RunLoop().RunUntilIdle();
  158. EXPECT_FALSE(frame_access_handler->released_buffer_ids().empty());
  159. }
  160. TEST_F(BroadcastingReceiverTest, ForwardsScaledFrames) {
  161. const int kBufferId = 10;
  162. const int kScaledBufferId = 11;
  163. FakeVideoFrameAccessHandler* frame_access_handler =
  164. CreateAndSendFakeVideoFrameAccessHandler();
  165. mock_video_frame_handler_1_->HoldAccessPermissions();
  166. media::mojom::VideoBufferHandlePtr buffer_handle =
  167. media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  168. base::UnsafeSharedMemoryRegion::Create(kArbitraryDummyBufferSize));
  169. broadcaster_.OnNewBuffer(kBufferId, std::move(buffer_handle));
  170. media::mojom::VideoBufferHandlePtr scaled_buffer_handle =
  171. media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  172. base::UnsafeSharedMemoryRegion::Create(kArbitraryDummyBufferSize));
  173. broadcaster_.OnNewBuffer(kScaledBufferId, std::move(scaled_buffer_handle));
  174. // Suspend the second client so that the first client alone controls buffer
  175. // access.
  176. broadcaster_.SuspendClient(client_id_2_);
  177. base::RunLoop on_buffer_ready;
  178. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnFrameReadyInBuffer(_, _, _))
  179. .WillOnce(
  180. InvokeWithoutArgs([&on_buffer_ready]() { on_buffer_ready.Quit(); }));
  181. mojom::ReadyFrameInBufferPtr ready_buffer =
  182. mojom::ReadyFrameInBuffer::New(kBufferId, kArbitraryFrameFeedbackId,
  183. media::mojom::VideoFrameInfo::New());
  184. std::vector<mojom::ReadyFrameInBufferPtr> scaled_ready_buffers;
  185. scaled_ready_buffers.push_back(
  186. mojom::ReadyFrameInBuffer::New(kScaledBufferId, kArbitraryFrameFeedbackId,
  187. media::mojom::VideoFrameInfo::New()));
  188. broadcaster_.OnFrameReadyInBuffer(std::move(ready_buffer),
  189. std::move(scaled_ready_buffers));
  190. on_buffer_ready.Run();
  191. EXPECT_TRUE(frame_access_handler->released_buffer_ids().empty());
  192. // Releasing the handler's buffers releases both frame and scaled frame.
  193. mock_video_frame_handler_1_->ReleaseAccessedFrames();
  194. base::RunLoop().RunUntilIdle();
  195. EXPECT_EQ(frame_access_handler->released_buffer_ids().size(), 2u);
  196. // Scaled buffers also get retired.
  197. base::RunLoop on_both_buffers_retired;
  198. size_t num_buffers_retired = 0u;
  199. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnBufferRetired(_))
  200. .WillRepeatedly(
  201. InvokeWithoutArgs([&on_both_buffers_retired, &num_buffers_retired]() {
  202. ++num_buffers_retired;
  203. if (num_buffers_retired == 2u)
  204. on_both_buffers_retired.Quit();
  205. }));
  206. broadcaster_.OnBufferRetired(kBufferId);
  207. broadcaster_.OnBufferRetired(kScaledBufferId);
  208. on_both_buffers_retired.Run();
  209. }
  210. TEST_F(BroadcastingReceiverTest, AccessPermissionsSurviveStop) {
  211. // For simplicitly, we only care about the first client in this test.
  212. broadcaster_.SuspendClient(client_id_2_);
  213. broadcaster_.OnStarted();
  214. // In this test, two frame handlers are used. In order to inspect all frame
  215. // IDs that have released after the first handler is destroyed, released
  216. // buffer IDs are stored in |released_buffer_ids|.
  217. std::vector<int32_t> released_buffer_ids;
  218. base::RepeatingCallback<void(int32_t)> buffer_released_callback =
  219. base::BindRepeating(
  220. [](std::vector<int32_t>* released_buffer_ids, int32_t buffer_id) {
  221. released_buffer_ids->push_back(buffer_id);
  222. },
  223. base::Unretained(&released_buffer_ids));
  224. mock_video_frame_handler_1_->HoldAccessPermissions();
  225. {
  226. mojo::PendingRemote<mojom::VideoFrameAccessHandler>
  227. frame_access_handler_proxy;
  228. auto frame_access_handler =
  229. mojo::MakeSelfOwnedReceiver<mojom::VideoFrameAccessHandler>(
  230. std::make_unique<FakeVideoFrameAccessHandler>(
  231. buffer_released_callback),
  232. frame_access_handler_proxy.InitWithNewPipeAndPassReceiver());
  233. broadcaster_.OnFrameAccessHandlerReady(
  234. std::move(frame_access_handler_proxy));
  235. }
  236. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnFrameReadyInBuffer(_, _, _))
  237. .Times(1);
  238. broadcaster_.OnFrameReadyInBuffer(
  239. mojom::ReadyFrameInBuffer::New(kArbitraryBufferId,
  240. kArbitraryFrameFeedbackId,
  241. media::mojom::VideoFrameInfo::New()),
  242. {});
  243. base::RunLoop().RunUntilIdle();
  244. // The first frame has not been released yet.
  245. EXPECT_TRUE(released_buffer_ids.empty());
  246. // Simulate a device restart.
  247. broadcaster_.OnStopped();
  248. broadcaster_.OnStarted();
  249. FakeVideoFrameAccessHandler* second_device_frame_access_handler;
  250. {
  251. mojo::PendingRemote<mojom::VideoFrameAccessHandler>
  252. frame_access_handler_proxy;
  253. auto frame_access_handler =
  254. mojo::MakeSelfOwnedReceiver<mojom::VideoFrameAccessHandler>(
  255. std::make_unique<FakeVideoFrameAccessHandler>(
  256. buffer_released_callback),
  257. frame_access_handler_proxy.InitWithNewPipeAndPassReceiver());
  258. broadcaster_.OnFrameAccessHandlerReady(
  259. std::move(frame_access_handler_proxy));
  260. second_device_frame_access_handler =
  261. static_cast<FakeVideoFrameAccessHandler*>(frame_access_handler->impl());
  262. }
  263. base::RunLoop().RunUntilIdle();
  264. // The first frame has still not been released yet.
  265. EXPECT_TRUE(released_buffer_ids.empty());
  266. // Receive another frame after device restart.
  267. base::UnsafeSharedMemoryRegion shm_region2 =
  268. base::UnsafeSharedMemoryRegion::Create(kArbitraryDummyBufferSize);
  269. ASSERT_TRUE(shm_region2.IsValid());
  270. media::mojom::VideoBufferHandlePtr buffer_handle2 =
  271. media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  272. std::move(shm_region2));
  273. broadcaster_.OnNewBuffer(kArbitraryBufferId + 1, std::move(buffer_handle2));
  274. EXPECT_CALL(*mock_video_frame_handler_1_, DoOnFrameReadyInBuffer(_, _, _))
  275. .Times(1);
  276. broadcaster_.OnFrameReadyInBuffer(
  277. mojom::ReadyFrameInBuffer::New(kArbitraryBufferId + 1,
  278. kArbitraryFrameFeedbackId + 1,
  279. media::mojom::VideoFrameInfo::New()),
  280. {});
  281. base::RunLoop().RunUntilIdle();
  282. // Neither frame has been released.
  283. EXPECT_TRUE(released_buffer_ids.empty());
  284. // Release all frames. This should inform both the old and the new handler.
  285. mock_video_frame_handler_1_->ReleaseAccessedFrames();
  286. base::RunLoop().RunUntilIdle();
  287. // Both buffers should now be released.
  288. EXPECT_EQ(released_buffer_ids.size(), 2u);
  289. // The first buffer was released by the first handler, which now no longer
  290. // exist. The second buffer was released by the second handler so we can
  291. // EXPECT it to only have observed a single frame release event.
  292. EXPECT_EQ(second_device_frame_access_handler->released_buffer_ids().size(),
  293. 1u);
  294. }
  295. } // namespace video_capture