From patchwork Thu Jun 30 00:02:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16438 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 6AD1FBD808 for ; Thu, 30 Jun 2022 00:03:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1317965639; Thu, 30 Jun 2022 02:03:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547397; bh=CT7O1pNyLzSsr9gZmwll0nfUhCUJxKJLN2rB555rDvo=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=utHb2pbhElYZ6kt/MtXtLzkjrZNHqj8eO+B2FYlYWX1OiS6fNuYDK6yvIsQQV0Szv iQm8EH8zp+Tx8QnIJpd8qYOZbxmmNzAgWPtimzGmM1DDQacrsibKUb2ALbI33GP6GF 63DzLcYNNMqzau0oyMcHRosvqY4FycwFM5TQlZPkzzort1C0HEnWEVMrP4KEKPPFTa QV6r8p++AnJno+rnagJX4Z0aE/7JorvSU3WV2ART2TE2JQt7uth6IGLH/w5EhQvYoV ci6RFj52wL2z9KVrcNV7sJO4C6oBwqf5JqCYyUShGAODFncbeEW/pYmSBjt7BWmAaB 308MYuOvHYRqw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7028665631 for ; Thu, 30 Jun 2022 02:03:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="EEXFXETL"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0FAC16D1; Thu, 30 Jun 2022 02:03:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547395; bh=CT7O1pNyLzSsr9gZmwll0nfUhCUJxKJLN2rB555rDvo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EEXFXETLrSL135t8Wn+R6DwlEMrp/XmjoHAcBsC/JHBankXa+57gLfZKuXbd3rpuB hcWCiJGq8D5i4vDL/e/wHevzWVZgFt/fX1zep+Km1/iBufQwDsN+tkVmh+zh0/ZR0q qp7sDdXcsMuPCRihJou4jhdn46UOLScgrxBcA1cg= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:40 +0300 Message-Id: <20220630000251.31295-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 01/12] gstreamer: Use gst_task_resume() when available 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The gst_libcamera_resume_task() helper is an implementation of the gst_task_resume() function that predates its addition to GStreamer. Use gst_task_resume() when available, and rename gst_libcamera_resume_task() to gst_task_resume() to support older GStreamer versions. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- src/gstreamer/gstlibcamera-utils.cpp | 16 ++++++++++------ src/gstreamer/gstlibcamera-utils.h | 4 +++- src/gstreamer/gstlibcamerasrc.cpp | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp index 3f2422863c03..c97c0d438de2 100644 --- a/src/gstreamer/gstlibcamera-utils.cpp +++ b/src/gstreamer/gstlibcamera-utils.cpp @@ -224,16 +224,20 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg, stream_cfg.size.height = height; } -void -gst_libcamera_resume_task(GstTask *task) +#if !GST_CHECK_VERSION(1, 17, 1) +gboolean +gst_task_resume(GstTask *task) { /* We only want to resume the task if it's paused. */ GLibLocker lock(GST_OBJECT(task)); - if (GST_TASK_STATE(task) == GST_TASK_PAUSED) { - GST_TASK_STATE(task) = GST_TASK_STARTED; - GST_TASK_SIGNAL(task); - } + if (GST_TASK_STATE(task) != GST_TASK_PAUSED) + return FALSE; + + GST_TASK_STATE(task) = GST_TASK_STARTED; + GST_TASK_SIGNAL(task); + return TRUE; } +#endif G_LOCK_DEFINE_STATIC(cm_singleton_lock); static std::weak_ptr cm_singleton_ptr; diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h index d54f15885d0c..164189a28965 100644 --- a/src/gstreamer/gstlibcamera-utils.h +++ b/src/gstreamer/gstlibcamera-utils.h @@ -18,7 +18,9 @@ GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &fo GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg); void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg, GstCaps *caps); -void gst_libcamera_resume_task(GstTask *task); +#if !GST_CHECK_VERSION(1, 17, 1) +gboolean gst_task_resume(GstTask *task); +#endif std::shared_ptr gst_libcamera_get_camera_manager(int &ret); /** diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 46fd02d207be..9d6be075a474 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -192,7 +192,7 @@ GstLibcameraSrcState::requestCompleted(Request *request) gst_libcamera_pad_queue_buffer(srcpad, buffer); } - gst_libcamera_resume_task(this->src_->task); + gst_task_resume(src_->task); } static bool @@ -453,7 +453,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator, stream_cfg.stream()); g_signal_connect_swapped(pool, "buffer-notify", - G_CALLBACK(gst_libcamera_resume_task), task); + G_CALLBACK(gst_task_resume), task); gst_libcamera_pad_set_pool(srcpad, pool); gst_flow_combiner_add_pad(self->flow_combiner, srcpad); From patchwork Thu Jun 30 00:02:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16439 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D5289BD808 for ; Thu, 30 Jun 2022 00:03:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5A65365636; Thu, 30 Jun 2022 02:03:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547398; bh=ABFPzWVJbl9jaOXCsm5Zt1bWOe+vVbWdzqIPZtNqzAc=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=mTiyI9fMzsmVnTMEwafL1gyIAM1bOG2UV/sX81NDoh7MEuUxrV4iu+pMxwVSA+kV+ M/1q2lHWto55F8x0gC0Ebzf5ni/+1fKi7t1eTfRiz2K3AG0GciGkKsdYLB4qz5DAzQ 5ewYjkmHp4hHTtAKZtB2nTydLkCXCWJKdkCCIlmXvg5d3ScN8XxRoc+gVg6hjUWu/N tFLJuEKv3R0PI8rzq+XyHkIO5sCOii09hiKMdkUsGvdLoDff5Gd8lpAtvEECRy3+wq bOxP4ZFK86NuIPHKw1ETlUK09Ku6zeqE/4VLFawLmxA71rKt9nW/ih8TciOjr6HU8Q s9hAVulJRqjHw== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DC4A665631 for ; Thu, 30 Jun 2022 02:03:15 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="I4wCfAR1"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7465559D; Thu, 30 Jun 2022 02:03:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547395; bh=ABFPzWVJbl9jaOXCsm5Zt1bWOe+vVbWdzqIPZtNqzAc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=I4wCfAR1CXP/F+V1zCytwRrjwEx3YKyAq48OpsErxPaHAiGZOPbJmNbFYA1h2EI00 PRm1dk/3fMwDDhhLfl9i7HstuRPddif0vyzhfvnoIjN5ugGxgyJXtHuYW6iXShxPw4 B0FS3LUnaoARKLbR4Y7daMr3QgDI429byIhBfZk0= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:41 +0300 Message-Id: <20220630000251.31295-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 02/12] gstreamer: Move variable to loop scope 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The GstBuffer variable in GstLibcameraSrcState::requestCompleted() is only used within the loop scope. Make it a local loop variable. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- src/gstreamer/gstlibcamerasrc.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 9d6be075a474..dea143961d69 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -165,10 +165,9 @@ GstLibcameraSrcState::requestCompleted(Request *request) return; } - GstBuffer *buffer; for (GstPad *srcpad : srcpads_) { Stream *stream = gst_libcamera_pad_get_stream(srcpad); - buffer = wrap->detachBuffer(stream); + GstBuffer *buffer = wrap->detachBuffer(stream); FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer); From patchwork Thu Jun 30 00:02:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16440 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 65411BD808 for ; Thu, 30 Jun 2022 00:03:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A90EB65649; Thu, 30 Jun 2022 02:03:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547402; bh=B3kxdjNm3quaucIqzryO44T44IywU5HNRV5Pl4jVILg=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=VKX/MHnFBeAi9ODu5I7hyN/6UL6ORT21oaNmwouuRu0X7GV5ivdp1AvHyMOt+/A+e nVeBypy6DRFIfVJkO9UGc3Cv4p/IIa9y7DzLlhy6pOBoaCc7mZKoq7d+WQHmJkPztk zzBiiMMlui0fHGYqTCXXcCxgU1CXMDje4xM3OFJrubHFYjPMr9xc4QFAHX2kv2HEQx kFpUeCOZSQde7STR+eSJzk6ieG9jYa7gzaJU0q/Ul3wQQWE6OOUdJRtPciRhhJcHfD mlkZaUkveeZlBHur+0TFfbU9LxD0HD0ftPnZUBtc6TB/xXVfYcLMi/YH9gMFiWEclt 16jdK4pW1K26w== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5CD0465635 for ; Thu, 30 Jun 2022 02:03:16 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="r5cDhFRZ"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D91216D1; Thu, 30 Jun 2022 02:03:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547396; bh=B3kxdjNm3quaucIqzryO44T44IywU5HNRV5Pl4jVILg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=r5cDhFRZMuVuVcfrabUtHJAoY3PAkKTeUoQsIWxw/A+ZvkGsR7deRqIBzbJl5Fari 3hLkZ/iCWW8MNTWTlDFPFxJftZPYJgyPUTW/lNCaNso+iSe0i3yl+d+a9+xILhSNiP Hz6J6kRhuvq5cPZhUgXmi9WkFwsG6rJNbSgUxhtE= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:42 +0300 Message-Id: <20220630000251.31295-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 03/12] gstreamer: Pass Stream to RequestWrap::addBuffer() 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" For symmetry with RequestWrap::removeBuffer(), pass the Stream pointer to addBuffer(). This handles streams at the GstPad level instead of the GstBuffer level, which allows making the GstLibcameraPool API a bit cleaner by removing the gst_libcamera_buffer_get_stream() helper function. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- src/gstreamer/gstlibcamerapool.cpp | 7 ------- src/gstreamer/gstlibcamerapool.h | 2 -- src/gstreamer/gstlibcamerasrc.cpp | 8 ++++---- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/gstreamer/gstlibcamerapool.cpp b/src/gstreamer/gstlibcamerapool.cpp index 1fde42135119..0c2be43ceeea 100644 --- a/src/gstreamer/gstlibcamerapool.cpp +++ b/src/gstreamer/gstlibcamerapool.cpp @@ -134,13 +134,6 @@ gst_libcamera_pool_get_stream(GstLibcameraPool *self) return self->stream; } -Stream * -gst_libcamera_buffer_get_stream(GstBuffer *buffer) -{ - auto *self = (GstLibcameraPool *)buffer->pool; - return self->stream; -} - FrameBuffer * gst_libcamera_buffer_get_frame_buffer(GstBuffer *buffer) { diff --git a/src/gstreamer/gstlibcamerapool.h b/src/gstreamer/gstlibcamerapool.h index 05795d21223e..ce3bf60b1426 100644 --- a/src/gstreamer/gstlibcamerapool.h +++ b/src/gstreamer/gstlibcamerapool.h @@ -25,6 +25,4 @@ GstLibcameraPool *gst_libcamera_pool_new(GstLibcameraAllocator *allocator, libcamera::Stream *gst_libcamera_pool_get_stream(GstLibcameraPool *self); -libcamera::Stream *gst_libcamera_buffer_get_stream(GstBuffer *buffer); - libcamera::FrameBuffer *gst_libcamera_buffer_get_frame_buffer(GstBuffer *buffer); diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index dea143961d69..700bee2bf877 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -51,7 +51,7 @@ struct RequestWrap { RequestWrap(std::unique_ptr request); ~RequestWrap(); - void attachBuffer(GstBuffer *buffer); + void attachBuffer(Stream *stream, GstBuffer *buffer); GstBuffer *detachBuffer(Stream *stream); std::unique_ptr request_; @@ -71,10 +71,9 @@ RequestWrap::~RequestWrap() } } -void RequestWrap::attachBuffer(GstBuffer *buffer) +void RequestWrap::attachBuffer(Stream *stream, GstBuffer *buffer) { FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer); - Stream *stream = gst_libcamera_buffer_get_stream(buffer); request_->addBuffer(stream, fb); @@ -275,6 +274,7 @@ gst_libcamera_src_task_run(gpointer user_data) std::make_unique(std::move(request)); for (GstPad *srcpad : state->srcpads_) { + Stream *stream = gst_libcamera_pad_get_stream(srcpad); GstLibcameraPool *pool = gst_libcamera_pad_get_pool(srcpad); GstBuffer *buffer; GstFlowReturn ret; @@ -290,7 +290,7 @@ gst_libcamera_src_task_run(gpointer user_data) break; } - wrap->attachBuffer(buffer); + wrap->attachBuffer(stream, buffer); } if (wrap) { From patchwork Thu Jun 30 00:02:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16441 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id AD4CFBD808 for ; Thu, 30 Jun 2022 00:03:26 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2D9716564D; Thu, 30 Jun 2022 02:03:26 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547406; bh=QuupnKHlYQE/5OxuJDMjEmlGrudsBuJBHh3NT/jjrOM=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=BZlD44eRDOsslesKRGJpceMrsuy3O4//Z/eaqh2zqhNTa28SLCkX0NswTV2+ETDjs Mq3z7OLJoA59acv2t+9zQtjtsVIdjkRNArxhjQE//Gzf+dgBZSxL+L/krCE8+etBfA QNp4Xwskjf8O/dk/rk+fEsqnZL5ji7kgdb6Z6WtxxMSlNaEmcgCt9mVarFoueoUGfU enKay1OSgbQEjw97ozW1XVUCm2M//2/blSYDjokWevvzzNpcLoMRRDGsRWK7pBQxoT J+rdPngPbQtz2aRwSjgY0B7c/+2NP5s00Uai/NfC1+IR+cxrLpVLNktSoA8m6MmakV vQP6aqI0oX0rA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C3E5D6563E for ; Thu, 30 Jun 2022 02:03:16 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="I7B36/r8"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5D67059D; Thu, 30 Jun 2022 02:03:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547396; bh=QuupnKHlYQE/5OxuJDMjEmlGrudsBuJBHh3NT/jjrOM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=I7B36/r8xycPeCxeOrhADTG4WrI0BnkKDiJzOR3BrUxXfeVyjLw8feiOINqOhzwPX PDiNaOar6kVlPDcse7kh4L1WUwjnUszmsXrkUqZLImNU/BldsH4HASHaDHOaSWI+As 3Fe69mXqSdLTgd0JJE/rC/Mke/YrD25ZZ9ztW+3Q= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:43 +0300 Message-Id: <20220630000251.31295-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 04/12] gstreamer: Move timestamp calculation out of pad loop 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The buffer pts and the pad latency are computed from the framebuffer timestamp, separately for each pad. Use the sensor timestamp provided through the request metadata instead, to compute the values once outside of the pads loop. Signed-off-by: Laurent Pinchart Reviewed-by: Umang Jain --- Changes since v1: - Use GST_CLOCK_TIME_NONE and GST_CLOCK_TIME_IS_VALID() --- src/gstreamer/gstlibcamerasrc.cpp | 34 ++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 700bee2bf877..37f201e89828 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -34,6 +34,7 @@ #include #include +#include #include @@ -164,22 +165,35 @@ GstLibcameraSrcState::requestCompleted(Request *request) return; } + GstClockTime latency; + GstClockTime pts; + + if (GST_ELEMENT_CLOCK(src_)) { + int64_t timestamp = request->metadata().get(controls::SensorTimestamp); + + 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); + pts = timestamp - sys_base_time; + latency = sys_now - timestamp; + } else { + latency = 0; + pts = GST_CLOCK_TIME_NONE; + } + for (GstPad *srcpad : srcpads_) { Stream *stream = gst_libcamera_pad_get_stream(srcpad); GstBuffer *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); + if (GST_CLOCK_TIME_IS_VALID(pts)) { + GST_BUFFER_PTS(buffer) = pts; + gst_libcamera_pad_set_latency(srcpad, latency); } else { GST_BUFFER_PTS(buffer) = 0; } From patchwork Thu Jun 30 00:02:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16444 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id D366BBD808 for ; Thu, 30 Jun 2022 00:03:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6591065647; Thu, 30 Jun 2022 02:03:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547410; bh=cqISnPxLu396AkxqcxXMBX2VVrZrc2x5mzNe5IcBhIk=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=mDjntka9ZLjOUJsezYlimhJfT/dW2kLLS3XLjISuwTyiaDYB9W70p6jRnMG0mEeEG aKEat5JOO4YlMVXKUhszWSuwnCxO1FOrf81TaP+hma0PZkpnaRWbB0QP0CGHNBGECn wn7go33ZaD/Y3sytHjDIxw3HhNq2vt5NkM5G4RkoaEpxn+fREumaSkFik1oNefc3c3 Vlx3xMAz0Cu9tKx2Ny3wcleDtyWzUiXFsQNHNRju9+k5Kv2bdQEbqX9etvcyJ7Ux2y VdTALoL4S43a9FyTv0930hRdzF3+p8WmwQQ2dOw/MSUlR3Y9L89VzyRBhPrzv6EqwD gztXEPflAWRhg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 33F0E6563F for ; Thu, 30 Jun 2022 02:03:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="n2AWoTRK"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C1FE06D1; Thu, 30 Jun 2022 02:03:16 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547397; bh=cqISnPxLu396AkxqcxXMBX2VVrZrc2x5mzNe5IcBhIk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=n2AWoTRKYFs9vgheaKN2tD/FRvLDX2QYevuLYSikgPjWiMPAjOhyM93Rd2QfCP3QY wQ6Zjzm7S/sDpAlKeFPnZ6WcnbjD82OKNAbZ4zXwmD+CGgaAc5z+1/ciewe48XWckV xGpwi0tFpRbBJgE/g2IRtGVtx3eM9rXz2gPaqYt4= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:44 +0300 Message-Id: <20220630000251.31295-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 05/12] gstreamer: Rename queued requests queue to queuedRequests_ 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" To prepare for the addition of a completed requests queue, rename the existing queued requests queue from requests_ to queuedRequests_. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- src/gstreamer/gstlibcamerasrc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 37f201e89828..f2f48d53991a 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -108,7 +108,7 @@ struct GstLibcameraSrcState { std::shared_ptr cam_; std::unique_ptr config_; std::vector srcpads_; - std::queue> requests_; + std::queue> queuedRequests_; guint group_id_; void requestCompleted(Request *request); @@ -155,8 +155,8 @@ GstLibcameraSrcState::requestCompleted(Request *request) GST_DEBUG_OBJECT(src_, "buffers are ready"); - std::unique_ptr wrap = std::move(requests_.front()); - requests_.pop(); + std::unique_ptr wrap = std::move(queuedRequests_.front()); + queuedRequests_.pop(); g_return_if_fail(wrap->request_.get() == request); @@ -311,7 +311,7 @@ gst_libcamera_src_task_run(gpointer user_data) GLibLocker lock(GST_OBJECT(self)); GST_TRACE_OBJECT(self, "Requesting buffers"); state->cam_->queueRequest(wrap->request_.get()); - state->requests_.push(std::move(wrap)); + state->queuedRequests_.push(std::move(wrap)); /* The RequestWrap will be deleted in the completion handler. */ } From patchwork Thu Jun 30 00:02:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16442 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 3D315BD808 for ; Thu, 30 Jun 2022 00:03:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A85876563F; Thu, 30 Jun 2022 02:03:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547407; bh=daSkBUqMGuW7q9N/BmNV/l8m4/bCX/bMskfiaEbpzsA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=ZY9uENotfJ33nYfW8zCJc6P5S9h7RntsTgqMPAmU2AuDldP3eUKNQ9lvEqAzQf/jY K1RIOVQ/QVB5aDae35jv3kBc8wjsSmS3AzNGPM0/pIXX12/VKsEqSIfB80jfBKchu9 cttaOqA+vg5Be7St1Rt5nFSv/cwOWagaFz9onlbsugFuZ5jFsE/ueyZEafhfGBwPuh IS1gXayFLNLoRpbLcQhL346lMqYoVEjP/6xzdgdL8Xl0BqJnLBdgRAhxlJCSMhCdOq 84Fgg5ttID3Z3QuNXWN09Ju5KAxGPFhB5kr3W2scBsFEQGX8MZOOOVH8XY9t49YH/u 9wTOOBAq1ag1w== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9EDA065641 for ; Thu, 30 Jun 2022 02:03:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="IKrEtFFN"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 307C759D; Thu, 30 Jun 2022 02:03:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547397; bh=daSkBUqMGuW7q9N/BmNV/l8m4/bCX/bMskfiaEbpzsA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IKrEtFFNWaTUjYxDXoo8NKo42SzAYHRNmNrFL0QXnbGGhOWR+J4j8Zl8WvWY3muXv Mc/+rfn+5EFda/BfHHg3T7hMBHFGoqOJQKHVQGXrx/qmLVNMHGaBTvPnJwqUiZ6IrR OIhee4DvMlEn5vqGLyEGp82K0K63DZFSk4wGz/ZI= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:45 +0300 Message-Id: <20220630000251.31295-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 06/12] gstreamer: Handle completed requests in the libcamerasrc task 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move the request wrap to a completed queue in the request completion handler to move more of the request completion processing to the libcamerasrc task. This lowers the amount of time spent in the completion handler, and prepares for reworking the usage of locks. Signed-off-by: Laurent Pinchart Reviewed-by: Umang Jain --- Changes since v1: - Use GST_CLOCK_TIME_NONE and GST_CLOCK_TIME_IS_VALID() --- src/gstreamer/gstlibcamerasrc.cpp | 82 ++++++++++++++++++------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index f2f48d53991a..2cb915637874 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -57,10 +57,13 @@ struct RequestWrap { std::unique_ptr request_; std::map buffers_; + + GstClockTime latency_; + GstClockTime pts_; }; RequestWrap::RequestWrap(std::unique_ptr request) - : request_(std::move(request)) + : request_(std::move(request)), latency_(0), pts_(GST_CLOCK_TIME_NONE) { } @@ -109,6 +112,7 @@ struct GstLibcameraSrcState { std::unique_ptr config_; std::vector srcpads_; std::queue> queuedRequests_; + std::queue> completedRequests_; guint group_id_; void requestCompleted(Request *request); @@ -165,9 +169,6 @@ GstLibcameraSrcState::requestCompleted(Request *request) return; } - GstClockTime latency; - GstClockTime pts; - if (GST_ELEMENT_CLOCK(src_)) { int64_t timestamp = request->metadata().get(controls::SensorTimestamp); @@ -178,31 +179,11 @@ GstLibcameraSrcState::requestCompleted(Request *request) /* Deduced from: sys_now - sys_base_time == gst_now - gst_base_time */ GstClockTime sys_base_time = sys_now - (gst_now - gst_base_time); - pts = timestamp - sys_base_time; - latency = sys_now - timestamp; - } else { - latency = 0; - pts = GST_CLOCK_TIME_NONE; + wrap->pts_ = timestamp - sys_base_time; + wrap->latency_ = sys_now - timestamp; } - for (GstPad *srcpad : srcpads_) { - Stream *stream = gst_libcamera_pad_get_stream(srcpad); - GstBuffer *buffer = wrap->detachBuffer(stream); - - FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer); - - if (GST_CLOCK_TIME_IS_VALID(pts)) { - GST_BUFFER_PTS(buffer) = pts; - gst_libcamera_pad_set_latency(srcpad, latency); - } 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); - } + completedRequests_.push(std::move(wrap)); gst_task_resume(src_->task); } @@ -316,6 +297,39 @@ gst_libcamera_src_task_run(gpointer user_data) /* The RequestWrap will be deleted in the completion handler. */ } + { + GLibLocker lock(GST_OBJECT(self)); + + if (!state->completedRequests_.empty()) { + wrap = std::move(state->completedRequests_.front()); + state->completedRequests_.pop(); + } + } + + if (!wrap) { + gst_task_pause(self->task); + return; + } + + for (GstPad *srcpad : state->srcpads_) { + Stream *stream = gst_libcamera_pad_get_stream(srcpad); + GstBuffer *buffer = wrap->detachBuffer(stream); + + FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer); + + if (GST_CLOCK_TIME_IS_VALID(wrap->pts_)) { + GST_BUFFER_PTS(buffer) = wrap->pts_; + gst_libcamera_pad_set_latency(srcpad, wrap->latency_); + } 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); + } + GstFlowReturn ret = GST_FLOW_OK; gst_flow_combiner_reset(self->flow_combiner); for (GstPad *srcpad : state->srcpads_) { @@ -344,13 +358,11 @@ gst_libcamera_src_task_run(gpointer user_data) * happen in lock step with the callback thread which may want * to resume the task and might push pending buffers. */ - GLibLocker lock(GST_OBJECT(self)); - bool do_pause = true; - for (GstPad *srcpad : state->srcpads_) { - if (gst_libcamera_pad_has_pending(srcpad)) { - do_pause = false; - break; - } + bool do_pause; + + { + GLibLocker lock(GST_OBJECT(self)); + do_pause = state->completedRequests_.empty(); } if (do_pause) @@ -504,6 +516,8 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task, state->cam_->stop(); + state->completedRequests_ = {}; + for (GstPad *srcpad : state->srcpads_) gst_libcamera_pad_set_pool(srcpad, nullptr); From patchwork Thu Jun 30 00:02:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16443 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 96A4DBD808 for ; Thu, 30 Jun 2022 00:03:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2420B65641; Thu, 30 Jun 2022 02:03:29 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547409; bh=KArOEihn7NjCMl3nOghpphHMjMcqw6JxyM+mUR+IgcA=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=eTMnab/NgkL+IVnFs4ASg7p3YdFIPOfepcj5UYlmT9gWI3+Wi7c97qhqVyjtt3hu/ 8BUjfafMeoLsR3JY2KyRVBsW1jXOdP86o+siRkvZpblNmEV3fxGHajTJQ4rJlJYCRp GANNX7KGMcknewGPEj7s7bDDHKXdK4+IMNdKTgK4xFyFvqm5oZPbRfIKHVR6aB8Ggu 6vQO5XY5GEwR6wXrUZeid6FZ4qYp5yFbazF6X8HA5K+NR5XWF2C1Jye/SP1CZ9VwAi fzQKAP0et9Zcol6O2Z8iOsLK6uuWf3tGZbNYbtCOnx6zd5vSsS/AuhjrkAlpNIoGY/ yRQXPTXGxIv6g== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0EB6265643 for ; Thu, 30 Jun 2022 02:03:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="JvwOTLAY"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9CDDE6D1; Thu, 30 Jun 2022 02:03:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547397; bh=KArOEihn7NjCMl3nOghpphHMjMcqw6JxyM+mUR+IgcA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JvwOTLAYiliiKgvUepWFyAhRaW6px6mXzOS6+CICfmCGBMboYdlGXwsU1apKD3g8x q4Mk5lJ0VrMB1DyyW3917F8CJAl3gbitk+67yDAFf6+R3isH7egny+DOZ6z/FmEQKB j8D6MFdv4M+eK1bH1DJiARDNfUZHRnQh62GuQXAo= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:46 +0300 Message-Id: <20220630000251.31295-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 07/12] gstreamer: Combine the two pad loops in the task run handler 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This simplifies the code, and allows removing the internal queue in the GstLibcameraPad object. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- src/gstreamer/gstlibcamerapad.cpp | 35 ------------------------------- src/gstreamer/gstlibcamerapad.h | 6 ------ src/gstreamer/gstlibcamerasrc.cpp | 11 ++++------ 3 files changed, 4 insertions(+), 48 deletions(-) diff --git a/src/gstreamer/gstlibcamerapad.cpp b/src/gstreamer/gstlibcamerapad.cpp index c00e81c8966e..87b4057ac101 100644 --- a/src/gstreamer/gstlibcamerapad.cpp +++ b/src/gstreamer/gstlibcamerapad.cpp @@ -18,7 +18,6 @@ struct _GstLibcameraPad { GstPad parent; StreamRole role; GstLibcameraPool *pool; - GQueue pending_buffers; GstClockTime latency; }; @@ -155,40 +154,6 @@ gst_libcamera_pad_get_stream(GstPad *pad) return nullptr; } -void -gst_libcamera_pad_queue_buffer(GstPad *pad, GstBuffer *buffer) -{ - auto *self = GST_LIBCAMERA_PAD(pad); - GLibLocker lock(GST_OBJECT(self)); - - g_queue_push_head(&self->pending_buffers, buffer); -} - -GstFlowReturn -gst_libcamera_pad_push_pending(GstPad *pad) -{ - auto *self = GST_LIBCAMERA_PAD(pad); - GstBuffer *buffer; - - { - GLibLocker lock(GST_OBJECT(self)); - buffer = GST_BUFFER(g_queue_pop_tail(&self->pending_buffers)); - } - - if (!buffer) - return GST_FLOW_OK; - - return gst_pad_push(pad, buffer); -} - -bool -gst_libcamera_pad_has_pending(GstPad *pad) -{ - auto *self = GST_LIBCAMERA_PAD(pad); - GLibLocker lock(GST_OBJECT(self)); - return self->pending_buffers.length > 0; -} - void gst_libcamera_pad_set_latency(GstPad *pad, GstClockTime latency) { diff --git a/src/gstreamer/gstlibcamerapad.h b/src/gstreamer/gstlibcamerapad.h index 207695173313..103ee57ab384 100644 --- a/src/gstreamer/gstlibcamerapad.h +++ b/src/gstreamer/gstlibcamerapad.h @@ -25,10 +25,4 @@ void gst_libcamera_pad_set_pool(GstPad *pad, GstLibcameraPool *pool); libcamera::Stream *gst_libcamera_pad_get_stream(GstPad *pad); -void gst_libcamera_pad_queue_buffer(GstPad *pad, GstBuffer *buffer); - -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); diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 2cb915637874..8c1cd7017d98 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -311,6 +311,9 @@ gst_libcamera_src_task_run(gpointer user_data) return; } + GstFlowReturn ret = GST_FLOW_OK; + gst_flow_combiner_reset(self->flow_combiner); + for (GstPad *srcpad : state->srcpads_) { Stream *stream = gst_libcamera_pad_get_stream(srcpad); GstBuffer *buffer = wrap->detachBuffer(stream); @@ -327,13 +330,7 @@ gst_libcamera_src_task_run(gpointer user_data) GST_BUFFER_OFFSET(buffer) = fb->metadata().sequence; GST_BUFFER_OFFSET_END(buffer) = fb->metadata().sequence; - gst_libcamera_pad_queue_buffer(srcpad, buffer); - } - - GstFlowReturn ret = GST_FLOW_OK; - gst_flow_combiner_reset(self->flow_combiner); - for (GstPad *srcpad : state->srcpads_) { - ret = gst_libcamera_pad_push_pending(srcpad); + ret = gst_pad_push(srcpad, buffer); ret = gst_flow_combiner_update_pad_flow(self->flow_combiner, srcpad, ret); } From patchwork Thu Jun 30 00:02:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16445 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id EEA99BD808 for ; Thu, 30 Jun 2022 00:03:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9AF0A65655; Thu, 30 Jun 2022 02:03:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547412; bh=nHf6gwYLwDJnSJ8B2Zk8XcZvNZ2LWnCgfGqPfNJFrMo=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=0GvNVMdmCNwfH3DV0RA2XYPR2ZlbHEEk2OQ0v5+XDnJQymVuNkFRcFDox5aoFMQe/ 3pIP2yC1NZqF+PliA13gS6mkOfknW6QduPscad2Y4H5uA5vX46lsLWJo0RgLRUM9se 4ZhEV5VvHrj9dZfnz8tXzjaQmd5yboZl08Kgjtgn3YzfILGt+JSk7SDgQ1u0gkCz83 PZPR/rKF3klsaXcItI3Gd9KEkJ7uBZRd8vpUwp7Py63ZtaPb0KvPG3F47ZMk9a3LXO IhwPiL+EBtsHSsL58+rJlMO5BBuBtf17QBQ897bWCeCiSyoOxtdKcv7jPyaW5hKXL6 5rcFmiKolgpEg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D5DA965634 for ; Thu, 30 Jun 2022 02:03:18 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="tPc9oeac"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0DD4659D; Thu, 30 Jun 2022 02:03:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547398; bh=nHf6gwYLwDJnSJ8B2Zk8XcZvNZ2LWnCgfGqPfNJFrMo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tPc9oeaciepF73lXkLZ4Hb/7ZW+J64Qt/bjPPc3VfbEa1/f15yjlyJbd9m0R+vkzM bAQP9F138TMcIrB7jgcxGVhh58MmrAq/xcfB6YkV0Z5bVC2QfAzluwkRHVAMHapC9g y6Pygz5WDK67XVEakpaW11HM8xuWC0vM26PI4X7g= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:47 +0300 Message-Id: <20220630000251.31295-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 08/12] gstreamer: Use dedicated lock for request queues 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a new lock to the GstLibcameraSrcState class to protect the queued and completed requests queues. This replaces the GstObject lock, and minimizes the lock contention between the request completion handler and the task run handler as the former must run as fast as possible. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- Changes since v1: - Add comment about lock_ --- src/gstreamer/gstlibcamerasrc.cpp | 44 +++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 8c1cd7017d98..6f9a03c515d2 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -32,6 +32,8 @@ #include #include +#include + #include #include #include @@ -111,8 +113,18 @@ struct GstLibcameraSrcState { std::shared_ptr cam_; std::unique_ptr config_; std::vector srcpads_; - std::queue> queuedRequests_; - std::queue> completedRequests_; + + /* + * Contention on this lock_ must be minimized, as it has to be taken in + * the realtime-sensitive requestCompleted() handler to protect + * queuedRequests_ and completedRequests_. + */ + Mutex lock_; + std::queue> queuedRequests_ + LIBCAMERA_TSA_GUARDED_BY(lock_); + std::queue> completedRequests_ + LIBCAMERA_TSA_GUARDED_BY(lock_); + guint group_id_; void requestCompleted(Request *request); @@ -155,12 +167,15 @@ GstStaticPadTemplate request_src_template = { void GstLibcameraSrcState::requestCompleted(Request *request) { - GLibLocker lock(GST_OBJECT(src_)); - GST_DEBUG_OBJECT(src_, "buffers are ready"); - std::unique_ptr wrap = std::move(queuedRequests_.front()); - queuedRequests_.pop(); + std::unique_ptr wrap; + + { + MutexLocker locker(lock_); + wrap = std::move(queuedRequests_.front()); + queuedRequests_.pop(); + } g_return_if_fail(wrap->request_.get() == request); @@ -183,7 +198,10 @@ GstLibcameraSrcState::requestCompleted(Request *request) wrap->latency_ = sys_now - timestamp; } - completedRequests_.push(std::move(wrap)); + { + MutexLocker locker(lock_); + completedRequests_.push(std::move(wrap)); + } gst_task_resume(src_->task); } @@ -289,16 +307,17 @@ gst_libcamera_src_task_run(gpointer user_data) } if (wrap) { - GLibLocker lock(GST_OBJECT(self)); GST_TRACE_OBJECT(self, "Requesting buffers"); state->cam_->queueRequest(wrap->request_.get()); + + MutexLocker locker(state->lock_); state->queuedRequests_.push(std::move(wrap)); /* The RequestWrap will be deleted in the completion handler. */ } { - GLibLocker lock(GST_OBJECT(self)); + MutexLocker locker(state->lock_); if (!state->completedRequests_.empty()) { wrap = std::move(state->completedRequests_.front()); @@ -358,7 +377,7 @@ gst_libcamera_src_task_run(gpointer user_data) bool do_pause; { - GLibLocker lock(GST_OBJECT(self)); + MutexLocker locker(state->lock_); do_pause = state->completedRequests_.empty(); } @@ -513,7 +532,10 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task, state->cam_->stop(); - state->completedRequests_ = {}; + { + MutexLocker locker(state->lock_); + state->completedRequests_ = {}; + } for (GstPad *srcpad : state->srcpads_) gst_libcamera_pad_set_pool(srcpad, nullptr); From patchwork Thu Jun 30 00:02:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16446 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id E8163BD808 for ; Thu, 30 Jun 2022 00:03:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 89A1965657; Thu, 30 Jun 2022 02:03:33 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547413; bh=0pZ9z6Uqpww/XQgU0bUnhvSJRvTe8SpNHy0Id5Hj9oo=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=IFq+Uny6Lb2lFyKBzRPwa1RG9MLldTSsXb18W+z+xPuttXQJOuJJ4FWqirQSL0KMq aWzhSnspmmkC6qfxw7qDKmYYziXQJmR+f9nWpoh8fMB4OX63UpWmEb8x+EBuv25m/A KQsBYK0rF7sAeXo8WW4Rq1DeHdY7k1mXUoijuHI7u2fQ3XyzStpBmJjIjHBf2nupTF 1oeJJsURnPEE503ZtkEet3DKBWKwRHJkpv0jx+AxkS0G/PdIGom+xtW6UVe/2xcwJ6 nHf6I5+56gUo5LZ7fIvhF3rnnoSMQ9hWjJdb8anCti6mzt9OuIfdoMctEHo83HVhZa 4ZJNDIQ3eSorA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4B2F765645 for ; Thu, 30 Jun 2022 02:03:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ABZ9FhkL"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CC7E274A; Thu, 30 Jun 2022 02:03:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547399; bh=0pZ9z6Uqpww/XQgU0bUnhvSJRvTe8SpNHy0Id5Hj9oo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ABZ9FhkLQYgK/409O/VPf59JmZe774Ac2XwhW2uk7O9Hs9cTZpoMo2q8r7a3/mhiq Z7N6LmSfmWUtTXR6jMQtPaclvKGepEVg4kV++qmfrzE98bfEjmn5od83wmIHNVYmg/ NGGAYwQWX85jI8umiNLqRon+I+5z3Ea40U3ly8Og= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:48 +0300 Message-Id: <20220630000251.31295-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 09/12] gstreamer: Fix pads locking 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The srcpads_ vector is protected by two different locks, the GstObject lock of the libcamerasrc element, and the stream_lock that covers the run function of the thread. This isn't correct. Use the stream_lock consistently to protect the pads. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- Changes since v1: - Add a comment about lock ordering --- src/gstreamer/gstlibcamerasrc.cpp | 73 +++++++++++++++++-------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 6f9a03c515d2..c92ca7d29fe6 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -112,12 +112,18 @@ struct GstLibcameraSrcState { std::shared_ptr cm_; std::shared_ptr cam_; std::unique_ptr config_; - std::vector srcpads_; + + std::vector srcpads_; /* Protected by stream_lock */ /* * Contention on this lock_ must be minimized, as it has to be taken in * the realtime-sensitive requestCompleted() handler to protect * queuedRequests_ and completedRequests_. + * + * stream_lock must be taken before lock_ in contexts where both locks + * need to be taken. In particular, this means that the lock_ must not + * be held while calling into other graph elements (e.g. when calling + * gst_pad_query()). */ Mutex lock_; std::queue> queuedRequests_ @@ -354,36 +360,34 @@ gst_libcamera_src_task_run(gpointer user_data) srcpad, ret); } + if (ret != GST_FLOW_OK) { + if (ret == GST_FLOW_EOS) { + g_autoptr(GstEvent) eos = gst_event_new_eos(); + guint32 seqnum = gst_util_seqnum_next(); + gst_event_set_seqnum(eos, seqnum); + for (GstPad *srcpad : state->srcpads_) + gst_pad_push_event(srcpad, gst_event_ref(eos)); + } else if (ret != GST_FLOW_FLUSHING) { + GST_ELEMENT_FLOW_ERROR(self, ret); + } + gst_task_stop(self->task); + return; + } + + /* + * Here we need to decide if we want to pause. This needs to + * happen in lock step with the callback thread which may want + * to resume the task and might push pending buffers. + */ + bool do_pause; + { - if (ret != GST_FLOW_OK) { - if (ret == GST_FLOW_EOS) { - g_autoptr(GstEvent) eos = gst_event_new_eos(); - guint32 seqnum = gst_util_seqnum_next(); - gst_event_set_seqnum(eos, seqnum); - for (GstPad *srcpad : state->srcpads_) - gst_pad_push_event(srcpad, gst_event_ref(eos)); - } else if (ret != GST_FLOW_FLUSHING) { - GST_ELEMENT_FLOW_ERROR(self, ret); - } - gst_task_stop(self->task); - return; - } - - /* - * Here we need to decide if we want to pause. This needs to - * happen in lock step with the callback thread which may want - * to resume the task and might push pending buffers. - */ - bool do_pause; - - { - MutexLocker locker(state->lock_); - do_pause = state->completedRequests_.empty(); - } - - if (do_pause) - gst_task_pause(self->task); + MutexLocker locker(state->lock_); + do_pause = state->completedRequests_.empty(); } + + if (do_pause) + gst_task_pause(self->task); } static void @@ -537,8 +541,11 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task, state->completedRequests_ = {}; } - for (GstPad *srcpad : state->srcpads_) - gst_libcamera_pad_set_pool(srcpad, nullptr); + { + GLibRecLocker locker(&self->stream_lock); + for (GstPad *srcpad : state->srcpads_) + gst_libcamera_pad_set_pool(srcpad, nullptr); + } g_clear_object(&self->allocator); g_clear_pointer(&self->flow_combiner, @@ -697,7 +704,7 @@ gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ, g_object_ref_sink(pad); if (gst_element_add_pad(element, pad)) { - GLibLocker lock(GST_OBJECT(self)); + GLibRecLocker lock(&self->stream_lock); self->state->srcpads_.push_back(reinterpret_cast(g_object_ref(pad))); } else { GST_ELEMENT_ERROR(element, STREAM, FAILED, @@ -717,7 +724,7 @@ gst_libcamera_src_release_pad(GstElement *element, GstPad *pad) GST_DEBUG_OBJECT(self, "Pad %" GST_PTR_FORMAT " being released", pad); { - GLibLocker lock(GST_OBJECT(self)); + GLibRecLocker lock(&self->stream_lock); std::vector &pads = self->state->srcpads_; auto begin_iterator = pads.begin(); auto end_iterator = pads.end(); From patchwork Thu Jun 30 00:02:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16447 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 18C22BD808 for ; Thu, 30 Jun 2022 00:03:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 84A9C65651; Thu, 30 Jun 2022 02:03:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547414; bh=Ae/27g0zHudhp25ye9Tl3b34HDNP1IjxR/EQ3EbRSb0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=De4XnUtZUjbbq3k/NVIwJbNwaOntzyFZ9sqio3tNP8NmUFZ07AzLKnuz5MK2tODx1 drhMaLu5IAi2u8WZgX0dj5f0GGmzt6+s9XjZdmFJT2hcAKJIr0qaJikralZcJcoizk KW1EQGjAl6+Lk73EIfEsosJfxviIHK/DEEpJHJ6v4P9IHjW1/lmilF61P6xHUlsitK YjBMfEnbY87j+yI3m4y+NjpK+onwQr8RJ0OTdi7Ig/eWLvK7aQyJ4hvV2BA3bNJo/0 5VYX8Lkrt42O4rnuyMBRkShXJSpNmhlZ4i4DXjC71os7BuAoLZxTKq00MUkT60uTKA ViGMyFjJvLhMA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B4B1065631 for ; Thu, 30 Jun 2022 02:03:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BpR8cO1Q"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 47D3759D; Thu, 30 Jun 2022 02:03:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547399; bh=Ae/27g0zHudhp25ye9Tl3b34HDNP1IjxR/EQ3EbRSb0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BpR8cO1QjgzxD2twPLbLVUMgw/Z3QjUk/k5qE/5lcEb/trD/X6i+vCPq9Yi7rMRf1 M9PMzl49DlMFxvlAKvMtGVNKprF8vR/AncO+VZOiVtfSVcXoq7cRu1SOM3LW3RczsU KXH5MXkGrPigNLqnP4CyB8m8BWPWurPJ6tqvJtpY= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:49 +0300 Message-Id: <20220630000251.31295-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 10/12] gstreamer: Split request creation to a separate function 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In order to prepare for creation and queuing of multiple requests, move the request creation and queueing code to a separate function. No functional change intended. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- Changes since v1: - Add comment about locking requirement - Add a scope around the locker --- src/gstreamer/gstlibcamerasrc.cpp | 79 ++++++++++++++++++------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index c92ca7d29fe6..d63083d0cd8f 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -133,6 +133,7 @@ struct GstLibcameraSrcState { guint group_id_; + int queueRequest(); void requestCompleted(Request *request); }; @@ -170,6 +171,47 @@ GstStaticPadTemplate request_src_template = { "src_%u", GST_PAD_SRC, GST_PAD_REQUEST, TEMPLATE_CAPS }; +/* Must be called with stream_lock held. */ +int GstLibcameraSrcState::queueRequest() +{ + std::unique_ptr request = cam_->createRequest(); + if (!request) + return -ENOMEM; + + std::unique_ptr wrap = + std::make_unique(std::move(request)); + + for (GstPad *srcpad : srcpads_) { + Stream *stream = gst_libcamera_pad_get_stream(srcpad); + GstLibcameraPool *pool = gst_libcamera_pad_get_pool(srcpad); + GstBuffer *buffer; + GstFlowReturn ret; + + ret = gst_buffer_pool_acquire_buffer(GST_BUFFER_POOL(pool), + &buffer, nullptr); + if (ret != GST_FLOW_OK) { + /* + * RequestWrap has ownership of the request, and we + * won't be queueing this one due to lack of buffers. + */ + return -ENOBUFS; + } + + wrap->attachBuffer(stream, buffer); + } + + GST_TRACE_OBJECT(src_, "Requesting buffers"); + cam_->queueRequest(wrap->request_.get()); + + { + MutexLocker locker(lock_); + queuedRequests_.push(std::move(wrap)); + } + + /* The RequestWrap will be deleted in the completion handler. */ + return 0; +} + void GstLibcameraSrcState::requestCompleted(Request *request) { @@ -279,8 +321,8 @@ gst_libcamera_src_task_run(gpointer user_data) GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data); GstLibcameraSrcState *state = self->state; - std::unique_ptr request = state->cam_->createRequest(); - if (!request) { + int err = state->queueRequest(); + if (err == -ENOMEM) { GST_ELEMENT_ERROR(self, RESOURCE, NO_SPACE_LEFT, ("Failed to allocate request for camera '%s'.", state->cam_->id().c_str()), @@ -289,38 +331,7 @@ gst_libcamera_src_task_run(gpointer user_data) return; } - std::unique_ptr wrap = - std::make_unique(std::move(request)); - - for (GstPad *srcpad : state->srcpads_) { - Stream *stream = gst_libcamera_pad_get_stream(srcpad); - GstLibcameraPool *pool = gst_libcamera_pad_get_pool(srcpad); - GstBuffer *buffer; - GstFlowReturn ret; - - ret = gst_buffer_pool_acquire_buffer(GST_BUFFER_POOL(pool), - &buffer, nullptr); - if (ret != GST_FLOW_OK) { - /* - * RequestWrap has ownership of the request, and we - * won't be queueing this one due to lack of buffers. - */ - wrap.release(); - break; - } - - wrap->attachBuffer(stream, buffer); - } - - if (wrap) { - GST_TRACE_OBJECT(self, "Requesting buffers"); - state->cam_->queueRequest(wrap->request_.get()); - - MutexLocker locker(state->lock_); - state->queuedRequests_.push(std::move(wrap)); - - /* The RequestWrap will be deleted in the completion handler. */ - } + std::unique_ptr wrap; { MutexLocker locker(state->lock_); From patchwork Thu Jun 30 00:02:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16448 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 30EE0BD808 for ; Thu, 30 Jun 2022 00:03:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BDD4F65652; Thu, 30 Jun 2022 02:03:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547415; bh=/Y6Gh5gSlLJaNtCb6JdJ/0zj1CcdRKeiIr10vTYnpTs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=AjvAMr4dEA45/kytqWew8qLJ6pZ5zDWwe2Zx2w6zOve/nmXgKCs/nx6KueWotjmX+ lNbWNB1zuPLq6aq51SL3UOVfQvtuKu1ukZLOpwzQWT8/yZKiuLpeV833KBGW+jTuh3 El4abZxse7vf6U86WSzsJ1fE0ytqZ9wXcewfrpaSjMTfvUrIMUEDqCw5C4suC5c7oB 7Quf99/VYMj22LQPf4mfnTTReP3H9WGzfV8IXQH9zh4jsy1I/IZSWb79SzvG0imaCl 14ccQsXNdczYUis7OY1WMK4/p9eThJjHQAbH8KUn0XacXBVVMhwtdHqUDzrHen1osY clNQPIUltAkOg== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 27E5A65638 for ; Thu, 30 Jun 2022 02:03:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="gIZ+cejF"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AD87D6D1; Thu, 30 Jun 2022 02:03:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547399; bh=/Y6Gh5gSlLJaNtCb6JdJ/0zj1CcdRKeiIr10vTYnpTs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gIZ+cejFd4P1oy96FWt/n07RZOvCAfXvHFmFFTUj12f45z1InL+D4eRimqY6Xc0n2 SwwvmJnWMbOrDvH8c1VleOJzpLho+wxbDSIl2k5VdQggRKXYBDE42zql9KyP/1nTIw zeZ6KJcVREUshNiGvKAyPlWl2j61TesJ9AdGLexM= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:50 +0300 Message-Id: <20220630000251.31295-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 11/12] gstreamer: Split completed request processing to a separate function 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Simplify the task run function futher by moving the processing of completed requests to a separate function. No functional change intended, only increased readability. Signed-off-by: Laurent Pinchart Reviewed-by: Nicolas Dufresne Reviewed-by: Umang Jain --- Changes since v1: - Add comment about locking requirement --- src/gstreamer/gstlibcamerasrc.cpp | 126 ++++++++++++++++++------------ 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index d63083d0cd8f..9ea59631a9f2 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -135,6 +135,7 @@ struct GstLibcameraSrcState { int queueRequest(); void requestCompleted(Request *request); + int processRequest(); }; struct _GstLibcameraSrc { @@ -254,6 +255,64 @@ GstLibcameraSrcState::requestCompleted(Request *request) gst_task_resume(src_->task); } +/* Must be called with stream_lock held. */ +int GstLibcameraSrcState::processRequest() +{ + std::unique_ptr wrap; + + { + MutexLocker locker(lock_); + + if (!completedRequests_.empty()) { + wrap = std::move(completedRequests_.front()); + completedRequests_.pop(); + } + } + + if (!wrap) + return -ENODATA; + + GstFlowReturn ret = GST_FLOW_OK; + gst_flow_combiner_reset(src_->flow_combiner); + + for (GstPad *srcpad : srcpads_) { + Stream *stream = gst_libcamera_pad_get_stream(srcpad); + GstBuffer *buffer = wrap->detachBuffer(stream); + + FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer); + + if (GST_CLOCK_TIME_IS_VALID(wrap->pts_)) { + GST_BUFFER_PTS(buffer) = wrap->pts_; + gst_libcamera_pad_set_latency(srcpad, wrap->latency_); + } else { + GST_BUFFER_PTS(buffer) = 0; + } + + GST_BUFFER_OFFSET(buffer) = fb->metadata().sequence; + GST_BUFFER_OFFSET_END(buffer) = fb->metadata().sequence; + + ret = gst_pad_push(srcpad, buffer); + ret = gst_flow_combiner_update_pad_flow(src_->flow_combiner, + srcpad, ret); + } + + if (ret != GST_FLOW_OK) { + if (ret == GST_FLOW_EOS) { + g_autoptr(GstEvent) eos = gst_event_new_eos(); + guint32 seqnum = gst_util_seqnum_next(); + gst_event_set_seqnum(eos, seqnum); + for (GstPad *srcpad : srcpads_) + gst_pad_push_event(srcpad, gst_event_ref(eos)); + } else if (ret != GST_FLOW_FLUSHING) { + GST_ELEMENT_FLOW_ERROR(src_, ret); + } + + return -EPIPE; + } + + return 0; +} + static bool gst_libcamera_src_open(GstLibcameraSrc *self) { @@ -321,8 +380,13 @@ gst_libcamera_src_task_run(gpointer user_data) GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data); GstLibcameraSrcState *state = self->state; - int err = state->queueRequest(); - if (err == -ENOMEM) { + /* + * Create and queue one request. If no buffers are available the + * function returns -ENOBUFS, which we ignore here as that's not a + * fatal error. + */ + int ret = state->queueRequest(); + if (ret == -ENOMEM) { GST_ELEMENT_ERROR(self, RESOURCE, NO_SPACE_LEFT, ("Failed to allocate request for camera '%s'.", state->cam_->id().c_str()), @@ -331,58 +395,16 @@ gst_libcamera_src_task_run(gpointer user_data) return; } - std::unique_ptr wrap; - - { - MutexLocker locker(state->lock_); - - if (!state->completedRequests_.empty()) { - wrap = std::move(state->completedRequests_.front()); - state->completedRequests_.pop(); - } - } - - if (!wrap) { - gst_task_pause(self->task); - return; - } - - GstFlowReturn ret = GST_FLOW_OK; - gst_flow_combiner_reset(self->flow_combiner); - - for (GstPad *srcpad : state->srcpads_) { - Stream *stream = gst_libcamera_pad_get_stream(srcpad); - GstBuffer *buffer = wrap->detachBuffer(stream); - - FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer); - - if (GST_CLOCK_TIME_IS_VALID(wrap->pts_)) { - GST_BUFFER_PTS(buffer) = wrap->pts_; - gst_libcamera_pad_set_latency(srcpad, wrap->latency_); - } else { - GST_BUFFER_PTS(buffer) = 0; - } - - GST_BUFFER_OFFSET(buffer) = fb->metadata().sequence; - GST_BUFFER_OFFSET_END(buffer) = fb->metadata().sequence; - - ret = gst_pad_push(srcpad, buffer); - ret = gst_flow_combiner_update_pad_flow(self->flow_combiner, - srcpad, ret); - } - - if (ret != GST_FLOW_OK) { - if (ret == GST_FLOW_EOS) { - g_autoptr(GstEvent) eos = gst_event_new_eos(); - guint32 seqnum = gst_util_seqnum_next(); - gst_event_set_seqnum(eos, seqnum); - for (GstPad *srcpad : state->srcpads_) - gst_pad_push_event(srcpad, gst_event_ref(eos)); - } else if (ret != GST_FLOW_FLUSHING) { - GST_ELEMENT_FLOW_ERROR(self, ret); - } + /* Process one completed request, if available. */ + ret = state->processRequest(); + switch (ret) { + case -EPIPE: gst_task_stop(self->task); return; + + case -ENODATA: + gst_task_pause(self->task); + return; } /* From patchwork Thu Jun 30 00:02:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 16449 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 3BDBCBD808 for ; Thu, 30 Jun 2022 00:03:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CFB6F6564F; Thu, 30 Jun 2022 02:03:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1656547416; bh=qBGpVUVKbXxHaRDq7EPNyffLvbZ/SABnSN8OUzibW2g=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=4ZTT3bD0mg+m0Uej1D+VZjByPUFEdeMf6nMicwRMb+ss4HWDQCyCDtsb3H18sPN/e wSRYicLsG2uwxkRxs3m6X/jgXxDurq4dvzBRt5nHpLN99xQYfuPbkGa8TrTsqi3eRe gvvCCOozpHSiihnZldc/Gsfk8BkpVwvpc5OGua8kcmtbIaLQJELYBXFAzqSDcbWoff UpEgYWDtntgxhTe3uSlzEFAUeLhCOtLWtLnGqdnLixRV/RLRbESaVHTOl2IqqEpWWT StsC23lCSXIVaUQoo1hmPgFZN0sz+387bg5PslGsGxgpKwsAtG2zfcujPAdgtBKLtT 1hUJOVGzCbTVA== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8BD5A65646 for ; Thu, 30 Jun 2022 02:03:20 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Hgnb9YsY"; dkim-atps=neutral Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 20E6159D; Thu, 30 Jun 2022 02:03:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1656547400; bh=qBGpVUVKbXxHaRDq7EPNyffLvbZ/SABnSN8OUzibW2g=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Hgnb9YsYoOQgLsnulTtOtlRNsOjXafVFj24JUv0WAFaquFNLpuZYGAkpxF17dsGk7 iq46oPFuXAtb9nJzMMRfnOdl/OnLNY8bnQAJ6eUCD8OsWQoVYYjybVhHxTK6Ozbq5U tUqcsavYtGVwkcjfM1g0X1UPLJqSHD42+LCcyiUA= To: libcamera-devel@lists.libcamera.org Date: Thu, 30 Jun 2022 03:02:51 +0300 Message-Id: <20220630000251.31295-13-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> References: <20220630000251.31295-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 12/12] gstreamer: Fix race conditions in task pause/resume 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-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Cc: Nicolas Dufresne Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The task run function races with two other threads that want to resume the task: the requestCompleted() handler and the buffer-notify signal handler. If the former queues completed requests or the latter queues back buffers to the pool, and then resume the task, after the task run handler checks the queues but before it attemps to pause the task, then the task may be paused without noticing that more work is available. The most immediate way to fix this is to take the stream_lock in the requestCompleted() and buffer-notify signal handlers, or cover the whole task run handler with the GstLibcameraSrcState lock. This could cause long delays in the requestCompleted() handler, so that's not a good option. Instead, add a wakeup flag, preotected by the GstLibcameraSrcState lock, that allows detection of a lost race, and retry the task run. Signed-off-by: Laurent Pinchart --- Changes since v1: - Fix incorrect wakeup and pause logic --- src/gstreamer/gstlibcamerasrc.cpp | 84 +++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp index 9ea59631a9f2..5471ab951252 100644 --- a/src/gstreamer/gstlibcamerasrc.cpp +++ b/src/gstreamer/gstlibcamerasrc.cpp @@ -118,7 +118,7 @@ struct GstLibcameraSrcState { /* * Contention on this lock_ must be minimized, as it has to be taken in * the realtime-sensitive requestCompleted() handler to protect - * queuedRequests_ and completedRequests_. + * queuedRequests_, completedRequests_ and wakeup_. * * stream_lock must be taken before lock_ in contexts where both locks * need to be taken. In particular, this means that the lock_ must not @@ -130,6 +130,7 @@ struct GstLibcameraSrcState { LIBCAMERA_TSA_GUARDED_BY(lock_); std::queue> completedRequests_ LIBCAMERA_TSA_GUARDED_BY(lock_); + bool wakeup_ LIBCAMERA_TSA_GUARDED_BY(lock_); guint group_id_; @@ -250,15 +251,17 @@ GstLibcameraSrcState::requestCompleted(Request *request) { MutexLocker locker(lock_); completedRequests_.push(std::move(wrap)); - } + wakeup_ = true; - gst_task_resume(src_->task); + gst_task_resume(src_->task); + } } /* Must be called with stream_lock held. */ int GstLibcameraSrcState::processRequest() { std::unique_ptr wrap; + int err = 0; { MutexLocker locker(lock_); @@ -267,10 +270,13 @@ int GstLibcameraSrcState::processRequest() wrap = std::move(completedRequests_.front()); completedRequests_.pop(); } + + if (completedRequests_.empty()) + err = -ENOBUFS; } if (!wrap) - return -ENODATA; + return -ENOBUFS; GstFlowReturn ret = GST_FLOW_OK; gst_flow_combiner_reset(src_->flow_combiner); @@ -310,7 +316,7 @@ int GstLibcameraSrcState::processRequest() return -EPIPE; } - return 0; + return err; } static bool @@ -374,53 +380,88 @@ gst_libcamera_src_open(GstLibcameraSrc *self) return true; } +static void +gst_libcamera_src_task_resume(gpointer user_data) +{ + GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data); + GstLibcameraSrcState *state = self->state; + + MutexLocker locker(state->lock_); + state->wakeup_ = true; + gst_task_resume(self->task); +} + static void gst_libcamera_src_task_run(gpointer user_data) { GstLibcameraSrc *self = GST_LIBCAMERA_SRC(user_data); GstLibcameraSrcState *state = self->state; + { + MutexLocker locker(state->lock_); + state->wakeup_ = false; + } + + bool doPause = true; + /* * Create and queue one request. If no buffers are available the * function returns -ENOBUFS, which we ignore here as that's not a * fatal error. */ int ret = state->queueRequest(); - if (ret == -ENOMEM) { + switch (ret) { + case 0: + /* + * The request was successfully queued, there may be enough + * buffers to create a new one. Don't pause the task to give it + * another try. + */ + doPause = false; + break; + + case -ENOMEM: GST_ELEMENT_ERROR(self, RESOURCE, NO_SPACE_LEFT, ("Failed to allocate request for camera '%s'.", state->cam_->id().c_str()), ("libcamera::Camera::createRequest() failed")); gst_task_stop(self->task); return; + + case -ENOBUFS: + default: + break; } - /* Process one completed request, if available. */ + /* + * Process one completed request, if available, and record if further + * requests are ready for processing. + */ ret = state->processRequest(); switch (ret) { + case -ENOBUFS: + doPause = false; + break; + case -EPIPE: gst_task_stop(self->task); return; - case -ENODATA: - gst_task_pause(self->task); - return; + case 0: + default: + break; } /* - * Here we need to decide if we want to pause. This needs to - * happen in lock step with the callback thread which may want - * to resume the task and might push pending buffers. + * Here we need to decide if we want to pause. This needs to happen in + * lock step with the requestCompleted callback and the buffer-notify + * signal handler that resume the task. */ - bool do_pause; - - { + if (doPause) { MutexLocker locker(state->lock_); - do_pause = state->completedRequests_.empty(); + if (!state->wakeup_) + gst_task_pause(self->task); } - - if (do_pause) - gst_task_pause(self->task); } static void @@ -531,7 +572,8 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread, GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator, stream_cfg.stream()); g_signal_connect_swapped(pool, "buffer-notify", - G_CALLBACK(gst_task_resume), task); + G_CALLBACK(gst_libcamera_src_task_resume), + self); gst_libcamera_pad_set_pool(srcpad, pool); gst_flow_combiner_add_pad(self->flow_combiner, srcpad);