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>
This commit is contained in:
Nicolas Dufresne 2020-01-28 17:16:17 -05:00 committed by Laurent Pinchart
parent d1d1348228
commit 0c4147c3b6
3 changed files with 45 additions and 0 deletions

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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);
}