broadcasting_receiver.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. // Copyright 2018 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 <utility>
  6. #include "base/bind.h"
  7. #include "base/files/scoped_file.h"
  8. #include "base/memory/platform_shared_memory_region.h"
  9. #include "base/memory/unsafe_shared_memory_region.h"
  10. #include "build/build_config.h"
  11. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  12. #include "mojo/public/cpp/system/platform_handle.h"
  13. namespace video_capture {
  14. namespace {
  15. media::mojom::VideoBufferHandlePtr
  16. CloneUnsafeShmemRegionToRawFileDescriptorHandle(
  17. const base::UnsafeSharedMemoryRegion& region) {
  18. base::subtle::PlatformSharedMemoryRegion platform_region =
  19. base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
  20. region.Duplicate());
  21. #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_WIN) || \
  22. BUILDFLAG(IS_ANDROID)
  23. // On these platforms, the PlatformHandle is a single scoper object.
  24. auto platform_handle = platform_region.PassPlatformHandle();
  25. #else
  26. // On Linux, a valid platform handle is a pair of FDs, and at least one of
  27. // those FDs must be valid: `fd`, if present, is readable and writable and
  28. // `readonly_fd`, if present, is only readable.
  29. //
  30. // For an `UnsafeSharedMemoryRegion` which is always writable, only `fd` is
  31. // present.
  32. base::ScopedFD platform_handle =
  33. std::move(platform_region.PassPlatformHandle().fd);
  34. #endif
  35. return media::mojom::VideoBufferHandle::NewSharedMemoryViaRawFileDescriptor(
  36. media::mojom::SharedMemoryViaRawFileDescriptor::New(
  37. mojo::PlatformHandle(std::move(platform_handle)), region.GetSize()));
  38. }
  39. } // namespace
  40. // A mojom::VideoFrameAccessHandler implementation that forwards buffer release
  41. // calls to the BroadcastingReceiver.
  42. class BroadcastingReceiver::ClientVideoFrameAccessHandler
  43. : public mojom::VideoFrameAccessHandler {
  44. public:
  45. explicit ClientVideoFrameAccessHandler(
  46. base::WeakPtr<BroadcastingReceiver> broadcasting_receiver)
  47. : broadcasting_receiver_(std::move(broadcasting_receiver)) {}
  48. // mojom::VideoFrameAccessHandler implementation.
  49. void OnFinishedConsumingBuffer(int32_t buffer_id) override {
  50. if (!broadcasting_receiver_) {
  51. return;
  52. }
  53. broadcasting_receiver_->OnClientFinishedConsumingFrame(buffer_id);
  54. }
  55. private:
  56. base::WeakPtr<BroadcastingReceiver> broadcasting_receiver_;
  57. };
  58. BroadcastingReceiver::ClientContext::ClientContext(
  59. mojo::PendingRemote<mojom::VideoFrameHandler> client,
  60. media::VideoCaptureBufferType target_buffer_type)
  61. : client_(std::move(client)),
  62. target_buffer_type_(target_buffer_type),
  63. is_suspended_(false),
  64. on_started_has_been_called_(false),
  65. on_started_using_gpu_decode_has_been_called_(false),
  66. has_client_frame_access_handler_remote_(false) {}
  67. BroadcastingReceiver::ClientContext::~ClientContext() = default;
  68. BroadcastingReceiver::ClientContext::ClientContext(
  69. BroadcastingReceiver::ClientContext&& other) = default;
  70. BroadcastingReceiver::ClientContext& BroadcastingReceiver::ClientContext::
  71. operator=(BroadcastingReceiver::ClientContext&& other) = default;
  72. void BroadcastingReceiver::ClientContext::OnStarted() {
  73. if (on_started_has_been_called_)
  74. return;
  75. on_started_has_been_called_ = true;
  76. client_->OnStarted();
  77. }
  78. void BroadcastingReceiver::ClientContext::OnStartedUsingGpuDecode() {
  79. if (on_started_using_gpu_decode_has_been_called_)
  80. return;
  81. on_started_using_gpu_decode_has_been_called_ = true;
  82. client_->OnStartedUsingGpuDecode();
  83. }
  84. BroadcastingReceiver::BufferContext::BufferContext(
  85. int buffer_id,
  86. media::mojom::VideoBufferHandlePtr buffer_handle)
  87. : buffer_id_(buffer_id),
  88. buffer_handle_(std::move(buffer_handle)),
  89. consumer_hold_count_(0),
  90. is_retired_(false) {
  91. static int next_buffer_context_id = 0;
  92. buffer_context_id_ = next_buffer_context_id++;
  93. }
  94. BroadcastingReceiver::BufferContext::~BufferContext() {
  95. // Signal that the buffer is no longer in use, if we haven't already.
  96. if (consumer_hold_count_ != 0) {
  97. DCHECK(frame_access_handler_remote_);
  98. (*frame_access_handler_remote_)->OnFinishedConsumingBuffer(buffer_id_);
  99. }
  100. }
  101. BroadcastingReceiver::BufferContext::BufferContext(
  102. BroadcastingReceiver::BufferContext&& other)
  103. : buffer_context_id_(other.buffer_context_id_),
  104. buffer_id_(other.buffer_id_),
  105. frame_access_handler_remote_(other.frame_access_handler_remote_),
  106. buffer_handle_(std::move(other.buffer_handle_)),
  107. consumer_hold_count_(other.consumer_hold_count_),
  108. is_retired_(other.is_retired_) {
  109. // The consumer hold was moved from |other|.
  110. other.consumer_hold_count_ = 0;
  111. other.frame_access_handler_remote_ = nullptr;
  112. }
  113. BroadcastingReceiver::BufferContext&
  114. BroadcastingReceiver::BufferContext::operator=(
  115. BroadcastingReceiver::BufferContext&& other) {
  116. buffer_context_id_ = other.buffer_context_id_;
  117. buffer_id_ = other.buffer_id_;
  118. frame_access_handler_remote_ = other.frame_access_handler_remote_;
  119. buffer_handle_ = std::move(other.buffer_handle_);
  120. consumer_hold_count_ = other.consumer_hold_count_;
  121. is_retired_ = other.is_retired_;
  122. // The consumer hold was moved from |other|.
  123. other.consumer_hold_count_ = 0;
  124. other.frame_access_handler_remote_ = nullptr;
  125. return *this;
  126. }
  127. void BroadcastingReceiver::BufferContext::SetFrameAccessHandlerRemote(
  128. scoped_refptr<VideoFrameAccessHandlerRemote> frame_access_handler_remote) {
  129. frame_access_handler_remote_ = frame_access_handler_remote;
  130. }
  131. void BroadcastingReceiver::BufferContext::IncreaseConsumerCount() {
  132. // The access handler should be ready if we have a consumer since it is needed
  133. // when the consumer decreases the consumer count.
  134. DCHECK(frame_access_handler_remote_);
  135. consumer_hold_count_++;
  136. }
  137. void BroadcastingReceiver::BufferContext::DecreaseConsumerCount() {
  138. DCHECK(frame_access_handler_remote_);
  139. consumer_hold_count_--;
  140. if (consumer_hold_count_ == 0) {
  141. (*frame_access_handler_remote_)->OnFinishedConsumingBuffer(buffer_id_);
  142. }
  143. }
  144. bool BroadcastingReceiver::BufferContext::IsStillBeingConsumed() const {
  145. return consumer_hold_count_ > 0;
  146. }
  147. media::mojom::VideoBufferHandlePtr
  148. BroadcastingReceiver::BufferContext::CloneBufferHandle(
  149. media::VideoCaptureBufferType target_buffer_type) {
  150. // If the source uses mailbox handles, i.e. textures, we pass those through
  151. // without conversion, no matter what clients requested.
  152. if (buffer_handle_->is_mailbox_handles()) {
  153. return media::mojom::VideoBufferHandle::NewMailboxHandles(
  154. buffer_handle_->get_mailbox_handles()->Clone());
  155. }
  156. // If the source uses GpuMemoryBuffer handles, we pass those through without
  157. // conversion, no matter what clients requested.
  158. if (buffer_handle_->is_gpu_memory_buffer_handle()) {
  159. return media::mojom::VideoBufferHandle::NewGpuMemoryBufferHandle(
  160. buffer_handle_->get_gpu_memory_buffer_handle().Clone());
  161. }
  162. switch (target_buffer_type) {
  163. case media::VideoCaptureBufferType::kMailboxHolder:
  164. NOTREACHED() << "Cannot convert buffer type to kMailboxHolder from "
  165. "handle type other than mailbox handles.";
  166. break;
  167. case media::VideoCaptureBufferType::kSharedMemory:
  168. if (buffer_handle_->is_unsafe_shmem_region()) {
  169. return media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  170. buffer_handle_->get_unsafe_shmem_region().Duplicate());
  171. } else if (buffer_handle_->is_shared_memory_via_raw_file_descriptor()) {
  172. ConvertRawFileDescriptorToUnsafeShmemRegion();
  173. return media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  174. buffer_handle_->get_unsafe_shmem_region().Duplicate());
  175. } else {
  176. NOTREACHED() << "Unexpected video buffer handle type";
  177. }
  178. break;
  179. case media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor:
  180. if (buffer_handle_->is_unsafe_shmem_region()) {
  181. return CloneUnsafeShmemRegionToRawFileDescriptorHandle(
  182. buffer_handle_->get_unsafe_shmem_region());
  183. } else if (buffer_handle_->is_shared_memory_via_raw_file_descriptor()) {
  184. ConvertRawFileDescriptorToUnsafeShmemRegion();
  185. return CloneUnsafeShmemRegionToRawFileDescriptorHandle(
  186. buffer_handle_->get_unsafe_shmem_region().Duplicate());
  187. } else {
  188. NOTREACHED() << "Unexpected video buffer handle type";
  189. }
  190. break;
  191. case media::VideoCaptureBufferType::kGpuMemoryBuffer:
  192. #if BUILDFLAG(IS_WIN)
  193. // On windows with MediaFoundationD3D11VideoCapture if the
  194. // texture capture path fails, a ShMem buffer might be produced instead.
  195. DCHECK(buffer_handle_->is_unsafe_shmem_region());
  196. return media::mojom::VideoBufferHandle::NewUnsafeShmemRegion(
  197. buffer_handle_->get_unsafe_shmem_region().Duplicate());
  198. #else
  199. NOTREACHED() << "Unexpected GpuMemoryBuffer handle type";
  200. break;
  201. #endif
  202. }
  203. return media::mojom::VideoBufferHandlePtr();
  204. }
  205. void BroadcastingReceiver::BufferContext::
  206. ConvertRawFileDescriptorToUnsafeShmemRegion() {
  207. DCHECK(buffer_handle_->is_shared_memory_via_raw_file_descriptor());
  208. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  209. const size_t handle_size =
  210. buffer_handle_->get_shared_memory_via_raw_file_descriptor()
  211. ->shared_memory_size_in_bytes;
  212. base::ScopedFD platform_file =
  213. buffer_handle_->get_shared_memory_via_raw_file_descriptor()
  214. ->file_descriptor_handle.TakeFD();
  215. base::UnguessableToken guid = base::UnguessableToken::Create();
  216. base::subtle::PlatformSharedMemoryRegion platform_region =
  217. base::subtle::PlatformSharedMemoryRegion::Take(
  218. std::move(platform_file),
  219. base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe, handle_size,
  220. guid);
  221. if (!platform_region.IsValid()) {
  222. NOTREACHED();
  223. return;
  224. }
  225. buffer_handle_->set_unsafe_shmem_region(
  226. base::UnsafeSharedMemoryRegion::Deserialize(std::move(platform_region)));
  227. #else
  228. NOTREACHED() << "Unable to consume buffer handle of type "
  229. "kSharedMemoryViaRawFileDescriptor on non-Linux platform.";
  230. #endif
  231. }
  232. BroadcastingReceiver::BroadcastingReceiver()
  233. : status_(Status::kOnStartedHasNotYetBeenCalled),
  234. error_(media::VideoCaptureError::kNone),
  235. next_client_id_(0) {}
  236. BroadcastingReceiver::~BroadcastingReceiver() {
  237. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  238. }
  239. void BroadcastingReceiver::HideSourceRestartFromClients(
  240. base::OnceClosure on_stopped_handler) {
  241. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  242. on_stopped_handler_ = std::move(on_stopped_handler);
  243. status_ = Status::kDeviceIsRestarting;
  244. }
  245. void BroadcastingReceiver::SetOnStoppedHandler(
  246. base::OnceClosure on_stopped_handler) {
  247. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  248. on_stopped_handler_ = std::move(on_stopped_handler);
  249. }
  250. int32_t BroadcastingReceiver::AddClient(
  251. mojo::PendingRemote<mojom::VideoFrameHandler> client,
  252. media::VideoCaptureBufferType target_buffer_type) {
  253. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  254. auto client_id = next_client_id_++;
  255. ClientContext context(std::move(client), target_buffer_type);
  256. auto& added_client_context =
  257. clients_.insert(std::make_pair(client_id, std::move(context)))
  258. .first->second;
  259. added_client_context.client().set_disconnect_handler(
  260. base::BindOnce(&BroadcastingReceiver::OnClientDisconnected,
  261. weak_factory_.GetWeakPtr(), client_id));
  262. if (status_ == Status::kOnErrorHasBeenCalled) {
  263. added_client_context.client()->OnError(error_);
  264. return client_id;
  265. }
  266. if (status_ == Status::kOnStartedHasBeenCalled) {
  267. added_client_context.OnStarted();
  268. }
  269. if (status_ == Status::kOnStartedUsingGpuDecodeHasBeenCalled) {
  270. added_client_context.OnStarted();
  271. added_client_context.OnStartedUsingGpuDecode();
  272. }
  273. for (auto& buffer_context : buffer_contexts_) {
  274. if (buffer_context.is_retired())
  275. continue;
  276. added_client_context.client()->OnNewBuffer(
  277. buffer_context.buffer_context_id(),
  278. buffer_context.CloneBufferHandle(
  279. added_client_context.target_buffer_type()));
  280. }
  281. return client_id;
  282. }
  283. void BroadcastingReceiver::SuspendClient(int32_t client_id) {
  284. clients_.at(client_id).set_is_suspended(true);
  285. }
  286. void BroadcastingReceiver::ResumeClient(int32_t client_id) {
  287. clients_.at(client_id).set_is_suspended(false);
  288. }
  289. mojo::Remote<mojom::VideoFrameHandler> BroadcastingReceiver::RemoveClient(
  290. int32_t client_id) {
  291. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  292. auto client = std::move(clients_.at(client_id));
  293. clients_.erase(client_id);
  294. return std::move(client.client());
  295. }
  296. void BroadcastingReceiver::OnNewBuffer(
  297. int32_t buffer_id,
  298. media::mojom::VideoBufferHandlePtr buffer_handle) {
  299. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  300. CHECK(FindUnretiredBufferContextFromBufferId(buffer_id) ==
  301. buffer_contexts_.end());
  302. buffer_contexts_.emplace_back(buffer_id, std::move(buffer_handle));
  303. auto& buffer_context = buffer_contexts_.back();
  304. for (auto& client : clients_) {
  305. client.second.client()->OnNewBuffer(
  306. buffer_context.buffer_context_id(),
  307. buffer_context.CloneBufferHandle(client.second.target_buffer_type()));
  308. }
  309. }
  310. void BroadcastingReceiver::OnFrameAccessHandlerReady(
  311. mojo::PendingRemote<video_capture::mojom::VideoFrameAccessHandler>
  312. pending_frame_access_handler) {
  313. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  314. DCHECK(!frame_access_handler_remote_);
  315. frame_access_handler_remote_ =
  316. base::MakeRefCounted<VideoFrameAccessHandlerRemote>(
  317. mojo::Remote<video_capture::mojom::VideoFrameAccessHandler>(
  318. std::move(pending_frame_access_handler)));
  319. }
  320. void BroadcastingReceiver::OnFrameReadyInBuffer(
  321. mojom::ReadyFrameInBufferPtr buffer,
  322. std::vector<mojom::ReadyFrameInBufferPtr> scaled_buffers) {
  323. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  324. bool has_consumers = false;
  325. for (auto& client : clients_) {
  326. if (!client.second.is_suspended()) {
  327. has_consumers = true;
  328. break;
  329. }
  330. }
  331. // If we don't have any consumers to forward the frame to, signal to finish
  332. // consuming the buffers immediately.
  333. if (!has_consumers) {
  334. if (frame_access_handler_remote_) {
  335. (*frame_access_handler_remote_)
  336. ->OnFinishedConsumingBuffer(buffer->buffer_id);
  337. for (const auto& scaled_buffer : scaled_buffers) {
  338. (*frame_access_handler_remote_)
  339. ->OnFinishedConsumingBuffer(scaled_buffer->buffer_id);
  340. }
  341. }
  342. return;
  343. }
  344. // Obtain buffer contexts for all frame representations.
  345. auto it = FindUnretiredBufferContextFromBufferId(buffer->buffer_id);
  346. CHECK(it != buffer_contexts_.end());
  347. BufferContext* buffer_context = &(*it);
  348. std::vector<BufferContext*> scaled_buffer_contexts;
  349. scaled_buffer_contexts.reserve(scaled_buffers.size());
  350. for (const auto& scaled_buffer : scaled_buffers) {
  351. it = FindUnretiredBufferContextFromBufferId(scaled_buffer->buffer_id);
  352. CHECK(it != buffer_contexts_.end());
  353. scaled_buffer_contexts.push_back(&(*it));
  354. }
  355. // Broadcast to all clients.
  356. for (auto& client : clients_) {
  357. if (client.second.is_suspended())
  358. continue;
  359. // Set up a frame access handler for this client, if we haven't already. The
  360. // frame access handler mojo pipe is open for the lifetime of the
  361. // ClientContext.
  362. if (!client.second.has_client_frame_access_handler_remote()) {
  363. mojo::PendingRemote<mojom::VideoFrameAccessHandler>
  364. pending_frame_access_handler;
  365. mojo::MakeSelfOwnedReceiver<mojom::VideoFrameAccessHandler>(
  366. std::make_unique<ClientVideoFrameAccessHandler>(
  367. weak_factory_.GetWeakPtr()),
  368. pending_frame_access_handler.InitWithNewPipeAndPassReceiver());
  369. client.second.client()->OnFrameAccessHandlerReady(
  370. std::move(pending_frame_access_handler));
  371. client.second.set_has_client_frame_access_handler_remote();
  372. }
  373. buffer_context->SetFrameAccessHandlerRemote(frame_access_handler_remote_);
  374. buffer_context->IncreaseConsumerCount();
  375. mojom::ReadyFrameInBufferPtr ready_buffer = mojom::ReadyFrameInBuffer::New(
  376. buffer_context->buffer_context_id(), buffer->frame_feedback_id,
  377. buffer->frame_info.Clone());
  378. std::vector<mojom::ReadyFrameInBufferPtr> scaled_ready_buffers;
  379. scaled_ready_buffers.reserve(scaled_buffers.size());
  380. for (size_t i = 0; i < scaled_buffers.size(); ++i) {
  381. scaled_buffer_contexts[i]->SetFrameAccessHandlerRemote(
  382. frame_access_handler_remote_);
  383. scaled_buffer_contexts[i]->IncreaseConsumerCount();
  384. scaled_ready_buffers.push_back(mojom::ReadyFrameInBuffer::New(
  385. scaled_buffer_contexts[i]->buffer_context_id(),
  386. scaled_buffers[i]->frame_feedback_id,
  387. scaled_buffers[i]->frame_info.Clone()));
  388. }
  389. client.second.client()->OnFrameReadyInBuffer(
  390. std::move(ready_buffer), std::move(scaled_ready_buffers));
  391. }
  392. }
  393. void BroadcastingReceiver::OnBufferRetired(int32_t buffer_id) {
  394. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  395. auto buffer_context_iter = FindUnretiredBufferContextFromBufferId(buffer_id);
  396. CHECK(buffer_context_iter != buffer_contexts_.end());
  397. const auto context_id = buffer_context_iter->buffer_context_id();
  398. if (buffer_context_iter->IsStillBeingConsumed())
  399. // Mark the buffer context as retired but keep holding on to it until the
  400. // last client finished consuming it, because it contains the
  401. // |access_permission| required during consumption.
  402. buffer_context_iter->set_retired();
  403. else
  404. buffer_contexts_.erase(buffer_context_iter);
  405. for (auto& client : clients_) {
  406. client.second.client()->OnBufferRetired(context_id);
  407. }
  408. }
  409. void BroadcastingReceiver::OnError(media::VideoCaptureError error) {
  410. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  411. for (auto& client : clients_) {
  412. client.second.client()->OnError(error);
  413. }
  414. status_ = Status::kOnErrorHasBeenCalled;
  415. error_ = error;
  416. }
  417. void BroadcastingReceiver::OnFrameDropped(
  418. media::VideoCaptureFrameDropReason reason) {
  419. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  420. for (auto& client : clients_) {
  421. if (client.second.is_suspended())
  422. continue;
  423. client.second.client()->OnFrameDropped(reason);
  424. }
  425. }
  426. void BroadcastingReceiver::OnNewCropVersion(uint32_t crop_version) {
  427. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  428. for (auto& client : clients_) {
  429. client.second.client()->OnNewCropVersion(crop_version);
  430. }
  431. }
  432. void BroadcastingReceiver::OnFrameWithEmptyRegionCapture() {
  433. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  434. for (auto& client : clients_) {
  435. client.second.client()->OnFrameWithEmptyRegionCapture();
  436. }
  437. }
  438. void BroadcastingReceiver::OnLog(const std::string& message) {
  439. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  440. for (auto& client : clients_) {
  441. client.second.client()->OnLog(message);
  442. }
  443. }
  444. void BroadcastingReceiver::OnStarted() {
  445. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  446. for (auto& client : clients_) {
  447. client.second.OnStarted();
  448. }
  449. status_ = Status::kOnStartedHasBeenCalled;
  450. }
  451. void BroadcastingReceiver::OnStartedUsingGpuDecode() {
  452. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  453. for (auto& client : clients_) {
  454. client.second.OnStartedUsingGpuDecode();
  455. }
  456. status_ = Status::kOnStartedUsingGpuDecodeHasBeenCalled;
  457. }
  458. void BroadcastingReceiver::OnStopped() {
  459. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  460. if (status_ == Status::kDeviceIsRestarting) {
  461. status_ = Status::kOnStartedHasNotYetBeenCalled;
  462. std::move(on_stopped_handler_).Run();
  463. } else {
  464. for (auto& client : clients_) {
  465. client.second.client()->OnStopped();
  466. }
  467. status_ = Status::kOnStoppedHasBeenCalled;
  468. if (on_stopped_handler_)
  469. std::move(on_stopped_handler_).Run();
  470. }
  471. // Reset the frame access handler so that it is possible to bind a new one if
  472. // BroadcastingReceiver is started again in the future.
  473. frame_access_handler_remote_.reset();
  474. }
  475. void BroadcastingReceiver::OnClientFinishedConsumingFrame(
  476. int32_t buffer_context_id) {
  477. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  478. auto buffer_context_iter =
  479. std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
  480. [buffer_context_id](const BufferContext& entry) {
  481. return entry.buffer_context_id() == buffer_context_id;
  482. });
  483. CHECK(buffer_context_iter != buffer_contexts_.end());
  484. buffer_context_iter->DecreaseConsumerCount();
  485. if (buffer_context_iter->is_retired() &&
  486. !buffer_context_iter->IsStillBeingConsumed()) {
  487. buffer_contexts_.erase(buffer_context_iter);
  488. }
  489. }
  490. void BroadcastingReceiver::OnClientDisconnected(int32_t client_id) {
  491. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  492. clients_.erase(client_id);
  493. }
  494. std::vector<BroadcastingReceiver::BufferContext>::iterator
  495. BroadcastingReceiver::FindUnretiredBufferContextFromBufferId(
  496. int32_t buffer_id) {
  497. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  498. return std::find_if(buffer_contexts_.begin(), buffer_contexts_.end(),
  499. [buffer_id](const BufferContext& entry) {
  500. return !entry.is_retired() &&
  501. entry.buffer_id() == buffer_id;
  502. });
  503. }
  504. } // namespace video_capture