single_client_video_capture_host.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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 "components/mirroring/browser/single_client_video_capture_host.h"
  5. #include "base/bind.h"
  6. #include "base/callback.h"
  7. #include "base/memory/weak_ptr.h"
  8. #include "base/token.h"
  9. #include "content/public/browser/web_contents_media_capture_id.h"
  10. #include "media/capture/video/video_capture_buffer_pool.h"
  11. #include "mojo/public/cpp/bindings/pending_remote.h"
  12. using media::VideoFrameConsumerFeedbackObserver;
  13. namespace mirroring {
  14. namespace {
  15. class DeviceLauncherCallbacks final
  16. : public content::VideoCaptureDeviceLauncher::Callbacks {
  17. public:
  18. explicit DeviceLauncherCallbacks(
  19. base::WeakPtr<SingleClientVideoCaptureHost> host)
  20. : video_capture_host_(host) {}
  21. DeviceLauncherCallbacks(const DeviceLauncherCallbacks&) = delete;
  22. DeviceLauncherCallbacks& operator=(const DeviceLauncherCallbacks&) = delete;
  23. ~DeviceLauncherCallbacks() override {}
  24. // content::VideoCaptureDeviceLauncher::Callbacks implementations
  25. void OnDeviceLaunched(
  26. std::unique_ptr<content::LaunchedVideoCaptureDevice> device) override {
  27. if (video_capture_host_)
  28. video_capture_host_->OnDeviceLaunched(std::move(device));
  29. }
  30. void OnDeviceLaunchFailed(media::VideoCaptureError error) override {
  31. if (video_capture_host_)
  32. video_capture_host_->OnDeviceLaunchFailed(error);
  33. }
  34. void OnDeviceLaunchAborted() override {
  35. if (video_capture_host_)
  36. video_capture_host_->OnDeviceLaunchAborted();
  37. }
  38. private:
  39. base::WeakPtr<SingleClientVideoCaptureHost> video_capture_host_;
  40. };
  41. } // namespace
  42. SingleClientVideoCaptureHost::SingleClientVideoCaptureHost(
  43. const std::string& device_id,
  44. blink::mojom::MediaStreamType type,
  45. DeviceLauncherCreateCallback callback)
  46. : device_id_(device_id),
  47. type_(type),
  48. device_launcher_callback_(std::move(callback)) {
  49. DCHECK(!device_launcher_callback_.is_null());
  50. }
  51. SingleClientVideoCaptureHost::~SingleClientVideoCaptureHost() {
  52. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  53. Stop(base::UnguessableToken());
  54. }
  55. void SingleClientVideoCaptureHost::Start(
  56. const base::UnguessableToken& device_id,
  57. const base::UnguessableToken& session_id,
  58. const VideoCaptureParams& params,
  59. mojo::PendingRemote<media::mojom::VideoCaptureObserver> observer) {
  60. DVLOG(1) << __func__;
  61. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  62. DCHECK(!observer_);
  63. observer_.Bind(std::move(observer));
  64. DCHECK(observer_);
  65. DCHECK(!launched_device_);
  66. // Start a video capture device.
  67. auto device_launcher_callbacks =
  68. std::make_unique<DeviceLauncherCallbacks>(weak_factory_.GetWeakPtr());
  69. DeviceLauncherCallbacks* callbacks = device_launcher_callbacks.get();
  70. std::unique_ptr<content::VideoCaptureDeviceLauncher> device_launcher =
  71. device_launcher_callback_.Run();
  72. content::VideoCaptureDeviceLauncher* launcher = device_launcher.get();
  73. launcher->LaunchDeviceAsync(
  74. device_id_, type_, params, weak_factory_.GetWeakPtr(),
  75. base::BindOnce(&SingleClientVideoCaptureHost::OnError,
  76. weak_factory_.GetWeakPtr(),
  77. media::VideoCaptureError::
  78. kSingleClientVideoCaptureHostLostConnectionToDevice),
  79. callbacks,
  80. // The |device_launcher| and |device_launcher_callbacks| must be kept
  81. // alive until the device launching completes.
  82. base::BindOnce([](std::unique_ptr<content::VideoCaptureDeviceLauncher>,
  83. std::unique_ptr<DeviceLauncherCallbacks>) {},
  84. std::move(device_launcher),
  85. std::move(device_launcher_callbacks)));
  86. }
  87. void SingleClientVideoCaptureHost::Stop(
  88. const base::UnguessableToken& device_id) {
  89. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  90. DVLOG(1) << __func__;
  91. if (!observer_)
  92. return;
  93. // Returns all the buffers.
  94. std::vector<int> buffers_in_use;
  95. buffers_in_use.reserve(buffer_context_map_.size());
  96. for (const auto& entry : buffer_context_map_)
  97. buffers_in_use.push_back(entry.first);
  98. for (int buffer_id : buffers_in_use) {
  99. OnFinishedConsumingBuffer(buffer_id, media::VideoCaptureFeedback());
  100. }
  101. DCHECK(buffer_context_map_.empty());
  102. observer_->OnStateChanged(media::mojom::VideoCaptureResult::NewState(
  103. media::mojom::VideoCaptureState::ENDED));
  104. observer_.reset();
  105. weak_factory_.InvalidateWeakPtrs();
  106. launched_device_ = nullptr;
  107. id_map_.clear();
  108. retired_buffers_.clear();
  109. }
  110. void SingleClientVideoCaptureHost::Pause(
  111. const base::UnguessableToken& device_id) {
  112. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  113. if (launched_device_)
  114. launched_device_->MaybeSuspendDevice();
  115. }
  116. void SingleClientVideoCaptureHost::Resume(
  117. const base::UnguessableToken& device_id,
  118. const base::UnguessableToken& session_id,
  119. const VideoCaptureParams& params) {
  120. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  121. if (launched_device_)
  122. launched_device_->ResumeDevice();
  123. }
  124. void SingleClientVideoCaptureHost::RequestRefreshFrame(
  125. const base::UnguessableToken& device_id) {
  126. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  127. if (launched_device_)
  128. launched_device_->RequestRefreshFrame();
  129. }
  130. void SingleClientVideoCaptureHost::ReleaseBuffer(
  131. const base::UnguessableToken& device_id,
  132. int32_t buffer_id,
  133. const media::VideoCaptureFeedback& feedback) {
  134. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  135. DVLOG(3) << __func__ << ": buffer_id=" << buffer_id;
  136. OnFinishedConsumingBuffer(buffer_id, feedback);
  137. }
  138. void SingleClientVideoCaptureHost::GetDeviceSupportedFormats(
  139. const base::UnguessableToken& device_id,
  140. const base::UnguessableToken& session_id,
  141. GetDeviceSupportedFormatsCallback callback) {
  142. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  143. NOTIMPLEMENTED();
  144. std::move(callback).Run(media::VideoCaptureFormats());
  145. }
  146. void SingleClientVideoCaptureHost::GetDeviceFormatsInUse(
  147. const base::UnguessableToken& device_id,
  148. const base::UnguessableToken& session_id,
  149. GetDeviceFormatsInUseCallback callback) {
  150. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  151. NOTIMPLEMENTED();
  152. std::move(callback).Run(media::VideoCaptureFormats());
  153. }
  154. void SingleClientVideoCaptureHost::OnFrameDropped(
  155. const base::UnguessableToken& device_id,
  156. media::VideoCaptureFrameDropReason reason) {
  157. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  158. // Ignore this call.
  159. }
  160. void SingleClientVideoCaptureHost::OnNewCropVersion(uint32_t crop_version) {
  161. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  162. // Ignore this call.
  163. }
  164. void SingleClientVideoCaptureHost::OnFrameWithEmptyRegionCapture() {
  165. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  166. // Ignore this call.
  167. }
  168. void SingleClientVideoCaptureHost::OnLog(
  169. const base::UnguessableToken& device_id,
  170. const std::string& message) {
  171. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  172. // Ignore this call.
  173. }
  174. void SingleClientVideoCaptureHost::OnNewBuffer(
  175. int buffer_id,
  176. media::mojom::VideoBufferHandlePtr buffer_handle) {
  177. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  178. DVLOG(3) << __func__ << ": buffer_id=" << buffer_id;
  179. DCHECK(observer_);
  180. DCHECK_NE(buffer_id, media::VideoCaptureBufferPool::kInvalidId);
  181. const auto insert_result =
  182. id_map_.emplace(std::make_pair(buffer_id, next_buffer_context_id_));
  183. DCHECK(insert_result.second);
  184. observer_->OnNewBuffer(next_buffer_context_id_++, std::move(buffer_handle));
  185. }
  186. void SingleClientVideoCaptureHost::OnFrameReadyInBuffer(
  187. media::ReadyFrameInBuffer frame,
  188. std::vector<media::ReadyFrameInBuffer> scaled_frames) {
  189. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  190. DVLOG(3) << __func__ << ": buffer_id=" << frame.buffer_id;
  191. DCHECK(observer_);
  192. const auto id_iter = id_map_.find(frame.buffer_id);
  193. DCHECK(id_iter != id_map_.end());
  194. const int buffer_context_id = id_iter->second;
  195. const auto insert_result = buffer_context_map_.emplace(
  196. std::make_pair(buffer_context_id,
  197. std::make_pair(frame.frame_feedback_id,
  198. std::move(frame.buffer_read_permission))));
  199. DCHECK(insert_result.second);
  200. // This implementation does not forward scaled frames.
  201. observer_->OnBufferReady(media::mojom::ReadyBuffer::New(
  202. buffer_context_id, std::move(frame.frame_info)),
  203. {});
  204. }
  205. void SingleClientVideoCaptureHost::OnBufferRetired(int buffer_id) {
  206. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  207. DVLOG(3) << __func__ << ": buffer_id=" << buffer_id;
  208. const auto id_iter = id_map_.find(buffer_id);
  209. DCHECK(id_iter != id_map_.end());
  210. const int buffer_context_id = id_iter->second;
  211. id_map_.erase(id_iter);
  212. if (buffer_context_map_.find(buffer_context_id) ==
  213. buffer_context_map_.end()) {
  214. DCHECK(observer_);
  215. observer_->OnBufferDestroyed(buffer_context_id);
  216. } else {
  217. // The consumer is still using the buffer. The BufferContext needs to be
  218. // held until the consumer finishes.
  219. const auto insert_result = retired_buffers_.insert(buffer_context_id);
  220. DCHECK(insert_result.second);
  221. }
  222. }
  223. void SingleClientVideoCaptureHost::OnError(media::VideoCaptureError error) {
  224. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  225. VLOG(1) << __func__;
  226. if (observer_)
  227. observer_->OnStateChanged(
  228. media::mojom::VideoCaptureResult::NewErrorCode(error));
  229. }
  230. void SingleClientVideoCaptureHost::OnFrameDropped(
  231. media::VideoCaptureFrameDropReason reason) {
  232. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  233. }
  234. void SingleClientVideoCaptureHost::OnLog(const std::string& message) {
  235. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  236. VLOG(3) << message;
  237. }
  238. void SingleClientVideoCaptureHost::OnStarted() {
  239. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  240. DVLOG(2) << __func__;
  241. DCHECK(observer_);
  242. observer_->OnStateChanged(media::mojom::VideoCaptureResult::NewState(
  243. media::mojom::VideoCaptureState::STARTED));
  244. }
  245. void SingleClientVideoCaptureHost::OnStartedUsingGpuDecode() {
  246. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  247. NOTIMPLEMENTED();
  248. }
  249. void SingleClientVideoCaptureHost::OnStopped() {
  250. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  251. }
  252. void SingleClientVideoCaptureHost::OnDeviceLaunched(
  253. std::unique_ptr<content::LaunchedVideoCaptureDevice> device) {
  254. DVLOG(1) << __func__;
  255. launched_device_ = std::move(device);
  256. }
  257. void SingleClientVideoCaptureHost::OnDeviceLaunchFailed(
  258. media::VideoCaptureError error) {
  259. DVLOG(1) << __func__;
  260. launched_device_ = nullptr;
  261. OnError(error);
  262. }
  263. void SingleClientVideoCaptureHost::OnDeviceLaunchAborted() {
  264. DVLOG(1) << __func__;
  265. launched_device_ = nullptr;
  266. OnError(
  267. media::VideoCaptureError::kSingleClientVideoCaptureDeviceLaunchAborted);
  268. }
  269. void SingleClientVideoCaptureHost::OnFinishedConsumingBuffer(
  270. int buffer_context_id,
  271. media::VideoCaptureFeedback feedback) {
  272. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  273. DCHECK(observer_);
  274. const auto buffer_context_iter = buffer_context_map_.find(buffer_context_id);
  275. if (buffer_context_iter == buffer_context_map_.end()) {
  276. // Stop() must have been called before.
  277. DCHECK(!launched_device_);
  278. return;
  279. }
  280. VideoFrameConsumerFeedbackObserver* feedback_observer =
  281. launched_device_.get();
  282. if (feedback_observer && !feedback.Empty()) {
  283. feedback.frame_id = buffer_context_iter->second.first;
  284. feedback_observer->OnUtilizationReport(feedback);
  285. }
  286. buffer_context_map_.erase(buffer_context_iter);
  287. const auto retired_iter = retired_buffers_.find(buffer_context_id);
  288. if (retired_iter != retired_buffers_.end()) {
  289. retired_buffers_.erase(retired_iter);
  290. observer_->OnBufferDestroyed(buffer_context_id);
  291. }
  292. }
  293. } // namespace mirroring