Commit 2dd1098a authored by Ren-Pei Zeng's avatar Ren-Pei Zeng Committed by Commit Bot

[CrOS VCD] Differentiate usage flags for preview/reprocessing buffers

crrev.com/c/2234684 introduces a new buffer usage flag for hardware VEA
(SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE). On Kukui this changes
buffer layout, and the camera driver failed to capture correct content
into the buffer in the RAW->YUV reprocessing case.

Since the reprocessing YUV buffer is not used for video encoding, this
CL changes the buffer usage for that use case back to the original
(SCANOUT_CAMERA_READ_WRITE).

This CL also cleans up places that hard-code buffer usage, or makes it
verbose when it has to do so.

Bug: 1105154
Test: capture_unittests
Test: CCA preview, video recording, take normal/Portrait photo (with #zero-copy-video-capture flag on and off)
Change-Id: I1c3d88f361faad43994fbf6fedc9514de7947366
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2315725Reviewed-by: default avatarRicky Liang <jcliang@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Commit-Queue: Ren-Pei Zeng <kamesan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792194}
parent 01777f31
......@@ -4,6 +4,7 @@
#include "media/capture/video/chromeos/camera_buffer_factory.h"
#include "base/stl_util.h"
#include "media/capture/video/chromeos/video_capture_device_factory_chromeos.h"
namespace media {
......@@ -14,24 +15,27 @@ CameraBufferFactory::~CameraBufferFactory() = default;
std::unique_ptr<gfx::GpuMemoryBuffer>
CameraBufferFactory::CreateGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format) {
gfx::BufferFormat format,
gfx::BufferUsage usage) {
gpu::GpuMemoryBufferManager* buf_manager =
VideoCaptureDeviceFactoryChromeOS::GetBufferManager();
if (!buf_manager) {
LOG(ERROR) << "GpuMemoryBufferManager not set";
return std::unique_ptr<gfx::GpuMemoryBuffer>();
}
return buf_manager->CreateGpuMemoryBuffer(
size, format, GetBufferUsage(format), gpu::kNullSurfaceHandle);
return buf_manager->CreateGpuMemoryBuffer(size, format, usage,
gpu::kNullSurfaceHandle);
}
// There's no good way to resolve the HAL pixel format to the platform-specific
// DRM format, other than to actually allocate the buffer and see if the
// allocation succeeds.
ChromiumPixelFormat CameraBufferFactory::ResolveStreamBufferFormat(
cros::mojom::HalPixelFormat hal_format) {
if (resolved_hal_formats_.find(hal_format) != resolved_hal_formats_.end()) {
return resolved_hal_formats_[hal_format];
cros::mojom::HalPixelFormat hal_format,
gfx::BufferUsage usage) {
const auto key = std::make_pair(hal_format, usage);
if (base::Contains(resolved_format_usages_, key)) {
return resolved_format_usages_[key];
}
ChromiumPixelFormat kUnsupportedFormat{PIXEL_FORMAT_UNKNOWN,
......@@ -44,25 +48,13 @@ ChromiumPixelFormat CameraBufferFactory::ResolveStreamBufferFormat(
}
for (const auto& f : cr_formats) {
auto buffer = CreateGpuMemoryBuffer(
gfx::Size(kDummyBufferWidth, kDummyBufferHeight), f.gfx_format);
gfx::Size(kDummyBufferWidth, kDummyBufferHeight), f.gfx_format, usage);
if (buffer) {
resolved_hal_formats_[hal_format] = f;
resolved_format_usages_[key] = f;
return f;
}
}
return kUnsupportedFormat;
}
// static
gfx::BufferUsage CameraBufferFactory::GetBufferUsage(gfx::BufferFormat format) {
switch (format) {
case gfx::BufferFormat::R_8:
// Usage for JPEG capture buffer backed by R8 pixel buffer.
return gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE;
default:
// Default usage for YUV camera buffer.
return gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE;
}
}
} // namespace media
......@@ -5,8 +5,8 @@
#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_BUFFER_FACTORY_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_BUFFER_FACTORY_H_
#include <map>
#include <memory>
#include <unordered_map>
#include "media/capture/video/chromeos/mojom/camera3.mojom.h"
#include "media/capture/video/chromeos/pixel_format_utils.h"
......@@ -24,16 +24,17 @@ class CAPTURE_EXPORT CameraBufferFactory {
virtual std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format);
gfx::BufferFormat format,
gfx::BufferUsage usage);
virtual ChromiumPixelFormat ResolveStreamBufferFormat(
cros::mojom::HalPixelFormat hal_format);
static gfx::BufferUsage GetBufferUsage(gfx::BufferFormat format);
cros::mojom::HalPixelFormat hal_format,
gfx::BufferUsage usage);
private:
std::unordered_map<cros::mojom::HalPixelFormat, ChromiumPixelFormat>
resolved_hal_formats_;
std::map<std::pair<cros::mojom::HalPixelFormat, gfx::BufferUsage>,
ChromiumPixelFormat>
resolved_format_usages_;
};
} // namespace media
......
......@@ -241,8 +241,13 @@ void CameraHalDelegate::GetSupportedFormats(
}
float max_fps = 1.0 * 1000000000LL / duration;
// There's no consumer information here to determine the buffer usage, so
// hard-code the usage that all the clients should be using.
constexpr gfx::BufferUsage kClientBufferUsage =
gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE;
const ChromiumPixelFormat cr_format =
camera_buffer_factory_->ResolveStreamBufferFormat(hal_format);
camera_buffer_factory_->ResolveStreamBufferFormat(hal_format,
kClientBufferUsage);
if (cr_format.video_format == PIXEL_FORMAT_UNKNOWN) {
continue;
}
......
......@@ -25,7 +25,15 @@ bool GpuMemoryBufferTracker::Init(const gfx::Size& dimensions,
<< VideoPixelFormatToString(format);
return false;
}
buffer_ = buffer_factory_.CreateGpuMemoryBuffer(dimensions, *gfx_format);
// 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::SCANOUT_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;
......
......@@ -62,16 +62,15 @@ class FakeCameraBufferFactory : public CameraBufferFactory {
}
std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format) override {
gfx::BufferFormat format,
gfx::BufferUsage usage) override {
return unittest_internal::MockGpuMemoryBufferManager::
CreateFakeGpuMemoryBuffer(
size, format,
gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE,
gpu::kNullSurfaceHandle);
CreateFakeGpuMemoryBuffer(size, format, usage, gpu::kNullSurfaceHandle);
}
ChromiumPixelFormat ResolveStreamBufferFormat(
cros::mojom::HalPixelFormat hal_format) override {
cros::mojom::HalPixelFormat hal_format,
gfx::BufferUsage usage) override {
return ChromiumPixelFormat{PIXEL_FORMAT_NV12,
gfx::BufferFormat::YUV_420_BIPLANAR};
}
......
......@@ -42,7 +42,9 @@ StreamBufferManager::~StreamBufferManager() {
}
void StreamBufferManager::ReserveBuffer(StreamType stream_type) {
if (video_capture_use_gmb_) {
// The YUV output buffer for reprocessing is not passed to client, so can be
// allocated by the local buffer factory without zero-copy concerns.
if (video_capture_use_gmb_ && stream_type != StreamType::kYUVOutput) {
ReserveBufferFromPool(stream_type);
} else {
ReserveBufferFromFactory(stream_type);
......@@ -160,8 +162,8 @@ StreamBufferManager::AcquireBufferForClientById(StreamType stream_type,
DCHECK(gfx_format);
auto rotated_gmb = gmb_support_->CreateGpuMemoryBufferImplFromHandle(
rotated_buffer.handle_provider->GetGpuMemoryBufferHandle(),
format->frame_size, *gfx_format,
CameraBufferFactory::GetBufferUsage(*gfx_format), base::NullCallback());
format->frame_size, *gfx_format, stream_context->buffer_usage,
base::NullCallback());
if (!rotated_gmb || !rotated_gmb->Map()) {
DLOG(WARNING) << "Failed to map rotated buffer";
......@@ -244,19 +246,19 @@ void StreamBufferManager::SetUpStreamsAndBuffers(
stream_context->capture_format = capture_format;
stream_context->stream = std::move(stream);
const ChromiumPixelFormat stream_format =
camera_buffer_factory_->ResolveStreamBufferFormat(
stream_context->stream->format);
// Internally we keep track of the VideoPixelFormat that's actually
// supported by the camera instead of the one requested by the client.
stream_context->capture_format.pixel_format = stream_format.video_format;
switch (stream_type) {
case StreamType::kPreviewOutput:
stream_context->buffer_dimension = gfx::Size(
stream_context->stream->width, stream_context->stream->height);
stream_context->buffer_usage =
gfx::BufferUsage::SCANOUT_VEA_READ_CAMERA_AND_CPU_READ_WRITE;
break;
case StreamType::kYUVInput:
case StreamType::kYUVOutput:
stream_context->buffer_dimension = gfx::Size(
stream_context->stream->width, stream_context->stream->height);
stream_context->buffer_usage =
gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE;
break;
case StreamType::kJpegOutput: {
auto jpeg_size = GetMetadataEntryAsSpan<int32_t>(
......@@ -264,12 +266,21 @@ void StreamBufferManager::SetUpStreamsAndBuffers(
cros::mojom::CameraMetadataTag::ANDROID_JPEG_MAX_SIZE);
CHECK_EQ(jpeg_size.size(), 1u);
stream_context->buffer_dimension = gfx::Size(jpeg_size[0], 1);
stream_context->buffer_usage =
gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE;
break;
}
default: {
NOTREACHED();
}
}
const ChromiumPixelFormat stream_format =
camera_buffer_factory_->ResolveStreamBufferFormat(
stream_context->stream->format, stream_context->buffer_usage);
// Internally we keep track of the VideoPixelFormat that's actually
// supported by the camera instead of the one requested by the client.
stream_context->capture_format.pixel_format = stream_format.video_format;
stream_context_[stream_type] = std::move(stream_context);
// For input stream, there is no need to allocate buffers.
......@@ -387,7 +398,8 @@ void StreamBufferManager::ReserveBufferFromFactory(StreamType stream_type) {
return;
}
auto gmb = camera_buffer_factory_->CreateGpuMemoryBuffer(
stream_context->buffer_dimension, *gfx_format);
stream_context->buffer_dimension, *gfx_format,
stream_context->buffer_usage);
if (!gmb) {
device_context_->SetErrorState(
media::VideoCaptureError::
......@@ -432,7 +444,7 @@ void StreamBufferManager::ReserveBufferFromPool(StreamType stream_type) {
auto gmb = gmb_support_->CreateGpuMemoryBufferImplFromHandle(
vcd_buffer.handle_provider->GetGpuMemoryBufferHandle(),
stream_context->buffer_dimension, *gfx_format,
CameraBufferFactory::GetBufferUsage(*gfx_format), base::NullCallback());
stream_context->buffer_usage, base::NullCallback());
stream_context->free_buffers.push(vcd_buffer.id);
stream_context->buffers.insert(std::make_pair(
vcd_buffer.id, BufferPair(std::move(gmb), std::move(vcd_buffer))));
......
......@@ -134,6 +134,8 @@ class CAPTURE_EXPORT StreamBufferManager final {
cros::mojom::Camera3StreamPtr stream;
// The dimension of the buffer layout.
gfx::Size buffer_dimension;
// The usage of the buffer.
gfx::BufferUsage buffer_usage;
// The allocated buffer pairs.
std::map<int, BufferPair> buffers;
// The free buffers of this stream. The queue stores keys into the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment