From cfb4c021871ae65a8836401768c1b816229c1191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Zanelli?= Date: Mon, 29 Sep 2014 11:49:45 +0200 Subject: [PATCH] v4l2object: set colorspace for output devices When the v4l2 device is an output device, the application shall set the colorspace. So map GStreamer colorimetry info to V4L2 colorspace and set on set_format. In case we have no colorimetry information, we try to guess it according to pixel format and video size. https://bugzilla.gnome.org/show_bug.cgi?id=737579 --- sys/v4l2/gstv4l2object.c | 50 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index b99bdbb028..dd5c0a9df4 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -2538,6 +2538,7 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps) gint n_v4l_planes; gint i = 0; gboolean is_mplane, format_changed; + enum v4l2_colorspace colorspace = 0; GST_V4L2_CHECK_OPEN (v4l2object); GST_V4L2_CHECK_NOT_ACTIVE (v4l2object); @@ -2573,6 +2574,28 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps) field = V4L2_FIELD_NONE; } + if (V4L2_TYPE_IS_OUTPUT (v4l2object->type)) { + /* We should set colorspace if we have it */ + if (gst_video_colorimetry_matches (&info.colorimetry, "bt601")) { + colorspace = V4L2_COLORSPACE_SMPTE170M; + } else if (gst_video_colorimetry_matches (&info.colorimetry, "bt709")) { + colorspace = V4L2_COLORSPACE_REC709; + } else if (gst_video_colorimetry_matches (&info.colorimetry, "smpte240m")) { + colorspace = V4L2_COLORSPACE_SMPTE240M; + } else { + /* 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; + } else if (GST_VIDEO_INFO_IS_RGB (&info)) { + colorspace = V4L2_COLORSPACE_SRGB; + } + } + } + GST_DEBUG_OBJECT (v4l2object->element, "Desired format %dx%d, format " "%" GST_FOURCC_FORMAT " stride: %d", width, height, GST_FOURCC_ARGS (pixelformat), GST_VIDEO_INFO_PLANE_STRIDE (&info, 0)); @@ -2600,6 +2623,16 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps) format.fmt.pix_mp.height != height || format.fmt.pix_mp.pixelformat != pixelformat || format.fmt.pix_mp.field != field; + + if (V4L2_TYPE_IS_OUTPUT (v4l2object->type)) { + if (is_mplane) { + format_changed = format_changed || + format.fmt.pix_mp.colorspace != colorspace; + } else { + format_changed = format_changed || + format.fmt.pix.colorspace != colorspace; + } + } } #ifndef GST_DISABLE_GST_DEBUG @@ -2689,14 +2722,25 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, GstCaps * caps) } #endif + if (V4L2_TYPE_IS_OUTPUT (v4l2object->type)) { + if (is_mplane) + format.fmt.pix_mp.colorspace = colorspace; + else + format.fmt.pix.colorspace = colorspace; + + GST_DEBUG_OBJECT (v4l2object->element, "Desired colorspace is %d", + colorspace); + } + if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) goto set_fmt_failed; GST_DEBUG_OBJECT (v4l2object->element, "Got format of %dx%d, format " - "%" GST_FOURCC_FORMAT ", nb planes %d", format.fmt.pix.width, - format.fmt.pix_mp.height, + "%" GST_FOURCC_FORMAT ", nb planes %d, colorspace %d", + format.fmt.pix.width, format.fmt.pix_mp.height, GST_FOURCC_ARGS (format.fmt.pix.pixelformat), - is_mplane ? format.fmt.pix_mp.num_planes : 1); + is_mplane ? format.fmt.pix_mp.num_planes : 1, + is_mplane ? format.fmt.pix_mp.colorspace : format.fmt.pix.colorspace); #ifndef GST_DISABLE_GST_DEBUG if (is_mplane) {