gstreamer: Fix concurrent access issues to CameraManager
It's not allowed to have multiple instances of CameraManager. This requirement is not easy for GStreamer were the device monitor and the camerasrc, or two camerasrc instances don't usually have any interaction between each other. Fix this by implementing a minimalist singleton around CameraManager constructor and start()/stop() operations. Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
parent
1ca5513396
commit
9c49106b97
4 changed files with 35 additions and 28 deletions
|
@ -178,3 +178,27 @@ gst_libcamera_resume_task(GstTask *task)
|
||||||
GST_TASK_SIGNAL(task);
|
GST_TASK_SIGNAL(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_LOCK_DEFINE_STATIC(cm_singleton_lock);
|
||||||
|
std::weak_ptr<CameraManager> cm_singleton_ptr;
|
||||||
|
|
||||||
|
std::shared_ptr<CameraManager>
|
||||||
|
gst_libcamera_get_camera_mananger(int &ret)
|
||||||
|
{
|
||||||
|
std::shared_ptr<CameraManager> cm;
|
||||||
|
|
||||||
|
G_LOCK(cm_singleton_lock);
|
||||||
|
|
||||||
|
cm = cm_singleton_ptr.lock();
|
||||||
|
if (!cm) {
|
||||||
|
cm = std::make_shared<CameraManager>();
|
||||||
|
cm_singleton_ptr = cm;
|
||||||
|
ret = cm->start();
|
||||||
|
} else {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_UNLOCK(cm_singleton_lock);
|
||||||
|
|
||||||
|
return cm;
|
||||||
|
}
|
||||||
|
|
|
@ -9,16 +9,18 @@
|
||||||
#ifndef __GST_LIBCAMERA_UTILS_H__
|
#ifndef __GST_LIBCAMERA_UTILS_H__
|
||||||
#define __GST_LIBCAMERA_UTILS_H__
|
#define __GST_LIBCAMERA_UTILS_H__
|
||||||
|
|
||||||
|
#include <libcamera/camera_manager.h>
|
||||||
|
#include <libcamera/stream.h>
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
#include <libcamera/stream.h>
|
|
||||||
|
|
||||||
GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);
|
GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);
|
||||||
GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg);
|
GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg);
|
||||||
void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,
|
void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,
|
||||||
GstCaps *caps);
|
GstCaps *caps);
|
||||||
void gst_libcamera_resume_task(GstTask *task);
|
void gst_libcamera_resume_task(GstTask *task);
|
||||||
|
std::shared_ptr<libcamera::CameraManager> gst_libcamera_get_camera_mananger(int &ret);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class GLibLocker
|
* \class GLibLocker
|
||||||
|
|
|
@ -158,7 +158,6 @@ gst_libcamera_device_new(const std::shared_ptr<Camera> &camera)
|
||||||
|
|
||||||
struct _GstLibcameraProvider {
|
struct _GstLibcameraProvider {
|
||||||
GstDeviceProvider parent;
|
GstDeviceProvider parent;
|
||||||
CameraManager *cm;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE(GstLibcameraProvider, gst_libcamera_provider,
|
G_DEFINE_TYPE_WITH_CODE(GstLibcameraProvider, gst_libcamera_provider,
|
||||||
|
@ -170,7 +169,7 @@ static GList *
|
||||||
gst_libcamera_provider_probe(GstDeviceProvider *provider)
|
gst_libcamera_provider_probe(GstDeviceProvider *provider)
|
||||||
{
|
{
|
||||||
GstLibcameraProvider *self = GST_LIBCAMERA_PROVIDER(provider);
|
GstLibcameraProvider *self = GST_LIBCAMERA_PROVIDER(provider);
|
||||||
CameraManager *cm = self->cm;
|
std::shared_ptr<CameraManager> cm;
|
||||||
GList *devices = nullptr;
|
GList *devices = nullptr;
|
||||||
gint ret;
|
gint ret;
|
||||||
|
|
||||||
|
@ -181,7 +180,7 @@ gst_libcamera_provider_probe(GstDeviceProvider *provider)
|
||||||
* gains monitoring support. Meanwhile we need to cycle start()/stop()
|
* gains monitoring support. Meanwhile we need to cycle start()/stop()
|
||||||
* to ensure every probe() calls return the latest list.
|
* to ensure every probe() calls return the latest list.
|
||||||
*/
|
*/
|
||||||
ret = cm->start();
|
cm = gst_libcamera_get_camera_mananger(ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
GST_ERROR_OBJECT(self, "Failed to retrieve device list: %s",
|
GST_ERROR_OBJECT(self, "Failed to retrieve device list: %s",
|
||||||
g_strerror(-ret));
|
g_strerror(-ret));
|
||||||
|
@ -194,8 +193,6 @@ gst_libcamera_provider_probe(GstDeviceProvider *provider)
|
||||||
g_object_ref_sink(gst_libcamera_device_new(camera)));
|
g_object_ref_sink(gst_libcamera_device_new(camera)));
|
||||||
}
|
}
|
||||||
|
|
||||||
cm->stop();
|
|
||||||
|
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,31 +201,16 @@ gst_libcamera_provider_init(GstLibcameraProvider *self)
|
||||||
{
|
{
|
||||||
GstDeviceProvider *provider = GST_DEVICE_PROVIDER(self);
|
GstDeviceProvider *provider = GST_DEVICE_PROVIDER(self);
|
||||||
|
|
||||||
self->cm = new CameraManager();
|
|
||||||
|
|
||||||
/* Avoid devices being duplicated. */
|
/* Avoid devices being duplicated. */
|
||||||
gst_device_provider_hide_provider(provider, "v4l2deviceprovider");
|
gst_device_provider_hide_provider(provider, "v4l2deviceprovider");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_libcamera_provider_finalize(GObject *object)
|
|
||||||
{
|
|
||||||
GstLibcameraProvider *self = GST_LIBCAMERA_PROVIDER(object);
|
|
||||||
gpointer klass = gst_libcamera_provider_parent_class;
|
|
||||||
|
|
||||||
delete self->cm;
|
|
||||||
|
|
||||||
return G_OBJECT_CLASS(klass)->finalize(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_libcamera_provider_class_init(GstLibcameraProviderClass *klass)
|
gst_libcamera_provider_class_init(GstLibcameraProviderClass *klass)
|
||||||
{
|
{
|
||||||
GstDeviceProviderClass *provider_class = GST_DEVICE_PROVIDER_CLASS(klass);
|
GstDeviceProviderClass *provider_class = GST_DEVICE_PROVIDER_CLASS(klass);
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
||||||
|
|
||||||
provider_class->probe = gst_libcamera_provider_probe;
|
provider_class->probe = gst_libcamera_provider_probe;
|
||||||
object_class->finalize = gst_libcamera_provider_finalize;
|
|
||||||
|
|
||||||
gst_device_provider_class_set_metadata(provider_class,
|
gst_device_provider_class_set_metadata(provider_class,
|
||||||
"libcamera Device Provider",
|
"libcamera Device Provider",
|
||||||
|
|
|
@ -108,7 +108,7 @@ GstBuffer *RequestWrap::detachBuffer(Stream *stream)
|
||||||
struct GstLibcameraSrcState {
|
struct GstLibcameraSrcState {
|
||||||
GstLibcameraSrc *src_;
|
GstLibcameraSrc *src_;
|
||||||
|
|
||||||
std::unique_ptr<CameraManager> cm_;
|
std::shared_ptr<CameraManager> cm_;
|
||||||
std::shared_ptr<Camera> cam_;
|
std::shared_ptr<Camera> cam_;
|
||||||
std::unique_ptr<CameraConfiguration> config_;
|
std::unique_ptr<CameraConfiguration> config_;
|
||||||
std::vector<GstPad *> srcpads_;
|
std::vector<GstPad *> srcpads_;
|
||||||
|
@ -202,13 +202,13 @@ GstLibcameraSrcState::requestCompleted(Request *request)
|
||||||
static bool
|
static bool
|
||||||
gst_libcamera_src_open(GstLibcameraSrc *self)
|
gst_libcamera_src_open(GstLibcameraSrc *self)
|
||||||
{
|
{
|
||||||
std::unique_ptr<CameraManager> cm = std::make_unique<CameraManager>();
|
std::shared_ptr<CameraManager> cm;
|
||||||
std::shared_ptr<Camera> cam;
|
std::shared_ptr<Camera> cam;
|
||||||
gint ret = 0;
|
gint ret;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT(self, "Opening camera device ...");
|
GST_DEBUG_OBJECT(self, "Opening camera device ...");
|
||||||
|
|
||||||
ret = cm->start();
|
cm = gst_libcamera_get_camera_mananger(ret);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
GST_ELEMENT_ERROR(self, LIBRARY, INIT,
|
GST_ELEMENT_ERROR(self, LIBRARY, INIT,
|
||||||
("Failed listing cameras."),
|
("Failed listing cameras."),
|
||||||
|
@ -254,7 +254,7 @@ gst_libcamera_src_open(GstLibcameraSrc *self)
|
||||||
cam->requestCompleted.connect(self->state, &GstLibcameraSrcState::requestCompleted);
|
cam->requestCompleted.connect(self->state, &GstLibcameraSrcState::requestCompleted);
|
||||||
|
|
||||||
/* No need to lock here, we didn't start our threads yet. */
|
/* No need to lock here, we didn't start our threads yet. */
|
||||||
self->state->cm_ = std::move(cm);
|
self->state->cm_ = cm;
|
||||||
self->state->cam_ = cam;
|
self->state->cam_ = cam;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -521,7 +521,6 @@ gst_libcamera_src_close(GstLibcameraSrc *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
state->cam_.reset();
|
state->cam_.reset();
|
||||||
state->cm_->stop();
|
|
||||||
state->cm_.reset();
|
state->cm_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue