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