libcamera: software_isp: Handle signals in the proper thread

inputBufferReady ready signal in the simple pipeline is handled in the
pipeline handler thread.  outputBufferReady and ispStatsReady signals
should be handled there too.

Rather than relying on the user of the SoftwareIsp instance, let
SoftwareIsp inherits Object.  SoftwareIsp serves as a signal proxy, the
signals above are emitted from signal handlers.  This means that if
SoftwareIsp inherits Object then the slots are invoked in SoftwareIsp
thread.  Which is the camera manager thread because the SoftwareIsp
instance is created there.

Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Milan Zamazal 2025-01-31 20:59:28 +01:00 committed by Kieran Bingham
parent 8aef7b4dfb
commit 9bc8b6a573
2 changed files with 3 additions and 16 deletions

View file

@ -18,6 +18,7 @@
#include <libcamera/base/class.h>
#include <libcamera/base/log.h>
#include <libcamera/base/object.h>
#include <libcamera/base/signal.h>
#include <libcamera/base/thread.h>
@ -43,7 +44,7 @@ struct StreamConfiguration;
LOG_DECLARE_CATEGORY(SoftwareIsp)
class SoftwareIsp
class SoftwareIsp : public Object
{
public:
SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,

View file

@ -537,21 +537,7 @@ int SimpleCameraData::init()
<< "Failed to create software ISP, disabling software debayering";
swIsp_.reset();
} else {
/*
* The inputBufferReady signal is emitted from the soft ISP thread,
* and needs to be handled in the pipeline handler thread. Signals
* implement queued delivery, but this works transparently only if
* the receiver is bound to the target thread. As the
* SimpleCameraData class doesn't inherit from the Object class, it
* is not bound to any thread, and the signal would be delivered
* synchronously. Instead, connect the signal to a lambda function
* bound explicitly to the pipe, which is bound to the pipeline
* handler thread. The function then simply forwards the call to
* conversionInputDone().
*/
swIsp_->inputBufferReady.connect(pipe, [this](FrameBuffer *buffer) {
this->conversionInputDone(buffer);
});
swIsp_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone);
swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady);
swIsp_->setSensorControls.connect(this, &SimpleCameraData::setSensorControls);