From patchwork Thu Feb 27 20:04:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Dufresne X-Patchwork-Id: 2905 Return-Path: Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e3e3]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E621E6273D for ; Thu, 27 Feb 2020 21:04:28 +0100 (CET) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: nicolas) with ESMTPSA id 71D1F2949DF From: Nicolas Dufresne To: libcamera-devel@lists.libcamera.org Date: Thu, 27 Feb 2020 15:04:03 -0500 Message-Id: <20200227200407.490616-24-nicolas.dufresne@collabora.com> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200227200407.490616-1-nicolas.dufresne@collabora.com> References: <20200227200407.490616-1-nicolas.dufresne@collabora.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 23/27] gst: libcamerasrc: Implement timestamp support X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Feb 2020 20:04:31 -0000 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 Reviewed-by: Laurent Pinchart --- src/gstreamer/gstlibcamerapad.cpp | 23 +++++++++++++++++++++++ src/gstreamer/gstlibcamerapad.h | 2 ++ src/gstreamer/gstlibcamerasrc.cpp | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/gstreamer/gstlibcamerapad.cpp b/src/gstreamer/gstlibcamerapad.cpp index 2cf1630..31d3edd 100644 --- a/src/gstreamer/gstlibcamerapad.cpp +++ b/src/gstreamer/gstlibcamerapad.cpp @@ -62,9 +62,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 @@ -172,3 +187,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 eb24000..a3291e8 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 70f2048..73a1360 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -151,6 +151,26 @@ GstLibcameraSrcState::requestCompleted(Request *request) for (GstPad *srcpad : this->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(this->src)) { + GstClockTime gst_base_time = GST_ELEMENT(this->src)->base_time; + GstClockTime gst_now = gst_clock_get_time(GST_ELEMENT_CLOCK(this->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_bae_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); }