| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "media/video/fake_gpu_memory_buffer.h" |
| |
| #include "base/atomic_sequence_num.h" |
| #include "base/no_destructor.h" |
| #include "build/build_config.h" |
| #include "media/base/format_utils.h" |
| #include "media/base/video_frame.h" |
| |
| #if defined(OS_LINUX) || defined(OS_CHROMEOS) |
| #include <fcntl.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #endif |
| |
| namespace media { |
| |
| namespace { |
| |
| class FakeGpuMemoryBufferImpl : public gpu::GpuMemoryBufferImpl { |
| public: |
| FakeGpuMemoryBufferImpl(const gfx::Size& size, gfx::BufferFormat format) |
| : gpu::GpuMemoryBufferImpl( |
| gfx::GpuMemoryBufferId(), |
| size, |
| format, |
| gpu::GpuMemoryBufferImpl::DestructionCallback()), |
| fake_gmb_(std::make_unique<media::FakeGpuMemoryBuffer>(size, format)) {} |
| |
| // gfx::GpuMemoryBuffer implementation |
| bool Map() override { return fake_gmb_->Map(); } |
| void* memory(size_t plane) override { return fake_gmb_->memory(plane); } |
| void Unmap() override { fake_gmb_->Unmap(); } |
| int stride(size_t plane) const override { return fake_gmb_->stride(plane); } |
| gfx::GpuMemoryBufferType GetType() const override { |
| return fake_gmb_->GetType(); |
| } |
| gfx::GpuMemoryBufferHandle CloneHandle() const override { |
| return fake_gmb_->CloneHandle(); |
| } |
| |
| private: |
| std::unique_ptr<media::FakeGpuMemoryBuffer> fake_gmb_; |
| }; |
| |
| } // namespace |
| |
| #if defined(OS_LINUX) || defined(OS_CHROMEOS) |
| base::ScopedFD GetDummyFD() { |
| base::ScopedFD fd(open("/dev/zero", O_RDWR)); |
| DCHECK(fd.is_valid()); |
| return fd; |
| } |
| #endif |
| |
| FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size, |
| gfx::BufferFormat format) |
| : FakeGpuMemoryBuffer(size, format, gfx::NativePixmapHandle::kNoModifier) {} |
| |
| FakeGpuMemoryBuffer::FakeGpuMemoryBuffer(const gfx::Size& size, |
| gfx::BufferFormat format, |
| uint64_t modifier) |
| : size_(size), format_(format) { |
| absl::optional<VideoPixelFormat> video_pixel_format = |
| GfxBufferFormatToVideoPixelFormat(format); |
| CHECK(video_pixel_format); |
| video_pixel_format_ = *video_pixel_format; |
| |
| const size_t allocation_size = |
| VideoFrame::AllocationSize(video_pixel_format_, size_); |
| data_ = std::vector<uint8_t>(allocation_size); |
| |
| handle_.type = gfx::NATIVE_PIXMAP; |
| |
| static base::AtomicSequenceNumber buffer_id_generator; |
| handle_.id = gfx::GpuMemoryBufferId(buffer_id_generator.GetNext()); |
| |
| #if defined(OS_LINUX) || defined(OS_CHROMEOS) |
| for (size_t i = 0; i < VideoFrame::NumPlanes(video_pixel_format_); i++) { |
| const gfx::Size plane_size_in_bytes = |
| VideoFrame::PlaneSize(video_pixel_format_, i, size_); |
| handle_.native_pixmap_handle.planes.emplace_back( |
| plane_size_in_bytes.width(), 0, plane_size_in_bytes.GetArea(), |
| GetDummyFD()); |
| } |
| handle_.native_pixmap_handle.modifier = modifier; |
| #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) |
| } |
| |
| FakeGpuMemoryBuffer::~FakeGpuMemoryBuffer() = default; |
| |
| bool FakeGpuMemoryBuffer::Map() { |
| return true; |
| } |
| |
| void* FakeGpuMemoryBuffer::memory(size_t plane) { |
| DCHECK_LT(plane, VideoFrame::NumPlanes(video_pixel_format_)); |
| auto* data_ptr = data_.data(); |
| for (size_t i = 1; i <= plane; i++) { |
| data_ptr += |
| VideoFrame::PlaneSize(video_pixel_format_, i - 1, size_).GetArea(); |
| } |
| return data_ptr; |
| } |
| |
| void FakeGpuMemoryBuffer::Unmap() {} |
| |
| gfx::Size FakeGpuMemoryBuffer::GetSize() const { |
| return size_; |
| } |
| |
| gfx::BufferFormat FakeGpuMemoryBuffer::GetFormat() const { |
| return format_; |
| } |
| |
| int FakeGpuMemoryBuffer::stride(size_t plane) const { |
| DCHECK_LT(plane, VideoFrame::NumPlanes(video_pixel_format_)); |
| return VideoFrame::PlaneSize(video_pixel_format_, plane, size_).width(); |
| } |
| |
| void FakeGpuMemoryBuffer::SetColorSpace(const gfx::ColorSpace& color_space) {} |
| |
| gfx::GpuMemoryBufferId FakeGpuMemoryBuffer::GetId() const { |
| return handle_.id; |
| } |
| |
| gfx::GpuMemoryBufferType FakeGpuMemoryBuffer::GetType() const { |
| return gfx::NATIVE_PIXMAP; |
| } |
| |
| gfx::GpuMemoryBufferHandle FakeGpuMemoryBuffer::CloneHandle() const { |
| gfx::GpuMemoryBufferHandle handle; |
| handle.type = gfx::NATIVE_PIXMAP; |
| handle.id = handle_.id; |
| #if defined(OS_LINUX) || defined(OS_CHROMEOS) |
| handle.native_pixmap_handle = |
| gfx::CloneHandleForIPC(handle_.native_pixmap_handle); |
| #endif |
| return handle; |
| } |
| |
| ClientBuffer FakeGpuMemoryBuffer::AsClientBuffer() { |
| NOTREACHED(); |
| return ClientBuffer(); |
| } |
| |
| void FakeGpuMemoryBuffer::OnMemoryDump( |
| base::trace_event::ProcessMemoryDump* pmd, |
| const base::trace_event::MemoryAllocatorDumpGuid& buffer_dump_guid, |
| uint64_t tracing_process_id, |
| int importance) const {} |
| |
| std::unique_ptr<gpu::GpuMemoryBufferImpl> |
| FakeGpuMemoryBufferSupport::CreateGpuMemoryBufferImplFromHandle( |
| gfx::GpuMemoryBufferHandle handle, |
| const gfx::Size& size, |
| gfx::BufferFormat format, |
| gfx::BufferUsage usage, |
| gpu::GpuMemoryBufferImpl::DestructionCallback callback, |
| gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, |
| scoped_refptr<base::UnsafeSharedMemoryPool> pool) { |
| return std::make_unique<FakeGpuMemoryBufferImpl>(size, format); |
| } |
| |
| } // namespace media |