[libcamera-devel] [PATCH 1/1] pipeline: rkisp1: Implement Bayer formats support

Florian Sylvestre fsylvestre at baylibre.com
Fri Sep 23 14:55:46 CEST 2022


Implement raw mode for RkISP1:
- The ISP resizer doesn't support raw formats, so when in raw mode we force the
output resolution to be the same as the sensor one.
- In raw mode, the ISP is bypassed, so we never get statistics buffers.
This means that the IPA is never instructed to set the controls nor the
metadata.
Add a completeRaw() function to the IPA for the purpose of instructing the IPA
to set controls and metadata when a frame is ready, as opposed to when the
statistics are ready.
We also need to skip queueing the stats buffer when in raw mode to prevent the
statistics bufferReady slot to be triggered at stream off.

Signed-off-by: Florian Sylvestre <fsylvestre at baylibre.com>
Signed-off-by: Paul Elder <paul.elder at ideasonboard.com>
---
 include/libcamera/ipa/rkisp1.mojom            |  1 +
 src/ipa/rkisp1/rkisp1.cpp                     | 10 +++
 src/libcamera/pipeline/rkisp1/rkisp1.cpp      | 63 ++++++++++++++++++-
 src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 51 ++++++++++++++-
 4 files changed, 120 insertions(+), 5 deletions(-)

diff --git a/include/libcamera/ipa/rkisp1.mojom b/include/libcamera/ipa/rkisp1.mojom
index eaf3955e..931ef357 100644
--- a/include/libcamera/ipa/rkisp1.mojom
+++ b/include/libcamera/ipa/rkisp1.mojom
@@ -27,6 +27,7 @@ interface IPARkISP1Interface {
 	[async] fillParamsBuffer(uint32 frame, uint32 bufferId);
 	[async] processStatsBuffer(uint32 frame, uint32 bufferId,
 				   libcamera.ControlList sensorControls);
+	[async] completeRaw(uint32 frame);
 };
 
 interface IPARkISP1EventInterface {
diff --git a/src/ipa/rkisp1/rkisp1.cpp b/src/ipa/rkisp1/rkisp1.cpp
index 61a091e6..4c784e8f 100644
--- a/src/ipa/rkisp1/rkisp1.cpp
+++ b/src/ipa/rkisp1/rkisp1.cpp
@@ -63,6 +63,7 @@ public:
 	void fillParamsBuffer(const uint32_t frame, const uint32_t bufferId) override;
 	void processStatsBuffer(const uint32_t frame, const uint32_t bufferId,
 				const ControlList &sensorControls) override;
+	void completeRaw(const uint32_t frame) override;
 
 protected:
 	std::string logPrefix() const override;
@@ -352,6 +353,15 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId
 	prepareMetadata(frame, aeState);
 }
 
+void IPARkISP1::completeRaw(const uint32_t frame)
+{
+	unsigned int aeState = 0;
+
+	setControls(frame);
+
+	prepareMetadata(frame, aeState);
+}
+
 void IPARkISP1::setControls(unsigned int frame)
 {
 	RkISP1FrameContext &frameContext = context_.frameContexts.get(frame);
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 25fbf9f1..bade024d 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -182,6 +182,7 @@ private:
 	std::unique_ptr<V4L2Subdevice> csi_;
 
 	bool hasSelfPath_;
+	bool isRaw_;
 
 	RkISP1MainPath mainPath_;
 	RkISP1SelfPath selfPath_;
@@ -363,7 +364,9 @@ void RkISP1CameraData::paramFilled(unsigned int frame)
 		return;
 
 	pipe->param_->queueBuffer(info->paramBuffer);
-	pipe->stat_->queueBuffer(info->statBuffer);
+
+	if (!pipe->isRaw_)
+		pipe->stat_->queueBuffer(info->statBuffer);
 
 	if (info->mainPathBuffer)
 		mainPath_->queueBuffer(info->mainPathBuffer);
@@ -413,6 +416,21 @@ bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg)
 	return true;
 }
 
