media: uvcvideo: Convey full colorspace information to V4L2
authorAdam Goode <agoode@google.com>
Wed, 2 Sep 2020 20:06:17 +0000 (22:06 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 10 Sep 2020 12:06:27 +0000 (14:06 +0200)
The Color Matching Descriptor has been present in USB cameras since
the original version of UVC, but it has never been fully exposed
in Linux.

This change informs V4L2 of all of the UVC colorspace parameters:
color primaries, transfer characteristics, and YCbCr encoding.
videodev2.h doesn't have values for all the possible UVC color settings,
so it is mapped as closely as possible.

Signed-off-by: Adam Goode <agoode@google.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/usb/uvc/uvc_driver.c
drivers/media/usb/uvc/uvc_v4l2.c
drivers/media/usb/uvc/uvcvideo.h

index 3b48451ead1fbd1b7c885140ee374fdc78cebc40..ddb9eaa11be71320adc20b4fd74ec3c7511c5c44 100644 (file)
@@ -253,10 +253,10 @@ static struct uvc_format_desc *uvc_format_by_guid(const u8 guid[16])
        return NULL;
 }
 
-static u32 uvc_colorspace(const u8 primaries)
+static enum v4l2_colorspace uvc_colorspace(const u8 primaries)
 {
-       static const u8 colorprimaries[] = {
-               0,
+       static const enum v4l2_colorspace colorprimaries[] = {
+               V4L2_COLORSPACE_DEFAULT,  /* Unspecified */
                V4L2_COLORSPACE_SRGB,
                V4L2_COLORSPACE_470_SYSTEM_M,
                V4L2_COLORSPACE_470_SYSTEM_BG,
@@ -267,7 +267,61 @@ static u32 uvc_colorspace(const u8 primaries)
        if (primaries < ARRAY_SIZE(colorprimaries))
                return colorprimaries[primaries];
 
-       return 0;
+       return V4L2_COLORSPACE_DEFAULT;  /* Reserved */
+}
+
+static enum v4l2_xfer_func uvc_xfer_func(const u8 transfer_characteristics)
+{
+       /*
+        * V4L2 does not currently have definitions for all possible values of
+        * UVC transfer characteristics. If v4l2_xfer_func is extended with new
+        * values, the mapping below should be updated.
+        *
+        * Substitutions are taken from the mapping given for
+        * V4L2_XFER_FUNC_DEFAULT documented in videodev2.h.
+        */
+       static const enum v4l2_xfer_func xfer_funcs[] = {
+               V4L2_XFER_FUNC_DEFAULT,    /* Unspecified */
+               V4L2_XFER_FUNC_709,
+               V4L2_XFER_FUNC_709,        /* Substitution for BT.470-2 M */
+               V4L2_XFER_FUNC_709,        /* Substitution for BT.470-2 B, G */
+               V4L2_XFER_FUNC_709,        /* Substitution for SMPTE 170M */
+               V4L2_XFER_FUNC_SMPTE240M,
+               V4L2_XFER_FUNC_NONE,
+               V4L2_XFER_FUNC_SRGB,
+       };
+
+       if (transfer_characteristics < ARRAY_SIZE(xfer_funcs))
+               return xfer_funcs[transfer_characteristics];
+
+       return V4L2_XFER_FUNC_DEFAULT;  /* Reserved */
+}
+
+static enum v4l2_ycbcr_encoding uvc_ycbcr_enc(const u8 matrix_coefficients)
+{
+       /*
+        * V4L2 does not currently have definitions for all possible values of
+        * UVC matrix coefficients. If v4l2_ycbcr_encoding is extended with new
+        * values, the mapping below should be updated.
+        *
+        * Substitutions are taken from the mapping given for
+        * V4L2_YCBCR_ENC_DEFAULT documented in videodev2.h.
+        *
+        * FCC is assumed to be close enough to 601.
+        */
+       static const enum v4l2_ycbcr_encoding ycbcr_encs[] = {
+               V4L2_YCBCR_ENC_DEFAULT,  /* Unspecified */
+               V4L2_YCBCR_ENC_709,
+               V4L2_YCBCR_ENC_601,      /* Substitution for FCC */
+               V4L2_YCBCR_ENC_601,      /* Substitution for BT.470-2 B, G */
+               V4L2_YCBCR_ENC_601,
+               V4L2_YCBCR_ENC_SMPTE240M,
+       };
+
+       if (matrix_coefficients < ARRAY_SIZE(ycbcr_encs))
+               return ycbcr_encs[matrix_coefficients];
+
+       return V4L2_YCBCR_ENC_DEFAULT;  /* Reserved */
 }
 
 /* Simplify a fraction using a simple continued fraction decomposition. The
@@ -709,6 +763,8 @@ static int uvc_parse_format(struct uvc_device *dev,
                }
 
                format->colorspace = uvc_colorspace(buffer[3]);
+               format->xfer_func = uvc_xfer_func(buffer[4]);
+               format->ycbcr_enc = uvc_ycbcr_enc(buffer[5]);
 
                buflen -= buffer[0];
                buffer += buffer[0];
index 5e6f3153b5ff878fc02fcda0f84d10943d663659..fa06bfa174ad3bf46d75d1bc53918485ad737ca9 100644 (file)
@@ -283,6 +283,8 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
        fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
        fmt->fmt.pix.pixelformat = format->fcc;
        fmt->fmt.pix.colorspace = format->colorspace;
+       fmt->fmt.pix.xfer_func = format->xfer_func;
+       fmt->fmt.pix.ycbcr_enc = format->ycbcr_enc;
 
        if (uvc_format != NULL)
                *uvc_format = format;
@@ -319,6 +321,8 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame);
        fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize;
        fmt->fmt.pix.colorspace = format->colorspace;
+       fmt->fmt.pix.xfer_func = format->xfer_func;
+       fmt->fmt.pix.ycbcr_enc = format->ycbcr_enc;
 
 done:
        mutex_unlock(&stream->mutex);
index c7f043121b418d9e17b9aefb118e58c6f6016fbd..a3dfacf069c44dede79b361f4c4e0d21002932b7 100644 (file)
@@ -374,7 +374,9 @@ struct uvc_format {
        u8 type;
        u8 index;
        u8 bpp;
-       u8 colorspace;
+       enum v4l2_colorspace colorspace;
+       enum v4l2_xfer_func xfer_func;
+       enum v4l2_ycbcr_encoding ycbcr_enc;
        u32 fcc;
        u32 flags;