sys/v4l2/: Implement LATENCY queries in the crudest way possible so I don't have...
authorTim-Philipp Müller <tim@centricular.net>
Wed, 5 Sep 2007 14:43:16 +0000 (14:43 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Wed, 5 Sep 2007 14:43:16 +0000 (14:43 +0000)
Original commit message from CVS:
* sys/v4l2/gstv4l2src.c:
* sys/v4l2/gstv4l2src.h:
* sys/v4l2/v4l2src_calls.c:
Implement LATENCY queries in the crudest way possible so I don't
have to use sync=false any longer when testing with videosinks.

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

index f72cd7defec56cf2a6d2974b908cad0994e965bf..b8e6117f67ece0420baa14fbbd7bc6703e9893f9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-09-05  Tim-Philipp Müller  <tim at centricular dot net>
+
+       * sys/v4l2/gstv4l2src.c:
+       * sys/v4l2/gstv4l2src.h:
+       * sys/v4l2/v4l2src_calls.c:
+         Implement LATENCY queries in the crudest way possible so I don't
+         have to use sync=false any longer when testing with videosinks.
+
 2007-09-05  Tim-Philipp Müller  <tim at centricular dot net>
 
        * configure.ac:
index d0c1ddb05a51a160bc8c2724fbf5d28ecea7b185..5a892bda8457e81b7b5665862352373018762e14 100644 (file)
@@ -237,6 +237,7 @@ static gboolean gst_v4l2src_start (GstBaseSrc * src);
 static gboolean gst_v4l2src_stop (GstBaseSrc * src);
 static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps);
 static GstCaps *gst_v4l2src_get_caps (GstBaseSrc * src);
+static gboolean gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query);
 static GstFlowReturn gst_v4l2src_create (GstPushSrc * src, GstBuffer ** out);
 
 static void gst_v4l2src_fixate (GstPad * pad, GstCaps * caps);
@@ -289,12 +290,13 @@ gst_v4l2src_class_init (GstV4l2SrcClass * klass)
           GST_V4L2_MIN_BUFFERS, GST_V4L2_MAX_BUFFERS, GST_V4L2_MIN_BUFFERS,
           G_PARAM_READWRITE));
 
-  basesrc_class->get_caps = gst_v4l2src_get_caps;
-  basesrc_class->set_caps = gst_v4l2src_set_caps;
-  basesrc_class->start = gst_v4l2src_start;
-  basesrc_class->stop = gst_v4l2src_stop;
+  basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_get_caps);
+  basesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2src_set_caps);
+  basesrc_class->start = GST_DEBUG_FUNCPTR (gst_v4l2src_start);
+  basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_v4l2src_stop);
+  basesrc_class->query = GST_DEBUG_FUNCPTR (gst_v4l2src_query);
 
-  pushsrc_class->create = gst_v4l2src_create;
+  pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_v4l2src_create);
 }
 
 static void
@@ -316,6 +318,9 @@ gst_v4l2src_init (GstV4l2Src * v4l2src, GstV4l2SrcClass * klass)
 
   gst_base_src_set_format (GST_BASE_SRC (v4l2src), GST_FORMAT_TIME);
   gst_base_src_set_live (GST_BASE_SRC (v4l2src), TRUE);
+
+  v4l2src->fps_d = 0;
+  v4l2src->fps_n = 0;
 }
 
 
@@ -865,6 +870,55 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
   return TRUE;
 }
 
+static gboolean
+gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
+{
+  GstV4l2Src *src;
+  gboolean res = FALSE;
+
+  src = GST_V4L2SRC (bsrc);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_LATENCY:{
+      GstClockTime min_latency, max_latency;
+
+      /* device must be open */
+      if (!GST_V4L2_IS_OPEN (src->v4l2object))
+        goto done;
+
+      /* we must have a framerate */
+      if (src->fps_n <= 0 || src->fps_d <= 0)
+        goto done;
+
+      /* min latency is the time to capture one frame */
+      min_latency =
+          gst_util_uint64_scale_int (GST_SECOND, src->fps_d, src->fps_n);
+
+      /* max latency is total duration of the frame buffer */
+      /* FIXME: what to use here? */
+      max_latency = 1 * min_latency;
+
+      GST_DEBUG_OBJECT (bsrc,
+          "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
+          GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
+
+      /* we are always live, the min latency is 1 frame and the max latency is
+       * the complete buffer of frames. */
+      gst_query_set_latency (query, TRUE, min_latency, max_latency);
+
+      res = TRUE;
+      break;
+    }
+    default:
+      res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
+      break;
+  }
+
+done:
+
+  return res;
+}
+
 /* start and stop are not symmetric -- start will open the device, but not start
  * capture. it's setcaps that will start capture, which is called via basesrc's
  * negotiate method. stop will both stop capture and close the device.
@@ -901,6 +955,9 @@ gst_v4l2src_stop (GstBaseSrc * src)
   if (!gst_v4l2_object_stop (v4l2src->v4l2object))
     return FALSE;
 
+  v4l2src->fps_d = 0;
+  v4l2src->fps_n = 0;
+
   return TRUE;
 }
 
@@ -950,9 +1007,20 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2src, GstBuffer ** buf)
     GST_OBJECT_UNLOCK (v4l2src);
 
     if (clock) {
+      GstClockTime latency;
+
       /* the time now is the time of the clock minus the base time */
       timestamp = gst_clock_get_time (clock) - timestamp;
       gst_object_unref (clock);
+
+      latency =
+          gst_util_uint64_scale_int (GST_SECOND, v4l2src->fps_d,
+          v4l2src->fps_n);
+
+      if (timestamp > latency)
+        timestamp -= latency;
+      else
+        timestamp = 0;
     }
 
     /* FIXME: use the timestamp from the buffer itself! */
index 809ddb46c8f1cbf5306f2a50c23942a635a3f428..f4677458bc8ed29a3bb449e455747bd071f10c2f 100644 (file)
@@ -106,6 +106,8 @@ struct _GstV4l2Src
   gboolean is_capturing;
 
   guint64 offset;
+
+  gint     fps_d, fps_n;       /* framerate if device is open */
 };
 
 struct _GstV4l2SrcClass
index 56b87909dccaf148d42a780785662307a5f67067..b9d74a53c3a6b07ecdba50c42f5b06ef20f55983 100644 (file)
@@ -968,6 +968,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
           || stream.parm.capture.timeperframe.denominator != fps_n)
         goto invalid_framerate;
     }
+
+    v4l2src->fps_d = fps_d;
+    v4l2src->fps_n = fps_n;
   }
 
   return TRUE;