[libcamera-devel] [RFC PATCH 1/2] android: Introduce PlatformFrameBufferAllocator
Hirokazu Honda
hiroh at chromium.org
Mon Sep 27 12:48:20 CEST 2021
PlatformFrameBufferAllocator allocates FrameBuffer(s) using
cros::CameraBufferManager on ChromeOS and gralloc on non
ChromeOS platform. The allocated FrameBuffer(s) are owned by
PlatformFrameBufferAllocator an destroyed when
PlatformFrameBufferAllocator is destroyed.
Signed-off-by: Hirokazu Honda <hiroh at chromium.org>
---
src/android/frame_buffer.h | 53 +++++++++++
src/android/mm/cros_frame_buffer.cpp | 85 +++++++++++++++++
src/android/mm/generic_frame_buffer.cpp | 116 ++++++++++++++++++++++++
src/android/mm/meson.build | 6 +-
4 files changed, 258 insertions(+), 2 deletions(-)
create mode 100644 src/android/frame_buffer.h
create mode 100644 src/android/mm/cros_frame_buffer.cpp
create mode 100644 src/android/mm/generic_frame_buffer.cpp
diff --git a/src/android/frame_buffer.h b/src/android/frame_buffer.h
new file mode 100644
index 00000000..6aafeaf3
--- /dev/null
+++ b/src/android/frame_buffer.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * frame_buffer.h - Frame buffer allocating interface definition
+ */
+#ifndef __ANDROID_FRAME_BUFFER_H__
+#define __ANDROID_FRAME_BUFFER_H__
+
+#include <memory>
+#include <vector>
+
+#include <libcamera/base/class.h>
+#include <libcamera/camera.h>
+#include <libcamera/framebuffer.h>
+#include <libcamera/geometry.h>
+
+class CameraDevice;
+
+class PlatformFrameBufferAllocator : libcamera::Extensible
+{
+ LIBCAMERA_DECLARE_PRIVATE()
+
+public:
+ explicit PlatformFrameBufferAllocator(CameraDevice *const cameraDevice);
+ ~PlatformFrameBufferAllocator();
+
+ const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &
+ allocate(int halPixelFormat,
+ const libcamera::Size &size,
+ uint32_t usage,
+ size_t numBuffers);
+};
+
+#define PUBLIC_FRAME_BUFFER_IMPLEMENTATION \
+PlatformFrameBufferAllocator::PlatformFrameBufferAllocator( \
+ CameraDevice *const cameraDevice) \
+ : Extensible(std::make_unique<Private>(this, cameraDevice)) \
+{ \
+} \
+PlatformFrameBufferAllocator::~PlatformFrameBufferAllocator() \
+{ \
+} \
+const std::vector<std::unique_ptr<libcamera::FrameBuffer>>& \
+PlatformFrameBufferAllocator::allocate(int halPixelFormat, \
+ const libcamera::Size& size, \
+ uint32_t usage, \
+ size_t numBuffers) \
+{ \
+ return _d()->allocate(halPixelFormat, size, usage, numBuffers); \
+}
+
+#endif /* __ANDROID_FRAME_BUFFER_H__ */
diff --git a/src/android/mm/cros_frame_buffer.cpp b/src/android/mm/cros_frame_buffer.cpp
new file mode 100644
index 00000000..114c739b
--- /dev/null
+++ b/src/android/mm/cros_frame_buffer.cpp
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * cros_frame_buffer.cpp - allocate FrameBuffer for Chromium OS buffer backend
+ * using CameraBufferManager
+ */
+
+#include "../frame_buffer.h"
+
+#include <libcamera/base/log.h>
+
+#include "cros-camera/camera_buffer_manager.h"
+
+#include "../camera_device.h"
+
+using namespace libcamera;
+
+LOG_DECLARE_CATEGORY(HAL)
+
+class PlatformFrameBufferAllocator::Private : public Extensible::Private
+{
+ LIBCAMERA_DECLARE_PUBLIC(PlatformFrameBufferAllocator)
+
+public:
+ Private([[maybe_unused]] PlatformFrameBufferAllocator *allocator,
+ [[maybe_unused]] CameraDevice *const cameraDevice)
+ {
+ }
+
+ ~Private() = default;
+
+ const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &
+ allocate(int halPixelFormat,
+ const libcamera::Size &size,
+ uint32_t usage,
+ size_t numBuffers);
+
+private:
+ std::vector<std::unique_ptr<libcamera::FrameBuffer>> allocatedBuffers_;
+ std::vector<cros::ScopedBufferHandle> allocatedHandles_;
+};
+
+const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &
+PlatformFrameBufferAllocator::Private::allocate(
+ int halPixelFormat, const libcamera::Size &size, uint32_t usage,
+ size_t numBuffers)
+{
+ ASSERT(allocatedBuffers_.empty());
+
+ std::vector<std::unique_ptr<libcamera::FrameBuffer>> buffers;
+ for (size_t i = 0; i < numBuffers; ++i) {
+ cros::ScopedBufferHandle handle =
+ cros::CameraBufferManager::AllocateScopedBuffer(
+ size.width, size.height, halPixelFormat, usage);
+ if (!handle) {
+ LOG(HAL, Error) << "Failed allocate buffer_handle";
+ return allocatedBuffers_;
+ }
+
+ const size_t numPlanes = cros::CameraBufferManager::GetNumPlanes(*handle);
+ std::vector<FrameBuffer::Plane> planes(numPlanes);
+ for (size_t j = 0; j < numPlanes; ++j) {
+ FileDescriptor fd{ (*handle)->data[0] };
+ if (!fd.isValid()) {
+ LOG(HAL, Fatal) << "Invalid fd";
+ return allocatedBuffers_;
+ }
+
+ planes[j].fd = fd;
+ planes[j].offset =
+ cros::CameraBufferManager::GetPlaneOffset(*handle, j);
+ planes[j].length =
+ cros::CameraBufferManager::GetPlaneSize(*handle, j);
+ }
+
+ buffers.push_back(std::make_unique<FrameBuffer>(planes));
+ allocatedHandles_.push_back(std::move(handle));
+ }
+
+ allocatedBuffers_ = std::move(buffers);
+ return allocatedBuffers_;
+}
+
+PUBLIC_FRAME_BUFFER_IMPLEMENTATION
diff --git a/src/android/mm/generic_frame_buffer.cpp b/src/android/mm/generic_frame_buffer.cpp
new file mode 100644
index 00000000..b387d5a2
--- /dev/null
+++ b/src/android/mm/generic_frame_buffer.cpp
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2021, Google Inc.
+ *
+ * generic_camera_buffer.cpp - allocate FrameBuffer for Generic Android frame
+ * buffer backend
+ */
+
+#include "../frame_buffer.h"
+
+#include <libcamera/base/log.h>
+#include <libcamera/internal/formats.h>
+
+#include <hardware/camera3.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+
+#include "../camera_device.h"
+
+using namespace libcamera;
+
+LOG_DECLARE_CATEGORY(HAL)
+
+class PlatformFrameBufferAllocator::Private : public Extensible::Private
+{
+ LIBCAMERA_DECLARE_PUBLIC(PlatformFrameBufferAllocator)
+
+public:
+ Private([[maybe_unused]] PlatformFrameBufferAllocator *allocator,
+ CameraDevice *const cameraDevice)
+ : cameraDevice_(cameraDevice),
+ hardwareModule_(cameraDevice->camera3Device()->common.module)
+ {
+ ASSERT(!!hardwareModule_);
+ }
+
+ ~Private() override;
+
+ const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &
+ allocate(int halPixelFormat,
+ const libcamera::Size &size,
+ uint32_t usage,
+ size_t numBuffers);
+
+private:
+ const CameraDevice *const cameraDevice_;
+ struct hw_module_t *const hardwareModule_;
+ struct alloc_device_t *allocDevice_;
+
+ std::vector<std::unique_ptr<libcamera::FrameBuffer>> allocatedBuffers_;
+ std::vector<buffer_handle_t> bufferHandles_;
+};
+
+PlatformFrameBufferAllocator::Private::~Private()
+{
+ for (buffer_handle_t &handle : bufferHandles_) {
+ ASSERT(allocDevice_);
+ allocDevice_->free(allocDevice_, handle);
+ }
+ if (allocDevice_)
+ gralloc_close(allocDevice_);
+}
+
+const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &
+PlatformFrameBufferAllocator::Private::allocate(
+ int halPixelFormat, const libcamera::Size &size, uint32_t usage,
+ size_t numBuffers)
+{
+ ASSERT(allocatedBuffers_.empty());
+ ASSERT(bufferHandles_.empty());
+ ASSERT(!allocDevice_);
+
+ int ret = gralloc_open(hardwareModule_, &allocDevice_);
+ if (ret) {
+ LOG(HAL, Error) << "gralloc_open() failed: " << ret;
+ return allocatedBuffers_;
+ }
+
+ int stride = 0;
+ for (size_t i = 0; i < numBuffers; ++i) {
+ buffer_handle_t handle{};
+ ret = allocDevice_->alloc(allocDevice_, size.width, size.height,
+ halPixelFormat, usage, &handle, &stride);
+ if (ret) {
+ LOG(HAL, Error) << "failed buffer allocating: " << ret;
+ return allocatedBuffers_;
+ }
+
+ bufferHandles_.push_back(handle);
+ }
+
+ const libcamera::PixelFormat pixelFormat =
+ cameraDevice_->capabilities()->toPixelFormat(halPixelFormat);
+ const auto &info = PixelFormatInfo::info(pixelFormat);
+ const unsigned int numPlanes = info.numPlanes();
+
+ allocatedBuffers_.reserve(numBuffers);
+ for (const buffer_handle_t &handle : bufferHandles_) {
+ std::vector<FrameBuffer::Plane> planes(numPlanes);
+ size_t offset = 0;
+ for (size_t i = 0; i < numPlanes; ++i) {
+ planes[i].fd = FileDescriptor(handle->data[i]);
+ size_t planeSize = info.planeSize(size.height, i, stride);
+
+ planes[i].offset = offset;
+ planes[i].length = planeSize;
+ offset += planeSize;
+ }
+
+ allocatedBuffers_.push_back(std::make_unique<FrameBuffer>(planes));
+ }
+
+ return allocatedBuffers_;
+}
+
+PUBLIC_FRAME_BUFFER_IMPLEMENTATION
diff --git a/src/android/mm/meson.build b/src/android/mm/meson.build
index eeb5cc2e..d1ad64d9 100644
--- a/src/android/mm/meson.build
+++ b/src/android/mm/meson.build
@@ -2,8 +2,10 @@
platform = get_option('android_platform')
if platform == 'generic'
- android_hal_sources += files(['generic_camera_buffer.cpp'])
+ android_hal_sources += files(['generic_camera_buffer.cpp',
+ 'generic_frame_buffer.cpp'])
elif platform == 'cros'
- android_hal_sources += files(['cros_camera_buffer.cpp'])
+ android_hal_sources += files(['cros_camera_buffer.cpp',
+ 'cros_frame_buffer.cpp'])
android_deps += [dependency('libcros_camera')]
endif
--
2.33.0.685.g46640cef36-goog
More information about the libcamera-devel
mailing list