libcamera: rpi: pipeline_base: Move findBestFormat to CameraData

The findBestFormat() helper operates on the list of sensor formats,
which is owned by the CameraData class. Move the function to that class
as well to:

1) Avoid passing the list of formats to the function
2) Remove a static helper in favour of a class function
3) Allow subclasses with access to CameraData to call the function

Move to the CameraData class the scoreFormat helper as well.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Naushir Patuck <naush@raspberrypi.com>
This commit is contained in:
Jacopo Mondi 2023-07-12 11:55:09 +01:00
parent 81fa10d87f
commit 4edc162e3d
2 changed files with 67 additions and 63 deletions

View file

@ -74,63 +74,6 @@ bool isMonoSensor(std::unique_ptr<CameraSensor> &sensor)
return bayer.order == BayerFormat::Order::MONO;
}
double scoreFormat(double desired, double actual)
{
double score = desired - actual;
/* Smaller desired dimensions are preferred. */
if (score < 0.0)
score = (-score) / 8;
/* Penalise non-exact matches. */
if (actual != desired)
score *= 2;
return score;
}
V4L2SubdeviceFormat findBestFormat(const SensorFormats &formatsMap, const Size &req, unsigned int bitDepth)
{
double bestScore = std::numeric_limits<double>::max(), score;
V4L2SubdeviceFormat bestFormat;
bestFormat.colorSpace = ColorSpace::Raw;
constexpr float penaltyAr = 1500.0;
constexpr float penaltyBitDepth = 500.0;
/* Calculate the closest/best mode from the user requested size. */
for (const auto &iter : formatsMap) {
const unsigned int mbusCode = iter.first;
const PixelFormat format = mbusCodeToPixelFormat(mbusCode,
BayerFormat::Packing::None);
const PixelFormatInfo &info = PixelFormatInfo::info(format);
for (const Size &size : iter.second) {
double reqAr = static_cast<double>(req.width) / req.height;
double fmtAr = static_cast<double>(size.width) / size.height;
/* Score the dimensions for closeness. */
score = scoreFormat(req.width, size.width);
score += scoreFormat(req.height, size.height);
score += penaltyAr * scoreFormat(reqAr, fmtAr);
/* Add any penalties... this is not an exact science! */
score += utils::abs_diff(info.bitsPerPixel, bitDepth) * penaltyBitDepth;
if (score <= bestScore) {
bestScore = score;
bestFormat.mbus_code = mbusCode;
bestFormat.size = size;
}
LOG(RPI, Debug) << "Format: " << size
<< " fmt " << format
<< " Score: " << score
<< " (best " << bestScore << ")";
}
}
return bestFormat;
}
const std::vector<ColorSpace> validColorSpaces = {
ColorSpace::Sycc,
ColorSpace::Smpte170m,
@ -276,7 +219,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()
const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat);
unsigned int bitDepth = info.isValid() ? info.bitsPerPixel : defaultRawBitDepth;
V4L2SubdeviceFormat sensorFormat = findBestFormat(data_->sensorFormats_, cfg.size, bitDepth);
V4L2SubdeviceFormat sensorFormat = data_->findBestFormat(cfg.size, bitDepth);
BayerFormat::Packing packing = BayerFormat::fromPixelFormat(cfg.pixelFormat).packing;
rawFormat = PipelineHandlerBase::toV4L2DeviceFormat(raw.dev, sensorFormat, packing);
@ -391,7 +334,7 @@ PipelineHandlerBase::generateConfiguration(Camera *camera, Span<const StreamRole
switch (role) {
case StreamRole::Raw:
size = sensorSize;
sensorFormat = findBestFormat(data->sensorFormats_, size, defaultRawBitDepth);
sensorFormat = data->findBestFormat(size, defaultRawBitDepth);
pixelFormat = mbusCodeToPixelFormat(sensorFormat.mbus_code,
BayerFormat::Packing::CSI2);
ASSERT(pixelFormat.isValid());
@ -531,10 +474,11 @@ int PipelineHandlerBase::configure(Camera *camera, CameraConfiguration *config)
bitDepth = bayerFormat.bitDepth;
}
V4L2SubdeviceFormat sensorFormat = findBestFormat(data->sensorFormats_,
rawStreams.empty() ? ispStreams[0].cfg->size
: rawStreams[0].cfg->size,
bitDepth);
V4L2SubdeviceFormat sensorFormat =
data->findBestFormat(rawStreams.empty() ? ispStreams[0].cfg->size
: rawStreams[0].cfg->size,
bitDepth);
/* Apply any cached transform. */
const RPiCameraConfiguration *rpiConfig = static_cast<const RPiCameraConfiguration *>(config);
@ -954,6 +898,63 @@ int PipelineHandlerBase::queueAllBuffers(Camera *camera)
return 0;
}
double CameraData::scoreFormat(double desired, double actual) const
{
double score = desired - actual;
/* Smaller desired dimensions are preferred. */
if (score < 0.0)
score = (-score) / 8;
/* Penalise non-exact matches. */
if (actual != desired)
score *= 2;
return score;
}
V4L2SubdeviceFormat CameraData::findBestFormat(const Size &req, unsigned int bitDepth) const
{
double bestScore = std::numeric_limits<double>::max(), score;
V4L2SubdeviceFormat bestFormat;
bestFormat.colorSpace = ColorSpace::Raw;
constexpr float penaltyAr = 1500.0;
constexpr float penaltyBitDepth = 500.0;
/* Calculate the closest/best mode from the user requested size. */
for (const auto &iter : sensorFormats_) {
const unsigned int mbusCode = iter.first;
const PixelFormat format = mbusCodeToPixelFormat(mbusCode,
BayerFormat::Packing::None);
const PixelFormatInfo &info = PixelFormatInfo::info(format);
for (const Size &size : iter.second) {
double reqAr = static_cast<double>(req.width) / req.height;
double fmtAr = static_cast<double>(size.width) / size.height;
/* Score the dimensions for closeness. */
score = scoreFormat(req.width, size.width);
score += scoreFormat(req.height, size.height);
score += penaltyAr * scoreFormat(reqAr, fmtAr);
/* Add any penalties... this is not an exact science! */
score += utils::abs_diff(info.bitsPerPixel, bitDepth) * penaltyBitDepth;
if (score <= bestScore) {
bestScore = score;
bestFormat.mbus_code = mbusCode;
bestFormat.size = size;
}
LOG(RPI, Debug) << "Format: " << size
<< " fmt " << format
<< " Score: " << score
<< " (best " << bestScore << ")";
}
}
return bestFormat;
}
void CameraData::freeBuffers()
{
if (ipa_) {

View file

@ -81,6 +81,9 @@ public:
virtual void platformStart() = 0;
virtual void platformStop() = 0;
double scoreFormat(double desired, double actual) const;
V4L2SubdeviceFormat findBestFormat(const Size &req, unsigned int bitDepth) const;
void freeBuffers();
virtual void platformFreeBuffers() = 0;