// Copyright 2022 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 ASH_CAPTURE_MODE_CAMERA_VIDEO_FRAME_HANDLER_H_ #define ASH_CAPTURE_MODE_CAMERA_VIDEO_FRAME_HANDLER_H_ #include #include #include "base/containers/flat_map.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "media/capture/mojom/video_capture_buffer.mojom-forward.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/video_capture/public/mojom/video_frame_handler.mojom.h" #include "services/video_capture/public/mojom/video_source.mojom.h" namespace media { class VideoFrame; } // namespace media namespace ash { // Defines an interface for an object that can hold and own a video buffer // handle, and able to extract a `VideoFrame` from the buffer when the frame // becomes ready in it. Concrete subclasses implements this frame extraction // differently based on the type of the buffer. class BufferHandleHolder { public: BufferHandleHolder(const BufferHandleHolder&) = delete; BufferHandleHolder& operator=(const BufferHandleHolder&) = delete; virtual ~BufferHandleHolder(); // Creates and returns a concrete implementation of this interface that // matches the buffer type of the given `buffer_handle`. // We only support the `kGpuMemoryBuffer` and `kSharedMemory` buffer types. static std::unique_ptr Create( media::mojom::VideoBufferHandlePtr buffer_handle); // Extracts and returns the ready video frame in the given `buffer`. virtual scoped_refptr OnFrameReadyInBuffer( video_capture::mojom::ReadyFrameInBufferPtr buffer) = 0; protected: BufferHandleHolder() = default; }; // ----------------------------------------------------------------------------- // Defines an object that will subscribe to a camera device, whose remote video // source is the given `camera_video_source`. It will handle the reception of // the video frames from that device and provide them to its `Delegate`. class CameraVideoFrameHandler : public video_capture::mojom::VideoFrameHandler { public: // Defines an interface for a delegate of this class, which will be provided // by the video frames received from the camera device. class Delegate { public: // Will be called on the UI thread whenever a video `frame` is received from // the camera device. virtual void OnCameraVideoFrame(scoped_refptr frame) = 0; protected: virtual ~Delegate() = default; }; // Creates an instance of this class which will subscribe to the given // `camera_video_source` requesting to receive video frames of its feed with // the given `capture_format`. The video frames will then be provided to the // `delegate`. CameraVideoFrameHandler( Delegate* delegate, mojo::Remote camera_video_source, const media::VideoCaptureFormat& capture_format); CameraVideoFrameHandler(const CameraVideoFrameHandler&) = delete; CameraVideoFrameHandler& operator=(const CameraVideoFrameHandler&) = delete; ~CameraVideoFrameHandler() override; // Activates the subscription so we start receiving video frames. void StartHandlingFrames(); // video_capture::mojom::VideoFrameHandler: void OnNewBuffer(int buffer_id, media::mojom::VideoBufferHandlePtr buffer_handle) override; void OnFrameAccessHandlerReady( mojo::PendingRemote pending_frame_access_handler) override; void OnFrameReadyInBuffer( video_capture::mojom::ReadyFrameInBufferPtr buffer, std::vector scaled_buffers) override; void OnBufferRetired(int buffer_id) override; void OnError(media::VideoCaptureError error) override; void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override; void OnNewCropVersion(uint32_t crop_version) override; void OnFrameWithEmptyRegionCapture() override; void OnLog(const std::string& message) override; void OnStarted() override; void OnStartedUsingGpuDecode() override; void OnStopped() override; // The `kGpuMemoryBuffer` type is requested only when running on an actual // device. This allows force-requesting them even when running on // linux-chromeos for unit testing purposes. static void SetForceUseGpuMemoryBufferForTest(bool value); private: // Called when a video frame is destroyed, which was backed by a buffer whose // ID is the given `buffer_id`. This lets us inform the video capture // service's `VideoFrameAccessHandler` that we're done consuming this buffer // so it can be reused again by the video frames producer. void OnVideoFrameGone(int buffer_id); // Called when a fatal error is reported in `OnError()` or the mojo remote to // `VideoSource` gets disconnected. void OnFatalErrorOrDisconnection(); Delegate* const delegate_; mojo::Receiver video_frame_handler_receiver_{this}; // A remote bound to the camera's `VideoSource` implementation in the video // capture service. mojo::Remote camera_video_source_remote_; // A remote bound to the `PushVideoStreamSubscription` implementation in the // video capture service. Once this subscription is activated, we start // receiving video frames. mojo::Remote camera_video_stream_subsciption_remote_; // A remote bound to the `VideoFrameAccessHandler` implementation in the video // capture service, which is used to signal that we're done consuming a buffer // so that the buffer can be reused by the frames producer. mojo::Remote video_frame_access_handler_remote_; // Maps the `BufferHandleHolder`s by the `buffer_id`. An entry is inserted // when `OnNewBuffer()` is called, and removed when `OnBufferRetired()` is // called. base::flat_map> buffer_map_; base::WeakPtrFactory weak_ptr_factory_{this}; }; } // namespace ash #endif // ASH_CAPTURE_MODE_CAMERA_VIDEO_FRAME_HANDLER_H_