#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <optional>
#include <utility>
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/tracing_buildflags.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "components/viz/common/frame_sinks/copy_output_util.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_manager.h"
#include "components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.h"
#include "components/viz/service/frame_sinks/video_capture/shared_memory_video_frame_pool.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
#include "media/base/video_types.h"
#include "media/base/video_util.h"
#include "media/capture/mojom/video_capture_buffer.mojom.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
VideoCaptureOracle;
VideoFrame;
VideoFrameMetadata;
#define UMA_HISTOGRAM_CAPTURE_DURATION(format, sample) …
#define UMA_HISTOGRAM_CAPTURE_SUCCEEDED(format, success) …
namespace viz {
namespace {
constexpr gfx::Rect kMaxRect = …;
std::unique_ptr<VideoFramePool> GetVideoFramePoolForFormat(
media::VideoPixelFormat format,
int capacity,
mojom::BufferFormatPreference buffer_format_preference,
GmbVideoFramePoolContextProvider* context_provider) { … }
CopyOutputRequest::ResultFormat VideoPixelFormatToCopyOutputRequestFormat(
media::VideoPixelFormat format) { … }
bool IsCompatibleWithFormat(const gfx::Rect& rect,
media::VideoPixelFormat format) { … }
int AsPercent(float value) { … }
perfetto::Track FrameInUseTrack(const media::VideoFrameMetadata& metadata) { … }
perfetto::Track CaptureTrack(const media::VideoFrameMetadata& metadata) { … }
}
constexpr media::VideoPixelFormat
FrameSinkVideoCapturerImpl::kDefaultPixelFormat;
constexpr gfx::ColorSpace FrameSinkVideoCapturerImpl::kDefaultColorSpace;
constexpr int FrameSinkVideoCapturerImpl::kDesignLimitMaxFrames;
constexpr int FrameSinkVideoCapturerImpl::kFramePoolCapacity;
constexpr float FrameSinkVideoCapturerImpl::kTargetPipelineUtilization;
constexpr base::TimeDelta FrameSinkVideoCapturerImpl::kMaxRefreshDelay;
FrameSinkVideoCapturerImpl::FrameSinkVideoCapturerImpl(
FrameSinkVideoCapturerManager& frame_sink_manager,
GmbVideoFramePoolContextProvider* gmb_video_frame_pool_context_provider,
mojo::PendingReceiver<mojom::FrameSinkVideoCapturer> receiver,
std::unique_ptr<media::VideoCaptureOracle> oracle,
bool log_to_webrtc)
: … { … }
FrameSinkVideoCapturerImpl::~FrameSinkVideoCapturerImpl() { … }
void FrameSinkVideoCapturerImpl::ResolveTarget() { … }
bool FrameSinkVideoCapturerImpl::TryResolveTarget() { … }
void FrameSinkVideoCapturerImpl::SetResolvedTarget(
CapturableFrameSink* target) { … }
void FrameSinkVideoCapturerImpl::OnTargetWillGoAway() { … }
void FrameSinkVideoCapturerImpl::SetFormat(media::VideoPixelFormat format) { … }
void FrameSinkVideoCapturerImpl::SetMinCapturePeriod(
base::TimeDelta min_capture_period) { … }
void FrameSinkVideoCapturerImpl::SetMinSizeChangePeriod(
base::TimeDelta min_period) { … }
void FrameSinkVideoCapturerImpl::SetResolutionConstraints(
const gfx::Size& min_size,
const gfx::Size& max_size,
bool use_fixed_aspect_ratio) { … }
void FrameSinkVideoCapturerImpl::SetAutoThrottlingEnabled(bool enabled) { … }
void FrameSinkVideoCapturerImpl::ChangeTarget(
const std::optional<VideoCaptureTarget>& target,
uint32_t sub_capture_target_version) { … }
void FrameSinkVideoCapturerImpl::Start(
mojo::PendingRemote<mojom::FrameSinkVideoConsumer> consumer,
mojom::BufferFormatPreference buffer_format_preference) { … }
void FrameSinkVideoCapturerImpl::Stop() { … }
void FrameSinkVideoCapturerImpl::RequestRefreshFrame() { … }
void FrameSinkVideoCapturerImpl::CreateOverlay(
int32_t stacking_index,
mojo::PendingReceiver<mojom::FrameSinkVideoCaptureOverlay> receiver) { … }
gfx::Size FrameSinkVideoCapturerImpl::GetSourceSize() { … }
void FrameSinkVideoCapturerImpl::InvalidateRect(const gfx::Rect& rect) { … }
void FrameSinkVideoCapturerImpl::OnOverlayConnectionLost(
VideoCaptureOverlay* overlay) { … }
void FrameSinkVideoCapturerImpl::RefreshNow() { … }
gfx::Rect FrameSinkVideoCapturerImpl::GetContentRectangle(
const gfx::Rect& visible_rect,
const gfx::Size& source_size,
media::VideoPixelFormat pixel_format) { … }
void FrameSinkVideoCapturerImpl::MaybeScheduleRefreshFrame() { … }
void FrameSinkVideoCapturerImpl::InvalidateEntireSource() { … }
base::TimeDelta FrameSinkVideoCapturerImpl::GetDelayBeforeNextRefreshAttempt()
const { … }
void FrameSinkVideoCapturerImpl::RefreshEntireSourceNow() { … }
void FrameSinkVideoCapturerImpl::RefreshInternal(
VideoCaptureOracle::Event event) { … }
void FrameSinkVideoCapturerImpl::OnFrameDamaged(
const gfx::Size& root_render_pass_size,
const gfx::Rect& damage_rect,
base::TimeTicks expected_display_time,
const CompositorFrameMetadata& frame_metadata) { … }
bool FrameSinkVideoCapturerImpl::IsVideoCaptureStarted() { … }
std::vector<VideoCaptureOverlay*>
FrameSinkVideoCapturerImpl::GetOverlaysInOrder() const { … }
FrameSinkVideoCapturerImpl::FrameCapture::FrameCapture(
int64_t capture_frame_number,
OracleFrameNumber oracle_frame_number,
int64_t content_version,
gfx::Rect content_rect,
CapturableFrameSink::RegionProperties region_properties,
scoped_refptr<media::VideoFrame> frame,
base::TimeTicks request_time)
: … { … }
FrameSinkVideoCapturerImpl::FrameCapture::FrameCapture() = default;
FrameSinkVideoCapturerImpl::FrameCapture::FrameCapture(
const FrameSinkVideoCapturerImpl::FrameCapture&) = default;
FrameSinkVideoCapturerImpl::FrameCapture::FrameCapture(
FrameSinkVideoCapturerImpl::FrameCapture&&) = default;
FrameSinkVideoCapturerImpl::FrameCapture&
FrameSinkVideoCapturerImpl::FrameCapture::operator=(
const FrameSinkVideoCapturerImpl::FrameCapture&) = default;
FrameSinkVideoCapturerImpl::FrameCapture&
FrameSinkVideoCapturerImpl::FrameCapture::operator=(
FrameSinkVideoCapturerImpl::FrameCapture&&) = default;
FrameSinkVideoCapturerImpl::FrameCapture::~FrameCapture() = default;
bool FrameSinkVideoCapturerImpl::FrameCapture::operator<(
const FrameSinkVideoCapturerImpl::FrameCapture& other) const { … }
void FrameSinkVideoCapturerImpl::FrameCapture::CaptureSucceeded() { … }
void FrameSinkVideoCapturerImpl::FrameCapture::CaptureFailed(
CaptureResult result) { … }
const media::VideoFrameMetadata&
FrameSinkVideoCapturerImpl::FrameCapture::frame_metadata() const { … }
void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
VideoCaptureOracle::Event event,
const gfx::Rect& damage_rect,
base::TimeTicks event_time,
const CompositorFrameMetadata& frame_metadata) { … }
void FrameSinkVideoCapturerImpl::DidCopyFrame(
FrameCapture frame_capture,
std::unique_ptr<CopyOutputResult> result) { … }
void FrameSinkVideoCapturerImpl::OnFrameReadyForDelivery(
const FrameCapture& frame_capture) { … }
void FrameSinkVideoCapturerImpl::MaybeDeliverFrame(FrameCapture frame_capture) { … }
gfx::Size FrameSinkVideoCapturerImpl::AdjustSizeForPixelFormat(
const gfx::Size& raw_size) const { … }
gfx::Rect FrameSinkVideoCapturerImpl::ExpandRectToI420SubsampleBoundaries(
const gfx::Rect& rect) { … }
void FrameSinkVideoCapturerImpl::OnLog(const std::string& message) { … }
bool FrameSinkVideoCapturerImpl::ShouldMark(const media::VideoFrame& frame,
int64_t content_version) const { … }
void FrameSinkVideoCapturerImpl::MarkFrame(
scoped_refptr<media::VideoFrame> frame,
int64_t content_version) { … }
bool FrameSinkVideoCapturerImpl::CanResurrectFrame(
const gfx::Size& size) const { … }
void FrameSinkVideoCapturerImpl::NotifyFrameReleased(
scoped_refptr<media::VideoFrame> frame) { … }
float FrameSinkVideoCapturerImpl::GetPipelineUtilization() const { … }
void FrameSinkVideoCapturerImpl::MaybeInformConsumerOfEmptyRegion() { … }
}