[{"id":23646,"web_url":"https://patchwork.libcamera.org/comment/23646/","msgid":"<588fb90ed4bf59b6f510a430cdf0141090cff6f8.camel@collabora.com>","date":"2022-06-28T13:21:07","subject":"Re: [libcamera-devel] [PATCH 10/13] gstreamer: Fix pads locking","submitter":{"id":31,"url":"https://patchwork.libcamera.org/api/people/31/","name":"Nicolas Dufresne","email":"nicolas.dufresne@collabora.com"},"content":"Le vendredi 24 juin 2022 à 02:22 +0300, Laurent Pinchart a écrit :\n> The srcpads_ vector is protected by two different locks, the GstObject\n> lock of the libcamerasrc element, and the stream_lock that covers the\n> run function of the thread. This isn't correct. Use the stream_lock\n> consistently to protect the pads.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/gstreamer/gstlibcamerasrc.cpp | 68 ++++++++++++++++---------------\n>  1 file changed, 35 insertions(+), 33 deletions(-)\n> \n> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> index b85ba39fb808..58a322b251c7 100644\n> --- a/src/gstreamer/gstlibcamerasrc.cpp\n> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> @@ -112,7 +112,8 @@ struct GstLibcameraSrcState {\n>  \tstd::shared_ptr<CameraManager> cm_;\n>  \tstd::shared_ptr<Camera> cam_;\n>  \tstd::unique_ptr<CameraConfiguration> config_;\n> -\tstd::vector<GstPad *> srcpads_;\n> +\n> +\tstd::vector<GstPad *> srcpads_; /* Protected by stream_lock */\n>  \n>  \tMutex lock_;\n>  \tstd::queue<std::unique_ptr<RequestWrap>> queuedRequests_\n> @@ -349,36 +350,34 @@ gst_libcamera_src_task_run(gpointer user_data)\n>  \t\t\t\t\t\t\tsrcpad, ret);\n>  \t}\n>  \n> +\tif (ret != GST_FLOW_OK) {\n> +\t\tif (ret == GST_FLOW_EOS) {\n> +\t\t\tg_autoptr(GstEvent) eos = gst_event_new_eos();\n> +\t\t\tguint32 seqnum = gst_util_seqnum_next();\n> +\t\t\tgst_event_set_seqnum(eos, seqnum);\n> +\t\t\tfor (GstPad *srcpad : state->srcpads_)\n> +\t\t\t\tgst_pad_push_event(srcpad, gst_event_ref(eos));\n> +\t\t} else if (ret != GST_FLOW_FLUSHING) {\n> +\t\t\tGST_ELEMENT_FLOW_ERROR(self, ret);\n> +\t\t}\n> +\t\tgst_task_stop(self->task);\n> +\t\treturn;\n> +\t}\n> +\n> +\t/*\n> +\t * Here we need to decide if we want to pause. This needs to\n> +\t * happen in lock step with the callback thread which may want\n> +\t * to resume the task and might push pending buffers.\n> +\t */\n> +\tbool do_pause;\n> +\n>  \t{\n> -\t\tif (ret != GST_FLOW_OK) {\n> -\t\t\tif (ret == GST_FLOW_EOS) {\n> -\t\t\t\tg_autoptr(GstEvent) eos = gst_event_new_eos();\n> -\t\t\t\tguint32 seqnum = gst_util_seqnum_next();\n> -\t\t\t\tgst_event_set_seqnum(eos, seqnum);\n> -\t\t\t\tfor (GstPad *srcpad : state->srcpads_)\n> -\t\t\t\t\tgst_pad_push_event(srcpad, gst_event_ref(eos));\n> -\t\t\t} else if (ret != GST_FLOW_FLUSHING) {\n> -\t\t\t\tGST_ELEMENT_FLOW_ERROR(self, ret);\n> -\t\t\t}\n> -\t\t\tgst_task_stop(self->task);\n> -\t\t\treturn;\n> -\t\t}\n> -\n> -\t\t/*\n> -\t\t * Here we need to decide if we want to pause. This needs to\n> -\t\t * happen in lock step with the callback thread which may want\n> -\t\t * to resume the task and might push pending buffers.\n> -\t\t */\n> -\t\tbool do_pause;\n> -\n> -\t\t{\n> -\t\t\tMutexLocker locker(state->lock_);\n> -\t\t\tdo_pause = state->completedRequests_.empty();\n> -\t\t}\n> -\n> -\t\tif (do_pause)\n> -\t\t\tgst_task_pause(self->task);\n> +\t\tMutexLocker locker(state->lock_);\n> +\t\tdo_pause = state->completedRequests_.empty();\n\nAs you introduce locking order restrictions here, you should also add a comment\nnext to the state->lock_ documetation that reminds users what order must be\nrespected. If my reading is correct, the recursive streaming lock must be taken\nbefore this lock (if both are to be taken).\n\nWe need to be careful with pads streaming lock, since serialized queries and\neven can be re-entrant. So we could be called back with the pad stream lock\nheld, which needs to be considered in our lock ordering scenarios. So to be\navoided:\n\n  StreamLock\n  Lock\n  gst_pad_query(...)\n  -> May be re-entrant, non-recursive lock held + locking order complexity\n  ...\n\nI would simply disallow the request lock from being held while calling into\nother element in the graph.\n\n>  \t}\n> +\n> +\tif (do_pause)\n> +\t\tgst_task_pause(self->task);\n\nThis is still racy, I believe you fix that in patch 13. What I would normally do\nis prevent concurrent request throughout the patchset, and only enable it in the\nlast patch. This is just to stay \"bisect\" friendly, but not strictly required.\n\n>  }\n>  \n>  static void\n> @@ -532,8 +531,11 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task,\n>  \t\tstate->completedRequests_ = {};\n>  \t}\n>  \n> -\tfor (GstPad *srcpad : state->srcpads_)\n> -\t\tgst_libcamera_pad_set_pool(srcpad, nullptr);\n> +\t{\n> +\t\tGLibRecLocker locker(&self->stream_lock);\n> +\t\tfor (GstPad *srcpad : state->srcpads_)\n> +\t\t\tgst_libcamera_pad_set_pool(srcpad, nullptr);\n> +\t}\n>  \n>  \tg_clear_object(&self->allocator);\n>  \tg_clear_pointer(&self->flow_combiner,\n> @@ -692,7 +694,7 @@ gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,\n>  \tg_object_ref_sink(pad);\n>  \n>  \tif (gst_element_add_pad(element, pad)) {\n> -\t\tGLibLocker lock(GST_OBJECT(self));\n> +\t\tGLibRecLocker lock(&self->stream_lock);\n>  \t\tself->state->srcpads_.push_back(reinterpret_cast<GstPad *>(g_object_ref(pad)));\n>  \t} else {\n>  \t\tGST_ELEMENT_ERROR(element, STREAM, FAILED,\n> @@ -712,7 +714,7 @@ gst_libcamera_src_release_pad(GstElement *element, GstPad *pad)\n>  \tGST_DEBUG_OBJECT(self, \"Pad %\" GST_PTR_FORMAT \" being released\", pad);\n>  \n>  \t{\n> -\t\tGLibLocker lock(GST_OBJECT(self));\n> +\t\tGLibRecLocker lock(&self->stream_lock);\n>  \t\tstd::vector<GstPad *> &pads = self->state->srcpads_;\n>  \t\tauto begin_iterator = pads.begin();\n>  \t\tauto end_iterator = pads.end();\n\nWith lock order documented:\n\nReviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 95397BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 28 Jun 2022 13:21:19 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E301565631;\n\tTue, 28 Jun 2022 15:21:18 +0200 (CEST)","from madras.collabora.co.uk (madras.collabora.co.uk\n\t[46.235.227.172])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 57B6C6059D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 28 Jun 2022 15:21:17 +0200 (CEST)","from nicolas-tpx395.localdomain (192-222-136-102.qc.cable.ebox.net\n\t[192.222.136.102])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (4096 bits))\n\t(No client certificate requested) (Authenticated sender: nicolas)\n\tby madras.collabora.co.uk (Postfix) with ESMTPSA id 4AB4F6601900;\n\tTue, 28 Jun 2022 14:21:16 +0100 (BST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1656422478;\n\tbh=pGi5MKG+M6wQqU8OiFWNZeVmU49Qsm18XOJs0wPYJhs=;\n\th=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=VrzMvBS4or4ujErx1ojRJBUvwpc8KEDx/wyvO2VafJ1MXpVByeIRidOpySxdgBnxK\n\tSZmYgx3Ew8Go21BXpCaA+ERQS7MDOx6mJ4xm5d3Yms/U7F6rTPjnJMCG5/e4KLA9hx\n\temdM+xlGbfLWdULvUD/zV4ppJeKUpPXaY0bJwIdvJ1RfhWloJVPVjFxMEIi/0coyU+\n\tG+vxvP9za/pNbI2xih1pgEmcmEIyIuBTIW2FN3XFqJssGrxl721nXMpjNDjLi9lS4B\n\t/wR5Skt4pbiPqFFmUn8yyiKeksV96Qji+yFqpyVsicfIiVQ0f4148IN5pbMLGMPM4E\n\tW0XDUbroFjz+w==","v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com;\n\ts=mail; t=1656422476;\n\tbh=pGi5MKG+M6wQqU8OiFWNZeVmU49Qsm18XOJs0wPYJhs=;\n\th=Subject:From:To:Cc:Date:In-Reply-To:References:From;\n\tb=SRbBLyBPn4ek+xeUblczmLmeUeFddiaJqc8J/2OmqWYKcpPTsLCeQROMYRqh+n7mm\n\tMAmUMH7pMhipauMjrvvH3rxCZe6kld2b7U+exNX7xDFt4PdUWLozmjgIixZsiG+/ep\n\timPuTcF/WyNNbEE2ZlTrf9UVEUJLhavHcfAqhRC3adRKkGOq5k9c+r8o0c0ZVH0xd/\n\tMA0Z2MJTG+TQpM6Gzxyi3IMhG/uHabpVjiJjJC0nCPRkgGlbfGQkUrUK/1ScEYY1KW\n\tzQxi2DKHmjAUMOUPlWAy54AN//q6s7imZV5sPbteGuiNzLKDv/BIP0P4g/V9wBsK53\n\tDcsqrhLC4b1+g=="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=collabora.com\n\theader.i=@collabora.com\n\theader.b=\"SRbBLyBP\"; dkim-atps=neutral","Message-ID":"<588fb90ed4bf59b6f510a430cdf0141090cff6f8.camel@collabora.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>, \n\tlibcamera-devel@lists.libcamera.org","Date":"Tue, 28 Jun 2022 09:21:07 -0400","In-Reply-To":"<20220623232210.18742-11-laurent.pinchart@ideasonboard.com>","References":"<20220623232210.18742-1-laurent.pinchart@ideasonboard.com>\n\t<20220623232210.18742-11-laurent.pinchart@ideasonboard.com>","Content-Type":"text/plain; charset=\"UTF-8\"","Content-Transfer-Encoding":"quoted-printable","User-Agent":"Evolution 3.44.2 (3.44.2-1.fc36) ","MIME-Version":"1.0","Subject":"Re: [libcamera-devel] [PATCH 10/13] gstreamer: Fix pads locking","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Nicolas Dufresne via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Nicolas Dufresne <nicolas.dufresne@collabora.com>","Cc":"Vedant Paranjape <vedantparanjape160201@gmail.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":23652,"web_url":"https://patchwork.libcamera.org/comment/23652/","msgid":"<YrtCFf+yUbMRlNFi@pendragon.ideasonboard.com>","date":"2022-06-28T18:01:57","subject":"Re: [libcamera-devel] [PATCH 10/13] gstreamer: Fix pads locking","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Nicolas,\n\nOn Tue, Jun 28, 2022 at 09:21:07AM -0400, Nicolas Dufresne wrote:\n> Le vendredi 24 juin 2022 à 02:22 +0300, Laurent Pinchart a écrit :\n> > The srcpads_ vector is protected by two different locks, the GstObject\n> > lock of the libcamerasrc element, and the stream_lock that covers the\n> > run function of the thread. This isn't correct. Use the stream_lock\n> > consistently to protect the pads.\n> > \n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/gstreamer/gstlibcamerasrc.cpp | 68 ++++++++++++++++---------------\n> >  1 file changed, 35 insertions(+), 33 deletions(-)\n> > \n> > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> > index b85ba39fb808..58a322b251c7 100644\n> > --- a/src/gstreamer/gstlibcamerasrc.cpp\n> > +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> > @@ -112,7 +112,8 @@ struct GstLibcameraSrcState {\n> >  \tstd::shared_ptr<CameraManager> cm_;\n> >  \tstd::shared_ptr<Camera> cam_;\n> >  \tstd::unique_ptr<CameraConfiguration> config_;\n> > -\tstd::vector<GstPad *> srcpads_;\n> > +\n> > +\tstd::vector<GstPad *> srcpads_; /* Protected by stream_lock */\n> >  \n> >  \tMutex lock_;\n> >  \tstd::queue<std::unique_ptr<RequestWrap>> queuedRequests_\n> > @@ -349,36 +350,34 @@ gst_libcamera_src_task_run(gpointer user_data)\n> >  \t\t\t\t\t\t\tsrcpad, ret);\n> >  \t}\n> >  \n> > +\tif (ret != GST_FLOW_OK) {\n> > +\t\tif (ret == GST_FLOW_EOS) {\n> > +\t\t\tg_autoptr(GstEvent) eos = gst_event_new_eos();\n> > +\t\t\tguint32 seqnum = gst_util_seqnum_next();\n> > +\t\t\tgst_event_set_seqnum(eos, seqnum);\n> > +\t\t\tfor (GstPad *srcpad : state->srcpads_)\n> > +\t\t\t\tgst_pad_push_event(srcpad, gst_event_ref(eos));\n> > +\t\t} else if (ret != GST_FLOW_FLUSHING) {\n> > +\t\t\tGST_ELEMENT_FLOW_ERROR(self, ret);\n> > +\t\t}\n> > +\t\tgst_task_stop(self->task);\n> > +\t\treturn;\n> > +\t}\n> > +\n> > +\t/*\n> > +\t * Here we need to decide if we want to pause. This needs to\n> > +\t * happen in lock step with the callback thread which may want\n> > +\t * to resume the task and might push pending buffers.\n> > +\t */\n> > +\tbool do_pause;\n> > +\n> >  \t{\n> > -\t\tif (ret != GST_FLOW_OK) {\n> > -\t\t\tif (ret == GST_FLOW_EOS) {\n> > -\t\t\t\tg_autoptr(GstEvent) eos = gst_event_new_eos();\n> > -\t\t\t\tguint32 seqnum = gst_util_seqnum_next();\n> > -\t\t\t\tgst_event_set_seqnum(eos, seqnum);\n> > -\t\t\t\tfor (GstPad *srcpad : state->srcpads_)\n> > -\t\t\t\t\tgst_pad_push_event(srcpad, gst_event_ref(eos));\n> > -\t\t\t} else if (ret != GST_FLOW_FLUSHING) {\n> > -\t\t\t\tGST_ELEMENT_FLOW_ERROR(self, ret);\n> > -\t\t\t}\n> > -\t\t\tgst_task_stop(self->task);\n> > -\t\t\treturn;\n> > -\t\t}\n> > -\n> > -\t\t/*\n> > -\t\t * Here we need to decide if we want to pause. This needs to\n> > -\t\t * happen in lock step with the callback thread which may want\n> > -\t\t * to resume the task and might push pending buffers.\n> > -\t\t */\n> > -\t\tbool do_pause;\n> > -\n> > -\t\t{\n> > -\t\t\tMutexLocker locker(state->lock_);\n> > -\t\t\tdo_pause = state->completedRequests_.empty();\n> > -\t\t}\n> > -\n> > -\t\tif (do_pause)\n> > -\t\t\tgst_task_pause(self->task);\n> > +\t\tMutexLocker locker(state->lock_);\n> > +\t\tdo_pause = state->completedRequests_.empty();\n> \n> As you introduce locking order restrictions here, you should also add a comment\n> next to the state->lock_ documetation that reminds users what order must be\n> respected. If my reading is correct, the recursive streaming lock must be taken\n> before this lock (if both are to be taken).\n> \n> We need to be careful with pads streaming lock, since serialized queries and\n> even can be re-entrant. So we could be called back with the pad stream lock\n> held, which needs to be considered in our lock ordering scenarios. So to be\n> avoided:\n> \n>   StreamLock\n>   Lock\n>   gst_pad_query(...)\n>   -> May be re-entrant, non-recursive lock held + locking order complexity\n>   ...\n> \n> I would simply disallow the request lock from being held while calling into\n> other element in the graph.\n\nSounds good. The request lock is meant to be held over as little code as\npossible, while the stream lock can cover larger sections (especially\ngiven that it covers the whole run function, by design of GstTask). I'll\ndocument that.\n\n> >  \t}\n> > +\n> > +\tif (do_pause)\n> > +\t\tgst_task_pause(self->task);\n> \n> This is still racy, I believe you fix that in patch 13. What I would normally do\n> is prevent concurrent request throughout the patchset, and only enable it in the\n> last patch. This is just to stay \"bisect\" friendly, but not strictly required.\n\nI tried to find a good way to do so, but in the end decided that it may\nnot be worth it, given that the current locking scheme is already racy.\nRemember I have little experience with GStreamer, so I'm navigating in\ndifficult waters for me :-) I couldn't immediately find a way to achieve\nthe result I wanted while bringing a clear improvement in each patch\nwithout any potential extension of existing race conditions, and without\nmaking patches too large for my own taste (which is also conditioned by\nmy lack of experience here).\n\n> >  }\n> >  \n> >  static void\n> > @@ -532,8 +531,11 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task,\n> >  \t\tstate->completedRequests_ = {};\n> >  \t}\n> >  \n> > -\tfor (GstPad *srcpad : state->srcpads_)\n> > -\t\tgst_libcamera_pad_set_pool(srcpad, nullptr);\n> > +\t{\n> > +\t\tGLibRecLocker locker(&self->stream_lock);\n> > +\t\tfor (GstPad *srcpad : state->srcpads_)\n> > +\t\t\tgst_libcamera_pad_set_pool(srcpad, nullptr);\n> > +\t}\n> >  \n> >  \tg_clear_object(&self->allocator);\n> >  \tg_clear_pointer(&self->flow_combiner,\n> > @@ -692,7 +694,7 @@ gst_libcamera_src_request_new_pad(GstElement *element, GstPadTemplate *templ,\n> >  \tg_object_ref_sink(pad);\n> >  \n> >  \tif (gst_element_add_pad(element, pad)) {\n> > -\t\tGLibLocker lock(GST_OBJECT(self));\n> > +\t\tGLibRecLocker lock(&self->stream_lock);\n> >  \t\tself->state->srcpads_.push_back(reinterpret_cast<GstPad *>(g_object_ref(pad)));\n> >  \t} else {\n> >  \t\tGST_ELEMENT_ERROR(element, STREAM, FAILED,\n> > @@ -712,7 +714,7 @@ gst_libcamera_src_release_pad(GstElement *element, GstPad *pad)\n> >  \tGST_DEBUG_OBJECT(self, \"Pad %\" GST_PTR_FORMAT \" being released\", pad);\n> >  \n> >  \t{\n> > -\t\tGLibLocker lock(GST_OBJECT(self));\n> > +\t\tGLibRecLocker lock(&self->stream_lock);\n> >  \t\tstd::vector<GstPad *> &pads = self->state->srcpads_;\n> >  \t\tauto begin_iterator = pads.begin();\n> >  \t\tauto end_iterator = pads.end();\n> \n> With lock order documented:\n> \n> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 5B299BD808\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 28 Jun 2022 18:02:20 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6432A65635;\n\tTue, 28 Jun 2022 20:02:19 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id DB1B16059D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 28 Jun 2022 20:02:17 +0200 (CEST)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 1B4064A8;\n\tTue, 28 Jun 2022 20:02:17 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1656439339;\n\tbh=/IdDe4dewlvq6v0zDPyM7rU8f9vwIYQywEPolzHWfNY=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=Y0/7KT88usKP1GijAk2yZ7Vsz1hZClN4gl2Q+AQJm08Ves+ljr05ZkFmkuGXkdl28\n\tfy9bDEugLTSd6U1iFEX477GpH6oih0hZTsFu2yEPsE/1sikai6Jou1rDFeUJPAdP8R\n\tgR26Iol/dhPTiBVuW/D+waeJhMtmE3kUjVPl1oixurYKuyoLlsvnfce4ezWSSTzjBP\n\t6CRxec1INCSwJK2eUvzjgDktmEfYsrCcJVaGrjw53OWtG0s0mNSeU2XRoyMMle3rN/\n\tSxwuBJKP17RdsZy3ybrjb8BH/rB8ks0UOrIFVqd+/Q/D7UQA373YnOzcxBE1uMPcMd\n\tXtPlv+I6ww3eg==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1656439337;\n\tbh=/IdDe4dewlvq6v0zDPyM7rU8f9vwIYQywEPolzHWfNY=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=b4Fcml1nB6wCPjIS0Ud87odf+k8h+lVwP8xRxQC7SNCl9U1p/6qcmjZNqaR353PAw\n\tku/zfbtH11Jg/ZwGiyCViDhr03E+EezJNjd1cLzfbCBWdSPS96H+sdCEn74F/xCCU1\n\t1Br6Rk64UjnMBUrv7grTTiigfrcSMsfXxo1arsok="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"b4Fcml1n\"; dkim-atps=neutral","Date":"Tue, 28 Jun 2022 21:01:57 +0300","To":"Nicolas Dufresne <nicolas.dufresne@collabora.com>","Message-ID":"<YrtCFf+yUbMRlNFi@pendragon.ideasonboard.com>","References":"<20220623232210.18742-1-laurent.pinchart@ideasonboard.com>\n\t<20220623232210.18742-11-laurent.pinchart@ideasonboard.com>\n\t<588fb90ed4bf59b6f510a430cdf0141090cff6f8.camel@collabora.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<588fb90ed4bf59b6f510a430cdf0141090cff6f8.camel@collabora.com>","Subject":"Re: [libcamera-devel] [PATCH 10/13] gstreamer: Fix pads locking","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Laurent Pinchart via libcamera-devel\n\t<libcamera-devel@lists.libcamera.org>","Reply-To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tVedant Paranjape <vedantparanjape160201@gmail.com>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]