The Extensible and Extensible::Private classes contain pointers to each other. These pointers are initialized in the respective class's constructor, by passing a pointer to the other class to each constructor. This particular construct reduces the flexibility of the Extensible pattern, as the Private class instance has to be allocated and constructed in the members initializer list of the Extensible class's constructor. It is thus impossible to perform any operation on the Private class between its construction and the construction of the Extensible class, or to subclass the Private class without subclassing the Extensible class. To make the design pattern more flexible, don't pass the pointer to the Extensible class to the Private class's constructor, but initialize the pointer manually in the Extensible class's constructor. This requires a const_cast as the o_ member of the Private class is const. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
90 lines
1.9 KiB
C++
90 lines
1.9 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2021, Google Inc.
|
|
*
|
|
* generic_camera_buffer.cpp - Generic Android frame buffer backend
|
|
*/
|
|
|
|
#include "../camera_buffer.h"
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <libcamera/base/log.h>
|
|
|
|
#include "libcamera/internal/framebuffer.h"
|
|
|
|
using namespace libcamera;
|
|
|
|
LOG_DECLARE_CATEGORY(HAL)
|
|
|
|
class CameraBuffer::Private : public Extensible::Private,
|
|
public libcamera::MappedBuffer
|
|
{
|
|
LIBCAMERA_DECLARE_PUBLIC(CameraBuffer)
|
|
|
|
public:
|
|
Private(CameraBuffer *cameraBuffer,
|
|
buffer_handle_t camera3Buffer, int flags);
|
|
~Private();
|
|
|
|
unsigned int numPlanes() const;
|
|
|
|
Span<uint8_t> plane(unsigned int plane);
|
|
|
|
size_t jpegBufferSize(size_t maxJpegBufferSize) const;
|
|
};
|
|
|
|
CameraBuffer::Private::Private([[maybe_unused]] CameraBuffer *cameraBuffer,
|
|
buffer_handle_t camera3Buffer, int flags)
|
|
{
|
|
maps_.reserve(camera3Buffer->numFds);
|
|
error_ = 0;
|
|
|
|
for (int i = 0; i < camera3Buffer->numFds; i++) {
|
|
if (camera3Buffer->data[i] == -1)
|
|
continue;
|
|
|
|
off_t length = lseek(camera3Buffer->data[i], 0, SEEK_END);
|
|
if (length < 0) {
|
|
error_ = -errno;
|
|
LOG(HAL, Error) << "Failed to query plane length";
|
|
break;
|
|
}
|
|
|
|
void *address = mmap(nullptr, length, flags, MAP_SHARED,
|
|
camera3Buffer->data[i], 0);
|
|
if (address == MAP_FAILED) {
|
|
error_ = -errno;
|
|
LOG(HAL, Error) << "Failed to mmap plane";
|
|
break;
|
|
}
|
|
|
|
maps_.emplace_back(static_cast<uint8_t *>(address),
|
|
static_cast<size_t>(length));
|
|
}
|
|
}
|
|
|
|
CameraBuffer::Private::~Private()
|
|
{
|
|
}
|
|
|
|
unsigned int CameraBuffer::Private::numPlanes() const
|
|
{
|
|
return maps_.size();
|
|
}
|
|
|
|
Span<uint8_t> CameraBuffer::Private::plane(unsigned int plane)
|
|
{
|
|
if (plane >= maps_.size())
|
|
return {};
|
|
|
|
return maps_[plane];
|
|
}
|
|
|
|
size_t CameraBuffer::Private::jpegBufferSize(size_t maxJpegBufferSize) const
|
|
{
|
|
return std::min<unsigned int>(maps_[0].size(),
|
|
maxJpegBufferSize);
|
|
}
|
|
|
|
PUBLIC_CAMERA_BUFFER_IMPLEMENTATION
|