From 4a301247017d896c8e76789895c5d1d8e2c652b6 Mon Sep 17 00:00:00 2001 From: Edgard Lima Date: Tue, 29 Aug 2006 20:59:47 +0000 Subject: [PATCH] Fixed framerate negotiation. Original commit message from CVS: Fixed framerate negotiation. --- sys/v4l2/gstv4l2src.c | 55 ++++++++++++++++++++++++++++--------- sys/v4l2/v4l2src_calls.c | 58 +++++++++++++++++++++++++++++++++++++++- sys/v4l2/v4l2src_calls.h | 7 ++++- 3 files changed, 106 insertions(+), 14 deletions(-) diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c index d5cb19404f..3ad39a4323 100644 --- a/sys/v4l2/gstv4l2src.c +++ b/sys/v4l2/gstv4l2src.c @@ -755,13 +755,9 @@ gst_v4l2src_get_caps (GstBaseSrc * src) gst_structure_set (structure, "width", GST_TYPE_INT_RANGE, min_w, max_w, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL); - if (fps_n > 0) { - gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, - fps_n, fps_d, NULL); - } else { - gst_structure_set (structure, "framerate", GST_TYPE_FRACTION_RANGE, - 1, 1, 100, 1, NULL); - } + + gst_structure_set (structure, "framerate", GST_TYPE_FRACTION_RANGE, + 1, 1, 100, 1, NULL); gst_caps_append_structure (caps, structure); @@ -778,6 +774,8 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) gint w, h; GstStructure *structure; struct v4l2_fmtdesc *format; + const GValue *framerate; + guint fps_n, fps_d; v4l2src = GST_V4L2SRC (src); @@ -803,18 +801,37 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) gst_structure_get_int (structure, "width", &w); gst_structure_get_int (structure, "height", &h); + framerate = gst_structure_get_value (structure, "framerate"); GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d, format %s", w, h, format->description); - /* this only fills in v4l2src->mmap values */ - if (!gst_v4l2src_set_capture (v4l2src, format, &w, &h)) { + + if (framerate) { + fps_n = gst_value_get_fraction_numerator (framerate); + fps_d = gst_value_get_fraction_denominator (framerate); + } else { + fps_n = 0; + fps_d = 1; + } + + if (!gst_v4l2src_set_capture (v4l2src, format, &w, &h, &fps_n, &fps_d)) { GST_WARNING_OBJECT (v4l2src, "could not set_capture %dx%d, format %s", w, h, format->description); return FALSE; } - gst_structure_set (structure, "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, - NULL); + if (fps_n) { + gst_structure_set (structure, + "width", G_TYPE_INT, w, + "height", G_TYPE_INT, h, + "framerate", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (framerate), + gst_value_get_fraction_denominator (framerate), NULL); + } else { + gst_structure_set (structure, + "width", G_TYPE_INT, w, + "height", G_TYPE_INT, h, "framerate", GST_TYPE_FRACTION, NULL); + } if (!gst_v4l2src_capture_init (v4l2src)) return FALSE; @@ -822,6 +839,20 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) if (!gst_v4l2src_capture_start (v4l2src)) return FALSE; + if (v4l2src->fps_n != fps_n || v4l2src->fps_d != fps_d) { + GST_WARNING_OBJECT (v4l2src, + "framerate changed after start capturing from %u/%u to %u/%u", fps_n, + fps_d, v4l2src->fps_n, v4l2src->fps_d); + if (fps_n) { + gst_structure_set (structure, + "width", G_TYPE_INT, w, + "height", G_TYPE_INT, h, + "framerate", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (framerate), + gst_value_get_fraction_denominator (framerate), NULL); + } + } + return TRUE; } @@ -948,7 +979,7 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf) if (v4l2src->use_fixed_fps && v4l2src->fps_n == 0) { GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL), - ("could not get frame rate for element")); + ("could not get frame rate for element, try to set use-fixed-fps property to false")); return GST_FLOW_ERROR; } diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c index 801120ffad..3cfd0b08aa 100644 --- a/sys/v4l2/v4l2src_calls.c +++ b/sys/v4l2/v4l2src_calls.c @@ -240,8 +240,13 @@ gst_v4l2src_get_capture (GstV4l2Src * v4l2src) gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src, - struct v4l2_fmtdesc * fmt, gint * width, gint * height) + struct v4l2_fmtdesc * fmt, gint * width, gint * height, + guint * fps_n, guint * fps_d) { + + guint new_fps_n = *fps_n; + guint new_fps_d = *fps_d; + DEBUG ("Setting capture format to %dx%d, format %s", *width, *height, fmt->description); @@ -279,9 +284,31 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, } if (fmt->pixelformat != v4l2src->format.fmt.pix.pixelformat) { + GST_ELEMENT_ERROR (v4l2src, RESOURCE, SETTINGS, (NULL), + ("failed to set pixelformat to %s @ %dx%d for device %s: %s", + fmt->description, *width, *height, + v4l2src->v4l2object->videodev, g_strerror (errno))); goto fail; } + if (*fps_n) { + if (gst_v4l2src_set_fps (v4l2src, &new_fps_n, &new_fps_d)) { + if (new_fps_n != *fps_n || new_fps_d != *fps_d) { + DEBUG ("Updating framerate from %u/%u to %u%u", + *fps_n, *fps_d, new_fps_n, new_fps_d); + *fps_n = new_fps_n; + *fps_d = new_fps_d; + } + } + } else { + if (gst_v4l2src_get_fps (v4l2src, &new_fps_n, &new_fps_d)) { + DEBUG ("framerate is %u/%u", new_fps_n, new_fps_d); + *fps_n = new_fps_n; + *fps_d = new_fps_d; + } + } + + *width = v4l2src->format.fmt.pix.width; *height = v4l2src->format.fmt.pix.height; @@ -644,6 +671,34 @@ gst_v4l2src_update_fps (GstV4l2Object * v4l2object) return gst_v4l2src_get_fps (v4l2src, &v4l2src->fps_n, &v4l2src->fps_d); } + +gboolean +gst_v4l2src_set_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d) +{ + + GstV4l2Object *v4l2object = v4l2src->v4l2object; + struct v4l2_streamparm stream; + + memset (&stream, 0x00, sizeof (struct v4l2_streamparm)); + stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (ioctl (v4l2object->video_fd, VIDIOC_G_PARM, &stream) == 0 && + stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) { + + stream.parm.capture.timeperframe.denominator = *fps_n; + stream.parm.capture.timeperframe.numerator = *fps_d; + + if (ioctl (v4l2object->video_fd, VIDIOC_S_PARM, &stream) == 0) { + *fps_n = stream.parm.capture.timeperframe.denominator; + *fps_d = stream.parm.capture.timeperframe.numerator; + return TRUE; + } + } + + return FALSE; + +} + + gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d) { @@ -656,6 +711,7 @@ gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d) return FALSE; /* Try to get the frame rate directly from the device using VIDIOC_G_PARM */ + memset (&stream, 0x00, sizeof (struct v4l2_streamparm)); stream.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (ioctl (v4l2object->video_fd, VIDIOC_G_PARM, &stream) == 0 && stream.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) { diff --git a/sys/v4l2/v4l2src_calls.h b/sys/v4l2/v4l2src_calls.h index 4b5a3871e0..6cb637b327 100644 --- a/sys/v4l2/v4l2src_calls.h +++ b/sys/v4l2/v4l2src_calls.h @@ -28,7 +28,8 @@ gboolean gst_v4l2src_get_capture (GstV4l2Src * v4l2src); gboolean gst_v4l2src_set_capture (GstV4l2Src * v4l2src, struct v4l2_fmtdesc *fmt, - gint * width, gint * height); + gint * width, gint * height, + guint *fps_n, guint * fps_d); gboolean gst_v4l2src_capture_init (GstV4l2Src * v4l2src); gboolean gst_v4l2src_capture_start (GstV4l2Src * v4l2src); gint gst_v4l2src_grab_frame (GstV4l2Src * v4l2src); @@ -54,6 +55,10 @@ gst_v4l2src_update_fps (GstV4l2Object * v4l2object); extern gboolean gst_v4l2src_get_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d); + +extern gboolean +gst_v4l2src_set_fps (GstV4l2Src * v4l2src, guint * fps_n, guint * fps_d); + GValue *gst_v4l2src_get_fps_list (GstV4l2Src * v4l2src); GstBuffer *gst_v4l2src_buffer_new (GstV4l2Src * v4l2src,