sys/v4l/: Fix duration and timestamping, taking latency into account.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 28 Feb 2007 15:05:03 +0000 (15:05 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 28 Feb 2007 15:05:03 +0000 (15:05 +0000)
Original commit message from CVS:
* sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init),
(gst_v4lsrc_fixate), (gst_v4lsrc_query):
* sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_new):
Fix duration and timestamping, taking latency into account.
Implement latency query.

ChangeLog
sys/v4l/gstv4lsrc.c
sys/v4l/v4lsrc_calls.c

index 3af914224821949302e79f1c7700b5a359e1e37c..52f367c7c68bd74d0a58dff35ba093c23d1c4a58 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-02-28  Wim Taymans  <wim@fluendo.com>
+
+       * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init),
+       (gst_v4lsrc_fixate), (gst_v4lsrc_query):
+       * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_new):
+       Fix duration and timestamping, taking latency into account.
+       Implement latency query.
+
 2007-02-28  Wim Taymans  <wim@fluendo.com>
 
        * gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_init),
index 8422ee188bb68225d324a6f5760b9ac51ec6358a..b75ac80186d694b9440d7bb1ad74753f2e8faabf 100644 (file)
@@ -60,8 +60,8 @@ static gboolean gst_v4lsrc_stop (GstBaseSrc * src);
 static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps);
 static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src);
 static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out);
-
-static void gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps);
+static gboolean gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query);
+static void gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps);
 
 static void gst_v4lsrc_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -119,6 +119,8 @@ gst_v4lsrc_class_init (GstV4lSrcClass * klass)
   basesrc_class->set_caps = gst_v4lsrc_set_caps;
   basesrc_class->start = gst_v4lsrc_start;
   basesrc_class->stop = gst_v4lsrc_stop;
+  basesrc_class->fixate = gst_v4lsrc_fixate;
+  basesrc_class->query = gst_v4lsrc_query;
 
   pushsrc_class->create = gst_v4lsrc_create;
 }
@@ -140,9 +142,6 @@ gst_v4lsrc_init (GstV4lSrc * v4lsrc, GstV4lSrcClass * klass)
 
   v4lsrc->fps_list = NULL;
 
-  gst_pad_set_fixatecaps_function (GST_BASE_SRC_PAD (v4lsrc),
-      gst_v4lsrc_fixate);
-
   gst_base_src_set_live (GST_BASE_SRC (v4lsrc), TRUE);
 }
 
@@ -201,12 +200,12 @@ gst_v4lsrc_get_property (GObject * object,
 
 /* this function is a bit of a last resort */
 static void
-gst_v4lsrc_fixate (GstPad * pad, GstCaps * caps)
+gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps)
 {
   GstStructure *structure;
   int i;
   int targetwidth, targetheight;
-  GstV4lSrc *v4lsrc = GST_V4LSRC (gst_pad_get_parent (pad));
+  GstV4lSrc *v4lsrc = GST_V4LSRC (bsrc);
   struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap;
   struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin;
 
@@ -615,6 +614,53 @@ gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps)
   return TRUE;
 }
 
+static gboolean
+gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query)
+{
+  GstV4lSrc *v4lsrc;
+  gboolean res = FALSE;
+
+  v4lsrc = GST_V4LSRC (bsrc);
+
+  switch (GST_QUERY_TYPE (query)) {
+    case GST_QUERY_LATENCY:
+    {
+      GstClockTime min_latency, max_latency;
+      gint fps_n, fps_d;
+
+      /* device must be open */
+      if (!GST_V4L_IS_OPEN (v4lsrc))
+        goto done;
+
+      /* we must have a framerate */
+      if (!(res = gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)))
+        goto done;
+
+      /* min latency is the time to capture one frame */
+      min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
+
+      /* max latency is total duration of the frame buffer */
+      max_latency = v4lsrc->mbuf.frames * 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.
index da33ffdfc8e6ead7885c0cb72ac183d4771ac6e9..39e45174a0209380999f72d1307e8d3eb672241b 100644 (file)
@@ -697,6 +697,7 @@ gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
 {
   GstBuffer *buf;
   gint fps_n, fps_d;
+  GstClockTime duration, timestamp, latency;
 
   GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num);
 
@@ -711,12 +712,19 @@ gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num)
   GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num);
   GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size;
   GST_BUFFER_OFFSET (buf) = v4lsrc->offset++;
-  GST_BUFFER_TIMESTAMP (buf) = gst_clock_get_time (GST_ELEMENT (v4lsrc)->clock);
-  GST_BUFFER_TIMESTAMP (buf) -= GST_ELEMENT (v4lsrc)->base_time;
-  /* FIXME: this is a most ghetto timestamp/duration */
 
-  GST_BUFFER_DURATION (buf) = gst_util_uint64_scale_int (GST_SECOND,
-      fps_n, fps_d);
+  duration = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
+  latency = duration;
+
+  timestamp = gst_clock_get_time (GST_ELEMENT_CAST (v4lsrc)->clock);
+  timestamp -= gst_element_get_base_time (GST_ELEMENT_CAST (v4lsrc));
+  if (timestamp > latency)
+    timestamp -= latency;
+  else
+    timestamp = 0;
+
+  GST_BUFFER_TIMESTAMP (buf) = timestamp;
+  GST_BUFFER_DURATION (buf) = duration;
 
   /* the negotiate() method already set caps on the source pad */
   gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (v4lsrc)));