/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2021, Google Inc. * * cros_camera_buffer.cpp - Chromium OS buffer backend using CameraBufferManager */ #include "../camera_buffer.h" #include <libcamera/base/log.h> #include "cros-camera/camera_buffer_manager.h" using namespace libcamera; LOG_DECLARE_CATEGORY(HAL) class CameraBuffer::Private : public Extensible::Private { LIBCAMERA_DECLARE_PUBLIC(CameraBuffer) public: Private(CameraBuffer *cameraBuffer, buffer_handle_t camera3Buffer, PixelFormat pixelFormat, const Size &size, int flags); ~Private(); bool isValid() const { return registered_; } unsigned int numPlanes() const; Span<uint8_t> plane(unsigned int plane); unsigned int stride(unsigned int plane) const; unsigned int offset(unsigned int plane) const; unsigned int size(unsigned int plane) const; size_t jpegBufferSize(size_t maxJpegBufferSize) const; private: void map(); cros::CameraBufferManager *bufferManager_; buffer_handle_t handle_; unsigned int numPlanes_; bool mapped_; bool registered_; union { void *addr; android_ycbcr ycbcr; } mem; }; CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer, buffer_handle_t camera3Buffer, [[maybe_unused]] PixelFormat pixelFormat, [[maybe_unused]] const Size &size, [[maybe_unused]] int flags) : handle_(camera3Buffer), numPlanes_(0), mapped_(false), registered_(false) { bufferManager_ = cros::CameraBufferManager::GetInstance(); int ret = bufferManager_->Register(camera3Buffer); if (ret) { LOG(HAL, Error) << "Failed registering a buffer: " << ret; return; } registered_ = true; numPlanes_ = bufferManager_->GetNumPlanes(camera3Buffer); } CameraBuffer::Private::~Private() { int ret; if (mapped_) { ret = bufferManager_->Unlock(handle_); if (ret != 0) LOG(HAL, Error) << "Failed to unlock buffer: " << strerror(-ret); } if (registered_) { ret = bufferManager_->Deregister(handle_); if (ret != 0) LOG(HAL, Error) << "Failed to deregister buffer: " << strerror(-ret); } } unsigned int CameraBuffer::Private::numPlanes() const { return bufferManager_->GetNumPlanes(handle_); } Span<uint8_t> CameraBuffer::Private::plane(unsigned int plane) { if (!mapped_) map(); if (!mapped_) return {}; void *addr; switch (numPlanes()) { case 1: addr = mem.addr; break; default: switch (plane) { case 0: addr = mem.ycbcr.y; break; case 1: addr = mem.ycbcr.cb; break; case 2: addr = mem.ycbcr.cr; break; } } return { static_cast<uint8_t *>(addr), bufferManager_->GetPlaneSize(handle_, plane) }; } unsigned int CameraBuffer::Private::stride(unsigned int plane) const { return cros::CameraBufferManager::GetPlaneStride(handle_, plane); } unsigned int CameraBuffer::Private::offset(unsigned int plane) const { return cros::CameraBufferManager::GetPlaneOffset(handle_, plane); } unsigned int CameraBuffer::Private::size(unsigned int plane) const { return cros::CameraBufferManager::GetPlaneSize(handle_, plane); } size_t CameraBuffer::Private::jpegBufferSize([[maybe_unused]] size_t maxJpegBufferSize) const { return bufferManager_->GetPlaneSize(handle_, 0); } void CameraBuffer::Private::map() { int ret; switch (numPlanes_) { case 1: { ret = bufferManager_->Lock(handle_, 0, 0, 0, 0, 0, &mem.addr); if (ret) { LOG(HAL, Error) << "Single plane buffer mapping failed"; return; } break; } case 2: case 3: { ret = bufferManager_->LockYCbCr(handle_, 0, 0, 0, 0, 0, &mem.ycbcr); if (ret) { LOG(HAL, Error) << "YCbCr buffer mapping failed"; return; } break; } default: LOG(HAL, Error) << "Invalid number of planes: " << numPlanes_; return; } mapped_ = true; return; } PUBLIC_CAMERA_BUFFER_IMPLEMENTATION