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; }