Show a patch.

GET /api/1.1/patches/24615/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 24615,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/24615/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/24615/",
    "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": "<20251014071533.270074-1-uajain@igalia.com>",
    "date": "2025-10-14T07:15:33",
    "name": "[v5] gstreamer: Add support for Orientation",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "0d50f342652237d7a586394dd6da4ee4e4289ec6",
    "submitter": {
        "id": 232,
        "url": "https://patchwork.libcamera.org/api/1.1/people/232/?format=api",
        "name": "Umang Jain",
        "email": "uajain@igalia.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/24615/mbox/",
    "series": [
        {
            "id": 5497,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5497/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5497",
            "date": "2025-10-14T07:15:33",
            "name": "[v5] gstreamer: Add support for Orientation",
            "version": 5,
            "mbox": "https://patchwork.libcamera.org/series/5497/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/24615/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/24615/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 C9284BF415\n\tfor <parsemail@patchwork.libcamera.org>;\n\tTue, 14 Oct 2025 07:15:25 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id D88D360550;\n\tTue, 14 Oct 2025 09:15:24 +0200 (CEST)",
            "from fanzine2.igalia.com (fanzine2.igalia.com [213.97.179.56])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 392E560316\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 14 Oct 2025 09:15:22 +0200 (CEST)",
            "from [49.36.127.56] (helo=uajain)\n\tby fanzine2.igalia.com with esmtpsa \n\t(Cipher TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256)\n\t(Exim) id 1v8ZFf-009IH4-Qt; Tue, 14 Oct 2025 09:15:20 +0200"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=igalia.com header.i=@igalia.com\n\theader.b=\"Dlcm76zO\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com;\n\ts=20170329;\n\th=Content-Transfer-Encoding:MIME-Version:Message-ID:Date:Subject:\n\tCc:To:From:Sender:Reply-To:Content-Type:Content-ID:Content-Description:\n\tResent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:\n\tIn-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:\n\tList-Post:List-Owner:List-Archive;\n\tbh=YbNeUTL0/JQn6us9V2wbjOf97S1l6Oj9Ah5DrunJNE4=;\n\tb=Dlcm76zOP+Nv8HBUzGo5xEtrrg\n\tazq4QxS4UkqKxkA6ljyMZ2IqhGahDQDZYusJyBi3otiJXel6cqhsgddKTR9tWxy+DVBcHJF22SRFl\n\tzRiLrd4Zc2gzV4VUv4nopZ7ZENnrYDvIp7zWlmjXprvBTDlrfCMVVy50TmbHwQEp4UXIwWJAfG125\n\tPEnHlGy8OgFpxqPnNz5sre3MYtUm56Q+9IJIUnllWZ22o796hKk4nEl6bo1RsJ2HqYEnpXTVGztTb\n\tl+7Vw5yENVV/M8bpmTV8lzOeAoUjSM8R9RQNqbLRIIge6ISf2ISIG0kKeI37s5pySAVtKHV2nbs1o\n\te2IShzNQ==;",
        "From": "Umang Jain <uajain@igalia.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Nicolas Dufresne <nicolas.dufresne@collabora.com>,\n\tGiacomo Cappellini <giacomo.cappellini.87@gmail.com>,\n\tUmang Jain <uajain@igalia.com>",
        "Subject": "[PATCH v5] gstreamer: Add support for Orientation",
        "Date": "Tue, 14 Oct 2025 12:45:33 +0530",
        "Message-ID": "<20251014071533.270074-1-uajain@igalia.com>",
        "X-Mailer": "git-send-email 2.51.0",
        "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": "From: Giacomo Cappellini <giacomo.cappellini.87@gmail.com>\n\nPlumb the support for CameraConfiguration::orientation in libcamerasrc.\nA new \"orientation\" property is introduced and mappings for\nlibcamera::Orientation <> GstVideoOrientationMethod are provided\nwith helpers.\n\nSigned-off-by: Giacomo Cappellini <giacomo.cappellini.87@gmail.com>\nCo-developed-by: Umang Jain <uajain@igalia.com>\nSigned-off-by: Umang Jain <uajain@igalia.com>\n---\nChanges in v5:\n- patch scrubbing and cleanup\n- If different orientation is returned than requested, update the\n  property\n- Minor string fixes, append appropriate tags\n\nLink to v4: https://patchwork.libcamera.org/patch/23965/\n\nNote: Checkstyle will complain on this patch on a hunk, but the existing format\nis quite read-able IMO, hence ignored.\n---\n src/gstreamer/gstlibcamera-utils.cpp | 36 ++++++++++++++++++++++++++++\n src/gstreamer/gstlibcamera-utils.h   |  3 +++\n src/gstreamer/gstlibcamerasrc.cpp    | 27 +++++++++++++++++++++\n 3 files changed, 66 insertions(+)",
    "diff": "diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp\nindex bfb094c9..44050cbb 100644\n--- a/src/gstreamer/gstlibcamera-utils.cpp\n+++ b/src/gstreamer/gstlibcamera-utils.cpp\n@@ -357,6 +357,42 @@ control_type_to_gtype(const ControlType &type)\n \treturn G_TYPE_INVALID;\n }\n \n+static const struct {\n+\tOrientation orientation;\n+\tGstVideoOrientationMethod method;\n+} orientation_map[]{\n+\t{ Orientation::Rotate0, GST_VIDEO_ORIENTATION_IDENTITY },\n+\t{ Orientation::Rotate90, GST_VIDEO_ORIENTATION_90R },\n+\t{ Orientation::Rotate180, GST_VIDEO_ORIENTATION_180 },\n+\t{ Orientation::Rotate270, GST_VIDEO_ORIENTATION_90L },\n+\t{ Orientation::Rotate0Mirror, GST_VIDEO_ORIENTATION_HORIZ },\n+\t{ Orientation::Rotate180Mirror, GST_VIDEO_ORIENTATION_VERT },\n+\t{ Orientation::Rotate90Mirror, GST_VIDEO_ORIENTATION_UL_LR },\n+\t{ Orientation::Rotate270Mirror, GST_VIDEO_ORIENTATION_UR_LL },\n+};\n+\n+Orientation\n+gst_video_orientation_to_libcamera_orientation(GstVideoOrientationMethod method)\n+{\n+\tfor (auto &b : orientation_map) {\n+\t\tif (b.method == method)\n+\t\t\treturn b.orientation;\n+\t}\n+\n+\treturn Orientation::Rotate0;\n+}\n+\n+GstVideoOrientationMethod\n+libcamera_orientation_to_gst_video_orientation(Orientation orientation)\n+{\n+\tfor (auto &a : orientation_map) {\n+\t\tif (a.orientation == orientation)\n+\t\t\treturn a.method;\n+\t}\n+\n+\treturn GST_VIDEO_ORIENTATION_IDENTITY;\n+}\n+\n GstCaps *\n gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)\n {\ndiff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h\nindex 35df56fb..4364811e 100644\n--- a/src/gstreamer/gstlibcamera-utils.h\n+++ b/src/gstreamer/gstlibcamera-utils.h\n@@ -10,6 +10,7 @@\n \n #include <libcamera/camera_manager.h>\n #include <libcamera/controls.h>\n+#include <libcamera/orientation.h>\n #include <libcamera/stream.h>\n \n #include <gst/gst.h>\n@@ -32,6 +33,8 @@ libcamera::Rectangle gst_libcamera_gvalue_get_rectangle(const GValue *value);\n int gst_libcamera_set_structure_field(GstStructure *structure,\n \t\t\t\t      const libcamera::ControlId *id,\n \t\t\t\t      const libcamera::ControlValue &value);\n+libcamera::Orientation gst_video_orientation_to_libcamera_orientation(GstVideoOrientationMethod method);\n+GstVideoOrientationMethod libcamera_orientation_to_gst_video_orientation(libcamera::Orientation orientation);\n \n #if !GST_CHECK_VERSION(1, 16, 0)\n static inline void gst_clear_event(GstEvent **event_ptr)\ndiff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\nindex 79a025a5..2d5f0bf5 100644\n--- a/src/gstreamer/gstlibcamerasrc.cpp\n+++ b/src/gstreamer/gstlibcamerasrc.cpp\n@@ -146,6 +146,7 @@ struct _GstLibcameraSrc {\n \tGstTask *task;\n \n \tgchar *camera_name;\n+\tGstVideoOrientationMethod orientation;\n \n \tstd::atomic<GstEvent *> pending_eos;\n \n@@ -157,6 +158,7 @@ struct _GstLibcameraSrc {\n enum {\n \tPROP_0,\n \tPROP_CAMERA_NAME,\n+\tPROP_ORIENTATION,\n \tPROP_LAST\n };\n \n@@ -616,6 +618,10 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n \t\tgst_libcamera_get_framerate_from_caps(caps, element_caps);\n \t}\n \n+\t/* Set orientation. */\n+\tOrientation requestedOrientation = gst_video_orientation_to_libcamera_orientation(self->orientation);\n+\tstate->config_->orientation = requestedOrientation;\n+\n \t/* Validate the configuration. */\n \tCameraConfiguration::Status status = state->config_->validate();\n \tif (status == CameraConfiguration::Invalid)\n@@ -637,6 +643,10 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n \tgst_libcamera_clamp_and_set_frameduration(state->initControls_,\n \t\t\t\t\t\t  state->cam_->controls(), element_caps);\n \n+\t/* If orientation is changed, update the property. */\n+\tif (state->config_->orientation != requestedOrientation)\n+\t\tg_object_set(G_OBJECT(self), \"orientation\", state->config_->orientation, nullptr);\n+\n \t/*\n \t * Regardless if it has been modified, create clean caps and push the\n \t * caps event. Downstream will decide if the caps are acceptable.\n@@ -936,6 +946,9 @@ 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_ORIENTATION:\n+\t\tself->orientation = static_cast<GstVideoOrientationMethod>(g_value_get_enum(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@@ -955,6 +968,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_ORIENTATION:\n+\t\tg_value_set_enum(value, static_cast<gint>(self->orientation));\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@@ -1164,6 +1180,17 @@ 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+\n+\tspec = g_param_spec_enum(\"orientation\", \"Orientation\",\n+\t\t\t\t \"Select the preferred image orientation.\",\n+\t\t\t\t GST_TYPE_VIDEO_ORIENTATION_METHOD,\n+\t\t\t\t GST_VIDEO_ORIENTATION_IDENTITY,\n+\t\t\t\t (GParamFlags)(GST_PARAM_MUTABLE_READY\n+\t\t\t\t\t       | G_PARAM_CONSTRUCT\n+\t\t\t\t\t       | G_PARAM_READWRITE\n+\t\t\t\t\t       | G_PARAM_STATIC_STRINGS));\n+\tg_object_class_install_property(object_class, PROP_ORIENTATION, spec);\n+\n \tGstCameraControls::installProperties(object_class, PROP_LAST);\n }\n \n",
    "prefixes": [
        "v5"
    ]
}