Fixed framerate negotiation.
authorEdgard Lima <edgard.lima@indt.org.br>
Tue, 29 Aug 2006 20:59:47 +0000 (20:59 +0000)
committerEdgard Lima <edgard.lima@indt.org.br>
Tue, 29 Aug 2006 20:59:47 +0000 (20:59 +0000)
Original commit message from CVS:
Fixed framerate negotiation.

ChangeLog
sys/v4l2/gstv4l2src.c
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index 5bcdcb8..3ce7674 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-08-29  Edgard Lima <edgard.lima@indt.org.br>
+
+       * sys/v4l2/gstv4l2src.c:
+       * sys/v4l2/v4l2src_calls.c:
+       * sys/v4l2/v4l2src_calls.h:
+       Fixed framerate negotiation.
+       
 2006-08-29  Tim-Philipp Müller  <tim at centricular dot net>
 
        Patch by: Andrew Andkjar  <enki at goodship net>
index d5cb194..3ad39a4 100644 (file)
@@ -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;
   }
 
index 801120f..3cfd0b0 100644 (file)
@@ -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) {
index 4b5a387..6cb637b 100644 (file)
@@ -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,