about summary refs log tree commit diff
path: root/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch
diff options
context:
space:
mode:
Diffstat (limited to 'users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch')
-rw-r--r--users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch302
1 files changed, 302 insertions, 0 deletions
diff --git a/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch b/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch
new file mode 100644
index 0000000000..378a43604f
--- /dev/null
+++ b/users/flokli/ipu6-softisp/libcamera/0012-libcamera-pipeline-simple-enable-use-of-Soft-ISP-and.patch
@@ -0,0 +1,302 @@
+From d64b0fca22ef25b8a14d7fc97dfab64eb1c4f21a Mon Sep 17 00:00:00 2001
+From: Andrey Konovalov <andrey.konovalov@linaro.org>
+Date: Mon, 11 Mar 2024 15:15:16 +0100
+Subject: [PATCH 12/21] 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 -Dipas=simple
+
+Also using the Soft ISP for the particular hardware platform must
+be enabled in the supportedDevices[] table.
+
+If the pipeline uses Converter, Soft ISP and Soft IPA aren't
+available.
+
+Tested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # sc8280xp Lenovo x13s
+Tested-by: Pavel Machek <pavel@ucw.cz>
+Reviewed-by: Pavel Machek <pavel@ucw.cz>
+Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+---
+ src/libcamera/pipeline/simple/simple.cpp | 137 ++++++++++++++++++-----
+ 1 file changed, 109 insertions(+), 28 deletions(-)
+
+diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
+index 78854ef8..c3ebb7b7 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/software_isp.h"
+ #include "libcamera/internal/v4l2_subdevice.h"
+ #include "libcamera/internal/v4l2_videodevice.h"
+ 
+@@ -185,17 +186,22 @@ struct SimplePipelineInfo {
+ 	 * and the number of streams it supports.
+ 	 */
+ 	std::vector<std::pair<const char *, unsigned int>> converters;
++	/*
++	 * Using Software ISP is to be enabled per driver.
++	 * The Software ISP can't be used together with the converters.
++	 */
++	bool swIspEnabled;
+ };
+ 
+ namespace {
+ 
+ static const SimplePipelineInfo supportedDevices[] = {
+-	{ "dcmipp", {} },
+-	{ "imx7-csi", { { "pxp", 1 } } },
+-	{ "j721e-csi2rx", {} },
+-	{ "mxc-isi", {} },
+-	{ "qcom-camss", {} },
+-	{ "sun6i-csi", {} },
++	{ "dcmipp", {}, false },
++	{ "imx7-csi", { { "pxp", 1 } }, false },
++	{ "j721e-csi2rx", {}, false },
++	{ "mxc-isi", {}, false },
++	{ "qcom-camss", {}, true },
++	{ "sun6i-csi", {}, false },
+ };
+ 
+ } /* namespace */
+@@ -274,6 +280,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 +288,9 @@ private:
+ 
+ 	void conversionInputDone(FrameBuffer *buffer);
+ 	void conversionOutputDone(FrameBuffer *buffer);
++
++	void ispStatsReady(int dummy);
++	void setSensorControls(const ControlList &sensorControls);
+ };
+ 
+ class SimpleCameraConfiguration : public CameraConfiguration
+@@ -332,6 +342,7 @@ public:
+ 	V4L2VideoDevice *video(const MediaEntity *entity);
+ 	V4L2Subdevice *subdev(const MediaEntity *entity);
+ 	MediaDevice *converter() { return converter_; }
++	bool swIspEnabled() { return swIspEnabled_; }
+ 
+ protected:
+ 	int queueRequestDevice(Camera *camera, Request *request) override;
+@@ -360,6 +371,7 @@ private:
+ 	std::map<const MediaEntity *, EntityData> entities_;
+ 
+ 	MediaDevice *converter_;
++	bool swIspEnabled_;
+ };
+ 
+ /* -----------------------------------------------------------------------------
+@@ -509,6 +521,29 @@ int SimpleCameraData::init()
+ 		}
+ 	}
+ 
++	/*
++	 * Instantiate Soft ISP if this is enabled for the given driver and no converter is used.
++	 */
++	if (!converter_ && pipe->swIspEnabled()) {
++		swIsp_ = std::make_unique<SoftwareIsp>(pipe, sensor_->controls());
++		if (!swIsp_->isValid()) {
++			LOG(SimplePipeline, Warning)
++				<< "Failed to create software ISP, disabling software debayering";
++			swIsp_.reset();
++		} else {
++			/*
++			 * \todo explain why SimpleCameraData::conversionInputDone() can't be directly
++			 * connected to inputBufferReady signal.
++			 */
++			swIsp_->inputBufferReady.connect(pipe, [this](FrameBuffer *buffer) {
++				this->conversionInputDone(buffer);
++			});
++			swIsp_->outputBufferReady.connect(this, &SimpleCameraData::conversionOutputDone);
++			swIsp_->ispStatsReady.connect(this, &SimpleCameraData::ispStatsReady);
++			swIsp_->setSensorControls.connect(this, &SimpleCameraData::setSensorControls);
++		}
++	}
++
+ 	video_ = pipe->video(entities_.back().entity);
+ 	ASSERT(video_);
+ 
+@@ -599,12 +634,21 @@ void SimpleCameraData::tryPipeline(unsigned int code, const Size &size)
+ 		config.captureFormat = pixelFormat;
+ 		config.captureSize = format.size;
+ 
+-		if (!converter_) {
++
++		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;
+-		} else {
+-			config.outputFormats = converter_->formats(pixelFormat);
+-			config.outputSizes = converter_->sizes(format.size);
+ 		}
+ 
+ 		configs_.push_back(config);
+@@ -750,9 +794,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 +842,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 +852,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 +882,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)
+ {
+@@ -1046,8 +1106,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 {
+@@ -1210,7 +1272,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,
+@@ -1224,8 +1288,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);
+ }
+@@ -1270,10 +1336,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. */
+@@ -1289,8 +1363,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();
+@@ -1452,6 +1531,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
+ 		}
+ 	}
+ 
++  swIspEnabled_ = info->swIspEnabled;
++
+ 	/* Locate the sensors. */
+ 	std::vector<MediaEntity *> sensors = locateSensors();
+ 	if (sensors.empty()) {
+-- 
+2.43.2
+