#ifndef COMPONENTS_VIZ_HOST_CLIENT_FRAME_SINK_VIDEO_CAPTURER_H_
#define COMPONENTS_VIZ_HOST_CLIENT_FRAME_SINK_VIDEO_CAPTURER_H_
#include <memory>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/host/viz_host_export.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
namespace viz {
class VIZ_HOST_EXPORT ClientFrameSinkVideoCapturer
: private mojom::FrameSinkVideoConsumer {
public:
class VIZ_HOST_EXPORT Overlay final
: public mojom::FrameSinkVideoCaptureOverlay {
public:
Overlay(base::WeakPtr<ClientFrameSinkVideoCapturer> client_capturer,
int32_t stacking_index);
Overlay(const Overlay&) = delete;
Overlay& operator=(const Overlay&) = delete;
~Overlay() final;
int32_t stacking_index() const { return stacking_index_; }
void SetImageAndBounds(const SkBitmap& image,
const gfx::RectF& bounds) final;
void SetBounds(const gfx::RectF& bounds) final;
void OnCapturedMouseEvent(const gfx::Point& coordinates) final;
private:
friend class ClientFrameSinkVideoCapturer;
void DisconnectPermanently();
void EstablishConnection(mojom::FrameSinkVideoCapturer* capturer);
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<ClientFrameSinkVideoCapturer> client_capturer_;
const int32_t stacking_index_;
mojo::Remote<mojom::FrameSinkVideoCaptureOverlay> overlay_;
SkBitmap image_;
gfx::RectF bounds_;
};
using EstablishConnectionCallback = base::RepeatingCallback<void(
mojo::PendingReceiver<mojom::FrameSinkVideoCapturer>)>;
explicit ClientFrameSinkVideoCapturer(EstablishConnectionCallback callback);
~ClientFrameSinkVideoCapturer() override;
void SetFormat(media::VideoPixelFormat format);
void SetMinCapturePeriod(base::TimeDelta min_capture_period);
void SetMinSizeChangePeriod(base::TimeDelta min_period);
void SetResolutionConstraints(const gfx::Size& min_size,
const gfx::Size& max_size,
bool use_fixed_aspect_ratio);
void SetAutoThrottlingEnabled(bool enabled);
void SetAnimationFpsLockIn(bool enabled,
float majority_damaged_pixel_min_ratio);
void ChangeTarget(const std::optional<VideoCaptureTarget>& target);
void ChangeTarget(const std::optional<VideoCaptureTarget>& target,
uint32_t sub_capture_target_version);
void Stop();
void RequestRefreshFrame();
void Start(mojom::FrameSinkVideoConsumer* consumer,
mojom::BufferFormatPreference buffer_format_preference);
void StopAndResetConsumer();
std::unique_ptr<Overlay> CreateOverlay(int32_t stacking_index);
std::optional<media::VideoPixelFormat> GetFormat() const { return format_; }
private:
struct ResolutionConstraints {
ResolutionConstraints(const gfx::Size& min_size,
const gfx::Size& max_size,
bool use_fixed_aspect_ratio);
gfx::Size min_size;
gfx::Size max_size;
bool use_fixed_aspect_ratio;
};
void OnFrameCaptured(
media::mojom::VideoBufferHandlePtr data,
media::mojom::VideoFrameInfoPtr info,
const gfx::Rect& content_rect,
mojo::PendingRemote<mojom::FrameSinkVideoConsumerFrameCallbacks>
callbacks) final;
void OnNewCaptureVersion(const media::CaptureVersion& capture_version) final;
void OnFrameWithEmptyRegionCapture() final;
void OnStopped() final;
void OnLog(const std::string& message) final;
void EstablishConnection();
void OnConnectionError();
void StartInternal();
void OnOverlayDestroyed(Overlay* overlay);
SEQUENCE_CHECKER(sequence_checker_);
std::optional<media::VideoPixelFormat> format_;
std::optional<base::TimeDelta> min_capture_period_;
std::optional<base::TimeDelta> min_size_change_period_;
std::optional<ResolutionConstraints> resolution_constraints_;
std::optional<bool> auto_throttling_enabled_;
std::optional<VideoCaptureTarget> target_;
std::optional<bool> animated_content_sampler_enabled_;
std::optional<float> majority_damaged_pixel_min_ratio_;
uint32_t sub_capture_version_ = 0;
std::vector<raw_ptr<Overlay, VectorExperimental>> overlays_;
bool is_started_ = false;
mojom::BufferFormatPreference buffer_format_preference_;
raw_ptr<mojom::FrameSinkVideoConsumer> consumer_ = nullptr;
EstablishConnectionCallback establish_connection_callback_;
mojo::Remote<mojom::FrameSinkVideoCapturer> capturer_remote_;
mojo::Receiver<mojom::FrameSinkVideoConsumer> consumer_receiver_{this};
base::WeakPtrFactory<ClientFrameSinkVideoCapturer> weak_factory_{this};
};
}
#endif