Patch Detail
Show a patch.
GET /api/1.1/patches/19225/?format=api
{ "id": 19225, "url": "https://patchwork.libcamera.org/api/1.1/patches/19225/?format=api", "web_url": "https://patchwork.libcamera.org/patch/19225/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20231122135406.14921-3-jaslo@ziska.de>", "date": "2023-11-22T13:43:55", "name": "[libcamera-devel,2/2] gstreamer: Implement renegotiation", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "527bc23032ecc92beee72804e91576d4b17c674c", "submitter": { "id": 173, "url": "https://patchwork.libcamera.org/api/1.1/people/173/?format=api", "name": "Jaslo Ziska", "email": "jaslo@ziska.de" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/19225/mbox/", "series": [ { "id": 4079, "url": "https://patchwork.libcamera.org/api/1.1/series/4079/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4079", "date": "2023-11-22T13:43:53", "name": "gstreamer: Implement renegotiation", "version": 1, "mbox": "https://patchwork.libcamera.org/series/4079/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/19225/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/19225/checks/", "tags": {}, "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 09A7FC3220\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 22 Nov 2023 13:55:27 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BB461629BC;\n\tWed, 22 Nov 2023 14:55:26 +0100 (CET)", "from mo4-p00-ob.smtp.rzone.de (mo4-p00-ob.smtp.rzone.de\n\t[85.215.255.21])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 45EC461DAD\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 22 Nov 2023 14:55:25 +0100 (CET)", "from archlinux.fritz.box by smtp.strato.de (RZmta 49.9.1 AUTH)\n\twith ESMTPSA id j3f4eezAMDtOnQ3\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits))\n\t(Client did not present a certificate);\n\tWed, 22 Nov 2023 14:55:24 +0100 (CET)" ], "DKIM-Signature": [ "v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1700661326;\n\tbh=VUBeSnAX+R8QfkSbKZ2jVILDxScnF1nIIKwhk2RJsUc=;\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=RH5IB2WKe+zh49l5w9BCmwz8l3QfqGnbBANFX2OVRd5Elp0PKQENqquiNla8NXLBq\n\tlp4zpiNI1RhsLMk56Br51BtOc4/01eoMa/fm0/SRi3LNefd2SwIjycaPo7XfP6KkRY\n\tOJ4QH+kOnXi/FkMeuq95xJEUHBnPCEiaSuiVvXhZ42kCQLzhZfrzuUTCzOKCZ3CP+2\n\t+cqxdHhsiB8wa6S3cCqvhVO2nNStCkZZsfTXDLdscaJ8Vma5F3wa/kCjkUijMreerI\n\trr/7CJA/zRqB05RYZkpCFqOuJ1QSOTrQYkNItUWzfvwCbQHf6S0YGo9YbE7utxREPf\n\tLlMSGN6xF6Wyg==", "v=1; a=rsa-sha256; c=relaxed/relaxed; t=1700661324;\n\ts=strato-dkim-0002; d=ziska.de;\n\th=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date:\n\tFrom:Subject:Sender;\n\tbh=NjoAQgXU5NeIvTedhSpZUyXJyHOywY+H8rZ/RMBpAxs=;\n\tb=twLwLjS5ITVL46GBJ08s1Rbmii6wGBg8aSS/8VEe4CiAg7wzf8BkUNnmQYYX7R4ClP\n\tN0ZjEOGXVSweKsAmKxQvS2dJh6pSGh+SdadYmfwEAXOf9s0tHsLyWPsUJ6A7fD2sKPE2\n\tOYQdqE0t/6YD10P580CxMEIm+ijeV0ardYhYs5RapolwlAHCaWFVISkhmUtEi1sbInH6\n\t9XMC7BQ3EuMzMdQpoIH0MzRP1yA7mJuHr5wvhW2w4y8jThjv4VdsEn67ffZVhRshFH1I\n\tjkw/E67Znm3QpINLK/P57kQ+in+oSmA7piUvRLQRCD0FDcKH+XMo4aDw1bGFRbEF6NEq\n\t6M0A==", "v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1700661324;\n\ts=strato-dkim-0003; d=ziska.de;\n\th=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date:\n\tFrom:Subject:Sender;\n\tbh=NjoAQgXU5NeIvTedhSpZUyXJyHOywY+H8rZ/RMBpAxs=;\n\tb=frwGEo4vwwrhTbuIDPAn0LxmRfsATRvhMOB7CmbpUjsbcnj8RH7+w9LqWjSPlDJm1F\n\tfAcS7by1lf6QMgNtjmBg==" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key; \n\tunprotected) header.d=ziska.de header.i=@ziska.de\n\theader.b=\"twLwLjS5\"; \n\tdkim=permerror (0-bit key) header.d=ziska.de header.i=@ziska.de\n\theader.b=\"frwGEo4v\"; dkim-atps=neutral", "ARC-Seal": "i=1; a=rsa-sha256; t=1700661324; cv=none;\n\td=strato.com; s=strato-dkim-0002;\n\tb=n5VCkFLMWuLmNixn6TIozXvJwiDWfqxnBdo8hMjhAYTmg0n8TBq1BpnYPQEAph7mL9\n\t3GQTJbmsIYZtGstvQPVGUzsUdZDOufNrIIb3kh4Xex7vPey5IdT0UwjctHtn7hNRRgMq\n\tpiZtOW98FrAY26QY+zsa1HttB6FRRD0ZOFtbGdvqcKFUlwfGLmUapUaKtiZwOk4R7sn4\n\thEZYle0un8whmKbAitx9C9qUfWQTb5iki8+yNMOm5mg4vRQCT6zjV2UbJhYnGgc+BA6W\n\t1k3zlxKDxEDxQYPXdFAQpgPHMU1I4zkDWt1ArCKNncpltmJePJ/2bPm0ixAfXpbjUoEP\n\tzrdg==", "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; t=1700661324;\n\ts=strato-dkim-0002; d=strato.com;\n\th=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date:\n\tFrom:Subject:Sender;\n\tbh=NjoAQgXU5NeIvTedhSpZUyXJyHOywY+H8rZ/RMBpAxs=;\n\tb=PK+igTCF2V6aUEB7a5kAYK6fPIRAvHzIXdprilLxK6+4zPCfbSM6f3/Wa0MyaQ60uq\n\tR0fb1p5cXCszUXmnXb+NVi7ECbXYCQT8/LTOGYz44UjVMbVBA2LsA2llcjUX9N4bT0o8\n\t1g9eVRRpo4A/wroT5YMai1ALwO3MRNOJ+tPELodvCnsT3tZd2c543WnRAAM4CNNZFKsZ\n\t/TmgC5rr/2LJozHTyHdNvddvq4gMi8WLdtrM2CReF15bZxXu2ahVViW+JYXacj7Xqs48\n\ttqMYzregvzhIlpUNYThvjPuEyr4EvoFoMKJH8xVh6MPyKbbYL9pHQ6MxD2Y7X1kFyvJB\n\t2fXA==", "ARC-Authentication-Results": "i=1; strato.com;\n arc=none;\n dkim=none", "X-RZG-CLASS-ID": "mo00", "X-RZG-AUTH": "\":Jm0XeU+IYfb0x77LHmrjN5Wlb7TBwusDqIM6Hizy8VdfzvKi4yoFC9cG0Yq6UfJaraj+i8jcRUV7OSd6ZI2VJZzV+od9\"", "To": "libcamera-devel@lists.libcamera.org", "Date": "Wed, 22 Nov 2023 14:43:55 +0100", "Message-ID": "<20231122135406.14921-3-jaslo@ziska.de>", "X-Mailer": "git-send-email 2.42.1", "In-Reply-To": "<20231122135406.14921-1-jaslo@ziska.de>", "References": "<20231122135406.14921-1-jaslo@ziska.de>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "Content-Type": "text/plain; charset=\"us-ascii\"", "Subject": "[libcamera-devel] [PATCH 2/2] gstreamer: Implement renegotiation", "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": "Jaslo Ziska via libcamera-devel <libcamera-devel@lists.libcamera.org>", "Reply-To": "Jaslo Ziska <jaslo@ziska.de>", "Cc": "Jaslo Ziska <jaslo@ziska.de>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "This commit implements renegotiation of the camera configuration and\nsource pad caps. A renegotiation can happen when a downstream element\ndecides to change caps or the pipeline is dynamically changed.\n\nTo handle the renegotiation the GST_FLOW_NOT_NEGOTIATED return value has\nto be handled in GstLibcameraSrcState::processRequest. Otherwise the\ndefault would be to print an error and stop streaming.\nTo archive this in a clean way the if-statement is altered into a switch\nstatement which now also has a case for GST_FLOW_NOT_NEGOTIATED. Just\nlike the case for GST_FLOW_OK, the function will return without an error\nbecause the renegotiation will happen later in the running task.\n\nIn gst_libcamera_src_task_run all the source pads are checked for the\nreconfigure flag by calling gst_pad_check_reconfigure. It is important\nto iterate all source pads and not break after one pad requested a\nreconfiguration because gst_pad_check_reconfigure clears the reconfigure\nflag and if two pads request a reconfiguration at the same time the\nrenegotiation would happen twice.\nIf a source pad requested a reconfiguration it is first checked whether\nthe old caps are still sufficient. If they are not the renegotiation\nwill happen.\nIf any pad requested a reconfiguration the following will happen:\n1. The camera is stopped because changing the configuration may not\n happen while running.\n2. The completedRequests queue will be cleared because the completed\n buffers have the wrong configuration (see below).\n3. The new caps are negotiated by calling gst_libcamera_src_negotiate.\n When the negotiation fails streaming will stop.\n4. The camera is started again.\n\nClearing the completedRequests queue is archived with a new method in\nGstLibcameraSrcState called clearRequests. This function is now also\nused in gst_libcamera_src_task_leave as the code there did the same\nthing.\n\nIn gst_libcamera_src_task_enter, after the initial negotiation, a call\nto gst_pad_check_reconfigure was added to clear the reconfigure flag to\navoid triggering a renegotiation when running the task for the first\ntime.\n\nSigned-off-by: Jaslo Ziska <jaslo@ziska.de>\n---\n src/gstreamer/gstlibcamerasrc.cpp | 72 +++++++++++++++++++++++--------\n 1 file changed, 55 insertions(+), 17 deletions(-)", "diff": "diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\nindex e7a49fef..868fa20a 100644\n--- a/src/gstreamer/gstlibcamerasrc.cpp\n+++ b/src/gstreamer/gstlibcamerasrc.cpp\n@@ -11,7 +11,6 @@\n * - Implement GstElement::send_event\n * + Allowing application to use FLUSH/FLUSH_STOP\n * + Prevent the main thread from accessing streaming thread\n- * - Implement renegotiation (even if slow)\n * - Implement GstElement::request-new-pad (multi stream)\n * + Evaluate if a single streaming thread is fine\n * - Add application driven request (snapshot)\n@@ -133,6 +132,7 @@ struct GstLibcameraSrcState {\n \tint queueRequest();\n \tvoid requestCompleted(Request *request);\n \tint processRequest();\n+\tvoid clearRequests();\n };\n \n struct _GstLibcameraSrc {\n@@ -301,23 +301,39 @@ int GstLibcameraSrcState::processRequest()\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 : 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(src_, ret);\n-\t\t}\n+\tswitch (ret) {\n+\tcase GST_FLOW_OK:\n+\tcase GST_FLOW_NOT_NEGOTIATED:\n+\t\tbreak;\n+\tcase GST_FLOW_EOS: {\n+\t\tg_autoptr(GstEvent) eos = gst_event_new_eos();\n+\t\tguint32 seqnum = gst_util_seqnum_next();\n+\t\tgst_event_set_seqnum(eos, seqnum);\n+\t\tfor (GstPad *srcpad : srcpads_)\n+\t\t\tgst_pad_push_event(srcpad, gst_event_ref(eos));\n+\n+\t\terr = -EPIPE;\n+\t\tbreak;\n+\t}\n+\tcase GST_FLOW_FLUSHING:\n+\t\terr = -EPIPE;\n+\t\tbreak;\n+\tdefault:\n+\t\tGST_ELEMENT_FLOW_ERROR(src_, ret);\n \n-\t\treturn -EPIPE;\n+\t\terr = -EPIPE;\n+\t\tbreak;\n \t}\n \n \treturn err;\n }\n \n+void GstLibcameraSrcState::clearRequests()\n+{\n+\tGLibLocker locker(&lock_);\n+\tcompletedRequests_ = {};\n+}\n+\n static bool\n gst_libcamera_src_open(GstLibcameraSrc *self)\n {\n@@ -488,6 +504,31 @@ gst_libcamera_src_task_run(gpointer user_data)\n \t\treturn;\n \t}\n \n+\t// check if a srcpad requested a renegotiation\n+\tgboolean reconfigure = FALSE;\n+\tfor (GstPad *srcpad : state->srcpads_) {\n+\t\tif (gst_pad_check_reconfigure(srcpad)) {\n+\t\t\t// check whether the caps even need changing\n+\t\t\tg_autoptr(GstCaps) caps = gst_pad_get_current_caps(srcpad);\n+\t\t\tg_autoptr(GstCaps) intersection = gst_pad_peer_query_caps(srcpad, caps);\n+\n+\t\t\tif (gst_caps_is_empty(intersection))\n+\t\t\t\treconfigure = TRUE;\n+\t\t}\n+\t}\n+\n+\tif (reconfigure) {\n+\t\tstate->cam_->stop();\n+\t\tstate->clearRequests();\n+\n+\t\tif (!gst_libcamera_src_negotiate(self)) {\n+\t\t\tGST_ELEMENT_FLOW_ERROR(self, GST_FLOW_NOT_NEGOTIATED);\n+\t\t\tgst_task_stop(self->task);\n+\t\t}\n+\n+\t\tstate->cam_->start(&state->initControls_);\n+\t}\n+\n \t/*\n \t * Create and queue one request. If no buffers are available the\n \t * function returns -ENOBUFS, which we ignore here as that's not a\n@@ -594,6 +635,7 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,\n \t\tgst_segment_init(&segment, GST_FORMAT_TIME);\n \t\tgst_pad_push_event(srcpad, gst_event_new_segment(&segment));\n \n+\t\tgst_pad_check_reconfigure(srcpad); // clear reconfigure flag\n \t}\n \n \tif (self->auto_focus_mode != controls::AfModeManual) {\n@@ -629,11 +671,7 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task,\n \tGST_DEBUG_OBJECT(self, \"Streaming thread is about to stop\");\n \n \tstate->cam_->stop();\n-\n-\t{\n-\t\tGLibLocker locker(&state->lock_);\n-\t\tstate->completedRequests_ = {};\n-\t}\n+\tstate->clearRequests();\n \n \t{\n \t\tGLibRecLocker locker(&self->stream_lock);\n", "prefixes": [ "libcamera-devel", "2/2" ] }