[libcamera-devel] [PATCH 4/4] v4l2: camera_proxy: Create format info array
Jacopo Mondi
jacopo at jmondi.org
Tue Jan 7 11:17:06 CET 2020
Hi Laurent,
On Mon, Jan 06, 2020 at 06:14:17PM +0200, Laurent Pinchart wrote:
> Create a PixelFormatInfo structure to store information about a format,
> and add a global array of format info for all the formats currently
> supported. Move the format helpers to use the information from the
> array.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> src/v4l2/v4l2_camera_proxy.cpp | 180 +++++++++++++--------------------
> 1 file changed, 70 insertions(+), 110 deletions(-)
>
> diff --git a/src/v4l2/v4l2_camera_proxy.cpp b/src/v4l2/v4l2_camera_proxy.cpp
> index 6a222d702e13..b8c1a53af1c2 100644
> --- a/src/v4l2/v4l2_camera_proxy.cpp
> +++ b/src/v4l2/v4l2_camera_proxy.cpp
> @@ -509,134 +509,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 } }} },
> +}};
While the table seems correct, I wonder
> +
> +} /* 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;
How does this work for planar YUV420 format where, if I read it
correctly, the Cr and Crb planes portion has half the width of the Y
one ?
https://www.kernel.org/doc/html/v5.4/media/uapi/v4l/pixfmt-yuv420.html
Otherwise, the table looks correct and should be made a library-wide
component later
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Thanks
j
> }
>
> 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;
> }
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20200107/04279c67/attachment-0001.sig>
More information about the libcamera-devel
mailing list