Show a patch.

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

{
    "id": 10282,
    "url": "https://patchwork.libcamera.org/api/1.1/patches/10282/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/10282/",
    "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": "<20201028010051.3830668-10-niklas.soderlund@ragnatech.se>",
    "date": "2020-10-28T01:00:51",
    "name": "[libcamera-devel,9/9] libcamera: pipeline: rkisp1: Remove Timeline",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "37a8ab4ae7a40f3f5b887ea3fb4acae7661309d5",
    "submitter": {
        "id": 5,
        "url": "https://patchwork.libcamera.org/api/1.1/people/5/?format=api",
        "name": "Niklas Söderlund",
        "email": "niklas.soderlund@ragnatech.se"
    },
    "delegate": {
        "id": 16,
        "url": "https://patchwork.libcamera.org/api/1.1/users/16/?format=api",
        "username": "neg",
        "first_name": "Niklas",
        "last_name": "Söderlund",
        "email": "niklas.soderlund@ragnatech.se"
    },
    "mbox": "https://patchwork.libcamera.org/patch/10282/mbox/",
    "series": [
        {
            "id": 1423,
            "url": "https://patchwork.libcamera.org/api/1.1/series/1423/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=1423",
            "date": "2020-10-28T01:00:42",
            "name": "libcamera: Add helper for controls that take effect with a delay",
            "version": 1,
            "mbox": "https://patchwork.libcamera.org/series/1423/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/10282/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/10282/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 226C7C3B5C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 28 Oct 2020 01:01:24 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id EE00E6225B;\n\tWed, 28 Oct 2020 02:01:23 +0100 (CET)",
            "from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net\n\t[195.74.38.228])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8233B62277\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 28 Oct 2020 02:01:19 +0100 (CET)",
            "from bismarck.berto.se (p4fca2458.dip0.t-ipconnect.de\n\t[79.202.36.88])\n\tby bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA\n\tid 15c9d570-18b9-11eb-954c-0050569116f7;\n\tWed, 28 Oct 2020 02:01:18 +0100 (CET)"
        ],
        "X-Halon-ID": "15c9d570-18b9-11eb-954c-0050569116f7",
        "Authorized-sender": "niklas.soderlund@fsdn.se",
        "From": "=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>",
        "To": "libcamera-devel@lists.libcamera.org, david.plowman@raspberrypi.com,\n\tnaush@raspberrypi.com",
        "Date": "Wed, 28 Oct 2020 02:00:51 +0100",
        "Message-Id": "<20201028010051.3830668-10-niklas.soderlund@ragnatech.se>",
        "X-Mailer": "git-send-email 2.29.1",
        "In-Reply-To": "<20201028010051.3830668-1-niklas.soderlund@ragnatech.se>",
        "References": "<20201028010051.3830668-1-niklas.soderlund@ragnatech.se>",
        "MIME-Version": "1.0",
        "Subject": "[libcamera-devel] [PATCH 9/9] libcamera: pipeline: rkisp1: Remove\n\tTimeline",
        "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>",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "base64",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "There are no users left of the Timeline and there is no longer a need to\nkeep emulating a start of exposure event as the CSI-2 resciver reports\nit. Remove the Timeline helper and what's left of it's integration in\nthe pipeline.\n\nThere is no functional change as nothing i the pipeline uses the\nTimeline.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n src/libcamera/pipeline/rkisp1/meson.build  |   1 -\n src/libcamera/pipeline/rkisp1/rkisp1.cpp   |  45 ----\n src/libcamera/pipeline/rkisp1/timeline.cpp | 227 ---------------------\n src/libcamera/pipeline/rkisp1/timeline.h   |  72 -------\n 4 files changed, 345 deletions(-)\n delete mode 100644 src/libcamera/pipeline/rkisp1/timeline.cpp\n delete mode 100644 src/libcamera/pipeline/rkisp1/timeline.h",
    "diff": "diff --git a/src/libcamera/pipeline/rkisp1/meson.build b/src/libcamera/pipeline/rkisp1/meson.build\nindex 5cd40d949d543fa9..cad66535c25f8cc0 100644\n--- a/src/libcamera/pipeline/rkisp1/meson.build\n+++ b/src/libcamera/pipeline/rkisp1/meson.build\n@@ -3,5 +3,4 @@\n libcamera_sources += files([\n     'rkisp1.cpp',\n     'rkisp1_path.cpp',\n-    'timeline.cpp',\n ])\ndiff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\nindex 552c9ebbd5617e59..424099d087528fb1 100644\n--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp\n@@ -33,7 +33,6 @@\n #include \"libcamera/internal/v4l2_videodevice.h\"\n \n #include \"rkisp1_path.h\"\n-#include \"timeline.h\"\n \n namespace libcamera {\n \n@@ -42,12 +41,6 @@ LOG_DEFINE_CATEGORY(RkISP1)\n class PipelineHandlerRkISP1;\n class RkISP1CameraData;\n \n-enum RkISP1ActionType {\n-\tSetSensor,\n-\tSOE,\n-\tQueueBuffers,\n-};\n-\n struct RkISP1FrameInfo {\n \tunsigned int frame;\n \tRequest *request;\n@@ -80,41 +73,6 @@ private:\n \tstd::map<unsigned int, RkISP1FrameInfo *> frameInfo_;\n };\n \n-class RkISP1Timeline : public Timeline\n-{\n-public:\n-\tRkISP1Timeline()\n-\t\t: Timeline()\n-\t{\n-\t\tsetDelay(SetSensor, -1, 5);\n-\t\tsetDelay(SOE, 0, -1);\n-\t\tsetDelay(QueueBuffers, -1, 10);\n-\t}\n-\n-\tvoid bufferReady(FrameBuffer *buffer)\n-\t{\n-\t\t/*\n-\t\t * Calculate SOE by taking the end of DMA set by the kernel and applying\n-\t\t * the time offsets provideprovided by the IPA to find the best estimate\n-\t\t * of SOE.\n-\t\t */\n-\n-\t\tASSERT(frameOffset(SOE) == 0);\n-\n-\t\tutils::time_point soe = std::chrono::time_point<utils::clock>()\n-\t\t\t+ std::chrono::nanoseconds(buffer->metadata().timestamp)\n-\t\t\t+ timeOffset(SOE);\n-\n-\t\tnotifyStartOfExposure(buffer->metadata().sequence, soe);\n-\t}\n-\n-\tvoid setDelay(unsigned int type, int frame, int msdelay)\n-\t{\n-\t\tutils::duration delay = std::chrono::milliseconds(msdelay);\n-\t\tsetRawDelay(type, frame, delay);\n-\t}\n-};\n-\n class RkISP1CameraData : public CameraData\n {\n public:\n@@ -140,7 +98,6 @@ public:\n \tunsigned int frame_;\n \tstd::vector<IPABuffer> ipaBuffers_;\n \tRkISP1Frames frameInfo_;\n-\tRkISP1Timeline timeline_;\n \n \tRkISP1MainPath *mainPath_;\n \tRkISP1SelfPath *selfPath_;\n@@ -877,8 +834,6 @@ void PipelineHandlerRkISP1::stop(Camera *camera)\n \n \tdata->ipa_->stop();\n \n-\tdata->timeline_.reset();\n-\n \tdata->frameInfo_.clear();\n \n \tfreeBuffers(camera);\ndiff --git a/src/libcamera/pipeline/rkisp1/timeline.cpp b/src/libcamera/pipeline/rkisp1/timeline.cpp\ndeleted file mode 100644\nindex 6b83bbe5b5892531..0000000000000000\n--- a/src/libcamera/pipeline/rkisp1/timeline.cpp\n+++ /dev/null\n@@ -1,227 +0,0 @@\n-/* SPDX-License-Identifier: LGPL-2.1-or-later */\n-/*\n- * Copyright (C) 2019, Google Inc.\n- *\n- * timeline.cpp - Timeline for per-frame control\n- */\n-\n-#include \"timeline.h\"\n-\n-#include \"libcamera/internal/log.h\"\n-\n-/**\n- * \\file timeline.h\n- * \\brief Timeline for per-frame control\n- */\n-\n-namespace libcamera {\n-\n-LOG_DEFINE_CATEGORY(Timeline)\n-\n-/**\n- * \\class FrameAction\n- * \\brief Action that can be schedule on a Timeline\n- *\n- * A frame action is an event schedule to be executed on a Timeline. A frame\n- * action has two primal attributes a frame number and a type.\n- *\n- * The frame number describes the frame to which the action is associated. The\n- * type is a numerical ID which identifies the action within the pipeline and\n- * IPA protocol.\n- */\n-\n-/**\n- * \\class Timeline\n- * \\brief Executor of FrameAction\n- *\n- * The timeline has three primary functions:\n- *\n- * 1. Keep track of the Start of Exposure (SOE) for every frame processed by\n- *    the hardware. Using this information it shall keep an up-to-date estimate\n- *    of the frame interval (time between two consecutive SOE events).\n- *\n- *    The estimated frame interval together with recorded SOE events are the\n- *    foundation for how the timeline schedule FrameAction at specific points\n- *    in time.\n- *    \\todo Improve the frame interval estimation algorithm.\n- *\n- * 2. Keep track of current delays for different types of actions. The delays\n- *    for different actions might differ during a capture session. Exposure time\n- *    effects the over all FPS and different ISP parameters might impacts its\n- *    processing time.\n- *\n- *    The action type delays shall be updated by the IPA in conjunction with\n- *    how it changes the capture parameters.\n- *\n- * 3. Schedule actions on the timeline. This is the process of taking a\n- *    FrameAction which contains an abstract description of what frame and\n- *    what type of action it contains and turning that into an time point\n- *    and make sure the action is executed at that time.\n- */\n-\n-Timeline::Timeline()\n-\t: frameInterval_(0)\n-{\n-\ttimer_.timeout.connect(this, &Timeline::timeout);\n-}\n-\n-/**\n- * \\brief Reset and stop the timeline\n- *\n- * The timeline needs to be reset when the timeline should no longer execute\n- * actions. A timeline should be reset between two capture sessions to prevent\n- * the old capture session to effect the second one.\n- */\n-void Timeline::reset()\n-{\n-\ttimer_.stop();\n-\n-\tactions_.clear();\n-\thistory_.clear();\n-}\n-\n-/**\n- * \\brief Schedule an action on the timeline\n- * \\param[in] action FrameAction to schedule\n- *\n- * The act of scheduling an action to the timeline is the process of taking\n- * the properties of the action (type, frame and time offsets) and translating\n- * that to a time point using the current values for the action type timings\n- * value recorded in the timeline. If an action is scheduled too late, execute\n- * it immediately.\n- */\n-void Timeline::scheduleAction(std::unique_ptr<FrameAction> action)\n-{\n-\tunsigned int lastFrame;\n-\tutils::time_point lastTime;\n-\n-\tif (history_.empty()) {\n-\t\tlastFrame = 0;\n-\t\tlastTime = std::chrono::steady_clock::now();\n-\t} else {\n-\t\tlastFrame = history_.back().first;\n-\t\tlastTime = history_.back().second;\n-\t}\n-\n-\t/*\n-\t * Calculate when the action shall be schedule by first finding out how\n-\t * many frames in the future the action acts on and then add the actions\n-\t * frame offset. After the spatial frame offset is found out translate\n-\t * that to a time point by using the last estimated start of exposure\n-\t * (SOE) as the fixed offset. Lastly add the action time offset to the\n-\t * time point.\n-\t */\n-\tint frame = action->frame() - lastFrame + frameOffset(action->type());\n-\tutils::time_point deadline = lastTime + frame * frameInterval_\n-\t\t+ timeOffset(action->type());\n-\n-\tutils::time_point now = std::chrono::steady_clock::now();\n-\tif (deadline < now) {\n-\t\tLOG(Timeline, Warning)\n-\t\t\t<< \"Action scheduled too late \"\n-\t\t\t<< utils::time_point_to_string(deadline)\n-\t\t\t<< \", run now \" << utils::time_point_to_string(now);\n-\t\taction->run();\n-\t} else {\n-\t\tactions_.emplace(deadline, std::move(action));\n-\t\tupdateDeadline();\n-\t}\n-}\n-\n-void Timeline::notifyStartOfExposure(unsigned int frame, utils::time_point time)\n-{\n-\thistory_.push_back(std::make_pair(frame, time));\n-\n-\tif (history_.size() <= HISTORY_DEPTH / 2)\n-\t\treturn;\n-\n-\twhile (history_.size() > HISTORY_DEPTH)\n-\t\thistory_.pop_front();\n-\n-\t/* Update esitmated time between two start of exposures. */\n-\tutils::duration sumExposures(0);\n-\tunsigned int numExposures = 0;\n-\n-\tutils::time_point lastTime;\n-\tfor (auto it = history_.begin(); it != history_.end(); it++) {\n-\t\tif (it != history_.begin()) {\n-\t\t\tsumExposures += it->second - lastTime;\n-\t\t\tnumExposures++;\n-\t\t}\n-\n-\t\tlastTime = it->second;\n-\t}\n-\n-\tframeInterval_ = sumExposures;\n-\tif (numExposures)\n-\t\tframeInterval_ /= numExposures;\n-}\n-\n-int Timeline::frameOffset(unsigned int type) const\n-{\n-\tconst auto it = delays_.find(type);\n-\tif (it == delays_.end()) {\n-\t\tLOG(Timeline, Error)\n-\t\t\t<< \"No frame offset set for action type \" << type;\n-\t\treturn 0;\n-\t}\n-\n-\treturn it->second.first;\n-}\n-\n-utils::duration Timeline::timeOffset(unsigned int type) const\n-{\n-\tconst auto it = delays_.find(type);\n-\tif (it == delays_.end()) {\n-\t\tLOG(Timeline, Error)\n-\t\t\t<< \"No time offset set for action type \" << type;\n-\t\treturn utils::duration::zero();\n-\t}\n-\n-\treturn it->second.second;\n-}\n-\n-void Timeline::setRawDelay(unsigned int type, int frame, utils::duration time)\n-{\n-\tdelays_[type] = std::make_pair(frame, time);\n-}\n-\n-void Timeline::updateDeadline()\n-{\n-\tif (actions_.empty())\n-\t\treturn;\n-\n-\tconst utils::time_point &deadline = actions_.begin()->first;\n-\n-\tif (timer_.isRunning() && deadline >= timer_.deadline())\n-\t\treturn;\n-\n-\tif (deadline <= std::chrono::steady_clock::now()) {\n-\t\ttimeout(&timer_);\n-\t\treturn;\n-\t}\n-\n-\ttimer_.start(deadline);\n-}\n-\n-void Timeline::timeout([[maybe_unused]] Timer *timer)\n-{\n-\tutils::time_point now = std::chrono::steady_clock::now();\n-\n-\tfor (auto it = actions_.begin(); it != actions_.end();) {\n-\t\tconst utils::time_point &sched = it->first;\n-\n-\t\tif (sched > now)\n-\t\t\tbreak;\n-\n-\t\tFrameAction *action = it->second.get();\n-\n-\t\taction->run();\n-\n-\t\tit = actions_.erase(it);\n-\t}\n-\n-\tupdateDeadline();\n-}\n-\n-} /* namespace libcamera */\ndiff --git a/src/libcamera/pipeline/rkisp1/timeline.h b/src/libcamera/pipeline/rkisp1/timeline.h\ndeleted file mode 100644\nindex 0c37b06fa6dfe14c..0000000000000000\n--- a/src/libcamera/pipeline/rkisp1/timeline.h\n+++ /dev/null\n@@ -1,72 +0,0 @@\n-/* SPDX-License-Identifier: LGPL-2.1-or-later */\n-/*\n- * Copyright (C) 2019, Google Inc.\n- *\n- * timeline.h - Timeline for per-frame controls\n- */\n-#ifndef __LIBCAMERA_TIMELINE_H__\n-#define __LIBCAMERA_TIMELINE_H__\n-\n-#include <list>\n-#include <map>\n-\n-#include <libcamera/timer.h>\n-\n-#include \"libcamera/internal/utils.h\"\n-\n-namespace libcamera {\n-\n-class FrameAction\n-{\n-public:\n-\tFrameAction(unsigned int frame, unsigned int type)\n-\t\t: frame_(frame), type_(type) {}\n-\n-\tvirtual ~FrameAction() = default;\n-\n-\tunsigned int frame() const { return frame_; }\n-\tunsigned int type() const { return type_; }\n-\n-\tvirtual void run() = 0;\n-\n-private:\n-\tunsigned int frame_;\n-\tunsigned int type_;\n-};\n-\n-class Timeline\n-{\n-public:\n-\tTimeline();\n-\tvirtual ~Timeline() = default;\n-\n-\tvirtual void reset();\n-\tvirtual void scheduleAction(std::unique_ptr<FrameAction> action);\n-\tvirtual void notifyStartOfExposure(unsigned int frame, utils::time_point time);\n-\n-\tutils::duration frameInterval() const { return frameInterval_; }\n-\n-protected:\n-\tint frameOffset(unsigned int type) const;\n-\tutils::duration timeOffset(unsigned int type) const;\n-\n-\tvoid setRawDelay(unsigned int type, int frame, utils::duration time);\n-\n-\tstd::map<unsigned int, std::pair<int, utils::duration>> delays_;\n-\n-private:\n-\tstatic constexpr unsigned int HISTORY_DEPTH = 10;\n-\n-\tvoid timeout(Timer *timer);\n-\tvoid updateDeadline();\n-\n-\tstd::list<std::pair<unsigned int, utils::time_point>> history_;\n-\tstd::multimap<utils::time_point, std::unique_ptr<FrameAction>> actions_;\n-\tutils::duration frameInterval_;\n-\n-\tTimer timer_;\n-};\n-\n-} /* namespace libcamera */\n-\n-#endif /* __LIBCAMERA_TIMELINE_H__ */\n",
    "prefixes": [
        "libcamera-devel",
        "9/9"
    ]
}