media: vivid: Add support to the CSC API
authorDafna Hirschfeld <dafna.hirschfeld@collabora.com>
Thu, 27 Aug 2020 19:46:09 +0000 (21:46 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Sat, 26 Sep 2020 08:21:34 +0000 (10:21 +0200)
The CSC API (Colorspace conversion) allows userspace to try
to configure the colorspace, transfer function, Y'CbCr/HSV encoding
and the quantization for capture devices. This patch adds support
to the CSC API in vivid.
Using the CSC API, userspace is allowed to do the following:

- Set the colorspace.
- Set the xfer_func.
- Set the ycbcr_enc function for YUV formats.
- Set the hsv_enc function for HSV formats
- Set the quantization for YUV and RGB formats.

Signed-off-by: Dafna Hirschfeld <dafna.hirschfeld@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/test-drivers/vivid/vivid-vid-cap.c
drivers/media/test-drivers/vivid/vivid-vid-common.c
include/media/v4l2-common.h

index e94beef008c8e620cc27f5114ef32d6bb31526c3..eadf28ab1e393d77da83684a637fd460c93adce2 100644 (file)
@@ -560,6 +560,7 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
        unsigned factor = 1;
        unsigned w, h;
        unsigned p;
+       bool user_set_csc = !!(mp->flags & V4L2_PIX_FMT_FLAG_SET_CSC);
 
        fmt = vivid_get_format(dev, mp->pixelformat);
        if (!fmt) {
@@ -633,13 +634,30 @@ int vivid_try_fmt_vid_cap(struct file *file, void *priv,
                        (fmt->bit_depth[p] / fmt->vdownsampling[p])) /
                        (fmt->bit_depth[0] / fmt->vdownsampling[0]);
 
-       mp->colorspace = vivid_colorspace_cap(dev);
-       if (fmt->color_enc == TGP_COLOR_ENC_HSV)
-               mp->hsv_enc = vivid_hsv_enc_cap(dev);
-       else
+       if (!user_set_csc || !v4l2_is_colorspace_valid(mp->colorspace))
+               mp->colorspace = vivid_colorspace_cap(dev);
+
+       if (!user_set_csc || !v4l2_is_xfer_func_valid(mp->xfer_func))
+               mp->xfer_func = vivid_xfer_func_cap(dev);
+
+       if (fmt->color_enc == TGP_COLOR_ENC_HSV) {
+               if (!user_set_csc || !v4l2_is_hsv_enc_valid(mp->hsv_enc))
+                       mp->hsv_enc = vivid_hsv_enc_cap(dev);
+       } else if (fmt->color_enc == TGP_COLOR_ENC_YCBCR) {
+               if (!user_set_csc || !v4l2_is_ycbcr_enc_valid(mp->ycbcr_enc))
+                       mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
+       } else {
                mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
-       mp->xfer_func = vivid_xfer_func_cap(dev);
-       mp->quantization = vivid_quantization_cap(dev);
+       }
+
+       if (fmt->color_enc == TGP_COLOR_ENC_YCBCR ||
+           fmt->color_enc == TGP_COLOR_ENC_RGB) {
+               if (!user_set_csc || !v4l2_is_quant_valid(mp->quantization))
+                       mp->quantization = vivid_quantization_cap(dev);
+       } else {
+               mp->quantization = vivid_quantization_cap(dev);
+       }
+
        memset(mp->reserved, 0, sizeof(mp->reserved));
        return 0;
 }
@@ -769,6 +787,14 @@ int vivid_s_fmt_vid_cap(struct file *file, void *priv,
        if (vivid_is_sdtv_cap(dev))
                dev->tv_field_cap = mp->field;
        tpg_update_mv_step(&dev->tpg);
+       dev->tpg.colorspace = mp->colorspace;
+       dev->tpg.xfer_func = mp->xfer_func;
+       if (dev->fmt_cap->color_enc == TGP_COLOR_ENC_YCBCR)
+               dev->tpg.ycbcr_enc = mp->ycbcr_enc;
+       else
+               dev->tpg.hsv_enc = mp->hsv_enc;
+       dev->tpg.quantization = mp->quantization;
+
        return 0;
 }
 
index 76b0be670ebb34b2c02d5a09beedf4a5581dda19..19701fe720304c3d34e7fb8e9ad6286f5eaf8304 100644 (file)
@@ -920,6 +920,31 @@ int vivid_enum_fmt_vid(struct file *file, void  *priv,
        fmt = &vivid_formats[f->index];
 
        f->pixelformat = fmt->fourcc;
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+           f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               return 0;
+       /*
+        * For capture devices, we support the CSC API.
+        * We allow userspace to:
+        * 1. set the colorspace
+        * 2. set the xfer_func
+        * 3. set the ycbcr_enc on YUV formats
+        * 4. set the hsv_enc on HSV formats
+        * 5. set the quantization on YUV and RGB formats
+        */
+       f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE;
+       f->flags |= V4L2_FMT_FLAG_CSC_XFER_FUNC;
+
+       if (fmt->color_enc == TGP_COLOR_ENC_YCBCR) {
+               f->flags |= V4L2_FMT_FLAG_CSC_YCBCR_ENC;
+               f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION;
+       } else if (fmt->color_enc == TGP_COLOR_ENC_HSV) {
+               f->flags |= V4L2_FMT_FLAG_CSC_HSV_ENC;
+       } else if (fmt->color_enc == TGP_COLOR_ENC_RGB) {
+               f->flags |= V4L2_FMT_FLAG_CSC_QUANTIZATION;
+       }
+
        return 0;
 }
 
index 150ee16ebd81184e68d66c934001d36973809e61..a3083529b698512e619f1b0a6261042c7299206d 100644 (file)
@@ -539,4 +539,33 @@ static inline void v4l2_buffer_set_timestamp(struct v4l2_buffer *buf,
        buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
 }
 
+static inline bool v4l2_is_colorspace_valid(__u32 colorspace)
+{
+       return colorspace > V4L2_COLORSPACE_DEFAULT &&
+              colorspace <= V4L2_COLORSPACE_DCI_P3;
+}
+
+static inline bool v4l2_is_xfer_func_valid(__u32 xfer_func)
+{
+       return xfer_func > V4L2_XFER_FUNC_DEFAULT &&
+              xfer_func <= V4L2_XFER_FUNC_SMPTE2084;
+}
+
+static inline bool v4l2_is_ycbcr_enc_valid(__u8 ycbcr_enc)
+{
+       return ycbcr_enc > V4L2_YCBCR_ENC_DEFAULT &&
+              ycbcr_enc <= V4L2_YCBCR_ENC_SMPTE240M;
+}
+
+static inline bool v4l2_is_hsv_enc_valid(__u8 hsv_enc)
+{
+       return hsv_enc == V4L2_HSV_ENC_180 || hsv_enc == V4L2_HSV_ENC_256;
+}
+
+static inline bool v4l2_is_quant_valid(__u8 quantization)
+{
+       return quantization == V4L2_QUANTIZATION_FULL_RANGE ||
+              quantization == V4L2_QUANTIZATION_LIM_RANGE;
+}
+
 #endif /* V4L2_COMMON_H_ */