The libcamera
starts
This commit is contained in:
parent
95c7b06e1e
commit
4783fe31a5
@ -60,12 +60,19 @@ option_value_t camera_formats[] = {
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
option_value_t camera_type[] = {
|
||||||
|
{ "v4l2", CAMERA_V4L2 },
|
||||||
|
{ "libcamera", CAMERA_LIBCAMERA },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
option_t all_options[] = {
|
option_t all_options[] = {
|
||||||
DEFINE_OPTION_PTR(camera, path, string),
|
DEFINE_OPTION_PTR(camera, path, string),
|
||||||
DEFINE_OPTION(camera, width, uint),
|
DEFINE_OPTION(camera, width, uint),
|
||||||
DEFINE_OPTION(camera, height, uint),
|
DEFINE_OPTION(camera, height, uint),
|
||||||
DEFINE_OPTION_VALUES(camera, format, camera_formats),
|
DEFINE_OPTION_VALUES(camera, format, camera_formats),
|
||||||
DEFINE_OPTION(camera, nbufs, uint),
|
DEFINE_OPTION(camera, nbufs, uint),
|
||||||
|
DEFINE_OPTION_VALUES(camera, type, camera_type),
|
||||||
DEFINE_OPTION(camera, fps, uint),
|
DEFINE_OPTION(camera, fps, uint),
|
||||||
DEFINE_OPTION_DEFAULT(camera, allow_dma, bool, "1"),
|
DEFINE_OPTION_DEFAULT(camera, allow_dma, bool, "1"),
|
||||||
DEFINE_OPTION(camera, high_res_factor, float),
|
DEFINE_OPTION(camera, high_res_factor, float),
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "device/camera/camera.h"
|
#include "device/camera/camera.h"
|
||||||
|
|
||||||
log_options_t log_options = {
|
log_options_t log_options = {
|
||||||
.debug = false,
|
.debug = true,
|
||||||
.verbose = false
|
.verbose = false
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -12,12 +12,17 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
device_t *dev = NULL;
|
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) {
|
if (!dev) {
|
||||||
printf("Failed to open libcamera\n");
|
printf("Failed to open libcamera\n");
|
||||||
return -1;
|
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");
|
printf("Opened libcamera\n");
|
||||||
|
|
||||||
device_close(dev);
|
device_close(dev);
|
||||||
|
@ -40,7 +40,19 @@ camera_t *camera_open(camera_options_t *options)
|
|||||||
camera->name = "CAMERA";
|
camera->name = "CAMERA";
|
||||||
camera->options = *options;
|
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) {
|
if (!camera->camera) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,16 @@
|
|||||||
#define CAMERA_DEVICE_CAMERA 0
|
#define CAMERA_DEVICE_CAMERA 0
|
||||||
#define CAMERA_OPTIONS_LENGTH 4096
|
#define CAMERA_OPTIONS_LENGTH 4096
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CAMERA_V4L2 = 0,
|
||||||
|
CAMERA_LIBCAMERA
|
||||||
|
} camera_type_t;
|
||||||
|
|
||||||
typedef struct camera_options_s {
|
typedef struct camera_options_s {
|
||||||
char path[256];
|
char path[256];
|
||||||
unsigned width, height, format;
|
unsigned width, height, format;
|
||||||
unsigned nbufs, fps;
|
unsigned nbufs, fps;
|
||||||
|
camera_type_t type;
|
||||||
bool allow_dma;
|
bool allow_dma;
|
||||||
float high_res_factor;
|
float high_res_factor;
|
||||||
float low_res_factor;
|
float low_res_factor;
|
||||||
|
@ -3,7 +3,44 @@
|
|||||||
int libcamera_buffer_open(buffer_t *buf)
|
int libcamera_buffer_open(buffer_t *buf)
|
||||||
{
|
{
|
||||||
buf->libcamera = new buffer_libcamera_t{};
|
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;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libcamera_buffer_close(buffer_t *buf)
|
void libcamera_buffer_close(buffer_t *buf)
|
||||||
|
@ -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 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) {
|
if (!buf_list->do_capture) {
|
||||||
E_LOG_INFO(buf_list, "Only capture mode is supported.");
|
E_LOG_INFO(buf_list, "Only capture mode is supported.");
|
||||||
return -1;
|
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{};
|
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)
|
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)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -4,18 +4,43 @@ int libcamera_device_open(device_t *dev)
|
|||||||
{
|
{
|
||||||
dev->libcamera = new device_libcamera_t{};
|
dev->libcamera = new device_libcamera_t{};
|
||||||
|
|
||||||
auto camera_manager = std::make_unique<libcamera::CameraManager>();
|
dev->libcamera->camera_manager = std::make_shared<libcamera::CameraManager>();
|
||||||
int ret = camera_manager->start();
|
int ret = dev->libcamera->camera_manager->start();
|
||||||
if (ret < 0) {
|
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;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void libcamera_device_close(device_t *dev)
|
void libcamera_device_close(device_t *dev)
|
||||||
{
|
{
|
||||||
if (dev->libcamera) {
|
if (dev->libcamera) {
|
||||||
|
if (dev->libcamera->camera) {
|
||||||
|
dev->libcamera->camera->stop();
|
||||||
|
dev->libcamera->camera->release();
|
||||||
|
}
|
||||||
|
|
||||||
delete dev->libcamera;
|
delete dev->libcamera;
|
||||||
dev->libcamera = NULL;
|
dev->libcamera = NULL;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ extern "C" {
|
|||||||
#include "device/buffer_list.h"
|
#include "device/buffer_list.h"
|
||||||
#include "device/buffer.h"
|
#include "device/buffer.h"
|
||||||
#include "opts/log.h"
|
#include "opts/log.h"
|
||||||
|
#include "opts/fourcc.h"
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -34,12 +35,17 @@ typedef struct device_s device_t;
|
|||||||
struct pollfd;
|
struct pollfd;
|
||||||
|
|
||||||
typedef struct device_libcamera_s {
|
typedef struct device_libcamera_s {
|
||||||
|
std::shared_ptr<libcamera::CameraManager> camera_manager;
|
||||||
|
std::shared_ptr<libcamera::Camera> camera;
|
||||||
} device_libcamera_t;
|
} device_libcamera_t;
|
||||||
|
|
||||||
typedef struct buffer_list_libcamera_s {
|
typedef struct buffer_list_libcamera_s {
|
||||||
|
std::shared_ptr<libcamera::CameraConfiguration> configuration;
|
||||||
|
std::shared_ptr<libcamera::FrameBufferAllocator> allocator;
|
||||||
} buffer_list_libcamera_t;
|
} buffer_list_libcamera_t;
|
||||||
|
|
||||||
typedef struct buffer_libcamera_s {
|
typedef struct buffer_libcamera_s {
|
||||||
|
std::shared_ptr<libcamera::Request> request;
|
||||||
} buffer_libcamera_t;
|
} buffer_libcamera_t;
|
||||||
|
|
||||||
int libcamera_device_open(device_t *dev);
|
int libcamera_device_open(device_t *dev);
|
||||||
|
12
libcamera_camera.sh
Executable file
12
libcamera_camera.sh
Executable 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 \
|
||||||
|
"$@"
|
Loading…
x
Reference in New Issue
Block a user