[libcamera-devel] [RFC PATCH v2 7/7] libcamera: pipeline: simple: enable use of Soft ISP and Soft IPA
Andrey Konovalov
andrey.konovalov at linaro.org
Tue Dec 12 12:50:46 CET 2023
To enable the Soft ISP and Soft IPA for simple pipeline handler
configure the build with:
-Dpipelines=simple/linaro -Dipas=simple/linaro
If the pipeline uses Converter, Soft ISP and Soft IPA aren't
available.
Configuring the build with just:
-Dpipelines=simple
makes it to work like before - Soft ISP and Soft IPA aren't used.
Signed-off-by: Andrey Konovalov <andrey.konovalov at linaro.org>
---
src/libcamera/pipeline/simple/simple.cpp | 106 ++++++++++++++++++-----
1 file changed, 83 insertions(+), 23 deletions(-)
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 878794f6..276e9d72 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -34,10 +34,10 @@
#include "libcamera/internal/device_enumerator.h"
#include "libcamera/internal/media_device.h"
#include "libcamera/internal/pipeline_handler.h"
+#include "libcamera/internal/software_isp.h"
#include "libcamera/internal/v4l2_subdevice.h"
#include "libcamera/internal/v4l2_videodevice.h"
-
namespace libcamera {
LOG_DEFINE_CATEGORY(SimplePipeline)
@@ -274,6 +274,7 @@ public:
bool useConversion_;
std::unique_ptr<Converter> converter_;
+ std::unique_ptr<SoftwareIsp> swIsp_;
private:
void tryPipeline(unsigned int code, const Size &size);
@@ -281,6 +282,9 @@ private:
void conversionInputDone(FrameBuffer *buffer);
void conversionOutputDone(FrameBuffer *buffer);
+
+ void ispStatsReady(int dummy);
+ void setSensorControls(const ControlList &sensorControls);
};
class SimpleCameraConfiguration : public CameraConfiguration
@@ -509,6 +513,25 @@ int SimpleCameraData::init()
}
}
+ /*
+ * Create Linaro's implementation of SoftwareIsp unconditionally if no converter is used
+ * - to be revisited
+ */
+ if (!converter_) {
+ swIsp_ = SoftwareIspFactoryBase::create(pipe, sensor_->controls());
+ if (!swIsp_) {
+ LOG(SimplePipeline, Warning)
+ << "Failed to create software ISP, disabling software debayering";
+ swIsp_.reset();
+ } else {
+ swIsp_->inputBufferReady.connect(this, &SimpleCameraData::conversionInputDone);
+ swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
+ swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady);
+
+ swIsp_->getSignalSetSensorControls().connect(this, &SimpleCameraData::setSensorControls);
+ }
+ }
+
video_ = pipe->video(entities_.back().entity);
ASSERT(video_);
@@ -599,12 +622,15 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size)
config.captureFormat = pixelFormat;
config.captureSize = format.size;
- if (!converter_) {
- config.outputFormats = { pixelFormat };
- config.outputSizes = config.captureSize;
- } else {
+ if (converter_) {
config.outputFormats = converter_->formats(pixelFormat);
config.outputSizes = converter_->sizes(format.size);
+ } else if (swIsp_) {
+ config.outputFormats = swIsp_->formats(pixelFormat);
+ config.outputSizes = swIsp_->sizes(pixelFormat, format.size);
+ } else {
+ config.outputFormats = { pixelFormat };
+ config.outputSizes = config.captureSize;
}
configs_.push_back(config);
@@ -750,9 +776,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
}
/*
- * The converter is in use. Requeue the internal buffer for
- * capture (unless the stream is being stopped), and complete
- * the request with all the user-facing buffers.
+ * The converter or Software ISP is in use. Requeue the internal
+ * buffer for capture (unless the stream is being stopped), and
+ * complete the request with all the user-facing buffers.
*/
if (buffer->metadata().status != FrameMetadata::FrameCancelled)
video_->queueBuffer(buffer);
@@ -798,9 +824,9 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
buffer->metadata().timestamp);
/*
- * Queue the captured and the request buffer to the converter if format
- * conversion is needed. If there's no queued request, just requeue the
- * captured buffer for capture.
+ * Queue the captured and the request buffer to the converter or Software
+ * ISP if format conversion is needed. If there's no queued request, just
+ * requeue the captured buffer for capture.
*/
if (useConversion_) {
if (conversionQueue_.empty()) {
@@ -808,7 +834,11 @@ void SimpleCameraData::bufferReady(FrameBuffer *buffer)
return;
}
- converter_->queueBuffers(buffer, conversionQueue_.front());
+ if (converter_)
+ converter_->queueBuffers(buffer, conversionQueue_.front());
+ else
+ swIsp_->queueBuffers(buffer, conversionQueue_.front());
+
conversionQueue_.pop();
return;
}
@@ -834,6 +864,18 @@ void SimpleCameraData::conversionOutputDone(FrameBuffer *buffer)
pipe->completeRequest(request);
}
+void SimpleCameraData::ispStatsReady([[maybe_unused]] int dummy)
+{
+ swIsp_->processStats(sensor_->getControls({ V4L2_CID_ANALOGUE_GAIN,
+ V4L2_CID_EXPOSURE }));
+}
+
+void SimpleCameraData::setSensorControls(const ControlList &sensorControls)
+{
+ ControlList ctrls(sensorControls);
+ sensor_->setControls(&ctrls);
+}
+
/* Retrieve all source pads connected to a sink pad through active routes. */
std::vector<const MediaPad *> SimpleCameraData::routedSourcePads(MediaPad *sink)
{
@@ -1013,8 +1055,10 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate()
/* Set the stride, frameSize and bufferCount. */
if (needConversion_) {
std::tie(cfg.stride, cfg.frameSize) =
- data_->converter_->strideAndFrameSize(cfg.pixelFormat,
- cfg.size);
+ (data_->converter_) ? data_->converter_->strideAndFrameSize(cfg.pixelFormat,
+ cfg.size)
+ : data_->swIsp_->strideAndFrameSize(cfg.pixelFormat,
+ cfg.size);
if (cfg.stride == 0)
return Invalid;
} else {
@@ -1177,7 +1221,8 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)
inputCfg.stride = captureFormat.planes[0].bpl;
inputCfg.bufferCount = kNumInternalBuffers;
- return data->converter_->configure(inputCfg, outputCfgs);
+ return (data->converter_) ? data->converter_->configure(inputCfg, outputCfgs)
+ : data->swIsp_->configure(inputCfg, outputCfgs);
}
int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
@@ -1191,8 +1236,10 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
* whether the converter is used or not.
*/
if (data->useConversion_)
- return data->converter_->exportBuffers(data->streamIndex(stream),
- count, buffers);
+ return (data->converter_) ? data->converter_->exportBuffers(data->streamIndex(stream),
+ count, buffers)
+ : data->swIsp_->exportBuffers(data->streamIndex(stream),
+ count, buffers);
else
return data->video_->exportBuffers(count, buffers);
}
@@ -1237,10 +1284,18 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL
}
if (data->useConversion_) {
- ret = data->converter_->start();
- if (ret < 0) {
- stop(camera);
- return ret;
+ if (data->converter_) {
+ ret = data->converter_->start();
+ if (ret < 0) {
+ stop(camera);
+ return ret;
+ }
+ } else if (data->swIsp_) {
+ ret = data->swIsp_->start();
+ if (ret < 0) {
+ stop(camera);
+ return ret;
+ }
}
/* Queue all internal buffers for capture. */
@@ -1256,8 +1311,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera)
SimpleCameraData *data = cameraData(camera);
V4L2VideoDevice *video = data->video_;
- if (data->useConversion_)
- data->converter_->stop();
+ if (data->useConversion_) {
+ if (data->converter_)
+ data->converter_->stop();
+ else if (data->swIsp_) {
+ data->swIsp_->stop();
+ }
+ }
video->streamOff();
video->releaseBuffers();
--
2.34.1
More information about the libcamera-devel
mailing list