summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/v4l2/v4l2_camera_proxy.cpp180
1 files changed, 70 insertions, 110 deletions
diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
index c7ef4d51..bdd4a6c3 100644
--- a/src/v4l2/v4l2_camera_proxy.cpp
+++ b/src/v4l2/v4l2_camera_proxy.cpp
@@ -508,134 +508,94 @@ int V4L2CameraProxy::ioctl(unsigned long request, void *arg)
return ret;
}
+struct PixelFormatPlaneInfo {
+ unsigned int bitsPerPixel;
+ unsigned int hSubSampling;
+ unsigned int vSubSampling;
+};
+
+struct PixelFormatInfo {
+ PixelFormat format;
+ uint32_t v4l2Format;
+ unsigned int numPlanes;
+ std::array<PixelFormatPlaneInfo, 3> planes;
+};
+
+namespace {
+
+constexpr std::array<PixelFormatInfo, 13> pixelFormatInfo = {{
+ /* RGB formats. */
+ { DRM_FORMAT_RGB888, V4L2_PIX_FMT_BGR24, 1, {{ { 24, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_BGR888, V4L2_PIX_FMT_RGB24, 1, {{ { 24, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_BGRA8888, V4L2_PIX_FMT_ARGB32, 1, {{ { 32, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ /* YUV packed formats. */
+ { DRM_FORMAT_UYVY, V4L2_PIX_FMT_UYVY, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_VYUY, V4L2_PIX_FMT_VYUY, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_YUYV, V4L2_PIX_FMT_YUYV, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_YVYU, V4L2_PIX_FMT_YVYU, 1, {{ { 16, 1, 1 }, { 0, 0, 0 }, { 0, 0, 0 } }} },
+ /* YUY planar formats. */
+ { DRM_FORMAT_NV12, V4L2_PIX_FMT_NV12, 2, {{ { 8, 1, 1 }, { 16, 2, 2 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_NV21, V4L2_PIX_FMT_NV21, 2, {{ { 8, 1, 1 }, { 16, 2, 2 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_NV16, V4L2_PIX_FMT_NV16, 2, {{ { 8, 1, 1 }, { 16, 2, 1 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_NV61, V4L2_PIX_FMT_NV61, 2, {{ { 8, 1, 1 }, { 16, 2, 1 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_NV24, V4L2_PIX_FMT_NV24, 2, {{ { 8, 1, 1 }, { 16, 2, 1 }, { 0, 0, 0 } }} },
+ { DRM_FORMAT_NV42, V4L2_PIX_FMT_NV42, 2, {{ { 8, 1, 1 }, { 16, 1, 1 }, { 0, 0, 0 } }} },
+}};
+
+} /* namespace */
+
/* \todo make libcamera export these */
unsigned int V4L2CameraProxy::bplMultiplier(uint32_t format)
{
- switch (format) {
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- case V4L2_PIX_FMT_NV24:
- case V4L2_PIX_FMT_NV42:
- return 1;
- case V4L2_PIX_FMT_BGR24:
- case V4L2_PIX_FMT_RGB24:
- return 3;
- case V4L2_PIX_FMT_ARGB32:
- return 4;
- case V4L2_PIX_FMT_VYUY:
- case V4L2_PIX_FMT_YVYU:
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_YUYV:
- return 2;
- default:
+ auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
+ [format](const PixelFormatInfo &info) {
+ return info.v4l2Format == format;
+ });
+ if (info == pixelFormatInfo.end())
return 0;
- };
+
+ return info->planes[0].bitsPerPixel / 8;
}
unsigned int V4L2CameraProxy::imageSize(uint32_t format, unsigned int width,
unsigned int height)
{
- switch (format) {
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- return width * height * 3 / 2;
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- return width * height * 2;
- case V4L2_PIX_FMT_NV24:
- case V4L2_PIX_FMT_NV42:
- return width * height * 3;
- case V4L2_PIX_FMT_BGR24:
- case V4L2_PIX_FMT_RGB24:
- return width * height * 3;
- case V4L2_PIX_FMT_ARGB32:
- return width * height * 4;
- case V4L2_PIX_FMT_VYUY:
- case V4L2_PIX_FMT_YVYU:
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_YUYV:
- return width * height * 2;
- default:
+ auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
+ [format](const PixelFormatInfo &info) {
+ return info.v4l2Format == format;
+ });
+ if (info == pixelFormatInfo.end())
return 0;
- };
+
+ unsigned int multiplier = 0;
+ for (unsigned int i = 0; i < info->numPlanes; ++i)
+ multiplier += info->planes[i].bitsPerPixel
+ / info->planes[i].hSubSampling
+ / info->planes[i].vSubSampling;
+
+ return width * height * multiplier / 8;
}
PixelFormat V4L2CameraProxy::v4l2ToDrm(uint32_t format)
{
- switch (format) {
- /* RGB formats. */
- case V4L2_PIX_FMT_RGB24:
- return DRM_FORMAT_BGR888;
- case V4L2_PIX_FMT_BGR24:
- return DRM_FORMAT_RGB888;
- case V4L2_PIX_FMT_ARGB32:
- return DRM_FORMAT_BGRA8888;
-
- /* YUV packed formats. */
- case V4L2_PIX_FMT_YUYV:
- return DRM_FORMAT_YUYV;
- case V4L2_PIX_FMT_YVYU:
- return DRM_FORMAT_YVYU;
- case V4L2_PIX_FMT_UYVY:
- return DRM_FORMAT_UYVY;
- case V4L2_PIX_FMT_VYUY:
- return DRM_FORMAT_VYUY;
-
- /* YUY planar formats. */
- case V4L2_PIX_FMT_NV16:
- return DRM_FORMAT_NV16;
- case V4L2_PIX_FMT_NV61:
- return DRM_FORMAT_NV61;
- case V4L2_PIX_FMT_NV12:
- return DRM_FORMAT_NV12;
- case V4L2_PIX_FMT_NV21:
- return DRM_FORMAT_NV21;
- case V4L2_PIX_FMT_NV24:
- return DRM_FORMAT_NV24;
- case V4L2_PIX_FMT_NV42:
- return DRM_FORMAT_NV42;
- default:
+ auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
+ [format](const PixelFormatInfo &info) {
+ return info.v4l2Format == format;
+ });
+ if (info == pixelFormatInfo.end())
return format;
- };
+
+ return info->format;
}
uint32_t V4L2CameraProxy::drmToV4L2(PixelFormat format)
{
- switch (format) {
- /* RGB formats. */
- case DRM_FORMAT_BGR888:
- return V4L2_PIX_FMT_RGB24;
- case DRM_FORMAT_RGB888:
- return V4L2_PIX_FMT_BGR24;
- case DRM_FORMAT_BGRA8888:
- return V4L2_PIX_FMT_ARGB32;
-
- /* YUV packed formats. */
- case DRM_FORMAT_YUYV:
- return V4L2_PIX_FMT_YUYV;
- case DRM_FORMAT_YVYU:
- return V4L2_PIX_FMT_YVYU;
- case DRM_FORMAT_UYVY:
- return V4L2_PIX_FMT_UYVY;
- case DRM_FORMAT_VYUY:
- return V4L2_PIX_FMT_VYUY;
-
- /* YUY planar formats. */
- case DRM_FORMAT_NV16:
- return V4L2_PIX_FMT_NV16;
- case DRM_FORMAT_NV61:
- return V4L2_PIX_FMT_NV61;
- case DRM_FORMAT_NV12:
- return V4L2_PIX_FMT_NV12;
- case DRM_FORMAT_NV21:
- return V4L2_PIX_FMT_NV21;
- case DRM_FORMAT_NV24:
- return V4L2_PIX_FMT_NV24;
- case DRM_FORMAT_NV42:
- return V4L2_PIX_FMT_NV42;
- default:
+ auto info = std::find_if(pixelFormatInfo.begin(), pixelFormatInfo.end(),
+ [format](const PixelFormatInfo &info) {
+ return info.format == format;
+ });
+ if (info == pixelFormatInfo.end())
return format;
- }
+
+ return info->v4l2Format;
}