#ifdef UNSAFE_BUFFERS_BUILD
#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 {
BASE_FEATURE(…);
}
class GpuMemoryBufferVideoFramePool::PoolImpl
: public base::RefCountedThreadSafe<
GpuMemoryBufferVideoFramePool::PoolImpl>,
public base::trace_event::MemoryDumpProvider { … };
namespace {
constexpr size_t kBytesPerCopyTarget = …;
gfx::BufferFormat GpuMemoryBufferFormat(
GpuVideoAcceleratorFactories::OutputFormat format) { … }
viz::SharedImageFormat OutputFormatToSharedImageFormat(
GpuVideoAcceleratorFactories::OutputFormat format) { … }
VideoPixelFormat VideoFormat(
GpuVideoAcceleratorFactories::OutputFormat format) { … }
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) { … }
}
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() { … }
void GpuMemoryBufferVideoFramePool::PoolImpl::CopyVideoFrameToGpuMemoryBuffer(
scoped_refptr<VideoFrame> video_frame,
FrameResource* frame_resource) { … }
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) { … }
GpuMemoryBufferVideoFramePool::PoolImpl::~PoolImpl() { … }
void GpuMemoryBufferVideoFramePool::PoolImpl::Shutdown() { … }
void GpuMemoryBufferVideoFramePool::PoolImpl::SetTickClockForTesting(
const base::TickClock* tick_clock) { … }
bool GpuMemoryBufferVideoFramePool::PoolImpl::IsMappableSIEnabled() const { … }
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) { … }
void GpuMemoryBufferVideoFramePool::PoolImpl::DeleteFrameResource(
GpuVideoAcceleratorFactories* const gpu_factories,
FrameResource* frame_resource) { … }
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 { … }
}