The libcamera starts

This commit is contained in:
Kamil Trzcinski 2022-04-11 10:01:18 +02:00
parent 95c7b06e1e
commit 4783fe31a5
9 changed files with 180 additions and 7 deletions

View File

@ -60,12 +60,19 @@ option_value_t camera_formats[] = {
{}
};
option_value_t camera_type[] = {
{ "v4l2", CAMERA_V4L2 },
{ "libcamera", CAMERA_LIBCAMERA },
{}
};
option_t all_options[] = {
DEFINE_OPTION_PTR(camera, path, string),
DEFINE_OPTION(camera, width, uint),
DEFINE_OPTION(camera, height, uint),
DEFINE_OPTION_VALUES(camera, format, camera_formats),
DEFINE_OPTION(camera, nbufs, uint),
DEFINE_OPTION_VALUES(camera, type, camera_type),
DEFINE_OPTION(camera, fps, uint),
DEFINE_OPTION_DEFAULT(camera, allow_dma, bool, "1"),
DEFINE_OPTION(camera, high_res_factor, float),

View File

@ -4,7 +4,7 @@
#include "device/camera/camera.h"
log_options_t log_options = {
.debug = false,
.debug = true,
.verbose = false
};
@ -12,12 +12,17 @@ int main(int argc, char *argv[])
{
device_t *dev = NULL;
dev = device_libcamera_open("CAMERA", "/dev/video0");
dev = device_libcamera_open("CAMERA", "/base/soc/i2c0mux/i2c@1/imx519@1a");
if (!dev) {
printf("Failed to open libcamera\n");
return -1;
}
if (device_open_buffer_list(dev, true, 2328, 1748, V4L2_PIX_FMT_VYUY, 0, 4, true) < 0) {
printf("Failed to open buffer list\n");
return -1;
}
printf("Opened libcamera\n");
device_close(dev);

View File

@ -40,7 +40,19 @@ camera_t *camera_open(camera_options_t *options)
camera->name = "CAMERA";
camera->options = *options;
camera->camera = device_v4l2_open(camera->name, camera->options.path);
switch (camera->options.type) {
case CAMERA_V4L2:
camera->camera = device_v4l2_open(camera->name, camera->options.path);
break;
case CAMERA_LIBCAMERA:
camera->camera = device_libcamera_open(camera->name, camera->options.path);
break;
default:
E_LOG_ERROR(camera, "Unsupported camera type");
}
if (!camera->camera) {
goto error;
}

View File

@ -9,10 +9,16 @@
#define CAMERA_DEVICE_CAMERA 0
#define CAMERA_OPTIONS_LENGTH 4096
typedef enum {
CAMERA_V4L2 = 0,
CAMERA_LIBCAMERA
} camera_type_t;
typedef struct camera_options_s {
char path[256];
unsigned width, height, format;
unsigned nbufs, fps;
camera_type_t type;
bool allow_dma;
float high_res_factor;
float low_res_factor;

View File

@ -3,7 +3,44 @@
int libcamera_buffer_open(buffer_t *buf)
{
buf->libcamera = new buffer_libcamera_t{};
buf->libcamera->request = buf->buf_list->dev->libcamera->camera->createRequest();
if (!buf->libcamera->request) {
E_LOG_ERROR(buf, "Can't create request");
}
for (libcamera::StreamConfiguration &stream_cfg : *buf->buf_list->libcamera->configuration) {
auto stream = stream_cfg.stream();
const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &buffers =
buf->buf_list->libcamera->allocator->buffers(stream);
auto const &buffer = buffers[buf->index];
if (buf->libcamera->request->addBuffer(stream, buffer.get()) < 0) {
E_LOG_ERROR(buf, "Can't set buffer for request");
}
for (auto const &plane : buffer->planes()) {
if (buf->start) {
E_LOG_ERROR(buf, "Too many planes open.");
}
buf->start = mmap(NULL, plane.length, PROT_READ | PROT_WRITE, MAP_SHARED, plane.fd.get(), 0);
buf->length = plane.length;
buf->used = 0;
buf->dma_fd = plane.fd.get();
if (!buf->start) {
E_LOG_ERROR(buf, "Failed to mmap DMA buffer");
}
E_LOG_DEBUG(buf, "Mapped buffer: start=%p, length=%d, fd=%d",
buf->start, buf->length, buf->dma_fd);
}
}
return 0;
error:
return -1;
}
void libcamera_buffer_close(buffer_t *buf)

View File

@ -2,13 +2,63 @@
int libcamera_buffer_list_open(buffer_list_t *buf_list, unsigned width, unsigned height, unsigned format, unsigned bytesperline, int nbufs)
{
int got_bufs = 0;
if (!buf_list->do_capture) {
E_LOG_INFO(buf_list, "Only capture mode is supported.");
return -1;
}
if (!buf_list->do_mmap) {
E_LOG_INFO(buf_list, "Only mmap buffers are supported.");
return -1;
}
buf_list->libcamera = new buffer_list_libcamera_t{};
return 0;
buf_list->libcamera->configuration = buf_list->dev->libcamera->camera->generateConfiguration(
{ libcamera::StreamRole::Viewfinder });
auto &configuration = buf_list->libcamera->configuration->at(0);
configuration.size = libcamera::Size(width, height);
configuration.pixelFormat = libcamera::PixelFormat(format);
if (bytesperline > 0) {
configuration.stride = bytesperline;
}
if (nbufs > 0) {
configuration.bufferCount = nbufs;
}
if (buf_list->libcamera->configuration->validate() == libcamera::CameraConfiguration::Invalid) {
E_LOG_ERROR(buf_list, "Camera configuration invalid");
}
if (buf_list->dev->libcamera->camera->configure(buf_list->libcamera->configuration.get()) < 0) {
E_LOG_ERROR(buf_list, "Failed to configure camera");
}
buf_list->fmt_width = configuration.size.width;
buf_list->fmt_height = configuration.size.height;
buf_list->fmt_format = configuration.pixelFormat.fourcc();
buf_list->fmt_bytesperline = configuration.stride;
buf_list->libcamera->allocator = std::make_shared<libcamera::FrameBufferAllocator>(
buf_list->dev->libcamera->camera);
got_bufs = configuration.bufferCount;
for (libcamera::StreamConfiguration &stream_config : *buf_list->libcamera->configuration) {
if (buf_list->libcamera->allocator->allocate(stream_config.stream()) < 0) {
E_LOG_ERROR(buf_list, "Can't allocate buffers");
}
int allocated = buf_list->libcamera->allocator->buffers(
stream_config.stream()).size();
got_bufs = std::min(got_bufs, allocated);
}
return got_bufs;
error:
return -1;
}
void libcamera_buffer_list_close(buffer_list_t *buf_list)
@ -21,5 +71,18 @@ void libcamera_buffer_list_close(buffer_list_t *buf_list)
int libcamera_buffer_list_set_stream(buffer_list_t *buf_list, bool do_on)
{
if (do_on) {
if (buf_list->dev->libcamera->camera->start() < 0) {
E_LOG_ERROR(buf_list, "Failed to start camera.");
}
} else {
if (buf_list->dev->libcamera->camera->stop() < 0) {
E_LOG_ERROR(buf_list, "Failed to stop camera.");
}
}
return 0;
error:
return -1;
}

View File

@ -4,18 +4,43 @@ int libcamera_device_open(device_t *dev)
{
dev->libcamera = new device_libcamera_t{};
auto camera_manager = std::make_unique<libcamera::CameraManager>();
int ret = camera_manager->start();
dev->libcamera->camera_manager = std::make_shared<libcamera::CameraManager>();
int ret = dev->libcamera->camera_manager->start();
if (ret < 0) {
return -1;
E_LOG_ERROR(dev, "Cannot start camera_manager.");
}
dev->libcamera->camera = dev->libcamera->camera_manager->get(dev->path);
if (!dev->libcamera->camera) {
if (dev->libcamera->camera_manager->cameras().size()) {
for(auto const &camera : dev->libcamera->camera_manager->cameras()) {
E_LOG_INFO(dev, "Available Camera: %s", camera->id().c_str());
}
} else {
E_LOG_INFO(dev, "No available cameras");
}
E_LOG_ERROR(dev, "Camera `%s` was not found.", dev->path);
}
if (dev->libcamera->camera->acquire()) {
E_LOG_ERROR(dev, "Failed to acquire `%s` camera.", dev->path);
}
printf("camera manager started, and camera was found: %s\n", dev->libcamera->camera->id().c_str());
return 0;
error:
return -1;
}
void libcamera_device_close(device_t *dev)
{
if (dev->libcamera) {
if (dev->libcamera->camera) {
dev->libcamera->camera->stop();
dev->libcamera->camera->release();
}
delete dev->libcamera;
dev->libcamera = NULL;
}

View File

@ -11,6 +11,7 @@ extern "C" {
#include "device/buffer_list.h"
#include "device/buffer.h"
#include "opts/log.h"
#include "opts/fourcc.h"
};
#include <optional>
@ -34,12 +35,17 @@ typedef struct device_s device_t;
struct pollfd;
typedef struct device_libcamera_s {
std::shared_ptr<libcamera::CameraManager> camera_manager;
std::shared_ptr<libcamera::Camera> camera;
} device_libcamera_t;
typedef struct buffer_list_libcamera_s {
std::shared_ptr<libcamera::CameraConfiguration> configuration;
std::shared_ptr<libcamera::FrameBufferAllocator> allocator;
} buffer_list_libcamera_t;
typedef struct buffer_libcamera_s {
std::shared_ptr<libcamera::Request> request;
} buffer_libcamera_t;
int libcamera_device_open(device_t *dev);

12
libcamera_camera.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
cd "$SCRIPT_DIR"
set -xeo pipefail
make -j$(nproc)
$GDB ./camera_stream \
-camera-path=/base/soc/i2c0mux/i2c@1/imx519@1a \
-camera-type=libcamera \
-camera-format=YUYV \
"$@"