Message ID | 20230313091944.9530-3-jacopo.mondi@ideasonboard.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Jacopo, Thank you for the patch. On Mon, Mar 13, 2023 at 10:19:40AM +0100, Jacopo Mondi wrote: > As per the RAW format selection, the media bus format selection > procedure relies on the direct association of PixelFormat and media > bus code in the formatsMap_ map. > > As the ISI can generate YUV and RGB formats from any non-Bayer media > bus format, break out the YUV/RGB media bus format selection to a > separate function. > > The newly introduced getYuvMediaBusFormat() tests a list of > known-supported media bus formats against the list of media bus > formats supported by the sensor and tries to prefer media bus > codes with the same encoding as the requested PixelFormat. > > Use the newly introduced function in > ISICameraConfiguration::validateYuv() to make sure the sensor can > produce a YUV/RGB media bus format. > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > Reviewed-by: Daniel Scally <dan.scally@ideasonboard.com> > Tested-by: Daniel Scally <dan.scally@ideasonboard.com> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > --- > src/libcamera/pipeline/imx8-isi/imx8-isi.cpp | 76 ++++++++++++++++++++ > 1 file changed, 76 insertions(+) > > diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp > index ffb96e6284f0..390e82b6947f 100644 > --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp > +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp > @@ -60,6 +60,7 @@ public: > } > > unsigned int getRawMediaBusFormat(PixelFormat *pixelFormat) const; > + unsigned int getYuvMediaBusFormat(PixelFormat *pixelFormat) const; > > std::unique_ptr<CameraSensor> sensor_; > std::unique_ptr<V4L2Subdevice> csis_; > @@ -255,6 +256,65 @@ unsigned int ISICameraData::getRawMediaBusFormat(PixelFormat *pixelFormat) const > return sensorCode; > } > > +/* > + * Get a YUV/RGB media bus format from which the ISI can produce a processed > + * stream, preferring codes with the same colour encoding as the requested > + * pixelformat. > + * > + * If the sensor does not provide any YUV/RGB media bus format the ISI cannot > + * generate any processed pixel format as it cannot debayer. > + */ > +unsigned int ISICameraData::getYuvMediaBusFormat(PixelFormat *pixelFormat) const > +{ > + std::vector<unsigned int> mbusCodes = sensor_->mbusCodes(); > + > + /* > + * The ISI can produce YUV/RGB pixel formats from any non-RAW Bayer > + * media bus formats. > + * > + * Keep the list in sync with the mxc_isi_bus_formats[] array in > + * the ISI driver. > + */ > + std::vector<unsigned int> yuvCodes = { > + MEDIA_BUS_FMT_UYVY8_1X16, > + MEDIA_BUS_FMT_YUV8_1X24, > + MEDIA_BUS_FMT_RGB565_1X16, > + MEDIA_BUS_FMT_RGB888_1X24, > + }; > + > + std::sort(mbusCodes.begin(), mbusCodes.end()); > + std::sort(yuvCodes.begin(), yuvCodes.end()); > + > + std::vector<unsigned int> supportedCodes; > + std::set_intersection(mbusCodes.begin(), mbusCodes.end(), > + yuvCodes.begin(), yuvCodes.end(), > + std::back_inserter(supportedCodes)); > + > + if (supportedCodes.empty()) { > + LOG(ISI, Warning) << "Cannot find a supported YUV/RGB format"; > + *pixelFormat = {}; *pixelFormat is only modified in this error path, and you then ignore is in the caller. I would turn the `PixelFormat *pixelFormat` argument into a `const PixelFormat pixelFormat` to make the API clearer. > + > + return 0; > + } > + > + /* Prefer codes with the same encoding as the requested pixel format. */ > + const PixelFormatInfo &info = PixelFormatInfo::info(*pixelFormat); > + for (unsigned int code : supportedCodes) { > + if (info.colourEncoding == PixelFormatInfo::ColourEncodingYUV && > + (code == MEDIA_BUS_FMT_UYVY8_1X16 || > + code == MEDIA_BUS_FMT_YUV8_1X24)) > + return code; > + > + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRGB && > + (code == MEDIA_BUS_FMT_RGB565_1X16 || > + code == MEDIA_BUS_FMT_RGB888_1X24)) > + return code; > + } > + > + /* Otherwise return the first found code. */ > + return supportedCodes[0]; > +} > + > /* ----------------------------------------------------------------------------- > * Camera Configuration > */ > @@ -455,6 +515,22 @@ ISICameraConfiguration::validateYuv(std::set<Stream *> &availableStreams, > { > CameraConfiguration::Status status = Valid; > > + StreamConfiguration &yuvConfig = config_[0]; > + PixelFormat yuvPixelFormat = yuvConfig.pixelFormat; > + > + /* > + * Make sure the sensor can produce a compatible YUV/RGB media bus > + * format. If the sensor can only produce RAW Bayer we can only fail > + * here as we can't adjust to anything but RAW. > + */ > + unsigned int yuvMediaBusCode = data_->getYuvMediaBusFormat(&yuvPixelFormat); > + if (!yuvMediaBusCode) { > + LOG(ISI, Error) << "Cannot adjust pixelformat " > + << yuvConfig.pixelFormat; > + return Invalid; > + } > + > + /* Adjust all the other streams. */ > for (const auto &[i, cfg] : utils::enumerate(config_)) { > > LOG(ISI, Debug) << "Stream " << i << ": " << cfg.toString();
diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp index ffb96e6284f0..390e82b6947f 100644 --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp @@ -60,6 +60,7 @@ public: } unsigned int getRawMediaBusFormat(PixelFormat *pixelFormat) const; + unsigned int getYuvMediaBusFormat(PixelFormat *pixelFormat) const; std::unique_ptr<CameraSensor> sensor_; std::unique_ptr<V4L2Subdevice> csis_; @@ -255,6 +256,65 @@ unsigned int ISICameraData::getRawMediaBusFormat(PixelFormat *pixelFormat) const return sensorCode; } +/* + * Get a YUV/RGB media bus format from which the ISI can produce a processed + * stream, preferring codes with the same colour encoding as the requested + * pixelformat. + * + * If the sensor does not provide any YUV/RGB media bus format the ISI cannot + * generate any processed pixel format as it cannot debayer. + */ +unsigned int ISICameraData::getYuvMediaBusFormat(PixelFormat *pixelFormat) const +{ + std::vector<unsigned int> mbusCodes = sensor_->mbusCodes(); + + /* + * The ISI can produce YUV/RGB pixel formats from any non-RAW Bayer + * media bus formats. + * + * Keep the list in sync with the mxc_isi_bus_formats[] array in + * the ISI driver. + */ + std::vector<unsigned int> yuvCodes = { + MEDIA_BUS_FMT_UYVY8_1X16, + MEDIA_BUS_FMT_YUV8_1X24, + MEDIA_BUS_FMT_RGB565_1X16, + MEDIA_BUS_FMT_RGB888_1X24, + }; + + std::sort(mbusCodes.begin(), mbusCodes.end()); + std::sort(yuvCodes.begin(), yuvCodes.end()); + + std::vector<unsigned int> supportedCodes; + std::set_intersection(mbusCodes.begin(), mbusCodes.end(), + yuvCodes.begin(), yuvCodes.end(), + std::back_inserter(supportedCodes)); + + if (supportedCodes.empty()) { + LOG(ISI, Warning) << "Cannot find a supported YUV/RGB format"; + *pixelFormat = {}; + + return 0; + } + + /* Prefer codes with the same encoding as the requested pixel format. */ + const PixelFormatInfo &info = PixelFormatInfo::info(*pixelFormat); + for (unsigned int code : supportedCodes) { + if (info.colourEncoding == PixelFormatInfo::ColourEncodingYUV && + (code == MEDIA_BUS_FMT_UYVY8_1X16 || + code == MEDIA_BUS_FMT_YUV8_1X24)) + return code; + + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRGB && + (code == MEDIA_BUS_FMT_RGB565_1X16 || + code == MEDIA_BUS_FMT_RGB888_1X24)) + return code; + } + + /* Otherwise return the first found code. */ + return supportedCodes[0]; +} + /* ----------------------------------------------------------------------------- * Camera Configuration */ @@ -455,6 +515,22 @@ ISICameraConfiguration::validateYuv(std::set<Stream *> &availableStreams, { CameraConfiguration::Status status = Valid; + StreamConfiguration &yuvConfig = config_[0]; + PixelFormat yuvPixelFormat = yuvConfig.pixelFormat; + + /* + * Make sure the sensor can produce a compatible YUV/RGB media bus + * format. If the sensor can only produce RAW Bayer we can only fail + * here as we can't adjust to anything but RAW. + */ + unsigned int yuvMediaBusCode = data_->getYuvMediaBusFormat(&yuvPixelFormat); + if (!yuvMediaBusCode) { + LOG(ISI, Error) << "Cannot adjust pixelformat " + << yuvConfig.pixelFormat; + return Invalid; + } + + /* Adjust all the other streams. */ for (const auto &[i, cfg] : utils::enumerate(config_)) { LOG(ISI, Debug) << "Stream " << i << ": " << cfg.toString();