Show a patch.

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

{
    "id": 22820,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/22820/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/22820/",
    "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": "<20250221112610.42402-3-stanislaw.gruszka@linux.intel.com>",
    "date": "2025-02-21T11:26:10",
    "name": "[v4,2/2] pipeline: simple: Use proper device for frame start events",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": false,
    "hash": "6db790a8858dc7ba3bee55b7bafcce9262d69741",
    "submitter": {
        "id": 211,
        "url": "https://patchwork.libcamera.org/api/1.1/people/211/?format=api",
        "name": "Stanislaw Gruszka",
        "email": "stanislaw.gruszka@linux.intel.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/22820/mbox/",
    "series": [
        {
            "id": 5010,
            "url": "https://patchwork.libcamera.org/api/1.1/series/5010/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=5010",
            "date": "2025-02-21T11:26:08",
            "name": "libcamera: start frame events changes",
            "version": 4,
            "mbox": "https://patchwork.libcamera.org/series/5010/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/22820/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/22820/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 CA316BEFBE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 21 Feb 2025 11:26:27 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7EBD1686B0;\n\tFri, 21 Feb 2025 12:26:27 +0100 (CET)",
            "from mgamail.intel.com (mgamail.intel.com [198.175.65.14])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 40C0D68686\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 21 Feb 2025 12:26:25 +0100 (CET)",
            "from fmviesa009.fm.intel.com ([10.60.135.149])\n\tby orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n\t21 Feb 2025 03:26:24 -0800",
            "from sgruszka-mobl.ger.corp.intel.com (HELO localhost)\n\t([10.245.97.15]) by fmviesa009-auth.fm.intel.com with\n\tESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:21 -0800"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=intel.com header.i=@intel.com\n\theader.b=\"gRLZZ7Se\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n\td=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n\tt=1740137185; x=1771673185;\n\th=from:to:cc:subject:date:message-id:in-reply-to:\n\treferences:mime-version:content-transfer-encoding;\n\tbh=54fDOP/oX+p7uk9qUdPX4gcO8WT9ItyPgz8hgCSpXnk=;\n\tb=gRLZZ7SeAtsheTBvykQGUg0LHCXVvGk8A9bJbBcmbD07MVUutqMsvntf\n\tZVsMH9vTIpzRkDdK6FTKN7rhIinTsZu6tPGaUbp6mt2yZr8OZhnBPS8k+\n\tJuXnrP67QvUMcZp2p/g3qHMWAWbTvGrrXsY4IRTzIbKxbSJBRyIKlKuFH\n\tb3iHKx1Qa/yO5n/x/O4noX5rOTF4qk/UTb5K4kM6ZUg9wOnPb1SojcGZa\n\tSLqYe6p4VfsgLaG72oodTjJF/SaOGmUyoaiVBsFeDLmmzme5NNfUSV9P/\n\tz58gTTNQkNqTXd+xqXEz/WDGIXkLVQgtG85h2D8H3IF3JN6tswccNCDdw w==;",
        "X-CSE-ConnectionGUID": [
            "YFK/fOXWTda+hK94WcyUKQ==",
            "Zvjl0p+1ROCQY+uX4ykN8Q=="
        ],
        "X-CSE-MsgGUID": [
            "tLGkB/oeR+aLjr0Lw/vG5g==",
            "cOi0Kly2QqiFqTttwx4srQ=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6700,10204,11351\"; a=\"44738605\"",
            "E=Sophos;i=\"6.13,304,1732608000\"; d=\"scan'208\";a=\"44738605\"",
            "E=Sophos;i=\"6.13,304,1732608000\"; d=\"scan'208\";a=\"115990715\""
        ],
        "X-ExtLoop1": "1",
        "From": "Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Milan Zamazal <mzamazal@redhat.com>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>,\n\tNaushir Patuck <naush@raspberrypi.com>,\n\tSakari Ailus <sakari.ailus@linux.intel.com>,\n\tHans de Goede <hdegoede@redhat.com>",
        "Subject": "[PATCH v4 2/2] pipeline: simple: Use proper device for frame start\n\tevents",
        "Date": "Fri, 21 Feb 2025 12:26:10 +0100",
        "Message-Id": "<20250221112610.42402-3-stanislaw.gruszka@linux.intel.com>",
        "X-Mailer": "git-send-email 2.34.1",
        "In-Reply-To": "<20250221112610.42402-1-stanislaw.gruszka@linux.intel.com>",
        "References": "<20250221112610.42402-1-stanislaw.gruszka@linux.intel.com>",
        "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": "Currently we use frame start event from video capture device to\napply controls. But the capture device might not generate the events.\nUsually CSI-2 receiver is proper device to subscribe for start\nframe events.\n\nTo fix, loop over devices in the pipeline (starting from the last one),\nfind one that emits start frame events and connect applyControls()\nto it. Additionally remove direct call to sensor_->setControls() if\nthe emitter device was found.\n\nThis also fixes the assertion like below:\n\n../src/libcamera/delayed_controls.cpp:227:\nlibcamera::ControlList libcamera::DelayedControls::get(uint32_t):\nAssertion `info.type() != ControlTypeNone' failed\n\nwhich can happen rarely at the beginning of streaming when\nControlRingBuffer is not yet filled and there are errors on CSI-2.\nIn such rare scenario we can have call to DelayedControls::get()\nwith frame number that exceed number of saved entries. Handing\nframe start signal assures we do DelayedConntrols::applyControls()\nwith (possibly out of sequence) frame number and later call\nto DelayedControls::get() will get proper not-empty control entry.\n\nBug: https://bugs.libcamera.org/show_bug.cgi?id=241\nCo-developed-by: Hans de Goede <hdegoede@redhat.com>\nSigned-off-by: Hans de Goede <hdegoede@redhat.com>\nReviewed-by: Hans de Goede <hdegoede@redhat.com> # v2\nTested-by: Hans de Goede <hdegoede@redhat.com> # Lenovo X1 Yoga IPU6 + ov2740 # v2\nReviewed-by: Milan Zamazal <mzamazal@redhat.com> # v2\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> # v3\nSigned-off-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>\n---\n src/libcamera/pipeline/simple/simple.cpp | 40 +++++++++++++++++++++---\n 1 file changed, 36 insertions(+), 4 deletions(-)",
    "diff": "diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp\nindex 6e039bf3..088b9156 100644\n--- a/src/libcamera/pipeline/simple/simple.cpp\n+++ b/src/libcamera/pipeline/simple/simple.cpp\n@@ -277,6 +277,7 @@ public:\n \tstd::list<Entity> entities_;\n \tstd::unique_ptr<CameraSensor> sensor_;\n \tV4L2VideoDevice *video_;\n+\tV4L2Subdevice *frameStartEmitter_;\n \n \tstd::vector<Configuration> configs_;\n \tstd::map<PixelFormat, std::vector<const Configuration *>> formats_;\n@@ -579,6 +580,19 @@ int SimpleCameraData::init()\n \n \tproperties_ = sensor_->properties();\n \n+\tframeStartEmitter_ = nullptr;\n+\tfor (auto it = entities_.rbegin(); it != entities_.rend(); ++it) {\n+\t\tV4L2Subdevice *sd = pipe->subdev(it->entity);\n+\t\tif (!sd || !sd->supportsFrameStartEvent())\n+\t\t\tcontinue;\n+\n+\t\tLOG(SimplePipeline, Debug)\n+\t\t\t<< \"Using \" << it->entity->name() << \" frameStart signal\";\n+\n+\t\tframeStartEmitter_ = sd;\n+\t\tbreak;\n+\t}\n+\n \treturn 0;\n }\n \n@@ -897,8 +911,11 @@ void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId)\n void SimpleCameraData::setSensorControls(const ControlList &sensorControls)\n {\n \tdelayedCtrls_->push(sensorControls);\n-\tControlList ctrls(sensorControls);\n-\tsensor_->setControls(&ctrls);\n+\t/* Directly apply controls now if there is no frameStart signal */\n+\tif (!frameStartEmitter_ || !frameStartEmitter_->frameStartEnabled()) {\n+\t\tControlList ctrls(sensorControls);\n+\t\tsensor_->setControls(&ctrls);\n+\t}\n }\n \n /* Retrieve all source pads connected to a sink pad through active routes. */\n@@ -1285,8 +1302,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c)\n \tdata->delayedCtrls_ =\n \t\tstd::make_unique<DelayedControls>(data->sensor_->device(),\n \t\t\t\t\t\t  params);\n-\tdata->video_->frameStart.connect(data->delayedCtrls_.get(),\n-\t\t\t\t\t &DelayedControls::applyControls);\n \n \tStreamConfiguration inputCfg;\n \tinputCfg.pixelFormat = pipeConfig->captureFormat;\n@@ -1325,6 +1340,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n {\n \tSimpleCameraData *data = cameraData(camera);\n \tV4L2VideoDevice *video = data->video_;\n+\tV4L2Subdevice *frameStartEmitter = data->frameStartEmitter_;\n \tint ret;\n \n \tconst MediaPad *pad = acquirePipeline(data);\n@@ -1354,6 +1370,15 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL\n \n \tvideo->bufferReady.connect(data, &SimpleCameraData::imageBufferReady);\n \n+\tif (frameStartEmitter) {\n+\t\tret = frameStartEmitter->setFrameStartEnabled(true);\n+\t\tif (ret == 0)\n+\t\t\tframeStartEmitter->frameStart.connect(data->delayedCtrls_.get(),\n+\t\t\t\t\t\t\t      &DelayedControls::applyControls);\n+\t}\n+\n+\tdata->delayedCtrls_->reset();\n+\n \tret = video->streamOn();\n \tif (ret < 0) {\n \t\tstop(camera);\n@@ -1385,6 +1410,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera)\n {\n \tSimpleCameraData *data = cameraData(camera);\n \tV4L2VideoDevice *video = data->video_;\n+\tV4L2Subdevice *frameStartEmitter = data->frameStartEmitter_;\n+\n+\tif (frameStartEmitter) {\n+\t\tframeStartEmitter->setFrameStartEnabled(false);\n+\t\tframeStartEmitter->frameStart.disconnect(data->delayedCtrls_.get(),\n+\t\t\t\t\t\t\t &DelayedControls::applyControls);\n+\t}\n \n \tif (data->useConversion_) {\n \t\tif (data->converter_)\n",
    "prefixes": [
        "v4",
        "2/2"
    ]
}