[libcamera-devel,v2,1/1] pipeline: rkisp1: Implement Bayer formats support
diff mbox series

Message ID 20221003143638.604343-2-fsylvestre@baylibre.com
State New
Headers show
Series
  • Add Bayer format support for RkISP1
Related show

Commit Message

Florian Sylvestre Oct. 3, 2022, 2:36 p.m. UTC
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@baylibre.com>
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
 include/libcamera/ipa/rkisp1.mojom            |  1 +
 src/ipa/rkisp1/rkisp1.cpp                     | 10 +++
 src/libcamera/pipeline/rkisp1/rkisp1.cpp      | 64 ++++++++++++++++++-
 src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 44 ++++++++++---
 4 files changed, 106 insertions(+), 13 deletions(-)

Patch
diff mbox series

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 1335e3d1..4fd12333 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;
@@ -349,6 +350,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)
 {
 	/*
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 25fbf9f1..80ca5547 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,10 @@  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 +417,21 @@  bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg)
 	return true;
 }
 
+std::map<PixelFormat, uint32_t> rawFormats = {
+	{ formats::SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8 },
+	{ formats::SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8 },
+	{ formats::SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8 },
+	{ formats::SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8 },
+	{ formats::SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10 },
+	{ formats::SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10 },
+	{ formats::SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10 },
+	{ formats::SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10 },
+	{ formats::SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12 },
+	{ formats::SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12 },
+	{ formats::SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12 },
+	{ formats::SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12 },
+};
+
 CameraConfiguration::Status RkISP1CameraConfiguration::validate()
 {
 	const CameraSensor *sensor = data_->sensor_.get();
@@ -504,8 +523,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 +554,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 +700,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 +1199,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..0ae006e8 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -101,6 +101,23 @@  CameraConfiguration::Status RkISP1Path::validate(StreamConfiguration *cfg)
 	return status;
 }
 
+std::map<PixelFormat, uint32_t> formatToMediaBus = {
+	{ formats::NV12, MEDIA_BUS_FMT_YUYV8_1_5X8 },
+	{ formats::NV21, MEDIA_BUS_FMT_YUYV8_1_5X8 },
+	{ formats::SBGGR8, MEDIA_BUS_FMT_SBGGR8_1X8 },
+	{ formats::SGBRG8, MEDIA_BUS_FMT_SGBRG8_1X8 },
+	{ formats::SGRBG8, MEDIA_BUS_FMT_SGRBG8_1X8 },
+	{ formats::SRGGB8, MEDIA_BUS_FMT_SRGGB8_1X8 },
+	{ formats::SBGGR10, MEDIA_BUS_FMT_SBGGR10_1X10 },
+	{ formats::SGBRG10, MEDIA_BUS_FMT_SGBRG10_1X10 },
+	{ formats::SGRBG10, MEDIA_BUS_FMT_SGRBG10_1X10 },
+	{ formats::SRGGB10, MEDIA_BUS_FMT_SRGGB10_1X10 },
+	{ formats::SBGGR12, MEDIA_BUS_FMT_SBGGR12_1X12 },
+	{ formats::SGBRG12, MEDIA_BUS_FMT_SGBRG12_1X12 },
+	{ formats::SGRBG12, MEDIA_BUS_FMT_SGRBG12_1X12 },
+	{ formats::SRGGB12, MEDIA_BUS_FMT_SRGGB12_1X12 },
+};
+
 int RkISP1Path::configure(const StreamConfiguration &config,
 			  const V4L2SubdeviceFormat &inputFormat)
 {
@@ -127,15 +144,11 @@  int RkISP1Path::configure(const StreamConfiguration &config,
 		<< "Configuring " << name_ << " resizer output pad with "
 		<< ispFormat;
 
-	switch (config.pixelFormat) {
-	case formats::NV12:
-	case formats::NV21:
-		ispFormat.mbus_code = MEDIA_BUS_FMT_YUYV8_1_5X8;
-		break;
-	default:
+	auto mbus = formatToMediaBus.find(config.pixelFormat);
+	if (mbus != formatToMediaBus.end())
+		ispFormat.mbus_code = mbus->second;
+	else
 		ispFormat.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
-		break;
-	}
 
 	ret = resizer_->setFormat(1, &ispFormat);
 	if (ret < 0)
@@ -207,14 +220,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 };