Patch Detail
Show a patch.
GET /api/patches/26515/?format=api
{ "id": 26515, "url": "https://patchwork.libcamera.org/api/patches/26515/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26515/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/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": "<20260409140656.648249-1-fabien.danieau@pollen-robotics.com>", "date": "2026-04-09T14:06:56", "name": "gstreamer: Add sensor-mode property to libcamerasrc", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "6c80c60d89b7c96571a8df2650486ec0b7ee85fd", "submitter": { "id": 265, "url": "https://patchwork.libcamera.org/api/people/265/?format=api", "name": "Fabien Danieau", "email": "fabien.danieau@pollen-robotics.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26515/mbox/", "series": [ { "id": 5879, "url": "https://patchwork.libcamera.org/api/series/5879/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5879", "date": "2026-04-09T14:06:56", "name": "gstreamer: Add sensor-mode property to libcamerasrc", "version": 1, "mbox": "https://patchwork.libcamera.org/series/5879/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26515/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26515/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 8F8F3BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 9 Apr 2026 14:07:41 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 5B79662E4A;\n\tThu, 9 Apr 2026 16:07:40 +0200 (CEST)", "from mail-wr1-x431.google.com (mail-wr1-x431.google.com\n\t[IPv6:2a00:1450:4864:20::431])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6AF7362010\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 9 Apr 2026 16:07:38 +0200 (CEST)", "by mail-wr1-x431.google.com with SMTP id\n\tffacd0b85a97d-43cfce3a195so590923f8f.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 09 Apr 2026 07:07:38 -0700 (PDT)", "from lotus.home\n\t(dynamic-2a00-1028-8388-1986-846d-8679-d49f-e84f.ipv6.o2.cz.\n\t[2a00:1028:8388:1986:846d:8679:d49f:e84f])\n\tby smtp.gmail.com with ESMTPSA id\n\tffacd0b85a97d-43d1e4f5016sm72258177f8f.33.2026.04.09.07.07.36\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tThu, 09 Apr 2026 07:07:37 -0700 (PDT)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=pollen-robotics-com.20251104.gappssmtp.com\n\theader.i=@pollen-robotics-com.20251104.gappssmtp.com\n\theader.b=\"otGeFR98\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=pollen-robotics-com.20251104.gappssmtp.com; s=20251104; t=1775743658;\n\tx=1776348458; darn=lists.libcamera.org; \n\th=content-transfer-encoding:mime-version:message-id:date:subject:cc\n\t:to:from:from:to:cc:subject:date:message-id:reply-to;\n\tbh=slgFSKl1EsDPeq7rNxCxPtTEMdw7NZylBDykwXdV3VQ=;\n\tb=otGeFR98CrnH1Gg5GTR2wUw3fXusrxDx36xxJwJnsAEgZZmdgYN8ctCTpti4Bs+CE3\n\teLXW5dXAns5A+faXJY9w1qdUsA3eZY2465GVi3u1GoaThmPXk0T49581JGMfaJxcYbFa\n\tZ78x0Ugq9jsQOifsXuU8k4+PbsZBPOCimMlukxfMiugF7058QOBvaLfYEt2ybHXRJI9o\n\tvv0ff6lGd2o8Uj9UAQHe3p/D2ihNluS35YZycZxhrXBFqxUVqnLl2HVRr8Tua/t2eJVe\n\tGAaz8DJieZIEqHc0XzHV8fRg3zh/klCqBVBSsvlIsK2dcijq9CRSvVvoVvvM5OCaBrCF\n\tFKKw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20251104; t=1775743658; x=1776348458;\n\th=content-transfer-encoding:mime-version:message-id:date:subject:cc\n\t:to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=slgFSKl1EsDPeq7rNxCxPtTEMdw7NZylBDykwXdV3VQ=;\n\tb=M3C3deHWI7uk/FGw6yE8lCK3Vb8dhycr/P0IaD9BJByg9ruMb1aodeqRJohC/oHzv1\n\tY6L4pwzOcI2xSA/0i35+MGlEH1/i/k7953pdiGE5n9k1HtEKfNxwfog31KB8QBBKCM3z\n\t24O1h6tuZlpGI2PiEWAYTB/zSKn4edxGo4s96nJLrarvIn8nLuF7/CcO/gNLDTbtxGw1\n\t6O3PFIYNxXXRcvoJ70vYL5CMipuY8AeImcI5bDQKPnPIUFS2xLBaS6Tj/DhWRK98hFUZ\n\tQEuYRKhlZ90sHbH5w3yGlmCKgbj9CRIfbsc0IITGAH2LsdTa0gQhQGiFkrD7vdYTQ6L4\n\tAjEQ==", "X-Gm-Message-State": "AOJu0Yx9xOBAA0deLC7Pm+4J+YQ+WQOoqk698eEcQcLg9PZrMOf08r3z\n\tBKvax65PC64DhQ6M9lqJdu8NhhhOdrotkwTHOgXmh1TxWJeq6t5Z8Xxgbxn9wJ0DIC5GE8CfLia\n\tiIuokv2Y=", "X-Gm-Gg": "AeBDievl+GMiS4v8SHB2WiwtGwep7cSTd0RqQbEYQODdMJ9HU40M6Fl5I2LAM5hL8Ta\n\tmPO5ymoUut23yOt4fTLSBrNj4uSyp8FHpBM/hTKfATOxopihYNO2QU/g7Q1WMPhHBUdXxd49lzF\n\t6vMnUTmOq5dwgVxNKzstl0es7q45uA1CtzMIB2B+jLDSEXVPd7pJJkSnG7BM63pbL7DM7riKHlb\n\t/tM1u32aB4eWRcg/7PvttPKQGNzeK7qUp7ELeOvFetTIECwyGnI11IrBXxoEASumqsLLGdLxyeI\n\ts7U9XHse7F8Fs9rikE+WesryAXONf3eMKxq3oBnhWctHJ6wRfNpuL+c3PkYcvZBHq8H2CYXVeTR\n\t+gs5Pyr7Ie2fn8fsBtmHXd+nsPW0bxMYxgsdoR7+LVSh98oS+AAsDck9Vkv0AXgN3GwEFXecu9U\n\tCFkten6+H/FBFYuNIsuqe+ip00e3xMd4CzNn9vtakspujI80M9Jo72khcxiNnLIGojrEqLb2fI6\n\t5wyev9SzdfP0ERxPhASGFy511lwFW9CT7yZs5caarLzWMmgyy4=", "X-Received": "by 2002:a05:6000:40cb:b0:43b:3cdc:941f with SMTP id\n\tffacd0b85a97d-43d5a13db02mr4890971f8f.17.1775743657753; \n\tThu, 09 Apr 2026 07:07:37 -0700 (PDT)", "From": "Fabien Danieau <fabien.danieau@pollen-robotics.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Fabien Danieau <fabien.danieau@pollen-robotics.com>", "Subject": "[PATCH] gstreamer: Add sensor-mode property to libcamerasrc", "Date": "Thu, 9 Apr 2026 16:06:56 +0200", "Message-ID": "<20260409140656.648249-1-fabien.danieau@pollen-robotics.com>", "X-Mailer": "git-send-email 2.47.3", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "Add a sensor-mode property that allows users to force a specific sensor\nmode regardless of the stream output resolution. The property accepts a\nstring in the format 'width:height:bit-depth' (e.g. '2304:1296:10').\n\nThis is useful when the desired output resolution is smaller than the\nsensor's native resolution but the full field of view must be preserved.\nWithout this property, the pipeline handler auto-selects a sensor mode\nbased on the output resolution, which may result in a cropped field of\nview.\n\nSigned-off-by: Fabien Danieau <fabien.danieau@pollen-robotics.com>\n---\n src/gstreamer/gstlibcamerasrc.cpp | 53 +++++++++++++++++++++++++++++++\n 1 file changed, 53 insertions(+)", "diff": "diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\nindex a7241e9b..00080ac4 100644\n--- a/src/gstreamer/gstlibcamerasrc.cpp\n+++ b/src/gstreamer/gstlibcamerasrc.cpp\n@@ -23,6 +23,7 @@\n \n #include <atomic>\n #include <queue>\n+#include <stdio.h>\n #include <tuple>\n #include <utility>\n #include <vector>\n@@ -141,6 +142,7 @@ struct _GstLibcameraSrc {\n \tGstTask *task;\n \n \tgchar *camera_name;\n+\tgchar *sensor_mode;\n \n \tstd::atomic<GstEvent *> pending_eos;\n \n@@ -152,6 +154,7 @@ struct _GstLibcameraSrc {\n enum {\n \tPROP_0,\n \tPROP_CAMERA_NAME,\n+\tPROP_SENSOR_MODE,\n \tPROP_LAST\n };\n \n@@ -810,6 +813,22 @@ gst_libcamera_src_task_run(gpointer user_data)\n \t\tgst_task_resume(self->task);\n }\n \n+static bool\n+gst_libcamera_src_parse_sensor_mode(const gchar *mode_str,\n+\t\t\t\t SensorConfiguration &sensorConfig)\n+{\n+\tunsigned int width, height, bitDepth;\n+\n+\tif (sscanf(mode_str, \"%u:%u:%u\", &width, &height, &bitDepth) != 3) {\n+\t\treturn false;\n+\t}\n+\n+\tsensorConfig.outputSize = Size(width, height);\n+\tsensorConfig.bitDepth = bitDepth;\n+\n+\treturn sensorConfig.isValid();\n+}\n+\n static void\n gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,\n \t\t\t gpointer user_data)\n@@ -846,6 +865,24 @@ gst_libcamera_src_task_enter(GstTask *task, [[maybe_unused]] GThread *thread,\n \t}\n \tg_assert(state->config_->size() == state->srcpads_.size());\n \n+\t/* Apply the sensor mode if specified. */\n+\t{\n+\t\tGLibLocker objLock(GST_OBJECT(self));\n+\t\tif (self->sensor_mode) {\n+\t\t\tSensorConfiguration sensorConfig;\n+\t\t\tif (gst_libcamera_src_parse_sensor_mode(self->sensor_mode,\n+\t\t\t\t\t\t\t\tsensorConfig)) {\n+\t\t\t\tstate->config_->sensorConfig = sensorConfig;\n+\t\t\t} else {\n+\t\t\t\tGST_ELEMENT_ERROR(self, RESOURCE, SETTINGS,\n+\t\t\t\t\t\t (\"Invalid sensor mode '%s'\", self->sensor_mode),\n+\t\t\t\t\t\t (\"Expected format: 'width:height:bit-depth'\"));\n+\t\t\t\tgst_task_stop(task);\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n \tif (!gst_libcamera_src_negotiate(self)) {\n \t\tstate->initControls_.clear();\n \t\tGST_ELEMENT_FLOW_ERROR(self, GST_FLOW_NOT_NEGOTIATED);\n@@ -934,6 +971,10 @@ gst_libcamera_src_set_property(GObject *object, guint prop_id,\n \t\tg_free(self->camera_name);\n \t\tself->camera_name = g_value_dup_string(value);\n \t\tbreak;\n+\tcase PROP_SENSOR_MODE:\n+\t\tg_free(self->sensor_mode);\n+\t\tself->sensor_mode = g_value_dup_string(value);\n+\t\tbreak;\n \tdefault:\n \t\tif (!state->controls_.setProperty(prop_id - PROP_LAST, value, pspec))\n \t\t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);\n@@ -953,6 +994,9 @@ gst_libcamera_src_get_property(GObject *object, guint prop_id, GValue *value,\n \tcase PROP_CAMERA_NAME:\n \t\tg_value_set_string(value, self->camera_name);\n \t\tbreak;\n+\tcase PROP_SENSOR_MODE:\n+\t\tg_value_set_string(value, self->sensor_mode);\n+\t\tbreak;\n \tdefault:\n \t\tif (!state->controls_.getProperty(prop_id - PROP_LAST, value, pspec))\n \t\t\tG_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);\n@@ -1040,6 +1084,7 @@ gst_libcamera_src_finalize(GObject *object)\n \tg_clear_object(&self->task);\n \tg_mutex_clear(&self->state->lock_);\n \tg_free(self->camera_name);\n+\tg_free(self->sensor_mode);\n \tdelete self->state;\n \n \treturn klass->finalize(object);\n@@ -1162,6 +1207,14 @@ gst_libcamera_src_class_init(GstLibcameraSrcClass *klass)\n \t\t\t\t\t\t\t | G_PARAM_STATIC_STRINGS));\n \tg_object_class_install_property(object_class, PROP_CAMERA_NAME, spec);\n \n+\tspec = g_param_spec_string(\"sensor-mode\", \"Sensor Mode\",\n+\t\t\t\t \"Sensor mode as 'width:height:bit-depth'. \"\n+\t\t\t\t \"This selects a specific sensor mode \"\n+\t\t\t\t \"regardless of the stream output resolution.\",\n+\t\t\t\t nullptr,\n+\t\t\t\t (GParamFlags)(GST_PARAM_MUTABLE_READY | G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));\n+\tg_object_class_install_property(object_class, PROP_SENSOR_MODE, spec);\n+\n \tGstCameraControls::installProperties(object_class, PROP_LAST);\n }\n \n", "prefixes": [] }