diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index e1cce2b877a6813ea7c96b72cdc79a1d13518b3e..f4512187c9193373df54d7a49077fcea241dd4cc 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -1361,8 +1361,8 @@ gst_v4l2_object_get_all_caps (void) */ gboolean gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, - struct v4l2_fmtdesc ** format, gint * w, gint * h, guint * fps_n, - guint * fps_d, guint * size) + struct v4l2_fmtdesc ** format, gint * w, gint * h, + gboolean * interlaced, guint * fps_n, guint * fps_d, guint * size) { GstStructure *structure; const GValue *framerate; @@ -1391,6 +1391,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, if (!gst_structure_get_int (structure, "height", h)) return FALSE; + if (!gst_structure_get_boolean (structure, "interlaced", interlaced)) + *interlaced = FALSE; + framerate = gst_structure_get_value (structure, "framerate"); if (!framerate) return FALSE; @@ -1987,15 +1990,15 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, fmt.fmt.pix.width = *width; fmt.fmt.pix.height = *height; fmt.fmt.pix.pixelformat = pixelformat; - fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + fmt.fmt.pix.field = V4L2_FIELD_NONE; r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt); if (r < 0 && errno == EINVAL) { - /* try again with progressive video */ + /* try again with interlaced video */ fmt.fmt.pix.width = *width; fmt.fmt.pix.height = *height; fmt.fmt.pix.pixelformat = pixelformat; - fmt.fmt.pix.field = V4L2_FIELD_NONE; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt); } @@ -2037,6 +2040,7 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, *height = fmt.fmt.pix.height; switch (fmt.fmt.pix.field) { + case V4L2_FIELD_ANY: case V4L2_FIELD_NONE: *interlaced = FALSE; break; @@ -2058,10 +2062,22 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, gboolean gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat, - guint32 width, guint32 height) + guint32 width, guint32 height, gboolean interlaced) { gint fd = v4l2object->video_fd; struct v4l2_format format; + enum v4l2_field field; + + if (interlaced) { + GST_DEBUG_OBJECT (v4l2object->element, "interlaced video"); + /* ideally we would differentiate between types of interlaced video + * but there is not sufficient information in the caps.. + */ + field = V4L2_FIELD_SEQ_TB; + } else { + GST_DEBUG_OBJECT (v4l2object->element, "progressive video"); + field = V4L2_FIELD_NONE; + } GST_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format " "%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat)); @@ -2081,7 +2097,8 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat, if (format.type == v4l2object->type && format.fmt.pix.width == width && format.fmt.pix.height == height && - format.fmt.pix.pixelformat == pixelformat) { + format.fmt.pix.pixelformat == pixelformat && + format.fmt.pix.field == field) { /* Nothing to do. We want to succeed immediately * here because setting the same format back * can still fail due to EBUSY. By short-circuiting @@ -2098,25 +2115,10 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat, format.fmt.pix.width = width; format.fmt.pix.height = height; format.fmt.pix.pixelformat = pixelformat; - /* FIXME: request whole frames; need to use gstreamer interlace support - * (INTERLACED mode returns frames where the fields have already been - * combined, there are other modes for requesting fields individually) */ - format.fmt.pix.field = V4L2_FIELD_INTERLACED; + format.fmt.pix.field = field; if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) { - /* we might also get EBUSY here */ - if (errno != EINVAL) - goto set_fmt_failed; - - GST_DEBUG_OBJECT (v4l2object->element, "trying again..."); - - /* try again with progressive video */ - format.fmt.pix.width = width; - format.fmt.pix.height = height; - format.fmt.pix.pixelformat = pixelformat; - format.fmt.pix.field = V4L2_FIELD_NONE; - if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) - goto set_fmt_failed; + goto set_fmt_failed; } if (format.fmt.pix.width != width || format.fmt.pix.height != height) diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h index b21c27d7665cb1e9a45445ea001e58d3f7dc0340..d83861a4d721d621e50ff52e796f03b4d1212336 100644 --- a/sys/v4l2/gstv4l2object.h +++ b/sys/v4l2/gstv4l2object.h @@ -181,7 +181,7 @@ GstCaps* gst_v4l2_object_probe_caps_for_format (GstV4l2Object *v4l2object, gboolean gst_v4l2_object_get_caps_info (GstV4l2Object *v4l2object, GstCaps *caps, struct v4l2_fmtdesc **format, gint *w, gint *h, - guint *fps_n, guint *fps_d, guint *size); + gboolean * interlaced, guint *fps_n, guint *fps_d, guint *size); GSList* gst_v4l2_object_get_format_list (GstV4l2Object *v4l2object); @@ -190,7 +190,7 @@ GstCaps* gst_v4l2_object_get_all_caps (void); GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc); -gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height); +gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height, gboolean interlaced); gboolean gst_v4l2_object_start_streaming (GstV4l2Object *v4l2object); gboolean gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object); diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c index 8652a9fde559d28af4b1792dbdf0edab14994cae..6b3da4e1a861e2176df995d143951763d852df1c 100644 --- a/sys/v4l2/gstv4l2sink.c +++ b/sys/v4l2/gstv4l2sink.c @@ -689,6 +689,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); gint w = 0, h = 0; + gboolean interlaced; struct v4l2_fmtdesc *format; guint fps_n, fps_d; guint size; @@ -724,7 +725,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) /* we want our own v4l2 type of fourcc codes */ if (!gst_v4l2_object_get_caps_info (v4l2sink->v4l2object, caps, - &format, &w, &h, &fps_n, &fps_d, &size)) { + &format, &w, &h, &interlaced, &fps_n, &fps_d, &size)) { GST_DEBUG_OBJECT (v4l2sink, "can't get capture format from caps %p", caps); return FALSE; } @@ -734,8 +735,8 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) return FALSE; } - if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat, w, - h)) { + if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat, + w, h, interlaced)) { /* error already posted */ return FALSE; } diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index 3fd26519ee2a99c878cda104412b0496409ed7b6..ed3b2ac6ef5a151fbe2dcca174ba478b7d1a8bac 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -611,6 +611,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) { GstV4l2Src *v4l2src; gint w = 0, h = 0; + gboolean interlaced; struct v4l2_fmtdesc *format; guint fps_n, fps_d; guint size; @@ -632,7 +633,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) /* we want our own v4l2 type of fourcc codes */ if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, &w, - &h, &fps_n, &fps_d, &size)) { + &h, &interlaced, &fps_n, &fps_d, &size)) { GST_INFO_OBJECT (v4l2src, "can't get capture format from caps %" GST_PTR_FORMAT, caps); return FALSE; @@ -641,8 +642,8 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, " "format %s", w, h, fps_n, fps_d, format->description); - if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, fps_n, - fps_d)) + if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, + interlaced, fps_n, fps_d)) /* error already posted */ return FALSE; diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index ecd54b843f1b2ecdb01fbeff289b3cc75fb37a63..fb6c37456ba610c6d3204c4ae9a0fc83ed50d3e8 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -214,7 +214,8 @@ too_many_trials: ******************************************************/ gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat, - guint32 width, guint32 height, guint fps_n, guint fps_d) + guint32 width, guint32 height, gboolean interlaced, + guint fps_n, guint fps_d) { gint fd = v4l2src->v4l2object->video_fd; struct v4l2_streamparm stream; @@ -223,7 +224,7 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat, return TRUE; if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width, - height)) { + height, interlaced)) { /* error already reported */ return FALSE; } diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h index 1fc7411fae17917db77e27bde0a2a305e24b9301..709191870e95afe6c0f4e7361bb6f8332d06f822 100644 --- a/sys/v4l2/v4l2src_calls.h +++ b/sys/v4l2/v4l2src_calls.h @@ -31,7 +31,8 @@ gboolean gst_v4l2src_get_capture (GstV4l2Src * v4l2src); gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat, guint32 width, guint32 height, - guint32 fps_n, guint32 fps_d); + gboolean interlaced, + guint32 fps_n, guint32 fps_d); gboolean gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps *caps); gboolean gst_v4l2src_capture_start (GstV4l2Src * v4l2src);