chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#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;

// Helper macro to log ".CaptureDuration" histograms. `format` needs to be a
// string literal, `sample` is a sample that will be logged.
#define UMA_HISTOGRAM_CAPTURE_DURATION(format, sample)

// Helper macro to log ".CaptureSucceeded" histograms. `format` needs to be a
// string literal, `success` is a boolean that will be logged.
#define UMA_HISTOGRAM_CAPTURE_SUCCEEDED(format, success)

namespace viz {

namespace {

// The largest Rect possible.
constexpr gfx::Rect kMaxRect =;

// Note about RGBA/BGRA/ARGB pixel format names:
// In FrameSinkVideoCapturer, ARGB is a "format name", the frames it gives
// could be RGBA/BGRA depends on platform and the preference of the buffer
// format. When user wants ARGB result, it requests a CopyOutputRequest with
// ResultFormat::RGBA which gives RGBA/BGRA results depends on platform and
// where the result is stored (buffer format preference).
// Currently, kPreferGpuMemoryBuffer + ARGB will request BGRA as pixel format,
// but kDefault + ARGB will be platform dependent because CopyOutputRequest
// will use kN32_SkColorType (RGBA on Android, BGRA elsewhere) mostly, and use
// kRGBA_8888_SkColorType on iOS.
// This is also documented in the mojom comments (https://crrev.com/c/5418235)
// about SetFormat, indicating the ARGB format may produce RGBA/BGRA frames
// depends on platform.

// Get the frame pool for the specific format. We need context_provider if the
// format is NV12 or ARGB (when buffer_format_preference is kNativeTexture).
// Thus, buffer_format_preference is also needed to tell which mode ARGB use.
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) {}

}  // namespace

// static
constexpr media::VideoPixelFormat
    FrameSinkVideoCapturerImpl::kDefaultPixelFormat;
// static
constexpr gfx::ColorSpace FrameSinkVideoCapturerImpl::kDefaultColorSpace;
// static
constexpr int FrameSinkVideoCapturerImpl::kDesignLimitMaxFrames;
// static
constexpr int FrameSinkVideoCapturerImpl::kFramePoolCapacity;
// static
constexpr float FrameSinkVideoCapturerImpl::kTargetPipelineUtilization;
// static
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 {}

// static
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() {}

}  // namespace viz