/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2019, Google Inc.
*
* imgu.cpp - Intel IPU3 ImgU
*/
#include "imgu.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <linux/media-bus-format.h>
#include <libcamera/base/log.h>
#include <libcamera/base/utils.h>
#include <libcamera/formats.h>
#include <libcamera/stream.h>
#include "libcamera/internal/media_device.h"
namespace libcamera {
LOG_DECLARE_CATEGORY(IPU3)
namespace {
/*
* The procedure to calculate the ImgU pipe configuration has been ported
* from the pipe_config.py python script, available at:
* https://github.com/intel/intel-ipu3-pipecfg
* at revision: 243d13446e44 ("Fix some bug for some resolutions")
*/
/* BSD scaling factors: min=1, max=2.5, step=1/32 */
const std::vector<float> bdsScalingFactors = {
1, 1.03125, 1.0625, 1.09375, 1.125, 1.15625, 1.1875, 1.21875, 1.25,
1.28125, 1.3125, 1.34375, 1.375, 1.40625, 1.4375, 1.46875, 1.5, 1.53125,
1.5625, 1.59375, 1.625, 1.65625, 1.6875, 1.71875, 1.75, 1.78125, 1.8125,
1.84375, 1.875, 1.90625, 1.9375, 1.96875, 2, 2.03125, 2.0625, 2.09375,
2.125, 2.15625, 2.1875, 2.21875, 2.25, 2.28125, 2.3125, 2.34375, 2.375,
2.40625, 2.4375, 2.46875, 2.5
};
/* GDC scaling factors: min=1, max=16, step=1/4 */
const std::vector<float> gdcScalingFactors = {
1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4, 4.25,
4.5, 4.75, 5, 5.25, 5.5, 5.75, 6, 6.25, 6.5, 6.75, 7, 7.25, 7.5, 7.75,
8, 8.25, 8.5, 8.75, 9, 9.25, 9.5, 9.75, 10, 10.25, 10.5, 10.75, 11,
11.25, 11.5, 11.75, 12, 12.25, 12.5, 12.75, 13, 13.25, 13.5, 13.75, 14,
14.25, 14.5, 14.75, 15, 15.25, 15.5, 15.75, 16,
};
std::vector<ImgUDevice::PipeConfig> pipeConfigs;
struct FOV {
float w;
float h;
bool isLarger(const FOV &other)
{
if (w > other.w)
return true;
if (w == other.w && h > other.h)
return true;
return false;
}
};
/* Approximate a scaling factor sf to the closest one available in a range. */
float findScaleFactor(float sf, const std::vector<float> &range,
bool roundDown = false)
{
if (sf <= range[0])
return range[0];
if (sf >= range[range.size() - 1])
return range[range.size() - 1];
float bestDiff = std::numeric_limits<float>::max();
unsigned int index = 0;
for (unsigned int i = 0; i < range.size(); ++i) {
float diff = utils::abs_diff(sf, range[i]);
if (diff < bestDiff) {
bestDiff = diff;
index = i;
}
}
if (roundDown && index > 0 && sf < range[index])
index--;
return range[index];
}
bool isSameRatio(const Size &in, const Size &out)
{
float inRatio = static_cast<float>(in.width) / in.height;
float outRatio = static_cast<float>(out.width) / out.height;
if (utils::abs_diff(inRatio, outRatio) > 0.1)
return false;
return true;
}
void calculateBDSHeight(ImgUDevice::Pipe *pipe, const Size &iif, const Size &gdc,
unsigned int bdsWidth, float bdsSF)
{
unsigned int minIFHeight = iif.height - ImgUDevice::kIFMaxCropHeight;
unsigned int minBDSHeight = gdc.height + ImgUDevice::kFilterHeight * 2;
unsigned int ifHeight;
float bdsHeight;
if (!isSameRatio(pipe->input, gdc)) {
unsigned int foundIfHeight = 0;
float estIFHeight = (iif.width * gdc.height) /
static_cast<float>(gdc.width);
|