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
diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c
index 5512ed9..69f7f5f 100644
--- a/sys/v4l2/gstv4l2object.c
+++ b/sys/v4l2/gstv4l2object.c
@@ -3198,6 +3198,32 @@
 }
 
 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 @@
   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 @@
 
   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;
   }