[libcamera-devel] [PATCH 3/7] libcamera: pipeline: vimc: Generate and Validate stream configurations

Kaaira Gupta kgupta at es.iitr.ac.in
Wed Jul 22 15:30:05 CEST 2020


Implement generating configurations for StillCaptureRaw role. Also
validate them.

Declare a bool which takes note of the configuration which is raw (if
any).
If two configurations are asked for, we consider one of them to be asking
for a raw stream.
If no role is provided, consider the configuration with least with to
be associated wth raw stream.
If both the pixelformat and size are provided, give preferance to pixelformat
in determining the configuration with raw stream.

Signed-off-by: Kaaira Gupta <kgupta at es.iitr.ac.in>
---
 src/libcamera/pipeline/vimc/vimc.cpp | 180 ++++++++++++++++++---------
 1 file changed, 122 insertions(+), 58 deletions(-)

diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
index bd6ddde..83dd541 100644
--- a/src/libcamera/pipeline/vimc/vimc.cpp
+++ b/src/libcamera/pipeline/vimc/vimc.cpp
@@ -117,6 +117,17 @@ static const std::map<PixelFormat, uint32_t> pixelformats{
 	{ formats::BGR888, MEDIA_BUS_FMT_RGB888_1X24 },
 };
 
+static const std::map<PixelFormat, uint32_t> pixelFormatsRaw{
+	{ 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 }
+};
+
 } /* namespace */
 
 VimcCameraConfiguration::VimcCameraConfiguration(VimcCameraData *data)
