af9a8d372b
This code adds support for the ipu6 webcams via libcamera, based on the work in https://copr.fedorainfracloud.org/coprs/jwrdegoede/ipu6-softisp/. It's supposed to be included in your NixOS configuration imports. Change-Id: Ifb71999ad61161fa23506b97cb449f73fb1270e3 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10709 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de> Autosubmit: flokli <flokli@flokli.de>
243 lines
8.2 KiB
Diff
243 lines
8.2 KiB
Diff
From ad61052d9aea1f1af6aaef9ce7e5d447c595187c Mon Sep 17 00:00:00 2001
|
|
From: Andrey Konovalov <andrey.konovalov@linaro.org>
|
|
Date: Tue, 12 Dec 2023 02:02:37 +0300
|
|
Subject: [PATCH 15/25] libcamera: pipeline: simple: enable use of Soft ISP and
|
|
Soft IPA
|
|
|
|
To enable the Simple Soft ISP and Soft IPA for simple pipeline handler
|
|
configure the build with:
|
|
-Dpipelines=simple/simple -Dipas=simple/simple
|
|
|
|
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@linaro.org>
|
|
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
|
Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
|
|
Tested-by: Pavel Machek <pavel@ucw.cz>
|
|
---
|
|
src/libcamera/pipeline/simple/simple.cpp | 111 ++++++++++++++++++-----
|
|
1 file changed, 89 insertions(+), 22 deletions(-)
|
|
|
|
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
|
|
index fa298746..c76510c2 100644
|
|
--- a/src/libcamera/pipeline/simple/simple.cpp
|
|
+++ b/src/libcamera/pipeline/simple/simple.cpp
|
|
@@ -34,6 +34,7 @@
|
|
#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"
|
|
|
|
@@ -274,6 +275,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 +283,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 +514,25 @@ int SimpleCameraData::init()
|
|
}
|
|
}
|
|
|
|
+ /*
|
|
+ * Create 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 +623,20 @@ 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);
|
|
+ if (config.outputFormats.empty()) {
|
|
+ /* Do not use swIsp for unsupported pixelFormat's */
|
|
+ config.outputFormats = { pixelFormat };
|
|
+ config.outputSizes = config.captureSize;
|
|
+ }
|
|
+ } else {
|
|
+ config.outputFormats = { pixelFormat };
|
|
+ config.outputSizes = config.captureSize;
|
|
}
|
|
|
|
configs_.push_back(config);
|
|
@@ -750,9 +782,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 +830,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 +840,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 +870,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)
|
|
{
|
|
@@ -1016,8 +1064,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 {
|
|
@@ -1180,7 +1230,9 @@ 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,
|
|
+ data->sensor_->controls());
|
|
}
|
|
|
|
int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream,
|
|
@@ -1194,8 +1246,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);
|
|
}
|
|
@@ -1240,10 +1294,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. */
|
|
@@ -1259,8 +1321,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.43.0
|
|
|