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

Message ID 20200722133009.26528-4-kgupta@es.iitr.ac.in
State New
Delegated to: Kieran Bingham
Headers show
Series
  • vimc: Introduce multiple streaming
Related show

Commit Message

Kaaira Gupta July 22, 2020, 1:30 p.m. UTC
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@es.iitr.ac.in>
---
 src/libcamera/pipeline/vimc/vimc.cpp | 180 ++++++++++++++++++---------
 1 file changed, 122 insertions(+), 58 deletions(-)

Patch

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;