summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2020-01-28 17:16:17 -0500
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2020-03-07 01:58:08 +0200
commit0c4147c3b652ebf8200680e7cfe371bbd9192c48 (patch)
treeab7187e6018ac460f5bd45d68adfd418a22c3c39
parentd1d1348228d559999fc8ec48596fb699ab3563c0 (diff)
gst: libcamerasrc: Implement timestamp support
This is an experimental patch adding timestamp support to the libcamerasrc element. This patch currently assume that the driver timestamp are relative to the system monotonic clock. Without a reference clock source, the timestamp are otherwise unusable, and without timestamp only minor use case can be achieved. Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--src/gstreamer/gstlibcamerapad.cpp23
-rw-r--r--src/gstreamer/gstlibcamerapad.h2
-rw-r--r--src/gstreamer/gstlibcamerasrc.cpp20
3 files changed, 45 insertions, 0 deletions
diff --git a/src/gstreamer/gstlibcamerapad.cpp b/src/gstreamer/gstlibcamerapad.cpp
index 840f391c..e184495a 100644
--- a/src/gstreamer/gstlibcamerapad.cpp
+++ b/src/gstreamer/gstlibcamerapad.cpp
@@ -63,9 +63,24 @@ gst_libcamera_pad_get_property(GObject *object, guint prop_id, GValue *value,
}
}
+static gboolean
+gst_libcamera_pad_query(GstPad *pad, GstObject *parent, GstQuery *query)
+{
+ auto *self = GST_LIBCAMERA_PAD(pad);
+
+ if (query->type != GST_QUERY_LATENCY)
+ return gst_pad_query_default(pad, parent, query);
+
+ /* TRUE here means live, we assumes that max latency is the same as min
+ * as we have no idea that duration of frames. */
+ gst_query_set_latency(query, TRUE, self->latency, self->latency);
+ return TRUE;
+}
+
static void
gst_libcamera_pad_init(GstLibcameraPad *self)
{
+ GST_PAD_QUERYFUNC(self) = gst_libcamera_pad_query;
}
static GType
@@ -173,3 +188,11 @@ gst_libcamera_pad_has_pending(GstPad *pad)
GLibLocker lock(GST_OBJECT(self));
return self->pending_buffers.length > 0;
}
+
+void
+gst_libcamera_pad_set_latency(GstPad *pad, GstClockTime latency)
+{
+ auto *self = GST_LIBCAMERA_PAD(pad);
+ GLibLocker lock(GST_OBJECT(self));
+ self->latency = latency;
+}
diff --git a/src/gstreamer/gstlibcamerapad.h b/src/gstreamer/gstlibcamerapad.h
index 9d431297..779f2d13 100644
--- a/src/gstreamer/gstlibcamerapad.h
+++ b/src/gstreamer/gstlibcamerapad.h
@@ -32,4 +32,6 @@ GstFlowReturn gst_libcamera_pad_push_pending(GstPad *pad);
bool gst_libcamera_pad_has_pending(GstPad *pad);
+void gst_libcamera_pad_set_latency(GstPad *pad, GstClockTime latency);
+
#endif /* __GST_LIBCAMERA_PAD_H__ */
diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index 0b4cae79..64077f36 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -154,6 +154,26 @@ GstLibcameraSrcState::requestCompleted(Request *request)
for (GstPad *srcpad : srcpads_) {
Stream *stream = gst_libcamera_pad_get_stream(srcpad);
buffer = wrap->detachBuffer(stream);
+
+ FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer);
+
+ if (GST_ELEMENT_CLOCK(src_)) {
+ GstClockTime gst_base_time = GST_ELEMENT(src_)->base_time;
+ GstClockTime gst_now = gst_clock_get_time(GST_ELEMENT_CLOCK(src_));
+ /* \todo Need to expose which reference clock the timestamp relates to. */
+ GstClockTime sys_now = g_get_monotonic_time() * 1000;
+
+ /* Deduced from: sys_now - sys_base_time == gst_now - gst_base_time */
+ GstClockTime sys_base_time = sys_now - (gst_now - gst_base_time);
+ GST_BUFFER_PTS(buffer) = fb->metadata().timestamp - sys_base_time;
+ gst_libcamera_pad_set_latency(srcpad, sys_now - fb->metadata().timestamp);
+ } else {
+ GST_BUFFER_PTS(buffer) = 0;
+ }
+
+ GST_BUFFER_OFFSET(buffer) = fb->metadata().sequence;
+ GST_BUFFER_OFFSET_END(buffer) = fb->metadata().sequence;
+
gst_libcamera_pad_queue_buffer(srcpad, buffer);
}