blob: 5b8c92838eaa6c8c43ddd885e012dee4bf02cd98 [file] [log] [blame]
// 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/capture/video/chromeos/gpu_memory_buffer_tracker.h"
#include "base/check.h"
#include "base/notreached.h"
#include "media/capture/video/chromeos/pixel_format_utils.h"
#include "media/capture/video/video_capture_buffer_handle.h"
#include "ui/gfx/geometry/size.h"
namespace media {
GpuMemoryBufferTracker::GpuMemoryBufferTracker() : buffer_(nullptr) {}
GpuMemoryBufferTracker::~GpuMemoryBufferTracker() = default;
bool GpuMemoryBufferTracker::Init(const gfx::Size& dimensions,
VideoPixelFormat format,
const mojom::PlaneStridesPtr& strides) {
absl::optional<gfx::BufferFormat> gfx_format = PixFormatVideoToGfx(format);
if (!gfx_format) {
NOTREACHED() << "Unsupported VideoPixelFormat "
<< VideoPixelFormatToString(format);
return false;
}
// There's no consumer information here to determine the precise buffer usage,
// so we try the usage flag that covers all use cases.
// JPEG capture buffer is backed by R8 pixel buffer.
const gfx::BufferUsage usage =
*gfx_format == gfx::BufferFormat::R_8
? gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE
: gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE;
buffer_ =
buffer_factory_.CreateGpuMemoryBuffer(dimensions, *gfx_format, usage);
if (!buffer_) {
NOTREACHED() << "Failed to create GPU memory buffer";
return false;
}
return true;
}
bool GpuMemoryBufferTracker::IsReusableForFormat(
const gfx::Size& dimensions,
VideoPixelFormat format,
const mojom::PlaneStridesPtr& strides) {
absl::optional<gfx::BufferFormat> gfx_format = PixFormatVideoToGfx(format);
if (!gfx_format) {
return false;
}
return (*gfx_format == buffer_->GetFormat() &&
dimensions == buffer_->GetSize());
}
std::unique_ptr<VideoCaptureBufferHandle>
GpuMemoryBufferTracker::GetMemoryMappedAccess() {
NOTREACHED() << "Unsupported operation";
return std::make_unique<NullHandle>();
}
base::UnsafeSharedMemoryRegion
GpuMemoryBufferTracker::DuplicateAsUnsafeRegion() {
NOTREACHED() << "Unsupported operation";
return base::UnsafeSharedMemoryRegion();
}
mojo::ScopedSharedBufferHandle GpuMemoryBufferTracker::DuplicateAsMojoBuffer() {
NOTREACHED() << "Unsupported operation";
return mojo::ScopedSharedBufferHandle();
}
gfx::GpuMemoryBufferHandle GpuMemoryBufferTracker::GetGpuMemoryBufferHandle() {
DCHECK(buffer_);
// Overriding the GpuMemoryBuffer id to an invalid id to avoid buffer
// collision in GpuMemoryBufferFactoryNativePixmap when we pass the handle
// to a different process. (crbug.com/993265)
//
// This will force the GPU process to look up the real native pixmap handle
// through the DMA-buf fds in [1] when creating SharedImage, instead of
// re-using a wrong pixmap handle in the cache.
//
// [1]: https://tinyurl.com/yymtv22y
constexpr int kInvalidId = -1;
gfx::GpuMemoryBufferHandle handle = buffer_->CloneHandle();
handle.id = gfx::GpuMemoryBufferId(kInvalidId);
return handle;
}
uint32_t GpuMemoryBufferTracker::GetMemorySizeInBytes() {
DCHECK(buffer_);
switch (buffer_->GetFormat()) {
case gfx::BufferFormat::YUV_420_BIPLANAR:
return buffer_->GetSize().width() * buffer_->GetSize().height() * 3 / 2;
case gfx::BufferFormat::R_8:
return buffer_->GetSize().width() * buffer_->GetSize().height();
default:
NOTREACHED() << "Unsupported gfx buffer format";
return buffer_->GetSize().width() * buffer_->GetSize().height();
}
}
} // namespace media