Merge branch 'spa_libcamera_misc' into 'master'

spa: libcamera: some more misc. changes

See merge request pipewire/pipewire!2868
This commit is contained in:
Barnabás Pőcze 2026-06-23 17:00:26 +02:00
commit 80eec4eee3
8 changed files with 101 additions and 91 deletions

View file

@ -21,8 +21,7 @@
#include <spa/monitor/utils.h> #include <spa/monitor/utils.h>
#include <spa/param/param.h> #include <spa/param/param.h>
#include "libcamera.h" #include "libcamera.hpp"
#include "libcamera-manager.hpp"
#include <libcamera/camera.h> #include <libcamera/camera.h>
#include <libcamera/property_ids.h> #include <libcamera/property_ids.h>
@ -99,7 +98,7 @@ const char *cameraRot(const Camera& camera)
int emit_info(struct impl *impl, bool full) int emit_info(struct impl *impl, bool full)
{ {
struct spa_dict_item items[10]; struct spa_dict_item items[12];
struct spa_dict dict; struct spa_dict dict;
uint32_t n_items = 0; uint32_t n_items = 0;
struct spa_device_info info; struct spa_device_info info;
@ -118,6 +117,8 @@ int emit_info(struct impl *impl, bool full)
ADD_ITEM(SPA_KEY_DEVICE_API, "libcamera"); ADD_ITEM(SPA_KEY_DEVICE_API, "libcamera");
ADD_ITEM(SPA_KEY_MEDIA_CLASS, "Video/Device"); ADD_ITEM(SPA_KEY_MEDIA_CLASS, "Video/Device");
ADD_ITEM(SPA_KEY_API_LIBCAMERA_PATH, impl->device_id.c_str()); ADD_ITEM(SPA_KEY_API_LIBCAMERA_PATH, impl->device_id.c_str());
ADD_ITEM(KEY_VERSION_LIBRARY, libcamera_library_version());
ADD_ITEM(KEY_VERSION_HEADER, libcamera_header_version());
if (auto location = cameraLoc(camera)) if (auto location = cameraLoc(camera))
ADD_ITEM(SPA_KEY_API_LIBCAMERA_LOCATION, location); ADD_ITEM(SPA_KEY_API_LIBCAMERA_LOCATION, location);

View file

@ -25,8 +25,7 @@ using namespace libcamera;
#include <spa/monitor/device.h> #include <spa/monitor/device.h>
#include <spa/monitor/utils.h> #include <spa/monitor/utils.h>
#include "libcamera.h" #include "libcamera.hpp"
#include "libcamera-manager.hpp"
namespace { namespace {
@ -118,9 +117,7 @@ void remove_device(struct impl *impl, struct device *device)
int emit_object_info(struct impl *impl, const struct device *device) int emit_object_info(struct impl *impl, const struct device *device)
{ {
struct spa_device_object_info info; struct spa_device_object_info info;
struct spa_dict_item items[20];
struct spa_dict dict; struct spa_dict dict;
uint32_t n_items = 0;
info = SPA_DEVICE_OBJECT_INFO_INIT(); info = SPA_DEVICE_OBJECT_INFO_INIT();
@ -130,14 +127,16 @@ int emit_object_info(struct impl *impl, const struct device *device)
SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS; SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.flags = 0; info.flags = 0;
#define ADD_ITEM(key, value) items[n_items++] = SPA_DICT_ITEM_INIT(key, value) const spa_dict_item items[] = {
ADD_ITEM(SPA_KEY_DEVICE_ENUM_API,"libcamera.manager"); { SPA_KEY_DEVICE_ENUM_API, "libcamera.manager" },
ADD_ITEM(SPA_KEY_DEVICE_API, "libcamera"); { SPA_KEY_DEVICE_API, "libcamera" },
ADD_ITEM(SPA_KEY_MEDIA_CLASS, "Video/Device"); { SPA_KEY_MEDIA_CLASS, "Video/Device" },
ADD_ITEM(SPA_KEY_API_LIBCAMERA_PATH, device->camera->id().c_str()); { SPA_KEY_API_LIBCAMERA_PATH, device->camera->id().c_str() },
#undef ADD_ITEM { KEY_VERSION_LIBRARY, libcamera_library_version() },
{ KEY_VERSION_HEADER, libcamera_header_version() },
};
dict = SPA_DICT_INIT(items, n_items); dict = SPA_DICT_INIT_ARRAY(items);
info.props = &dict; info.props = &dict;
spa_device_emit_object_info(&impl->hooks, impl->id_of(*device), &info); spa_device_emit_object_info(&impl->hooks, impl->id_of(*device), &info);
@ -390,22 +389,3 @@ const struct spa_handle_factory spa_libcamera_manager_factory = {
impl_enum_interface_info, impl_enum_interface_info,
}; };
} }
std::shared_ptr<CameraManager> libcamera_manager_acquire(int& res)
{
static std::weak_ptr<CameraManager> global_manager;
static std::mutex lock;
std::lock_guard guard(lock);
if (auto manager = global_manager.lock())
return manager;
auto manager = std::make_shared<CameraManager>();
if ((res = manager->start()) < 0)
return {};
global_manager = manager;
return manager;
}

View file

@ -1,9 +0,0 @@
/* Spa libcamera support */
/* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> */
/* SPDX-License-Identifier: MIT */
#include <memory>
#include <libcamera/camera_manager.h>
std::shared_ptr<libcamera::CameraManager> libcamera_manager_acquire(int& res);

View file

@ -42,8 +42,7 @@
#include <libcamera/framebuffer.h> #include <libcamera/framebuffer.h>
#include <libcamera/framebuffer_allocator.h> #include <libcamera/framebuffer_allocator.h>
#include "libcamera.h" #include "libcamera.hpp"
#include "libcamera-manager.hpp"
using namespace libcamera; using namespace libcamera;
@ -1219,8 +1218,8 @@ spa_libcamera_alloc_buffers(struct impl *impl, struct port *port,
for (uint32_t i = 0; i < n_buffers; i++) { for (uint32_t i = 0; i < n_buffers; i++) {
struct buffer *b; struct buffer *b;
if (buffers[i]->n_datas < 1) { if (buffers[i]->n_datas != port->buffers_blocks) {
spa_log_error(impl->log, "invalid buffer data"); spa_log_error(impl->log, "invalid number of data planes");
return -EINVAL; return -EINVAL;
} }
@ -1243,6 +1242,8 @@ spa_libcamera_alloc_buffers(struct impl *impl, struct port *port,
const auto& planes = bufs[i]->planes(); const auto& planes = bufs[i]->planes();
spa_data *d = buffers[i]->datas; spa_data *d = buffers[i]->datas;
spa_assert(buffers[i]->n_datas <= planes.size());
for(uint32_t j = 0; j < buffers[i]->n_datas; ++j) { for(uint32_t j = 0; j < buffers[i]->n_datas; ++j) {
const auto memtype = choose_memtype(d[j].type); const auto memtype = choose_memtype(d[j].type);
if (memtype == SPA_DATA_Invalid) { if (memtype == SPA_DATA_Invalid) {
@ -1258,30 +1259,22 @@ spa_libcamera_alloc_buffers(struct impl *impl, struct port *port,
d[j].chunk->stride = port->streamConfig.stride; d[j].chunk->stride = port->streamConfig.stride;
d[j].chunk->flags = 0; d[j].chunk->flags = 0;
/* Update parameters according to the plane information */ /* Update parameters according to the plane information */
unsigned int numPlanes = planes.size(); if (buffers[i]->n_datas < planes.size()) {
if (buffers[i]->n_datas < numPlanes) {
if (j < buffers[i]->n_datas - 1) { if (j < buffers[i]->n_datas - 1) {
d[j].maxsize = planes[j].length; d[j].maxsize = planes[j].length;
d[j].chunk->offset = planes[j].offset; d[j].chunk->offset = planes[j].offset;
d[j].chunk->size = planes[j].length; d[j].chunk->size = planes[j].length;
} else { } else {
d[j].chunk->offset = planes[j].offset; d[j].chunk->offset = planes[j].offset;
for (uint8_t k = j; k < numPlanes; k++) { for (uint8_t k = j; k < planes.size(); k++) {
d[j].maxsize += planes[k].length; d[j].maxsize += planes[k].length;
d[j].chunk->size += planes[k].length; d[j].chunk->size += planes[k].length;
} }
} }
} else if (buffers[i]->n_datas == numPlanes) { } else {
d[j].maxsize = planes[j].length; d[j].maxsize = planes[j].length;
d[j].chunk->offset = planes[j].offset; d[j].chunk->offset = planes[j].offset;
d[j].chunk->size = planes[j].length; d[j].chunk->size = planes[j].length;
} else {
spa_log_warn(impl->log, "buffer index: i: %d, data member "
"numbers: %d is greater than plane number: %d",
i, buffers[i]->n_datas, numPlanes);
d[j].maxsize = port->streamConfig.frameSize;
d[j].chunk->offset = 0;
d[j].chunk->size = port->streamConfig.frameSize;
} }
switch (memtype) { switch (memtype) {
@ -1609,6 +1602,8 @@ void emit_node_info(struct impl *impl, bool full)
{ SPA_KEY_MEDIA_CLASS, "Video/Source" }, { SPA_KEY_MEDIA_CLASS, "Video/Source" },
{ SPA_KEY_MEDIA_ROLE, "Camera" }, { SPA_KEY_MEDIA_ROLE, "Camera" },
{ SPA_KEY_NODE_DRIVER, "true" }, { SPA_KEY_NODE_DRIVER, "true" },
{ KEY_VERSION_LIBRARY, libcamera_library_version() },
{ KEY_VERSION_HEADER, libcamera_header_version() },
}; };
uint64_t old = full ? impl->info.change_mask : 0; uint64_t old = full ? impl->info.change_mask : 0;
if (full) if (full)

View file

@ -2,12 +2,17 @@
/* SPDX-FileCopyrightText: Copyright © 2020 collabora */ /* SPDX-FileCopyrightText: Copyright © 2020 collabora */
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
#include <errno.h> #include <memory>
#include <mutex>
#include <libcamera/camera_manager.h>
#include <spa/support/plugin.h> #include <spa/support/plugin.h>
#include <spa/support/log.h> #include <spa/support/log.h>
#include "libcamera.h" #include "libcamera.hpp"
extern "C" {
SPA_LOG_TOPIC_DEFINE(libcamera_log_topic, "spa.libcamera"); SPA_LOG_TOPIC_DEFINE(libcamera_log_topic, "spa.libcamera");
@ -36,3 +41,24 @@ int spa_handle_factory_enum(const struct spa_handle_factory **factory,
(*index)++; (*index)++;
return 1; return 1;
} }
}
std::shared_ptr<libcamera::CameraManager> libcamera_manager_acquire(int& res)
{
static std::weak_ptr<libcamera::CameraManager> global_manager;
static std::mutex lock;
std::lock_guard guard(lock);
if (auto manager = global_manager.lock())
return manager;
auto manager = std::make_shared<libcamera::CameraManager>();
if ((res = manager->start()) < 0)
return {};
global_manager = manager;
return manager;
}

View file

@ -1,31 +0,0 @@
/* Spa libcamera support */
/* SPDX-FileCopyrightText: Copyright © 2020 collabora */
/* SPDX-License-Identifier: MIT */
#include <errno.h>
#include <linux/media.h>
#include <spa/support/log.h>
#include <spa/support/system.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern const struct spa_handle_factory spa_libcamera_source_factory;
extern const struct spa_handle_factory spa_libcamera_manager_factory;
extern const struct spa_handle_factory spa_libcamera_device_factory;
#undef SPA_LOG_TOPIC_DEFAULT
#define SPA_LOG_TOPIC_DEFAULT &libcamera_log_topic
extern struct spa_log_topic libcamera_log_topic;
static inline void libcamera_log_topic_init(struct spa_log *log)
{
spa_log_topic_init(log, &libcamera_log_topic);
}
#ifdef __cplusplus
}
#endif /* __cplusplus */

View file

@ -0,0 +1,48 @@
/* Spa libcamera support */
/* SPDX-FileCopyrightText: Copyright © 2020 collabora */
/* SPDX-License-Identifier: MIT */
#pragma once
#include <memory>
#include <libcamera/camera_manager.h>
#include <libcamera/version.h>
#include <spa/support/log.h>
#include <spa/utils/defs.h>
#define KEY_VERSION_LIBRARY "api.libcamera.version.library"
#define KEY_VERSION_HEADER "api.libcamera.version.header"
extern "C" {
extern const struct spa_handle_factory spa_libcamera_source_factory;
extern const struct spa_handle_factory spa_libcamera_manager_factory;
extern const struct spa_handle_factory spa_libcamera_device_factory;
#undef SPA_LOG_TOPIC_DEFAULT
#define SPA_LOG_TOPIC_DEFAULT &libcamera_log_topic
extern struct spa_log_topic libcamera_log_topic;
}
static inline void libcamera_log_topic_init(struct spa_log *log)
{
spa_log_topic_init(log, &libcamera_log_topic);
}
static inline const char *libcamera_library_version()
{
return libcamera::CameraManager::version().c_str();
}
static inline const char *libcamera_header_version()
{
return
SPA_STRINGIFY(LIBCAMERA_VERSION_MAJOR) "."
SPA_STRINGIFY(LIBCAMERA_VERSION_MINOR) "."
SPA_STRINGIFY(LIBCAMERA_VERSION_PATCH);
}
std::shared_ptr<libcamera::CameraManager> libcamera_manager_acquire(int& res);

View file

@ -1,5 +1,5 @@
libcamera_sources = [ libcamera_sources = [
'libcamera.c', 'libcamera.cpp',
'libcamera-manager.cpp', 'libcamera-manager.cpp',
'libcamera-device.cpp', 'libcamera-device.cpp',
'libcamera-source.cpp' 'libcamera-source.cpp'