summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/camera_sensor.cpp14
-rw-r--r--src/libcamera/pipeline/imx8-isi/imx8-isi.cpp234
2 files changed, 172 insertions, 76 deletions
diff --git a/src/libcamera/camera_sensor.cpp b/src/libcamera/camera_sensor.cpp
index a210aa4f..dfe59303 100644
--- a/src/libcamera/camera_sensor.cpp
+++ b/src/libcamera/camera_sensor.cpp
@@ -758,6 +758,20 @@ int CameraSensor::setFormat(V4L2SubdeviceFormat *format)
}
/**
+ * \brief Try the sensor output format
+ * \param[in] format The desired sensor output format
+ *
+ * The ranges of any controls associated with the sensor are not updated.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int CameraSensor::tryFormat(V4L2SubdeviceFormat *format) const
+{
+ return subdev_->setFormat(pad_, format,
+ V4L2Subdevice::Whence::TryFormat);
+}
+
+/**
* \brief Retrieve the supported V4L2 controls and their information
*
* Control information is updated automatically to reflect the current sensor
diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
index 764e2121..7a888310 100644
--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
@@ -145,6 +145,10 @@ private:
Pipe *pipeFromStream(Camera *camera, const Stream *stream);
+ StreamConfiguration generateYUVConfiguration(Camera *camera,
+ const Size &size);
+ StreamConfiguration generateRawConfiguration(Camera *camera);
+
void bufferReady(FrameBuffer *buffer);
MediaDevice *isiDev_;
@@ -697,6 +701,132 @@ PipelineHandlerISI::PipelineHandlerISI(CameraManager *manager)
{
}
+/*
+ * Generate a StreamConfiguration for YUV/RGB use case.
+ *
+ * Verify it the sensor can produce a YUV/RGB media bus format and ollect
+ * all the processed pixel formats the ISI can generate as supported stream
+ * configurations.
+ */
+StreamConfiguration PipelineHandlerISI::generateYUVConfiguration(Camera *camera,
+ const Size &size)
+{
+ ISICameraData *data = cameraData(camera);
+ PixelFormat pixelFormat = formats::YUYV;
+ unsigned int mbusCode;
+
+ mbusCode = data->getYuvMediaBusFormat(&pixelFormat);
+ if (!mbusCode)
+ return {};
+
+ /* Adjust the requested size to the sensor's capabilities. */
+ const CameraSensor *sensor = data->sensor_.get();
+
+ V4L2SubdeviceFormat sensorFmt;
+ sensorFmt.mbus_code = mbusCode;
+ sensorFmt.size = size;
+
+ int ret = sensor->tryFormat(&sensorFmt);
+ if (ret) {
+ LOG(ISI, Error) << "Failed to try sensor format.";
+ return {};
+ }
+
+ Size sensorSize = sensorFmt.size;
+
+ /*
+ * Populate the StreamConfiguration.
+ *
+ * As the sensor supports at least one YUV/RGB media bus format all the
+ * processed ones in formatsMap_ can be generated from it.
+ */
+ std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
+
+ for (const auto &[pixFmt, pipeFmt] : ISICameraConfiguration::formatsMap_) {
+ const PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);
+ if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
+ continue;
+
+ streamFormats[pixFmt] = { { kMinISISize, sensorSize } };
+ }
+
+ StreamFormats formats(streamFormats);
+
+ StreamConfiguration cfg(formats);
+ cfg.pixelFormat = pixelFormat;
+ cfg.size = sensorSize;
+ cfg.bufferCount = 4;
+
+ return cfg;
+}
+
+/*
+ * Generate a StreamConfiguration for Raw Bayer use case.
+ *
+ * Verify if the sensor can produce a RAW bayer format
+ * The Raw Bayer format with the largest bit depth is selected as default and
+ * one stream configuration is collected for each Raw Bayer format the sensor
+ * can produce.
+ */
+StreamConfiguration PipelineHandlerISI::generateRawConfiguration(Camera *camera)
+{
+ const std::map<unsigned int, PixelFormat> rawFormats = {
+ { MEDIA_BUS_FMT_SBGGR8_1X8, formats::SBGGR8 },
+ { MEDIA_BUS_FMT_SGBRG8_1X8, formats::SGBRG8 },
+ { MEDIA_BUS_FMT_SGRBG8_1X8, formats::SGRBG8 },
+ { MEDIA_BUS_FMT_SRGGB8_1X8, formats::SRGGB8 },
+ { MEDIA_BUS_FMT_SBGGR10_1X10, formats::SBGGR10 },
+ { MEDIA_BUS_FMT_SGBRG10_1X10, formats::SGBRG10 },
+ { MEDIA_BUS_FMT_SGRBG10_1X10, formats::SGRBG10 },
+ { MEDIA_BUS_FMT_SRGGB10_1X10, formats::SRGGB10 },
+ { MEDIA_BUS_FMT_SBGGR12_1X12, formats::SBGGR12 },
+ { MEDIA_BUS_FMT_SGBRG12_1X12, formats::SGBRG12 },
+ { MEDIA_BUS_FMT_SGRBG12_1X12, formats::SGRBG12 },
+ { MEDIA_BUS_FMT_SRGGB12_1X12, formats::SRGGB12 },
+ };
+
+ ISICameraData *data = cameraData(camera);
+ PixelFormat pixelFormat = formats::SBGGR10;
+ unsigned int mbusCode;
+
+ /* pixelFormat will be adjusted, if the sensor can produce RAW. */
+ mbusCode = data->getRawMediaBusFormat(&pixelFormat);
+ if (!mbusCode)
+ return {};
+
+ /*
+ * Populate the StreamConfiguration with all the supported Bayer
+ * formats the sensor can produce.
+ */
+ std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
+ const CameraSensor *sensor = data->sensor_.get();
+
+ for (unsigned int code : sensor->mbusCodes()) {
+ /* Find a Bayer media bus code from the sensor. */
+ const BayerFormat &bayerFormat = BayerFormat::fromMbusCode(code);
+ if (!bayerFormat.isValid())
+ continue;
+
+ auto it = rawFormats.find(code);
+ if (it == rawFormats.end()) {
+ LOG(ISI, Warning) << bayerFormat
+ << " not supported in ISI formats map.";
+ continue;
+ }
+
+ streamFormats[it->second] = { { kMinISISize, sensor->resolution() } };
+ }
+
+ StreamFormats formats(streamFormats);
+
+ StreamConfiguration cfg(formats);
+ cfg.size = sensor->resolution();
+ cfg.pixelFormat = pixelFormat;
+ cfg.bufferCount = 4;
+
+ return cfg;
+}
+
std::unique_ptr<CameraConfiguration>
PipelineHandlerISI::generateConfiguration(Camera *camera,
const StreamRoles &roles)
@@ -714,79 +844,45 @@ PipelineHandlerISI::generateConfiguration(Camera *camera,
return nullptr;
}
- bool isRaw = false;
for (const auto &role : roles) {
/*
- * Prefer the following formats
+ * Prefer the following formats:
* - Still Capture: Full resolution YUYV
* - ViewFinder/VideoRecording: 1080p YUYV
- * - RAW: sensor's native format and resolution
+ * - RAW: Full resolution Bayer
*/
- std::map<PixelFormat, std::vector<SizeRange>> streamFormats;
- PixelFormat pixelFormat;
- Size size;
+ StreamConfiguration cfg;
switch (role) {
case StreamRole::StillCapture:
- /*
- * \todo Make sure the sensor can produce non-RAW formats
- * compatible with the ones supported by the pipeline.
- */
- size = data->sensor_->resolution();
- pixelFormat = formats::YUYV;
+ cfg = generateYUVConfiguration(camera,
+ data->sensor_->resolution());
+ if (!cfg.pixelFormat.isValid()) {
+ /*
+ * Fallback to use a Bayer format if that's what
+ * the sensor supports.
+ */
+ cfg = generateRawConfiguration(camera);
+ }
+
break;
case StreamRole::Viewfinder:
case StreamRole::VideoRecording:
- /*
- * \todo Make sure the sensor can produce non-RAW formats
- * compatible with the ones supported by the pipeline.
- */
- size = PipelineHandlerISI::kPreviewSize;
- pixelFormat = formats::YUYV;
- break;
-
- case StreamRole::Raw: {
- /*
- * Make sure the sensor can generate a RAW format and
- * prefer the ones with a larger bitdepth.
- */
- const ISICameraConfiguration::FormatMap::value_type *rawPipeFormat = nullptr;
- unsigned int maxDepth = 0;
-
- for (unsigned int code : data->sensor_->mbusCodes()) {
- const BayerFormat &bayerFormat = BayerFormat::fromMbusCode(code);
- if (!bayerFormat.isValid())
- continue;
-
- /* Make sure the format is supported by the pipeline handler. */
- auto it = std::find_if(ISICameraConfiguration::formatsMap_.begin(),
- ISICameraConfiguration::formatsMap_.end(),
- [code](auto &isiFormat) {
- auto &pipe = isiFormat.second;
- return pipe.sensorCode == code;
- });
- if (it == ISICameraConfiguration::formatsMap_.end())
- continue;
-
- if (bayerFormat.bitDepth > maxDepth) {
- maxDepth = bayerFormat.bitDepth;
- rawPipeFormat = &(*it);
- }
- }
-
- if (!rawPipeFormat) {
- LOG(ISI, Error)
- << "Cannot generate a configuration for RAW stream";
- return nullptr;
+ cfg = generateYUVConfiguration(camera,
+ PipelineHandlerISI::kPreviewSize);
+ if (!cfg.pixelFormat.isValid()) {
+ /*
+ * Fallback to use a Bayer format if that's what
+ * the sensor supports.
+ */
+ cfg = generateRawConfiguration(camera);
}
- size = data->sensor_->resolution();
- pixelFormat = rawPipeFormat->first;
-
- streamFormats[pixelFormat] = { { kMinISISize, size } };
- isRaw = true;
+ break;
+ case StreamRole::Raw: {
+ cfg = generateRawConfiguration(camera);
break;
}
@@ -795,26 +891,12 @@ PipelineHandlerISI::generateConfiguration(Camera *camera,
return nullptr;
}
- /*
- * For non-RAW configurations the ISI can perform colorspace
- * conversion. List all the supported output formats here.
- */
- if (!isRaw) {
- for (const auto &[pixFmt, pipeFmt] : ISICameraConfiguration::formatsMap_) {
- const PixelFormatInfo &info = PixelFormatInfo::info(pixFmt);
- if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
- continue;
-
- streamFormats[pixFmt] = { { kMinISISize, size } };
- }
+ if (!cfg.pixelFormat.isValid()) {
+ LOG(ISI, Error)
+ << "Cannot generate configuration for role: " << role;
+ return nullptr;
}
- StreamFormats formats(streamFormats);
-
- StreamConfiguration cfg(formats);
- cfg.pixelFormat = pixelFormat;
- cfg.size = size;
- cfg.bufferCount = 4;
config->addConfiguration(cfg);
}