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
This commit is contained in:
Philipp Zabel 2018-08-09 15:08:59 +02:00 committed by Nicolas Dufresne
parent 9595fd08e3
commit 02d3f9748b

View file

@ -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)) {
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;
}