1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2021, Google Inc.
*
* generic_camera_buffer.cpp - Allocate FrameBuffer using gralloc API
*/
#include <dlfcn.h>
#include <memory>
#include <vector>
#include <libcamera/base/log.h>
#include <libcamera/base/shared_fd.h>
#include "libcamera/internal/formats.h"
#include "libcamera/internal/framebuffer.h"
#include <hardware/camera3.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wextra-semi"
#include <ui/GraphicBufferAllocator.h>
#pragma GCC diagnostic pop
#include <utils/Errors.h>
#include "../camera_device.h"
#include "../frame_buffer_allocator.h"
#include "../hal_framebuffer.h"
using namespace libcamera;
LOG_DECLARE_CATEGORY(HAL)
namespace {
class GenericFrameBufferData : public FrameBuffer::Private
{
LIBCAMERA_DECLARE_PUBLIC(FrameBuffer)
public:
GenericFrameBufferData(buffer_handle_t handle,
const std::vector<FrameBuffer::Plane> &planes)
: FrameBuffer::Private(planes), handle_(handle)
{
ASSERT(handle_);
}
~GenericFrameBufferData() override
{
/*
* \todo Thread safety against alloc_device_t is not documented.
* Is it no problem to call alloc/free in parallel?
*/
auto &allocator = android::GraphicBufferAllocator::get();
android::status_t status = allocator.free(handle_);
if (status != android::NO_ERROR)
LOG(HAL, Error) << "Error freeing framebuffer: " << status;
}
private:
const buffer_handle_t handle_;
};
} /* namespace */
class PlatformFrameBufferAllocator::Private : public Extensible::Private
{
LIBCAMERA_DECLARE_PUBLIC(PlatformFrameBufferAllocator)
public:
Private(CameraDevice *const cameraDevice)
: cameraDevice_(cameraDevice)
{
}
~Private() = default;
std::unique_ptr<HALFrameBuffer>
allocate(int halPixelFormat, const libcamera::Size &size, uint32_t usage);
private:
const CameraDevice *const cameraDevice_;
};
std::unique_ptr<HALFrameBuffer>
PlatformFrameBufferAllocator::Private::allocate(int halPixelFormat,
const libcamera::Size &size,
uint32_t usage)
{
uint32_t stride = 0;
buffer_handle_t handle = nullptr;
auto &allocator = android::GraphicBufferAllocator::get();
android::status_t status = allocator.allocate(size.width, size.height, halPixelFormat,
1 /*layerCount*/, usage, &handle, &stride,
"libcameraHAL");
if (status != android::NO_ERROR) {
LOG(HAL, Error) << "failed buffer allocation: " << status;
return nullptr;
}
if (!handle) {
LOG(HAL, Fatal) << "invalid buffer_handle_t";
return nullptr;
}
/* This code assumes the planes are mapped consecutively. */
const libcamera::PixelFormat pixelFormat =
cameraDevice_->capabilities()->toPixelFormat(halPixelFormat);
const auto &info = PixelFormatInfo::info(pixelFormat);
std::vector<FrameBuffer::Plane> planes(info.numPlanes());
SharedFD fd{ handle->data[0] };
size_t offset = 0;
for (auto [i, plane] : utils::enumerate(planes)) {
const size_t planeSize = info.planeSize(size.height, i, stride);
plane.fd = fd;
plane.offset = offset;
plane.length = planeSize;
offset += planeSize;
}
return std::make_unique<HALFrameBuffer>(
std::make_unique<GenericFrameBufferData>(
handle, planes),
handle);
}
PUBLIC_FRAME_BUFFER_ALLOCATOR_IMPLEMENTATION
|