From 02d3f9748bebac4c22e8dd33b55cf5dff8259d2a Mon Sep 17 00:00:00 2001
From: Philipp Zabel
Date: Thu, 9 Aug 2018 15:08:59 +0200
Subject: [PATCH] v4l2object: improve colorspace handling for JPEG sources
gstjpegdec sets 1:4:0:0 colorimetry (full range BT.601 YCbCr encoding
with unknown primaries and unknown transfer function). This currently
gets translated to bt601 or bt709 depending on resolution.
Both cases result in a negotiation failure:
ERROR: from element /GstPipeline:pipeline0/v4l2video0convert:v4l2video0convert0: Device '/dev/video0' does not support 1:4:0:0 colorimetry
Improve the guessing game by selecting JPEG colorimetry (JPEG colorspace
with sRGB transfer function) under these specific conditions, and loosen
the matching so that 1:4:0:0 input gets accepted if the device is
actually configured to 1:4:7:1 (V4L2_PIX_FMT_JPEG default).
https://bugzilla.gnome.org/show_bug.cgi?id=796940
---
sys/v4l2/gstv4l2object.c | 50 ++++++++++++++++++++++++++++++++--------
1 file changed, 41 insertions(+), 9 deletions(-)
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 4b650a0c02..4003e1d198 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3197,6 +3197,32 @@ gst_v4l2_object_extrapolate_stride (const GstVideoFormatInfo * finfo,
return estride;
}
+static gboolean
+gst_v4l2_video_colorimetry_matches (const GstVideoColorimetry * cinfo,
+ const gchar * color)
+{
+ GstVideoColorimetry ci;
+ static const GstVideoColorimetry ci_likely_jpeg = {
+ GST_VIDEO_COLOR_RANGE_0_255, GST_VIDEO_COLOR_MATRIX_BT601,
+ GST_VIDEO_TRANSFER_UNKNOWN, GST_VIDEO_COLOR_PRIMARIES_UNKNOWN };
+ static const GstVideoColorimetry ci_jpeg = {
+ GST_VIDEO_COLOR_RANGE_0_255, GST_VIDEO_COLOR_MATRIX_BT601,
+ GST_VIDEO_TRANSFER_SRGB, GST_VIDEO_COLOR_PRIMARIES_BT709 };
+
+ if (!gst_video_colorimetry_from_string (&ci, color))
+ return FALSE;
+
+ if (gst_video_colorimetry_is_equal (&ci, cinfo))
+ return TRUE;
+
+ /* Allow 1:4:0:0 (produced by jpegdec) if the device expects 1:4:7:1 */
+ if (gst_video_colorimetry_is_equal (&ci, &ci_likely_jpeg)
+ && gst_video_colorimetry_is_equal (cinfo, &ci_jpeg))
+ return TRUE;
+
+ return FALSE;
+}
+
static gboolean
gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
gboolean try_only, GstV4l2Error * error)
@@ -3376,11 +3402,19 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
if (colorspace == 0) {
/* Try to guess colorspace according to pixelformat and size */
if (GST_VIDEO_INFO_IS_YUV (&info)) {
- /* SD streams likely use SMPTE170M and HD streams REC709 */
- if (width <= 720 && height <= 576)
- colorspace = V4L2_COLORSPACE_SMPTE170M;
- else
- colorspace = V4L2_COLORSPACE_REC709;
+ if (range == V4L2_QUANTIZATION_FULL_RANGE
+ && matrix == V4L2_YCBCR_ENC_601 && transfer == 0) {
+ /* Full range BT.601 YCbCr encoding with unknown primaries and transfer
+ * function most likely is JPEG */
+ colorspace = V4L2_COLORSPACE_JPEG;
+ transfer = V4L2_XFER_FUNC_SRGB;
+ } else {
+ /* SD streams likely use SMPTE170M and HD streams REC709 */
+ if (width <= 720 && height <= 576)
+ colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else
+ colorspace = V4L2_COLORSPACE_REC709;
+ }
} else if (GST_VIDEO_INFO_IS_RGB (&info)) {
colorspace = V4L2_COLORSPACE_SRGB;
transfer = V4L2_XFER_FUNC_NONE;
@@ -3527,10 +3561,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
s = gst_caps_get_structure (caps, 0);
if (gst_structure_has_field (s, "colorimetry")) {
- GstVideoColorimetry ci;
- if (!gst_video_colorimetry_from_string (&ci,
- gst_structure_get_string (s, "colorimetry"))
- || !gst_video_colorimetry_is_equal (&ci, &info.colorimetry))
+ if (!gst_v4l2_video_colorimetry_matches (&info.colorimetry,
+ gst_structure_get_string (s, "colorimetry")))
goto invalid_colorimetry;
}