mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 04:46:13 +00:00
v4l2: get_nearest_size: Fix "Unsupported field type" errors
Most V4L2 ioctls like try_fmt will adjust input fields to match what the hardware can do rather then returning -EINVAL. As is docmented here: http://linuxtv.org/downloads/v4l-dvb-apis/vidioc-g-fmt.html EINVAL is only returned if the buffer type field is invalid or not supported. So upon requesting V4L2_FIELD_NONE devices which can only do interlaced mode will change the field value to e.g. V4L2_FIELD_BOTTOM as only returning half the lines is the closest they can do to progressive modes. In essence this means that we've failed to get a (usable) progessive mode and should fall back to interlaced mode. This commit adds a check for having gotten a usable field value after the first try_fmt, to force fallback to interlaced mode even if the try_fmt succeeded, thereby fixing get_nearest_size failing on these devices. https://bugzilla.gnome.org/show_bug.cgi?id=735660
This commit is contained in:
parent
8ad0509a1c
commit
116649371e
1 changed files with 27 additions and 17 deletions
|
@ -2140,6 +2140,24 @@ default_frame_sizes:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_v4l2_object_get_interlace (int field, gboolean * interlaced)
|
||||||
|
{
|
||||||
|
switch (field) {
|
||||||
|
case V4L2_FIELD_ANY:
|
||||||
|
case V4L2_FIELD_NONE:
|
||||||
|
*interlaced = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
case V4L2_FIELD_INTERLACED:
|
||||||
|
case V4L2_FIELD_INTERLACED_TB:
|
||||||
|
case V4L2_FIELD_INTERLACED_BT:
|
||||||
|
*interlaced = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
||||||
guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
|
guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
|
||||||
|
@ -2169,7 +2187,8 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
||||||
fmt.fmt.pix.field = V4L2_FIELD_NONE;
|
fmt.fmt.pix.field = V4L2_FIELD_NONE;
|
||||||
|
|
||||||
r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
|
r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
|
||||||
if (r < 0 && errno == EINVAL) {
|
if ((r < 0 && errno == EINVAL) ||
|
||||||
|
!gst_v4l2_object_get_interlace (fmt.fmt.pix.field, interlaced)) {
|
||||||
/* try again with interlaced video */
|
/* try again with interlaced video */
|
||||||
memset (&fmt, 0, sizeof (fmt));
|
memset (&fmt, 0, sizeof (fmt));
|
||||||
fmt.type = v4l2object->type;
|
fmt.type = v4l2object->type;
|
||||||
|
@ -2202,7 +2221,8 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
||||||
fmt.fmt.pix.field = V4L2_FIELD_NONE;
|
fmt.fmt.pix.field = V4L2_FIELD_NONE;
|
||||||
|
|
||||||
r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
|
r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
|
||||||
if (r < 0 && errno == EINVAL) {
|
if ((r < 0 && errno == EINVAL) ||
|
||||||
|
!gst_v4l2_object_get_interlace (fmt.fmt.pix.field, interlaced)) {
|
||||||
/* try again with interlaced video */
|
/* try again with interlaced video */
|
||||||
memset (&fmt, 0, sizeof (fmt));
|
memset (&fmt, 0, sizeof (fmt));
|
||||||
fmt.type = v4l2object->type;
|
fmt.type = v4l2object->type;
|
||||||
|
@ -2223,21 +2243,11 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
|
||||||
*width = fmt.fmt.pix.width;
|
*width = fmt.fmt.pix.width;
|
||||||
*height = fmt.fmt.pix.height;
|
*height = fmt.fmt.pix.height;
|
||||||
|
|
||||||
switch (fmt.fmt.pix.field) {
|
if (!gst_v4l2_object_get_interlace (fmt.fmt.pix.field, interlaced)) {
|
||||||
case V4L2_FIELD_ANY:
|
GST_WARNING_OBJECT (v4l2object->element,
|
||||||
case V4L2_FIELD_NONE:
|
"Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u: %u",
|
||||||
*interlaced = FALSE;
|
GST_FOURCC_ARGS (pixelformat), *width, *height, fmt.fmt.pix.field);
|
||||||
break;
|
goto error;
|
||||||
case V4L2_FIELD_INTERLACED:
|
|
||||||
case V4L2_FIELD_INTERLACED_TB:
|
|
||||||
case V4L2_FIELD_INTERLACED_BT:
|
|
||||||
*interlaced = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
GST_WARNING_OBJECT (v4l2object->element,
|
|
||||||
"Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
|
|
||||||
GST_FOURCC_ARGS (pixelformat), *width, *height);
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
Loading…
Reference in a new issue