chromium/media/video/gpu_memory_buffer_video_frame_pool.cc

// Copyright 2015 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 "media/video/gpu_memory_buffer_video_frame_pool.h"

#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <stddef.h>
#include <stdint.h>

#include <atomic>
#include <list>
#include <memory>
#include <utility>

#include "base/barrier_closure.h"
#include "base/bits.h"
#include "base/command_line.h"
#include "base/containers/circular_deque.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/not_fatal_until.h"
#include "base/ranges/algorithm.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/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/viz/common/resources/shared_image_format.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/client_shared_image.h"
#include "gpu/command_buffer/client/shared_image_interface.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/config/gpu_switches.h"
#include "media/base/media_switches.h"
#include "media/base/video_types.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/libyuv/include/libyuv.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/trace_util.h"

#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#include "media/base/mac/video_frame_mac.h"
#endif

namespace media {
namespace {

// Allow MappableSI to be used for GpuMemoryBufferVideoFramePool. Note that
// enabling this flag does not necessarily enables MappableSI usage as it also
// currently needs MultiPlanarSI support. MultiPlanarSI is now enabled by
// default on ToT but the flag is still alive for 1 full release as a
// kill-switch.
BASE_FEATURE();

}  // namespace

// Implementation of a pool of GpuMemoryBuffers used to back VideoFrames.
class GpuMemoryBufferVideoFramePool::PoolImpl
    : public base::RefCountedThreadSafe<
          GpuMemoryBufferVideoFramePool::PoolImpl>,
      public base::trace_event::MemoryDumpProvider {};

namespace {

// VideoFrame copies to GpuMemoryBuffers will be split in copies where the
// output size is |kBytesPerCopyTarget| bytes and run in parallel.
constexpr size_t kBytesPerCopyTarget =;  // 1MB

// Return the GpuMemoryBuffer format to use for a specific VideoPixelFormat.
gfx::BufferFormat GpuMemoryBufferFormat(
    GpuVideoAcceleratorFactories::OutputFormat format) {}

// Return the SharedImageFormat format to use for a specific VideoPixelFormat.
viz::SharedImageFormat OutputFormatToSharedImageFormat(
    GpuVideoAcceleratorFactories::OutputFormat format) {}

VideoPixelFormat VideoFormat(
    GpuVideoAcceleratorFactories::OutputFormat format) {}

// The number of output rows to be copied in each iteration.
int RowsPerCopy(VideoPixelFormat format, int width) {}

void CopyRowsToI420Buffer(int first_row,
                          int rows,
                          int bytes_per_row,
                          size_t bit_depth,
                          const uint8_t* source,
                          int source_stride,
                          uint8_t* output,
                          int dest_stride) {}

void CopyRowsToP010Buffer(int first_row,
                          int rows,
                          int width,
                          const VideoFrame* source_frame,
                          uint8_t* dest_y,
                          int dest_stride_y,
                          uint8_t* dest_uv,
                          int dest_stride_uv) {}

void CopyRowsToNV12Buffer(int first_row,
                          int rows_y,
                          int rows_uv,
                          int bytes_per_row_y,
                          int bytes_per_row_uv,
                          const VideoFrame* source_frame,
                          uint8_t* dest_y,
                          int dest_stride_y,
                          uint8_t* dest_uv,
                          int dest_stride_uv) {}

void CopyRowsToRGB10Buffer(bool is_argb,
                           int first_row,
                           int rows,
                           int width,
                           const VideoFrame* source_frame,
                           uint8_t* output,
                           int dest_stride) {}

void CopyRowsToRGBABuffer(bool is_rgba,
                          int first_row,
                          int rows,
                          int width,
                          const VideoFrame* source_frame,
                          uint8_t* output,
                          int dest_stride) {}

gfx::Size CodedSize(const VideoFrame* video_frame,
                    GpuVideoAcceleratorFactories::OutputFormat output_format) {}

void SetPrefersExternalSampler(viz::SharedImageFormat& format) {}

}  // unnamed namespace

// Creates a VideoFrame backed by native textures starting from a software
// VideoFrame.
// The data contained in |video_frame| is copied into the VideoFrame passed to
// |frame_ready_cb|.
// This has to be called on the thread where |media_task_runner_| is current.
void GpuMemoryBufferVideoFramePool::PoolImpl::CreateHardwareFrame(
    scoped_refptr<VideoFrame> video_frame,
    FrameReadyCB frame_ready_cb) {}

bool GpuMemoryBufferVideoFramePool::PoolImpl::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {}

void GpuMemoryBufferVideoFramePool::PoolImpl::Abort() {}

void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDone(
    bool copy_failed,
    scoped_refptr<VideoFrame> video_frame,
    FrameResource* frame_resource) {}

void GpuMemoryBufferVideoFramePool::PoolImpl::StartCopy() {}

// Copies |video_frame| into |frame_resource| asynchronously, posting n tasks
// that will be synchronized by a barrier.
// After the barrier is passed OnCopiesDone will be called.
void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffer(
    scoped_refptr<VideoFrame> video_frame,
    FrameResource* frame_resource) {}

// static
void GpuMemoryBufferVideoFramePool::PoolImpl::CopyRowsToBuffer(
    GpuVideoAcceleratorFactories::OutputFormat output_format,
    const size_t row,
    const size_t rows_to_copy,
    const gfx::Size coded_size,
    const VideoFrame* video_frame,
    FrameResource* frame_resource,
    base::OnceClosure done) {}

void GpuMemoryBufferVideoFramePool::PoolImpl::OnCopiesDoneOnMediaThread(
    bool copy_failed,
    scoped_refptr<VideoFrame> video_frame,
    FrameResource* frame_resource) {}

scoped_refptr<VideoFrame> GpuMemoryBufferVideoFramePool::PoolImpl::
    BindAndCreateMailboxHardwareFrameResource(
        FrameResource* frame_resource,
        const gfx::Size& coded_size,
        const gfx::Rect& visible_rect,
        const gfx::Size& natural_size,
        const gfx::ColorSpace& color_space,
        base::TimeDelta timestamp,
        bool video_frame_allow_overlay,
        const std::optional<gpu::VulkanYCbCrInfo>& ycbcr_info) {}

// Destroy all the resources posting one task per FrameResource
// to the |media_task_runner_|.
GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() {}

void GpuMemoryBufferVideoFramePool::PoolImpl::Shutdown() {}

void GpuMemoryBufferVideoFramePool::PoolImpl::SetTickClockForTesting(
    const base::TickClock* tick_clock) {}

bool GpuMemoryBufferVideoFramePool::PoolImpl::IsMappableSIEnabled() const {}

// Tries to find the resource in the pool or creates it.
// Incompatible resource will be dropped.
GpuMemoryBufferVideoFramePool::PoolImpl::FrameResource*
GpuMemoryBufferVideoFramePool::PoolImpl::GetOrCreateFrameResource(
    const gfx::Size& size,
    gfx::BufferUsage usage,
    const gfx::ColorSpace& color_space) {}

void GpuMemoryBufferVideoFramePool::PoolImpl::
    CompleteCopyRequestAndMaybeStartNextCopy(
        scoped_refptr<VideoFrame> video_frame) {}

// static
void GpuMemoryBufferVideoFramePool::PoolImpl::DeleteFrameResource(
    GpuVideoAcceleratorFactories* const gpu_factories,
    FrameResource* frame_resource) {}

// Called when a VideoFrame is no longer referenced. Put back the resource in
// the pool.
void GpuMemoryBufferVideoFramePool::PoolImpl::MailboxHolderReleased(
    FrameResource* frame_resource,
    const gpu::SyncToken& release_sync_token) {}

GpuMemoryBufferVideoFramePool::GpuMemoryBufferVideoFramePool() = default;

GpuMemoryBufferVideoFramePool::GpuMemoryBufferVideoFramePool(
    const scoped_refptr<base::SequencedTaskRunner>& media_task_runner,
    const scoped_refptr<base::TaskRunner>& worker_task_runner,
    GpuVideoAcceleratorFactories* gpu_factories)
    :{}

GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() {}

void GpuMemoryBufferVideoFramePool::MaybeCreateHardwareFrame(
    scoped_refptr<VideoFrame> video_frame,
    FrameReadyCB frame_ready_cb) {}

void GpuMemoryBufferVideoFramePool::Abort() {}

void GpuMemoryBufferVideoFramePool::SetTickClockForTesting(
    const base::TickClock* tick_clock) {}

bool GpuMemoryBufferVideoFramePool::IsMappableSIEnabledForTesting() const {}

}  // namespace media