[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