+std::map<PixelFormat, uint32_t> rawFormats = {
+	{ formats::SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8 },
+	{ formats::SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8 },
+	{ formats::SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8 },
+	{ formats::SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8 },
+	{ formats::SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10 },
+	{ formats::SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10 },
+	{ formats::SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10 },
+	{ formats::SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10 },
+	{ formats::SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12 },
+	{ formats::SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12 },
+	{ formats::SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12 },
+	{ formats::SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12 },
+};
+
 CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 {
 	const CameraSensor *sensor = data_->sensor_.get();
@@ -504,8 +522,23 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 
 	/* Select the sensor format. */
 	Size maxSize;
-	for (const StreamConfiguration &cfg : config_)
+	PixelFormat rawFormat;
+	bool hasRawFormat = false;
+	for (StreamConfiguration &cfg : config_) {
+		if (PixelFormatInfo::info(cfg.pixelFormat).colourEncoding ==
+		    PixelFormatInfo::ColourEncodingRAW) {
+			hasRawFormat = true;
+			rawFormat = cfg.pixelFormat;
+
+			/* Raw format cannot be resized by ISP. */
+			if (cfg.size != sensor->resolution()) {
+				cfg.size = sensor->resolution();
+				status = Adjusted;
+			}
+		}
+
 		maxSize = std::max(maxSize, cfg.size);
+	}
 
 	sensorFormat_ = sensor->getFormat({ MEDIA_BUS_FMT_SBGGR12_1X12,
 					    MEDIA_BUS_FMT_SGBRG12_1X12,
@@ -520,6 +553,13 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 					    MEDIA_BUS_FMT_SGRBG8_1X8,
 					    MEDIA_BUS_FMT_SRGGB8_1X8 },
 					  maxSize);
+
+	if (hasRawFormat) {
+		auto mbus = rawFormats.find(rawFormat);
+		if (mbus != rawFormats.end())
+			sensorFormat_ = sensor->getFormat({ mbus->second }, maxSize);
+	}
+
 	if (sensorFormat_.size.isNull())
 		sensorFormat_.size = sensor->resolution();
 
@@ -659,8 +699,14 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
 		<< "ISP input pad configured with " << format
 		<< " crop " << rect;
 
+	const PixelFormat &streamFormat = config->at(0).pixelFormat;
+	const PixelFormatInfo &info = PixelFormatInfo::info(streamFormat);
+	isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
+
 	/* YUYV8_2X8 is required on the ISP source path pad for YUV output. */
-	format.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
+	if (!isRaw_)
+		format.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
+
 	LOG(RkISP1, Debug)
 		<< "Configuring ISP output pad with " << format
 		<< " crop " << rect;
@@ -1152,6 +1198,17 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer)
 	request->metadata().set(controls::SensorTimestamp,
 				buffer->metadata().timestamp);
 
+	if (isRaw_) {
+		ASSERT(activeCamera_);
+		RkISP1CameraData *data = cameraData(activeCamera_);
+
+		RkISP1FrameInfo *info = data->frameInfo_.find(buffer);
+		if (!info)
+			return;
+
+		data->ipa_->completeRaw(info->frame);
+	}
+
 	completeBuffer(request, buffer);
 	tryCompleteRequest(request);
 }
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index 2d38f0fb..0a33d9ed 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -132,6 +132,42 @@ int RkISP1Path::configure(const StreamConfiguration &config,
 	case formats::NV21:
 		ispFormat.mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8;
 		break;
+	case formats::SRGGB8:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8;
+		break;
+	case formats::SGRBG8:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8;
+		break;
+	case formats::SGBRG8:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8;
+		break;
+	case formats::SBGGR8:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8;
+		break;
+	case formats::SRGGB10:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10;
+		break;
+	case formats::SGRBG10:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10;
+		break;
+	case formats::SGBRG10:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10;
+		break;
+	case formats::SBGGR10:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10;
+		break;
+	case formats::SRGGB12:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12;
+		break;
+	case formats::SGRBG12:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12;
+		break;
+	case formats::SGBRG12:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12;
+		break;
+	case formats::SBGGR12:
+		ispFormat.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12;
+		break;
 	default:
 		ispFormat.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
 		break;
@@ -207,14 +243,25 @@ void RkISP1Path::stop()
 namespace {
 constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 };
 constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 };
-constexpr std::array<PixelFormat, 6> RKISP1_RSZ_MP_FORMATS{
+constexpr std::array<PixelFormat, 18> RKISP1_RSZ_MP_FORMATS{
 	formats::YUYV,
 	formats::NV16,
 	formats::NV61,
 	formats::NV21,
 	formats::NV12,
 	formats::R8,
-	/* \todo Add support for RAW formats. */
+	formats::SRGGB8,
+	formats::SGRBG8,
+	formats::SGBRG8,
+	formats::SBGGR8,
+	formats::SRGGB10,
+	formats::SGRBG10,
+	formats::SGBRG10,
+	formats::SBGGR10,
+	formats::SRGGB12,
+	formats::SGRBG12,
+	formats::SGBRG12,
+	formats::SBGGR12,
 };
 
 constexpr Size RKISP1_RSZ_SP_SRC_MIN{ 32, 16 };
-- 
2.34.1



More information about the libcamera-devel mailing list