3e85b920fb
We can, theoretically, now change the v4l camera's mode.
147 lines
3.5 KiB
C++
147 lines
3.5 KiB
C++
#include <planarYuvFormatPolicy.h>
|
|
#include <libcamera/formats.h>
|
|
#include <sstream>
|
|
#include <stdexcept>
|
|
|
|
namespace lcamera_dev {
|
|
|
|
namespace {
|
|
|
|
using libcamera::formats::NV12;
|
|
using libcamera::formats::NV16;
|
|
using libcamera::formats::NV21;
|
|
using libcamera::formats::NV24;
|
|
using libcamera::formats::NV42;
|
|
using libcamera::formats::NV61;
|
|
using libcamera::formats::UYVY;
|
|
using libcamera::formats::VYUY;
|
|
using libcamera::formats::YUYV;
|
|
using libcamera::formats::YUV420;
|
|
using libcamera::formats::YUV422;
|
|
using libcamera::formats::YUV444;
|
|
using libcamera::formats::YVU420;
|
|
using libcamera::formats::YVU422;
|
|
using libcamera::formats::YVU444;
|
|
using libcamera::formats::YVYU;
|
|
|
|
bool pixelFormatMatches(
|
|
const libcamera::PixelFormat& pixelFormat,
|
|
const libcamera::PixelFormat& expectedFormat)
|
|
{
|
|
return pixelFormat == expectedFormat;
|
|
}
|
|
|
|
bool isFullyPlanarYuvFourcc(const libcamera::PixelFormat& pixelFormat)
|
|
{
|
|
return pixelFormatMatches(pixelFormat, YUV420)
|
|
|| pixelFormatMatches(pixelFormat, YVU420)
|
|
|| pixelFormatMatches(pixelFormat, YUV422)
|
|
|| pixelFormatMatches(pixelFormat, YVU422)
|
|
|| pixelFormatMatches(pixelFormat, YUV444)
|
|
|| pixelFormatMatches(pixelFormat, YVU444);
|
|
}
|
|
|
|
bool isSemiPlanarYuvFourcc(const libcamera::PixelFormat& pixelFormat)
|
|
{
|
|
return pixelFormatMatches(pixelFormat, NV12)
|
|
|| pixelFormatMatches(pixelFormat, NV21)
|
|
|| pixelFormatMatches(pixelFormat, NV16)
|
|
|| pixelFormatMatches(pixelFormat, NV61)
|
|
|| pixelFormatMatches(pixelFormat, NV24)
|
|
|| pixelFormatMatches(pixelFormat, NV42);
|
|
}
|
|
|
|
bool isPackedYuvFourcc(const libcamera::PixelFormat& pixelFormat)
|
|
{
|
|
return pixelFormatMatches(pixelFormat, YUYV)
|
|
|| pixelFormatMatches(pixelFormat, YVYU)
|
|
|| pixelFormatMatches(pixelFormat, UYVY)
|
|
|| pixelFormatMatches(pixelFormat, VYUY);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool isFullyPlanarYuv(const libcamera::PixelFormat& pixelFormat)
|
|
{
|
|
return isFullyPlanarYuvFourcc(pixelFormat);
|
|
}
|
|
|
|
bool isKnownYuvCaptureFormat(const libcamera::PixelFormat& pixelFormat)
|
|
{
|
|
return isFullyPlanarYuvFourcc(pixelFormat)
|
|
|| isSemiPlanarYuvFourcc(pixelFormat)
|
|
|| isPackedYuvFourcc(pixelFormat);
|
|
}
|
|
|
|
unsigned yuvCapturePlaneCount(const libcamera::PixelFormat& pixelFormat)
|
|
{
|
|
if (isFullyPlanarYuvFourcc(pixelFormat)) {
|
|
return 3;
|
|
}
|
|
|
|
if (isSemiPlanarYuvFourcc(pixelFormat)) {
|
|
return 2;
|
|
}
|
|
|
|
if (isPackedYuvFourcc(pixelFormat)) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
std::string formatCandidateListForDiagnostics(
|
|
const std::vector<libcamera::PixelFormat>& candidates)
|
|
{
|
|
std::ostringstream stream;
|
|
for (std::size_t i = 0; i < candidates.size(); ++i)
|
|
{
|
|
if (i > 0) {
|
|
stream << ", ";
|
|
}
|
|
|
|
stream << candidates[i].toString();
|
|
}
|
|
|
|
return stream.str();
|
|
}
|
|
|
|
std::optional<libcamera::PixelFormat>
|
|
selectYuvCaptureFormat(
|
|
const std::vector<libcamera::PixelFormat>& candidates,
|
|
bool fullPlanarIsOptional)
|
|
{
|
|
if (candidates.empty())
|
|
{
|
|
throw std::runtime_error(
|
|
"lcameraDev: no YUV pixel-format candidates available");
|
|
}
|
|
|
|
if (!fullPlanarIsOptional)
|
|
{
|
|
for (const libcamera::PixelFormat& candidate : candidates)
|
|
{
|
|
if (isFullyPlanarYuv(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
throw std::runtime_error(
|
|
"lcameraDev: no fully planar YUV format among candidates: "
|
|
+ formatCandidateListForDiagnostics(candidates));
|
|
}
|
|
|
|
for (const libcamera::PixelFormat& candidate : candidates)
|
|
{
|
|
if (isKnownYuvCaptureFormat(candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
|
|
throw std::runtime_error(
|
|
"lcameraDev: no known YUV capture format among candidates: "
|
|
+ formatCandidateListForDiagnostics(candidates));
|
|
}
|
|
|
|
} // namespace lcamera_dev
|