@@ -127,53 +138,90 @@ VimcCameraConfiguration::VimcCameraConfiguration(VimcCameraData *data)
 CameraConfiguration::Status VimcCameraConfiguration::validate()
 {
 	Status status = Valid;
+	bool hasRaw = false;
+	unsigned rindex = 2;
+	int ret;
 
 	if (config_.empty())
 		return Invalid;
 
 	/* Cap the number of entries to the available streams. */
-	if (config_.size() > 1) {
-		config_.resize(1);
+	if (config_.size() > 2) {
+		config_.resize(2);
 		status = Adjusted;
 	}
 
-	StreamConfiguration &cfg = config_[0];
-
-	/* Adjust the pixel format. */
-	const std::vector<libcamera::PixelFormat> formats = cfg.formats().pixelformats();
-	if (std::find(formats.begin(), formats.end(), cfg.pixelFormat) == formats.end()) {
-		LOG(VIMC, Debug) << "Adjusting format to BGR888";
-		cfg.pixelFormat = formats::BGR888;
-		status = Adjusted;
+	if (config_.size() > 1) {
+		if (config_[0].size.width < config_[1].size.width) {
+			rindex = 0;
+		} else {
+			rindex = 1;
+		}
+		hasRaw = true;
 	}
 
-	/* Clamp the size based on the device limits. */
-	const Size size = cfg.size;
-
-	/* The scaler hardcodes a x3 scale-up ratio. */
-	cfg.size.width = std::max(48U, std::min(4096U, cfg.size.width));
-	cfg.size.height = std::max(48U, std::min(2160U, cfg.size.height));
-	cfg.size.width -= cfg.size.width % 3;
-	cfg.size.height -= cfg.size.height % 3;
-
-	if (cfg.size != size) {
-		LOG(VIMC, Debug)
-			<< "Adjusting size to " << cfg.size.toString();
-		status = Adjusted;
+	for (unsigned i = 0; i < config_.size(); i++) {
+		const PixelFormatInfo &info = PixelFormatInfo::info(config_[i].pixelFormat);
+		if (info.isRaw(config_[i].pixelFormat)) {
+			rindex = i;
+			hasRaw = true;
+		}
 	}
 
-	cfg.bufferCount = 4;
+	for (unsigned i = 0; i < config_.size(); i++) {
+		StreamConfiguration &cfg = config_[i];
+		V4L2DeviceFormat format = {};
+		const Size size = cfg.size;
+		if (i == rindex) {
+			/* Clamp the size based on the device limits. */
+			cfg.size.width = std::max(16U, std::min(1365U, cfg.size.width));
+			cfg.size.height = std::max(16U, std::min(720U, cfg.size.height));
+			/* Adjust the pixel format. */
+			if (pixelFormatsRaw.find(cfg.pixelFormat) == pixelFormatsRaw.end()) {
+				LOG(VIMC, Debug) << "Adjusting format to SGRBG8";
+				cfg.pixelFormat = formats::SGRBG8;
+				status = Adjusted;
+			}
+			format.fourcc = data_->raw_->toV4L2PixelFormat(cfg.pixelFormat);
+			format.size = cfg.size;
+			ret = data_->raw_->tryFormat(&format);
+		} else {
+			const std::vector<libcamera::PixelFormat> formats = cfg.formats().pixelformats();
+			if (hasRaw) {
+				cfg.size.width = config_[(i + 1) % 2].size.width * 3;
+				cfg.size.height = config_[(i + 1) % 2].size.height * 3;
+			} else {
+				/* Clamp the size based on the device limits. */
+				cfg.size.width = std::max(48U, std::min(4096U, cfg.size.width));
+				cfg.size.height = std::max(48U, std::min(2160U, cfg.size.height));
+				/* The scaler hardcodes a x3 scale-up ratio. */
+				cfg.size.width -= cfg.size.width % 3;
+				cfg.size.height -= cfg.size.height % 3;
+			}
 
-	V4L2DeviceFormat format = {};
-	format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);
-	format.size = cfg.size;
+			/* Adjust the pixel format. */
+			if (std::find(formats.begin(), formats.end(), cfg.pixelFormat) == formats.end()) {
+				LOG(VIMC, Debug) << "Adjusting format to BGR888";
+				cfg.pixelFormat = formats::BGR888;
+				status = Adjusted;
+			}
+			format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat);
+			format.size = cfg.size;
+			ret = data_->video_->tryFormat(&format);
+		}
 
-	int ret = data_->video_->tryFormat(&format);
-	if (ret)
-		return Invalid;
+		if (ret)
+			return Invalid;
+		if (cfg.size != size) {
+			LOG(VIMC, Debug)
+				<< "Adjusting size to " << cfg.size.toString();
+			status = Adjusted;
+		}
 
-	cfg.stride = format.planes[0].bpl;
-	cfg.frameSize = format.planes[0].size;
+		cfg.bufferCount = 4;
+		cfg.stride = format.planes[0].bpl;
+		cfg.frameSize = format.planes[0].size;
+	}
 
 	return status;
 }
@@ -194,35 +242,51 @@ CameraConfiguration *PipelineHandlerVimc::generateConfiguration(Camera *camera,
 
 	std::map<PixelFormat, std::vector<SizeRange>> formats;
 
-	for (const auto &pixelformat : pixelformats) {
-		/*
-		 * Kernels prior to v5.7 incorrectly report support for RGB888,
-		 * but it isn't functional within the pipeline.
-		 */
-		if (data->media_->version() < KERNEL_VERSION(5, 7, 0)) {
-			if (pixelformat.first != formats::BGR888) {
-				LOG(VIMC, Info)
-					<< "Skipping unsupported pixel format "
-					<< pixelformat.first.toString();
-				continue;
+	for (const StreamRole role : roles) {
+		switch (role) {
+		case StreamRole::StillCaptureRaw: {
+			for (const auto &pixelformat : pixelFormatsRaw) {
+				std::vector<SizeRange> sizes{
+					SizeRange{ { 16, 16 }, { 1365, 720 } }
+				};
+				formats[pixelformat.first] = sizes;
+			}
+			StreamConfiguration cfg(formats);
+			cfg.pixelFormat = formats::SGRBG8;
+			cfg.size = { 640, 360 };
+			cfg.bufferCount = 4;
+			config->addConfiguration(cfg);
+			break;
+		}
+		default:
+			for (const auto &pixelformat : pixelformats) {
+				/*
+				 * Kernels prior to v5.7 incorrectly report support for RGB888,
+				 * but it isn't functional within the pipeline.
+				 */
+				if (data->media_->version() < KERNEL_VERSION(5, 7, 0)) {
+					if (pixelformat.first != formats::BGR888) {
+						LOG(VIMC, Info)
+							<< "Skipping unsupported pixel format "
+							<< pixelformat.first.toString();
+						continue;
+					}
+				}
+
+				/* The scaler hardcodes a x3 scale-up ratio. */
+				std::vector<SizeRange> sizes{
+					SizeRange{ { 48, 48 }, { 4096, 2160 } }
+				};
+				formats[pixelformat.first] = sizes;
 			}
+			StreamConfiguration cfg(formats);
+			cfg.pixelFormat = formats::BGR888;
+			cfg.size = { 1920, 1080 };
+			cfg.bufferCount = 4;
+			config->addConfiguration(cfg);
+			break;
 		}
-
-		/* The scaler hardcodes a x3 scale-up ratio. */
-		std::vector<SizeRange> sizes{
-			SizeRange{ { 48, 48 }, { 4096, 2160 } }
-		};
-		formats[pixelformat.first] = sizes;
 	}
-
-	StreamConfiguration cfg(formats);
-
-	cfg.pixelFormat = formats::BGR888;
-	cfg.size = { 1920, 1080 };
-	cfg.bufferCount = 4;
-
-	config->addConfiguration(cfg);
-
 	config->validate();
 
 	return config;
-- 
2.17.1



More information about the libcamera-devel mailing list