mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
spa: libcamera: manage libcamera::CameraManager via a shared_ptr
Using a shared_ptr removes the need for manually calling `libcamera_manager_release()` to drop the reference as it is done automatically whenever the shared_ptr is destroyed or reset.
This commit is contained in:
parent
330686d3aa
commit
13357fec20
4 changed files with 38 additions and 78 deletions
|
|
@ -66,11 +66,11 @@ struct impl {
|
||||||
|
|
||||||
struct spa_hook_list hooks;
|
struct spa_hook_list hooks;
|
||||||
|
|
||||||
CameraManager *manager;
|
std::shared_ptr<CameraManager> manager;
|
||||||
std::shared_ptr<Camera> camera;
|
std::shared_ptr<Camera> camera;
|
||||||
|
|
||||||
impl(spa_log *log,
|
impl(spa_log *log,
|
||||||
CameraManager *manager,
|
std::shared_ptr<CameraManager> manager,
|
||||||
std::shared_ptr<Camera> camera,
|
std::shared_ptr<Camera> camera,
|
||||||
std::string device_id);
|
std::string device_id);
|
||||||
};
|
};
|
||||||
|
|
@ -234,20 +234,18 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
||||||
|
|
||||||
static int impl_clear(struct spa_handle *handle)
|
static int impl_clear(struct spa_handle *handle)
|
||||||
{
|
{
|
||||||
auto impl = reinterpret_cast<struct impl *>(handle);
|
std::destroy_at(reinterpret_cast<impl *>(handle));
|
||||||
auto manager = impl->manager;
|
|
||||||
|
|
||||||
std::destroy_at(impl);
|
|
||||||
libcamera_manager_release(manager);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl::impl(spa_log *log, CameraManager *manager, std::shared_ptr<Camera> camera, std::string device_id)
|
impl::impl(spa_log *log,
|
||||||
|
std::shared_ptr<CameraManager> manager,
|
||||||
|
std::shared_ptr<Camera> camera,
|
||||||
|
std::string device_id)
|
||||||
: handle({ SPA_VERSION_HANDLE, impl_get_interface, impl_clear }),
|
: handle({ SPA_VERSION_HANDLE, impl_get_interface, impl_clear }),
|
||||||
log(log),
|
log(log),
|
||||||
device_id(std::move(device_id)),
|
device_id(std::move(device_id)),
|
||||||
manager(manager),
|
manager(std::move(manager)),
|
||||||
camera(std::move(camera))
|
camera(std::move(camera))
|
||||||
{
|
{
|
||||||
libcamera_log_topic_init(log);
|
libcamera_log_topic_init(log);
|
||||||
|
|
@ -282,9 +280,8 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
|
|
||||||
auto log = static_cast<spa_log *>(spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log));
|
auto log = static_cast<spa_log *>(spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log));
|
||||||
|
|
||||||
auto manager = libcamera_manager_acquire();
|
auto manager = libcamera_manager_acquire(res);
|
||||||
if (!manager) {
|
if (!manager) {
|
||||||
res = -errno;
|
|
||||||
spa_log_error(log, "can't start camera manager: %s", spa_strerror(res));
|
spa_log_error(log, "can't start camera manager: %s", spa_strerror(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -296,11 +293,10 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
auto camera = manager->get(device_id);
|
auto camera = manager->get(device_id);
|
||||||
if (!camera) {
|
if (!camera) {
|
||||||
spa_log_error(log, "unknown camera id %s", device_id.c_str());
|
spa_log_error(log, "unknown camera id %s", device_id.c_str());
|
||||||
libcamera_manager_release(manager);
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
new (handle) impl(log, manager, std::move(camera), std::move(device_id));
|
new (handle) impl(log, std::move(manager), std::move(camera), std::move(device_id));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,6 @@ using namespace libcamera;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct global {
|
|
||||||
int ref;
|
|
||||||
CameraManager *manager;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct global global;
|
|
||||||
|
|
||||||
struct device {
|
struct device {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
std::shared_ptr<Camera> camera;
|
std::shared_ptr<Camera> camera;
|
||||||
|
|
@ -79,7 +72,7 @@ typedef struct impl {
|
||||||
static constexpr uint64_t info_all = SPA_DEVICE_CHANGE_MASK_FLAGS | SPA_DEVICE_CHANGE_MASK_PROPS;
|
static constexpr uint64_t info_all = SPA_DEVICE_CHANGE_MASK_FLAGS | SPA_DEVICE_CHANGE_MASK_PROPS;
|
||||||
struct spa_device_info info = SPA_DEVICE_INFO_INIT();
|
struct spa_device_info info = SPA_DEVICE_INFO_INIT();
|
||||||
|
|
||||||
CameraManager *manager = nullptr;
|
std::shared_ptr<CameraManager> manager;
|
||||||
void addCamera(std::shared_ptr<libcamera::Camera> camera);
|
void addCamera(std::shared_ptr<libcamera::Camera> camera);
|
||||||
void removeCamera(std::shared_ptr<libcamera::Camera> camera);
|
void removeCamera(std::shared_ptr<libcamera::Camera> camera);
|
||||||
|
|
||||||
|
|
@ -91,35 +84,20 @@ typedef struct impl {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int libcamera_manager_release(CameraManager *manager)
|
static std::weak_ptr<CameraManager> global_manager;
|
||||||
|
|
||||||
|
std::shared_ptr<CameraManager> libcamera_manager_acquire(int& res)
|
||||||
{
|
{
|
||||||
if (global.manager != manager)
|
if (auto manager = global_manager.lock())
|
||||||
return -EINVAL;
|
return manager;
|
||||||
|
|
||||||
if (--global.ref == 0) {
|
auto manager = std::make_shared<CameraManager>();
|
||||||
global.manager->stop();
|
if ((res = manager->start()) < 0)
|
||||||
delete global.manager;
|
return {};
|
||||||
global.manager = NULL;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CameraManager *libcamera_manager_acquire(void)
|
global_manager = manager;
|
||||||
{
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (global.ref++ == 0) {
|
return manager;
|
||||||
global.manager = new CameraManager();
|
|
||||||
if (global.manager == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if ((res = global.manager->start()) < 0) {
|
|
||||||
libcamera_manager_release(global.manager);
|
|
||||||
errno = -res;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return global.manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct device *add_device(struct impl *impl, std::shared_ptr<Camera> camera)
|
static struct device *add_device(struct impl *impl, std::shared_ptr<Camera> camera)
|
||||||
|
|
@ -227,7 +205,7 @@ static int start_monitor(struct impl *impl)
|
||||||
|
|
||||||
static int stop_monitor(struct impl *impl)
|
static int stop_monitor(struct impl *impl)
|
||||||
{
|
{
|
||||||
if (impl->manager != NULL) {
|
if (impl->manager) {
|
||||||
impl->manager->cameraAdded.disconnect(impl, &Impl::addCamera);
|
impl->manager->cameraAdded.disconnect(impl, &Impl::addCamera);
|
||||||
impl->manager->cameraRemoved.disconnect(impl, &Impl::removeCamera);
|
impl->manager->cameraRemoved.disconnect(impl, &Impl::removeCamera);
|
||||||
}
|
}
|
||||||
|
|
@ -269,9 +247,7 @@ static void impl_hook_removed(struct spa_hook *hook)
|
||||||
struct impl *impl = (struct impl*)hook->priv;
|
struct impl *impl = (struct impl*)hook->priv;
|
||||||
if (spa_hook_list_is_empty(&impl->hooks)) {
|
if (spa_hook_list_is_empty(&impl->hooks)) {
|
||||||
stop_monitor(impl);
|
stop_monitor(impl);
|
||||||
if (impl->manager)
|
impl->manager.reset();
|
||||||
libcamera_manager_release(impl->manager);
|
|
||||||
impl->manager = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,9 +262,9 @@ impl_device_add_listener(void *object, struct spa_hook *listener,
|
||||||
spa_return_val_if_fail(impl != NULL, -EINVAL);
|
spa_return_val_if_fail(impl != NULL, -EINVAL);
|
||||||
spa_return_val_if_fail(events != NULL, -EINVAL);
|
spa_return_val_if_fail(events != NULL, -EINVAL);
|
||||||
|
|
||||||
impl->manager = libcamera_manager_acquire();
|
impl->manager = libcamera_manager_acquire(res);
|
||||||
if (impl->manager == NULL)
|
if (!impl->manager)
|
||||||
return -errno;
|
return res;
|
||||||
|
|
||||||
spa_hook_list_isolate(&impl->hooks, &save, listener, events, data);
|
spa_hook_list_isolate(&impl->hooks, &save, listener, events, data);
|
||||||
|
|
||||||
|
|
@ -333,14 +309,10 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
||||||
static int impl_clear(struct spa_handle *handle)
|
static int impl_clear(struct spa_handle *handle)
|
||||||
{
|
{
|
||||||
auto impl = reinterpret_cast<struct impl *>(handle);
|
auto impl = reinterpret_cast<struct impl *>(handle);
|
||||||
auto manager = impl->manager;
|
|
||||||
|
|
||||||
stop_monitor(impl);
|
stop_monitor(impl);
|
||||||
std::destroy_at(impl);
|
std::destroy_at(impl);
|
||||||
|
|
||||||
if (manager)
|
|
||||||
libcamera_manager_release(manager);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,8 @@
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <libcamera/camera_manager.h>
|
#include <libcamera/camera_manager.h>
|
||||||
|
|
||||||
#include <linux/media.h>
|
std::shared_ptr<libcamera::CameraManager> libcamera_manager_acquire(int& res);
|
||||||
|
|
||||||
using namespace libcamera;
|
|
||||||
|
|
||||||
CameraManager *libcamera_manager_acquire(void);
|
|
||||||
int libcamera_manager_release(CameraManager *manager);
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@
|
||||||
#include "libcamera.h"
|
#include "libcamera.h"
|
||||||
#include "libcamera-manager.hpp"
|
#include "libcamera-manager.hpp"
|
||||||
|
|
||||||
|
using namespace libcamera;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#define MAX_BUFFERS 32
|
#define MAX_BUFFERS 32
|
||||||
|
|
@ -160,7 +162,7 @@ typedef struct impl {
|
||||||
struct spa_io_position *position = nullptr;
|
struct spa_io_position *position = nullptr;
|
||||||
struct spa_io_clock *clock = nullptr;
|
struct spa_io_clock *clock = nullptr;
|
||||||
|
|
||||||
CameraManager *manager;
|
std::shared_ptr<CameraManager> manager;
|
||||||
std::shared_ptr<Camera> camera;
|
std::shared_ptr<Camera> camera;
|
||||||
|
|
||||||
FrameBufferAllocator *allocator = nullptr;
|
FrameBufferAllocator *allocator = nullptr;
|
||||||
|
|
@ -178,7 +180,7 @@ typedef struct impl {
|
||||||
bool acquired = false;
|
bool acquired = false;
|
||||||
|
|
||||||
impl(spa_log *log, spa_loop *data_loop, spa_system *system,
|
impl(spa_log *log, spa_loop *data_loop, spa_system *system,
|
||||||
CameraManager *manager, std::shared_ptr<Camera> camera, std::string device_id);
|
std::shared_ptr<CameraManager> manager, std::shared_ptr<Camera> camera, std::string device_id);
|
||||||
} Impl;
|
} Impl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -915,24 +917,19 @@ static int impl_get_interface(struct spa_handle *handle, const char *type, void
|
||||||
|
|
||||||
static int impl_clear(struct spa_handle *handle)
|
static int impl_clear(struct spa_handle *handle)
|
||||||
{
|
{
|
||||||
auto impl = reinterpret_cast<struct impl *>(handle);
|
std::destroy_at(reinterpret_cast<impl *>(handle));
|
||||||
auto manager = impl->manager;
|
|
||||||
|
|
||||||
std::destroy_at(impl);
|
|
||||||
libcamera_manager_release(manager);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl::impl(spa_log *log, spa_loop *data_loop, spa_system *system,
|
impl::impl(spa_log *log, spa_loop *data_loop, spa_system *system,
|
||||||
CameraManager *manager, std::shared_ptr<Camera> camera, std::string device_id)
|
std::shared_ptr<CameraManager> manager, std::shared_ptr<Camera> camera, std::string device_id)
|
||||||
: handle({ SPA_VERSION_HANDLE, impl_get_interface, impl_clear }),
|
: handle({ SPA_VERSION_HANDLE, impl_get_interface, impl_clear }),
|
||||||
log(log),
|
log(log),
|
||||||
data_loop(data_loop),
|
data_loop(data_loop),
|
||||||
system(system),
|
system(system),
|
||||||
device_id(std::move(device_id)),
|
device_id(std::move(device_id)),
|
||||||
out_ports{{this}},
|
out_ports{{this}},
|
||||||
manager(manager),
|
manager(std::move(manager)),
|
||||||
camera(std::move(camera))
|
camera(std::move(camera))
|
||||||
{
|
{
|
||||||
libcamera_log_topic_init(log);
|
libcamera_log_topic_init(log);
|
||||||
|
|
@ -987,9 +984,8 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto manager = libcamera_manager_acquire();
|
auto manager = libcamera_manager_acquire(res);
|
||||||
if (!manager) {
|
if (!manager) {
|
||||||
res = -errno;
|
|
||||||
spa_log_error(log, "can't start camera manager: %s", spa_strerror(res));
|
spa_log_error(log, "can't start camera manager: %s", spa_strerror(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -1001,12 +997,11 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
auto camera = manager->get(device_id);
|
auto camera = manager->get(device_id);
|
||||||
if (!camera) {
|
if (!camera) {
|
||||||
spa_log_error(log, "unknown camera id %s", device_id.c_str());
|
spa_log_error(log, "unknown camera id %s", device_id.c_str());
|
||||||
libcamera_manager_release(manager);
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
new (handle) impl(log, data_loop, system,
|
new (handle) impl(log, data_loop, system,
|
||||||
manager, std::move(camera), std::move(device_id));
|
std::move(manager), std::move(camera), std::move(device_id));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue