|  | // Copyright 2018 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. | 
|  |  | 
|  | #ifndef COMPONENTS_MIRRORING_BROWSER_SINGLE_CLIENT_VIDEO_CAPTURE_HOST_H_ | 
|  | #define COMPONENTS_MIRRORING_BROWSER_SINGLE_CLIENT_VIDEO_CAPTURE_HOST_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <string> | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/callback.h" | 
|  | #include "base/containers/flat_map.h" | 
|  | #include "base/containers/flat_set.h" | 
|  | #include "base/memory/scoped_refptr.h" | 
|  | #include "base/sequence_checker.h" | 
|  | #include "content/public/browser/video_capture_device_launcher.h" | 
|  | #include "media/capture/mojom/video_capture.mojom.h" | 
|  | #include "media/capture/video/video_frame_receiver.h" | 
|  |  | 
|  | using media::VideoCaptureParams; | 
|  | using media::VideoCaptureDevice; | 
|  |  | 
|  | namespace mirroring { | 
|  |  | 
|  | // Implements a subset of mojom::VideoCaptureHost to proxy between a | 
|  | // content::LaunchedVideoCaptureDevice and a single client. On Start(), uses the | 
|  | // provided DeviceLauncherCreateCallback to launch a video capture device that | 
|  | // outputs frames to |this|. The frames are received through the | 
|  | // VideoFrameReceiver interface and are forwarded to |observer| through the | 
|  | // mojom::VideoCaptureObserver interface. | 
|  | // Instances of this class must be operated from the same thread that is reqired | 
|  | // by the DeviceLauncherCreateCallback. | 
|  | class SingleClientVideoCaptureHost final | 
|  | : public media::mojom::VideoCaptureHost, | 
|  | public media::VideoFrameReceiver { | 
|  | public: | 
|  | using DeviceLauncherCreateCallback = base::RepeatingCallback< | 
|  | std::unique_ptr<content::VideoCaptureDeviceLauncher>()>; | 
|  | SingleClientVideoCaptureHost(const std::string& device_id, | 
|  | content::MediaStreamType type, | 
|  | DeviceLauncherCreateCallback callback); | 
|  | ~SingleClientVideoCaptureHost() override; | 
|  |  | 
|  | // media::mojom::VideoCaptureHost implementations | 
|  | // |device_id| and |session_id| are ignored since there will be only one | 
|  | // device and one client. | 
|  | void Start(int32_t device_id, | 
|  | int32_t session_id, | 
|  | const VideoCaptureParams& params, | 
|  | media::mojom::VideoCaptureObserverPtr observer) override; | 
|  | void Stop(int32_t device_id) override; | 
|  | void Pause(int32_t device_id) override; | 
|  | void Resume(int32_t device_id, | 
|  | int32_t session_id, | 
|  | const VideoCaptureParams& params) override; | 
|  | void RequestRefreshFrame(int32_t device_id) override; | 
|  | void ReleaseBuffer(int32_t device_id, | 
|  | int32_t buffer_id, | 
|  | double consumer_resource_utilization) override; | 
|  | void GetDeviceSupportedFormats( | 
|  | int32_t device_id, | 
|  | int32_t session_id, | 
|  | GetDeviceSupportedFormatsCallback callback) override; | 
|  | void GetDeviceFormatsInUse(int32_t device_id, | 
|  | int32_t session_id, | 
|  | GetDeviceFormatsInUseCallback callback) override; | 
|  |  | 
|  | // media::VideoFrameReceiver implementations | 
|  | using Buffer = VideoCaptureDevice::Client::Buffer; | 
|  | void OnNewBuffer(int buffer_id, | 
|  | media::mojom::VideoBufferHandlePtr buffer_handle) override; | 
|  | void OnFrameReadyInBuffer( | 
|  | int buffer_id, | 
|  | int frame_feedback_id, | 
|  | std::unique_ptr< | 
|  | VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> | 
|  | buffer_read_permission, | 
|  | media::mojom::VideoFrameInfoPtr frame_info) override; | 
|  | void OnBufferRetired(int buffer_id) override; | 
|  | void OnError(media::VideoCaptureError error) override; | 
|  | void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override; | 
|  | void OnLog(const std::string& message) override; | 
|  | void OnStarted() override; | 
|  | void OnStartedUsingGpuDecode() override; | 
|  |  | 
|  | void OnDeviceLaunched( | 
|  | std::unique_ptr<content::LaunchedVideoCaptureDevice> device); | 
|  | void OnDeviceLaunchFailed(media::VideoCaptureError error); | 
|  | void OnDeviceLaunchAborted(); | 
|  |  | 
|  | private: | 
|  | // Reports the |consumer_resource_utilization| and removes the buffer context. | 
|  | void OnFinishedConsumingBuffer(int buffer_context_id, | 
|  | double consumer_resource_utilization); | 
|  |  | 
|  | const std::string device_id_; | 
|  | const content::MediaStreamType type_; | 
|  | const DeviceLauncherCreateCallback device_launcher_callback_; | 
|  |  | 
|  | media::mojom::VideoCaptureObserverPtr observer_; | 
|  | std::unique_ptr<content::LaunchedVideoCaptureDevice> launched_device_; | 
|  |  | 
|  | // Unique ID assigned for the next buffer provided by OnNewBufferHandle(). | 
|  | int next_buffer_context_id_ = 0; | 
|  |  | 
|  | // Records the assigned buffer_context_id for buffers that are not retired. | 
|  | // The |buffer_id| provided by OnNewBufferHandle() is used as the key. | 
|  | base::flat_map<int, int> id_map_; | 
|  |  | 
|  | // Tracks the the retired buffers that are still held by |observer_|. | 
|  | base::flat_set<int> retired_buffers_; | 
|  |  | 
|  | // Records the |frame_feedback_id| and |buffer_read_permission| provided by | 
|  | // OnFrameReadyInBuffer(). The key is the assigned buffer context id. Each | 
|  | // entry is removed after the |observer_| finishes consuming the buffer by | 
|  | // calling ReleaseBuffer(). When Stop() is called, all the buffers are cleared | 
|  | // immediately. | 
|  | using BufferContext = std::pair< | 
|  | int, | 
|  | std::unique_ptr< | 
|  | VideoCaptureDevice::Client::Buffer::ScopedAccessPermission>>; | 
|  | base::flat_map<int, BufferContext> buffer_context_map_; | 
|  |  | 
|  | SEQUENCE_CHECKER(sequence_checker_); | 
|  |  | 
|  | base::WeakPtrFactory<SingleClientVideoCaptureHost> weak_factory_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(SingleClientVideoCaptureHost); | 
|  | }; | 
|  |  | 
|  | }  // namespace mirroring | 
|  |  | 
|  | #endif  // COMPONENTS_MIRRORING_BROWSER_SINGLE_CLIENT_VIDEO_CAPTURE_HOST_H_ |