Commit 6c8268db authored by Rob Clark's avatar Rob Clark

v4l2: add interlaced support

parent 538d3a95
...@@ -1361,8 +1361,8 @@ gst_v4l2_object_get_all_caps (void) ...@@ -1361,8 +1361,8 @@ gst_v4l2_object_get_all_caps (void)
*/ */
gboolean gboolean
gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
struct v4l2_fmtdesc ** format, gint * w, gint * h, guint * fps_n, struct v4l2_fmtdesc ** format, gint * w, gint * h,
guint * fps_d, guint * size) gboolean * interlaced, guint * fps_n, guint * fps_d, guint * size)
{ {
GstStructure *structure; GstStructure *structure;
const GValue *framerate; const GValue *framerate;
...@@ -1391,6 +1391,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, ...@@ -1391,6 +1391,9 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
if (!gst_structure_get_int (structure, "height", h)) if (!gst_structure_get_int (structure, "height", h))
return FALSE; return FALSE;
if (!gst_structure_get_boolean (structure, "interlaced", interlaced))
*interlaced = FALSE;
framerate = gst_structure_get_value (structure, "framerate"); framerate = gst_structure_get_value (structure, "framerate");
if (!framerate) if (!framerate)
return FALSE; return FALSE;
...@@ -1987,15 +1990,15 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, ...@@ -1987,15 +1990,15 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
fmt.fmt.pix.width = *width; fmt.fmt.pix.width = *width;
fmt.fmt.pix.height = *height; fmt.fmt.pix.height = *height;
fmt.fmt.pix.pixelformat = pixelformat; 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); r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
if (r < 0 && errno == EINVAL) { if (r < 0 && errno == EINVAL) {
/* try again with progressive video */ /* try again with interlaced video */
fmt.fmt.pix.width = *width; fmt.fmt.pix.width = *width;
fmt.fmt.pix.height = *height; fmt.fmt.pix.height = *height;
fmt.fmt.pix.pixelformat = pixelformat; 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); r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
} }
...@@ -2037,6 +2040,7 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, ...@@ -2037,6 +2040,7 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
*height = fmt.fmt.pix.height; *height = fmt.fmt.pix.height;
switch (fmt.fmt.pix.field) { switch (fmt.fmt.pix.field) {
case V4L2_FIELD_ANY:
case V4L2_FIELD_NONE: case V4L2_FIELD_NONE:
*interlaced = FALSE; *interlaced = FALSE;
break; break;
...@@ -2058,10 +2062,22 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, ...@@ -2058,10 +2062,22 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
gboolean gboolean
gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat, gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
guint32 width, guint32 height) guint32 width, guint32 height, gboolean interlaced)
{ {
gint fd = v4l2object->video_fd; gint fd = v4l2object->video_fd;
struct v4l2_format format; 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_DEBUG_OBJECT (v4l2object->element, "Setting format to %dx%d, format "
"%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat)); "%" GST_FOURCC_FORMAT, width, height, GST_FOURCC_ARGS (pixelformat));
...@@ -2081,7 +2097,8 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat, ...@@ -2081,7 +2097,8 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
if (format.type == v4l2object->type && if (format.type == v4l2object->type &&
format.fmt.pix.width == width && format.fmt.pix.width == width &&
format.fmt.pix.height == height && 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 /* Nothing to do. We want to succeed immediately
* here because setting the same format back * here because setting the same format back
* can still fail due to EBUSY. By short-circuiting * can still fail due to EBUSY. By short-circuiting
...@@ -2098,25 +2115,10 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat, ...@@ -2098,25 +2115,10 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
format.fmt.pix.width = width; format.fmt.pix.width = width;
format.fmt.pix.height = height; format.fmt.pix.height = height;
format.fmt.pix.pixelformat = pixelformat; format.fmt.pix.pixelformat = pixelformat;
/* FIXME: request whole frames; need to use gstreamer interlace support format.fmt.pix.field = field;
* (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;
if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) { if (v4l2_ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
/* we might also get EBUSY here */ goto set_fmt_failed;
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;
} }
if (format.fmt.pix.width != width || format.fmt.pix.height != height) if (format.fmt.pix.width != width || format.fmt.pix.height != height)
......
...@@ -181,7 +181,7 @@ GstCaps* gst_v4l2_object_probe_caps_for_format (GstV4l2Object *v4l2object, ...@@ -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, gboolean gst_v4l2_object_get_caps_info (GstV4l2Object *v4l2object, GstCaps *caps,
struct v4l2_fmtdesc **format, gint *w, gint *h, 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); GSList* gst_v4l2_object_get_format_list (GstV4l2Object *v4l2object);
...@@ -190,7 +190,7 @@ GstCaps* gst_v4l2_object_get_all_caps (void); ...@@ -190,7 +190,7 @@ GstCaps* gst_v4l2_object_get_all_caps (void);
GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc); 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_start_streaming (GstV4l2Object *v4l2object);
gboolean gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object); gboolean gst_v4l2_object_stop_streaming (GstV4l2Object *v4l2object);
......
...@@ -689,6 +689,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) ...@@ -689,6 +689,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{ {
GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink);
gint w = 0, h = 0; gint w = 0, h = 0;
gboolean interlaced;
struct v4l2_fmtdesc *format; struct v4l2_fmtdesc *format;
guint fps_n, fps_d; guint fps_n, fps_d;
guint size; guint size;
...@@ -724,7 +725,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) ...@@ -724,7 +725,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
/* we want our own v4l2 type of fourcc codes */ /* we want our own v4l2 type of fourcc codes */
if (!gst_v4l2_object_get_caps_info (v4l2sink->v4l2object, caps, 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); GST_DEBUG_OBJECT (v4l2sink, "can't get capture format from caps %p", caps);
return FALSE; return FALSE;
} }
...@@ -734,8 +735,8 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) ...@@ -734,8 +735,8 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
return FALSE; return FALSE;
} }
if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat, w, if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat,
h)) { w, h, interlaced)) {
/* error already posted */ /* error already posted */
return FALSE; return FALSE;
} }
......
...@@ -611,6 +611,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) ...@@ -611,6 +611,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
{ {
GstV4l2Src *v4l2src; GstV4l2Src *v4l2src;
gint w = 0, h = 0; gint w = 0, h = 0;
gboolean interlaced;
struct v4l2_fmtdesc *format; struct v4l2_fmtdesc *format;
guint fps_n, fps_d; guint fps_n, fps_d;
guint size; guint size;
...@@ -632,7 +633,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) ...@@ -632,7 +633,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
/* we want our own v4l2 type of fourcc codes */ /* we want our own v4l2 type of fourcc codes */
if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, &w, 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, GST_INFO_OBJECT (v4l2src,
"can't get capture format from caps %" GST_PTR_FORMAT, caps); "can't get capture format from caps %" GST_PTR_FORMAT, caps);
return FALSE; return FALSE;
...@@ -641,8 +642,8 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) ...@@ -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, " GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
"format %s", w, h, fps_n, fps_d, format->description); "format %s", w, h, fps_n, fps_d, format->description);
if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, fps_n, if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h,
fps_d)) interlaced, fps_n, fps_d))
/* error already posted */ /* error already posted */
return FALSE; return FALSE;
......
...@@ -214,7 +214,8 @@ too_many_trials: ...@@ -214,7 +214,8 @@ too_many_trials:
******************************************************/ ******************************************************/
gboolean gboolean
gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat, 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; gint fd = v4l2src->v4l2object->video_fd;
struct v4l2_streamparm stream; struct v4l2_streamparm stream;
...@@ -223,7 +224,7 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat, ...@@ -223,7 +224,7 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
return TRUE; return TRUE;
if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width, if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width,
height)) { height, interlaced)) {
/* error already reported */ /* error already reported */
return FALSE; return FALSE;
} }
......
...@@ -31,7 +31,8 @@ gboolean gst_v4l2src_get_capture (GstV4l2Src * v4l2src); ...@@ -31,7 +31,8 @@ gboolean gst_v4l2src_get_capture (GstV4l2Src * v4l2src);
gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src, gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src,
guint32 pixelformat, guint32 pixelformat,
guint32 width, guint32 height, 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_init (GstV4l2Src * v4l2src, GstCaps *caps);
gboolean gst_v4l2src_capture_start (GstV4l2Src * v4l2src); gboolean gst_v4l2src_capture_start (GstV4l2Src * v4l2src);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment