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);
gint w, h;
GstStructure *structure;
struct v4l2_fmtdesc *format;
+ const GValue *framerate;
+ guint fps_n, fps_d;
v4l2src = GST_V4L2SRC (src);
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;
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;
}
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;
}
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);
}
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;
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)
{
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) {
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);
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,