From patchwork Tue Feb 16 08:53:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 11300 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9FDFFBD1EF for ; Tue, 16 Feb 2021 08:53:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6D971637DE; Tue, 16 Feb 2021 09:53:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="FPktfobB"; dkim-atps=neutral Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6694563762 for ; Tue, 16 Feb 2021 09:53:48 +0100 (CET) Received: by mail-wm1-x32e.google.com with SMTP id a16so5183398wmm.0 for ; Tue, 16 Feb 2021 00:53:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=zQui2zXLsHlBseTfiwUN/JnL2KB7sNZ+RtAzvzuJznA=; b=FPktfobBD18RFxy4jo2xDWKmFx0fBarpoxFJwjfkySDQh3ea2kw9HVFvDHUf9jRM25 nTYZkHyBgRxxt0c7EoWXGZAfeIH2Y/h9xI1+yjAw3y8wEwx1VqtBHV5pHkFQuFl6dHYd LeLkZrnplrNLmmq8ahDvdt5x3b8d31rr8+rbHp7mnruS4RUcJK68mabmodUON+5lzr2V hf0ExRLxdQW3Ya16aMdCrL0+po83TCNbgxOes1FaEgVTnWygc7TYexpUxK3OTJtm/BVA Sg45RuFhOem/jNGkaTX0kSrgVieIdkX06x5EvR5uLrLpEAMSlpSb5bAHULnZ3JDF7AMj 1nBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zQui2zXLsHlBseTfiwUN/JnL2KB7sNZ+RtAzvzuJznA=; b=tFwkTK9fuzTs+oSkAD7obMUzS9yBm6w/IeuaBF19p9+ON9hZ81NNXCTsAjTn0mTjHa tZt2ybAOnVQr8LwXrH2mVLqLLvFnvrUbIGnyEXQ2X846bDYgkSex6qb2jLfDZfPWYQr3 5aFLVT1huvH6S8N6A0j7jj8vgAjLQbIDd+uiY2Pg9oxzGauxmuvy1SjnjAmNjTgkhkfR 6XqsWf+IP7bY1fQtrJk8TeTrpOJ4hAHlGoi1PGKdXWofS7EfKEM0B8zMItNjZGoe2Aud NHe+q3MRZFa5vtuumTCv5IUqr6oueMpGvNR5/GjY4E8G2QJYNVpMTyjxnRKKSwnCu9zb yuZA== X-Gm-Message-State: AOAM531j8S8zV//VjEorfeN8XdNsHaCndoH3xDmsxONvu6MP9BbanFHh 5PBdleAtR/FYWzzcnenvuBLcJN9btb3d85uR X-Google-Smtp-Source: ABdhPJzUTXOMSf7kh5/uqfI/BAQ5qht62yiq0c28vlQqNauCiRLo5OFq1Gkre+sKqU2hYjs/oKoSiQ== X-Received: by 2002:a05:600c:2904:: with SMTP id i4mr754991wmd.146.1613465627783; Tue, 16 Feb 2021 00:53:47 -0800 (PST) Received: from naush-laptop.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id e1sm9300369wrd.44.2021.02.16.00.53.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Feb 2021 00:53:47 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Feb 2021 08:53:38 +0000 Message-Id: <20210216085342.1012717-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210216085342.1012717-1-naush@raspberrypi.com> References: <20210216085342.1012717-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/5] libcamera: delayed_controls: Add notion of priority write X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" If an exposure time change adjusts the vblanking limits, and we write both VBLANK and EXPOSURE controls as a set, the latter may fail if the value is outside of the limits calculated by the old VBLANK value. This is a limitation in V4L2 and cannot be fixed by writing VBLANK before EXPOSURE. The workaround here is to have the DelayedControls object mark the VBLANK control as "priority write", which then write VBLANK separately from (and ahead of) any other controls. This way, the sensor driver will update the EXPOSURE control with new limits before the new values is presented, and will thus be seen as valid. To support this, a new struct DelayedControls::ControlParams is used in the constructor to provide the control delay value as well as the priority write flag. Signed-off-by: Naushir Patuck Reviewed-by: Paul Elder --- include/libcamera/internal/delayed_controls.h | 9 +++- src/libcamera/delayed_controls.cpp | 54 +++++++++++++------ src/libcamera/pipeline/ipu3/ipu3.cpp | 8 +-- .../pipeline/raspberrypi/raspberrypi.cpp | 13 +++-- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 8 +-- test/delayed_contols.cpp | 20 +++---- 6 files changed, 68 insertions(+), 44 deletions(-) diff --git a/include/libcamera/internal/delayed_controls.h b/include/libcamera/internal/delayed_controls.h index dc447a882514..564d9f2e2440 100644 --- a/include/libcamera/internal/delayed_controls.h +++ b/include/libcamera/internal/delayed_controls.h @@ -19,8 +19,13 @@ class V4L2Device; class DelayedControls { public: + struct ControlParams { + unsigned int delay; + bool priorityWrite; + }; + DelayedControls(V4L2Device *device, - const std::unordered_map &delays); + const std::unordered_map &controlParams); void reset(); @@ -64,7 +69,7 @@ private: V4L2Device *device_; /* \todo Evaluate if we should index on ControlId * or unsigned int */ - std::unordered_map delays_; + std::unordered_map controlParams_; unsigned int maxDelay_; bool running_; diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp index ab1d40057c5f..3ed1dfebd035 100644 --- a/src/libcamera/delayed_controls.cpp +++ b/src/libcamera/delayed_controls.cpp @@ -40,15 +40,19 @@ LOG_DEFINE_CATEGORY(DelayedControls) /** * \brief Construct a DelayedControls instance * \param[in] device The V4L2 device the controls have to be applied to - * \param[in] delays Map of the numerical V4L2 control ids to their associated - * delays (in frames) + * \param[in] controlParams Map of the numerical V4L2 control ids to their + * associated control parameters. * - * Only controls specified in \a delays are handled. If it's desired to mix - * delayed controls and controls that take effect immediately the immediate - * controls must be listed in the \a delays map with a delay value of 0. + * The control parameters comprise of delays (in frames) and a priority write + * flag. If this flag is set, the relevant control is written separately from, + * ahead of the reset of the batched controls. + * + * Only controls specified in \a controlParams are handled. If it's desired to + * mix delayed controls and controls that take effect immediately the immediate + * controls must be listed in the \a controlParams map with a delay value of 0. */ DelayedControls::DelayedControls(V4L2Device *device, - const std::unordered_map &delays) + const std::unordered_map &controlParams) : device_(device), maxDelay_(0) { const ControlInfoMap &controls = device_->controls(); @@ -57,12 +61,12 @@ DelayedControls::DelayedControls(V4L2Device *device, * Create a map of control ids to delays for controls exposed by the * device. */ - for (auto const &delay : delays) { - auto it = controls.find(delay.first); + for (auto const ¶m : controlParams) { + auto it = controls.find(param.first); if (it == controls.end()) { LOG(DelayedControls, Error) << "Delay request for control id " - << utils::hex(delay.first) + << utils::hex(param.first) << " but control is not exposed by device " << device_->deviceNode(); continue; @@ -70,13 +74,14 @@ DelayedControls::DelayedControls(V4L2Device *device, const ControlId *id = it->first; - delays_[id] = delay.second; + controlParams_[id] = param.second; LOG(DelayedControls, Debug) - << "Set a delay of " << delays_[id] + << "Set a delay of " << controlParams_[id].delay + << " and priority write flag " << controlParams_[id].priorityWrite << " for " << id->name(); - maxDelay_ = std::max(maxDelay_, delays_[id]); + maxDelay_ = std::max(maxDelay_, controlParams_[id].delay); } reset(); @@ -97,8 +102,8 @@ void DelayedControls::reset() /* Retrieve control as reported by the device. */ std::vector ids; - for (auto const &delay : delays_) - ids.push_back(delay.first->id()); + for (auto const ¶m : controlParams_) + ids.push_back(param.first->id()); ControlList controls = device_->getControls(ids); @@ -140,7 +145,7 @@ bool DelayedControls::push(const ControlList &controls) const ControlId *id = it->second; - if (delays_.find(id) == delays_.end()) + if (controlParams_.find(id) == controlParams_.end()) return false; Info &info = values_[id][queueCount_]; @@ -220,12 +225,27 @@ void DelayedControls::applyControls(uint32_t sequence) ControlList out(device_->controls()); for (const auto &ctrl : values_) { const ControlId *id = ctrl.first; - unsigned int delayDiff = maxDelay_ - delays_[id]; + unsigned int delayDiff = maxDelay_ - controlParams_[id].delay; unsigned int index = std::max(0, writeCount_ - delayDiff); const Info &info = ctrl.second[index]; if (info.updated) { - out.set(id->id(), info); + if (controlParams_[id].priorityWrite) { + /* + * This control must be written now, it could + * affect validity of the other controls. + */ + ControlList priority(device_->controls()); + priority.set(id->id(), info); + device_->setControls(&priority); + } else { + /* + * Batch up the list of controls and write them + * at the end of the function. + */ + out.set(id->id(), info); + } + LOG(DelayedControls, Debug) << "Setting " << id->name() << " to " << info.toString() diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 61f7bf43ea08..eda07d915f0c 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -988,14 +988,14 @@ int PipelineHandlerIPU3::registerCameras() * a sensor database. For now use generic values taken from * the Raspberry Pi and listed as 'generic values'. */ - std::unordered_map delays = { - { V4L2_CID_ANALOGUE_GAIN, 1 }, - { V4L2_CID_EXPOSURE, 2 }, + std::unordered_map params = { + { V4L2_CID_ANALOGUE_GAIN, { 1, false } }, + { V4L2_CID_EXPOSURE, { 2, false } }, }; data->delayedCtrls_ = std::make_unique(cio2->sensor()->device(), - delays); + params); data->cio2_.frameStart().connect(data->delayedCtrls_.get(), &DelayedControls::applyControls); diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index b0bb12ab0f37..bdb439021c46 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -1273,16 +1273,15 @@ int RPiCameraData::configureIPA(const CameraConfiguration *config) if (result.operation & RPi::IPA_RESULT_SENSOR_PARAMS) { /* * Setup our delayed control writer with the sensor default - * gain and exposure delays. + * gain and exposure delays. Mark VBLANK for priority write. */ - std::unordered_map delays = { - { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] }, - { V4L2_CID_EXPOSURE, result.data[resultIdx++] }, - { V4L2_CID_VBLANK, result.data[resultIdx++] } + std::unordered_map params = { + { V4L2_CID_ANALOGUE_GAIN, { result.data[resultIdx++], false } }, + { V4L2_CID_EXPOSURE, { result.data[resultIdx++], false } }, + { V4L2_CID_VBLANK, { result.data[resultIdx++], true } } }; - delayedCtrls_ = std::make_unique(unicam_[Unicam::Image].dev(), delays); - + delayedCtrls_ = std::make_unique(unicam_[Unicam::Image].dev(), params); sensorMetadata_ = result.data[resultIdx++]; } diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index e85979a719b7..ea9b1e2b9fcb 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -942,14 +942,14 @@ int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor) * a sensor database. For now use generic values taken from * the Raspberry Pi and listed as generic values. */ - std::unordered_map delays = { - { V4L2_CID_ANALOGUE_GAIN, 1 }, - { V4L2_CID_EXPOSURE, 2 }, + std::unordered_map params = { + { V4L2_CID_ANALOGUE_GAIN, { 1, false } }, + { V4L2_CID_EXPOSURE, { 2, false } }, }; data->delayedCtrls_ = std::make_unique(data->sensor_->device(), - delays); + params); isp_->frameStart.connect(data->delayedCtrls_.get(), &DelayedControls::applyControls); diff --git a/test/delayed_contols.cpp b/test/delayed_contols.cpp index 50169b12e566..3855eb18ecd4 100644 --- a/test/delayed_contols.cpp +++ b/test/delayed_contols.cpp @@ -72,8 +72,8 @@ protected: int singleControlNoDelay() { - std::unordered_map delays = { - { V4L2_CID_BRIGHTNESS, 0 }, + std::unordered_map delays = { + { V4L2_CID_BRIGHTNESS, { 0, false } }, }; std::unique_ptr delayed = std::make_unique(dev_.get(), delays); @@ -109,8 +109,8 @@ protected: int singleControlWithDelay() { - std::unordered_map delays = { - { V4L2_CID_BRIGHTNESS, 1 }, + std::unordered_map delays = { + { V4L2_CID_BRIGHTNESS, { 1, false } }, }; std::unique_ptr delayed = std::make_unique(dev_.get(), delays); @@ -150,9 +150,9 @@ protected: int dualControlsWithDelay(uint32_t startOffset) { - std::unordered_map delays = { - { V4L2_CID_BRIGHTNESS, 1 }, - { V4L2_CID_CONTRAST, 2 }, + std::unordered_map delays = { + { V4L2_CID_BRIGHTNESS, { 1, false } }, + { V4L2_CID_CONTRAST, { 2, false } }, }; std::unique_ptr delayed = std::make_unique(dev_.get(), delays); @@ -197,9 +197,9 @@ protected: int dualControlsMultiQueue() { - std::unordered_map delays = { - { V4L2_CID_BRIGHTNESS, 1 }, - { V4L2_CID_CONTRAST, 2 }, + std::unordered_map delays = { + { V4L2_CID_BRIGHTNESS, { 1, false } }, + { V4L2_CID_CONTRAST, { 2, false } } }; std::unique_ptr delayed = std::make_unique(dev_.get(), delays); From patchwork Tue Feb 16 08:53:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 11301 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id B9B72BD1EF for ; Tue, 16 Feb 2021 08:53:52 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BEC52637E4; Tue, 16 Feb 2021 09:53:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="imi5vIDH"; dkim-atps=neutral Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 952B0637CC for ; Tue, 16 Feb 2021 09:53:49 +0100 (CET) Received: by mail-wr1-x430.google.com with SMTP id t15so11940932wrx.13 for ; Tue, 16 Feb 2021 00:53:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+ImmBSuKB64yJiFyMrEt9UThLRyd9r3D1+xm3Snp0RU=; b=imi5vIDHQahPJzkjIAym22LGcN2fG5SZPBqMSJwZV0FGCK2sh2lVBrVGyKpd4J/pMz x1vC0xRGd+MP2nagfN+qtaC+rA20ZyJmODscLtAlGNvMaC+NHNKN1CTybEcYILKH72cq O+XpHOzJuj8XdAPyUED/OJ736aZLsviGXtE5IZ/rqINaJw0JB/nG8jlC3eQ5FHWvDC0s eeeRE1xzczYxdUMi6ZVLsTUk2J2ObEdjXHNvDoBnHEnFVqO5AVPX7wp2xNdXrwqH8C1k IDzC8Pr1amoOHBQCSwQBuTqbHITwtVgNsn1UPQg2N1PtfvIVqLHH9MrKQll0jkAmPHgb XQJQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+ImmBSuKB64yJiFyMrEt9UThLRyd9r3D1+xm3Snp0RU=; b=ZOxDBvjaWSjvR7gkVxH2yXjzvOU3jnNsYI7SYudl+BYRhl3aFNX5rAjvwYJHEdh9TV T5+paczf6Z24QxV7w7wD/D0aGOaebl+VZjTOCMIGpdM5gmfc7wv70XE0sXnDn3aeWQmU KeAU+rC09oyZpSWiL/RTc8FLkVm6/Gv6xmhf+c321oNdZSv33yCxkARF1lBpc5fbFGT9 RnBIqCzdFPOQKOa0D2AX75SVzi4ZMMlAqvYehghYhT+d0qwcdr8bzroCD5BIOGHOGgy0 0OKufoDTNd32Vue/CPx+Ps94SiJ4vnbksbuGIJAsRDLO9wNZgolLfgOnpaRkV1bcE4SR E+AA== X-Gm-Message-State: AOAM531RuO/+a23em01+S4ho32Fs9k/7bVHBg02YGgs1o5yLEMDIG4pg M7ir27m5wh9CkHUyeU7fuLzqnKXqPZQEZ9bF X-Google-Smtp-Source: ABdhPJzY1mfybuTppVcnxFDLGczNKPMujgvVyprKVVjs4yiMpsi5r2b1BuW0EFha+cO1Zjrb9Uyz0Q== X-Received: by 2002:a05:6000:108f:: with SMTP id y15mr22895022wrw.195.1613465628622; Tue, 16 Feb 2021 00:53:48 -0800 (PST) Received: from naush-laptop.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id e1sm9300369wrd.44.2021.02.16.00.53.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Feb 2021 00:53:48 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Feb 2021 08:53:39 +0000 Message-Id: <20210216085342.1012717-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210216085342.1012717-1-naush@raspberrypi.com> References: <20210216085342.1012717-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/5] utils: raspberrypi: Add a DelayedControls log parser X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" This script will parse log output from the DelayedControls helper, when enabled with: LIBCAMERA_LOG_LEVELS=DelayedControls:0 It tabulates all control queuing/writing/getting per frame and warns about potential issues related to frame delays not being account for, or writes that are lagging behind or missed. Run with the following command: python3 ./delayedctrls_parse.py Signed-off-by: Naushir Patuck Acked-by: Paul Elder --- utils/raspberrypi/delayedctrls_parse.py | 98 +++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 utils/raspberrypi/delayedctrls_parse.py diff --git a/utils/raspberrypi/delayedctrls_parse.py b/utils/raspberrypi/delayedctrls_parse.py new file mode 100644 index 000000000000..20c92fb620e6 --- /dev/null +++ b/utils/raspberrypi/delayedctrls_parse.py @@ -0,0 +1,98 @@ +import re +import sys +import os + +if len(sys.argv) != 2: + print("Usage: {} ".format(sys.argv[0])) + sys.exit() + +infile = sys.argv[1] +insplit = os.path.splitext(infile) +outfile = insplit[0] + '_parsed' + insplit[1] + +frame_re = re.compile('frame (\d+) started') + +delays = {'Analogue Gain': 1, 'Exposure': 2, 'Vertical Blanking': 2} +ctrl_action = {'Write': {}, 'Get': {}, 'Queue': {}, 'No-op': {}} +ctrl_re = {'Write': re.compile('Setting (.*?) to (\d+) at index (\d+)'), + 'No-op': re.compile('Queue is empty, (.*?) (.*?) (.*?)'), + 'Get': re.compile('Reading (.*?) to (\d+) at index (\d+)'), + 'Queue': re.compile('Queuing (.*?) to (\d+) at index (\d+)')} + +frame_num = -1 + +max_delay = 0 +for k, d in delays.items(): + if max_delay < d: + max_delay = d + +with open(infile) as f: + lines = f.readlines() + +for line in lines: + r = frame_re.search(line) + if r: + frame_num = int(r.group(1)) + + for (key, re) in ctrl_re.items(): + r = re.search(line) + if r: + ctrl_action[key][(frame_num, r.group(1))] = (r.group(2), r.group(3)) + +with open(outfile, 'wt') as f: + queueIndex = 1 + f.write('{:<10}{:<15}{:<12}{:<18}{}\n'.format('Frame', 'Action', 'Gain', 'Exposure', 'Vblank')) + for frame in range(0, frame_num + 1): + for (k, a) in ctrl_action.items(): + str = '{:<10}{:<10}'.format(frame, k) + + for c in delays.keys(): + # Tabulate all results + str += '{:>5} {:<10}'.format(a[(frame, c)][0] if (frame, c) in a.keys() else '---', + '[' + (a[(frame, c)][1] if (frame, c) in a.keys() else '-') + ']') + + f.write(str.strip() + '\n') + +# Test the write -> get matches the set delay. +for (frame, c) in ctrl_action['Write'].keys(): + set_value = ctrl_action['Write'][(frame, c)][0] + delay_frame = frame + delays[c] + if (delay_frame <= frame_num): + if (delay_frame, c) in ctrl_action['Get']: + get_value = ctrl_action['Get'][(delay_frame, c)][0] + if get_value != set_value: + print('Error: {} written at frame {} to value {} != {} at frame {}' + .format(c, frame, set_value, get_value, delay_frame)) + else: + print('Warning: {} written at frame {} to value {} did not get logged on frame {} - dropped frame?' + .format(c, frame, set_value, delay_frame)) + +# Test the queue -> write matches the set delay. +for (frame, c) in ctrl_action['Queue'].keys(): + set_value = ctrl_action['Queue'][(frame, c)][0] + delay_frame = frame + max_delay - delays[c] + 1 + if (delay_frame <= frame_num): + if (delay_frame, c) in ctrl_action['Write']: + write_value = ctrl_action['Write'][(delay_frame, c)][0] + if write_value != set_value: + print('Info: {} queued at frame {} to value {} != {} written at frame {}' + ' - lagging behind or double queue on a single frame!' + .format(c, frame, set_value, write_value, delay_frame)) + else: + print('Warning: {} queued at frame {} to value {} did not get logged on frame {} - dropped frame?' + .format(c, frame, set_value, delay_frame)) + +# Test the get -> write matches the set delay going backwards. +for (frame, c) in ctrl_action['Get'].keys(): + get_value = ctrl_action['Get'][(frame, c)][0] + delay_frame = frame - delays[c] + if (delay_frame >= 6): + if (delay_frame, c) in ctrl_action['Write']: + write_value = ctrl_action['Write'][(delay_frame, c)][0] + if get_value != write_value: + print('Info: {} got at frame {} to value {} != {} written at frame {}' + ' - lagging behind or double queue on a single frame!' + .format(c, frame, get_value, write_value, delay_frame)) + else: + print('Warning: {} got at frame {} to value {} did not get written on frame {}' + .format(c, frame, get_value, delay_frame)) From patchwork Tue Feb 16 08:53:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 11302 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 637ECBD1EF for ; Tue, 16 Feb 2021 08:53:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8EE0D637E5; Tue, 16 Feb 2021 09:53:52 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="B/1e6Lvu"; dkim-atps=neutral Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CDD38637C9 for ; Tue, 16 Feb 2021 09:53:49 +0100 (CET) Received: by mail-wm1-x331.google.com with SMTP id l17so8458946wmq.2 for ; Tue, 16 Feb 2021 00:53:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pE0pD3Pm7d1Q+xfAn0kd1mKoyC0oxhMkAlASrfwQPfc=; b=B/1e6Lvu616sIYfhsWZWjt/kiSbd/z/Sud8k2zKOQ18AM0uIr2vRCz9ClDpN8NuefG lvqEl2xFuqoTmTNJVRrYlv5YhqjvgkKCov0lFt2Ogj7PMifgMrgWce7/5c1YkLpOaovK 0Y1CYLUs+OcDG+R/tl+wP4FIGdAD1T8Av/rj5DZEoUYtqijqyjQPNkRrK2Pe7KAC6xAX tZlP1Pmoz5kmwUwHzCLt/56CzJ4OcBU+KqBnVpQl6uze5d7lIyjfWO4k8gJVgyjvn2lb rvqyQG8IF99n82TxmwUlfA+/3o7JNImtik79I5qGNS7CzixJUQQpDI48CoyvHQj4hsMb Kgqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pE0pD3Pm7d1Q+xfAn0kd1mKoyC0oxhMkAlASrfwQPfc=; b=GJNfpiqse/BBXpE2JKP5M32KhbG7EQheGvy1Yxtc4AIWbf/Vy/T5n9M5yhHUhVa5LZ A8qiSStYljdLYPjZA9BoWaMrWxNaDc4rYcc23mocuViC/sbkroIOny1B3n74PNwKvXuN s3zth23CIE0fqf/bjb+lCLp1sGOPw8RnHZlW/HcfSjJ6Fj/cry15mx0bbShMJ1/79hrK XWKPPjME+u+XpW49Iju2BegGmL9rePq4YYmS5vm4GC9Cz2S68est6wQy9ZIymWsjcQjn XMOw73IUCEzV5flltYZevLLpgDAgojjNq1voFxNxyXfUP8Sw6TDX2HeBSOFgZUcyDJ51 TmJw== X-Gm-Message-State: AOAM5301ckPbhnmDJxDfDdYesFZfjInDhBmGBlh+z9ifgmL9WaYRr4dt HtzKG+Ma7MedWAo4fv4sDObygfpdLz8yJkF8 X-Google-Smtp-Source: ABdhPJz8qxlmY2Cu9+Vg9cssBPKOkEnwlvgkvN0yVIuvP3ldG8NqhwD5VlhIlvURHEbovldkGNIIEQ== X-Received: by 2002:a05:600c:4788:: with SMTP id k8mr2330641wmo.138.1613465629171; Tue, 16 Feb 2021 00:53:49 -0800 (PST) Received: from naush-laptop.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id e1sm9300369wrd.44.2021.02.16.00.53.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Feb 2021 00:53:48 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Feb 2021 08:53:40 +0000 Message-Id: <20210216085342.1012717-4-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210216085342.1012717-1-naush@raspberrypi.com> References: <20210216085342.1012717-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 3/5] libcamera: delayed_controls: Remove unneeded write when starting up X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" On DelayedControls::reset(), the values retrieved from the sensor device were added to the queues with the updated flag set to true. This would cause the helper to write out the value to the device again on the first DelayedControls::applyControls() call. This is unnecessary, as the controls written are identical to what is stored in the device driver. Fix this by explicitly setting the update flag to false in DelayedControls::reset() when adding the controls to the queue. Additionally, use the Info() constructor when adding items to the queue for consistency. Signed-off-by: Naushir Patuck Fixes: 3d4b7b005911 ("libcamera: delayed_controls: Add helper for controls that apply with a delay") --- include/libcamera/internal/delayed_controls.h | 4 ++-- src/libcamera/delayed_controls.cpp | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/libcamera/internal/delayed_controls.h b/include/libcamera/internal/delayed_controls.h index 564d9f2e2440..2a6a912bde10 100644 --- a/include/libcamera/internal/delayed_controls.h +++ b/include/libcamera/internal/delayed_controls.h @@ -43,8 +43,8 @@ private: { } - Info(const ControlValue &v) - : ControlValue(v), updated(true) + Info(const ControlValue &v, bool updated_ = true) + : ControlValue(v), updated(updated_) { } diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp index 3ed1dfebd035..21dc3e164fe9 100644 --- a/src/libcamera/delayed_controls.cpp +++ b/src/libcamera/delayed_controls.cpp @@ -111,7 +111,11 @@ void DelayedControls::reset() values_.clear(); for (const auto &ctrl : controls) { const ControlId *id = device_->controls().idmap().at(ctrl.first); - values_[id][0] = Info(ctrl.second); + /* + * Do not mark this control value as updated, it does not need + * to be written to to device on startup. + */ + values_[id][0] = Info(ctrl.second, false); } } @@ -126,11 +130,10 @@ void DelayedControls::reset() */ bool DelayedControls::push(const ControlList &controls) { - /* Copy state from previous frame. */ + /* Copy state from previous frame and clear the updated flag */ for (auto &ctrl : values_) { Info &info = ctrl.second[queueCount_]; - info = values_[ctrl.first][queueCount_ - 1]; - info.updated = false; + info = Info(values_[ctrl.first][queueCount_ - 1], false); } /* Update with new controls. */ @@ -150,8 +153,7 @@ bool DelayedControls::push(const ControlList &controls) Info &info = values_[id][queueCount_]; - info = control.second; - info.updated = true; + info = Info(control.second); LOG(DelayedControls, Debug) << "Queuing " << id->name() From patchwork Tue Feb 16 08:53:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 11303 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 02A14BD1EF for ; Tue, 16 Feb 2021 08:53:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7983D637DC; Tue, 16 Feb 2021 09:53:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="UjaFdmGg"; dkim-atps=neutral Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C0F13637C9 for ; Tue, 16 Feb 2021 09:53:50 +0100 (CET) Received: by mail-wm1-x330.google.com with SMTP id n10so13671985wmq.0 for ; Tue, 16 Feb 2021 00:53:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=X83bfbi6hYD9/lgpvD3X6XcqhNR4s9wHCFQad4teq1A=; b=UjaFdmGg7PnL8TXTWuOWhrDQBnMdWdWnrFjEmQIcKPtJO2WPumqeOaSX1ratZjj4ZW jIJQJ7D461dgHrHDVEL0vXng6u5pkrOJ/C97YB8yP9L7jF99vprs2WW52TiLtNHajDez ceQraCUwDeB1lPN5u6GRpcmLitdaPc/tqvT0xMnqhG8p1Kc6wxHTb2p6yl1IMq5ZczKb jsRISSSjWIpOTNsFGsiwWYBRLKfK60IKRR/wCFZ9wnAJiLJX/VJcdnn3k1V66MB2ayKl hy40o0M34vbWiOZAKxgXP2b16dvlwAtpqPPE8hJ/UlKiO3Otyy9hyR4oAzwXij3t9C8z oy5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=X83bfbi6hYD9/lgpvD3X6XcqhNR4s9wHCFQad4teq1A=; b=Kn3xJ57WBkCK0+TVRq4PXj0A9pRd+T7bTHeZ9aUWvj47wTIn0hpI7fYgCO3Ub6PXJ3 Xkj8q9w8UGnA/EPYS30JtjL9KGAxDuwuVlyiMUzqsXzZELPc/aBF8/FvEwK2OLJZTyuD KSEJXjm73Bf1sLtvy7h0K/TUvAjJ4gxX5yCt7purwR0r8A8zn8g1iEWVHGaF94haA492 1kmJZv3lWWyBVYlb8dTFu3uF5JyYfnrOP1YTyTOVI2Ts5/KJnRRZkMrWdz+p+uu2bS7R L4jpVI7pwrpht0zW5HoyrbcjOxf4+96ETytOUyDqHS6C80Y9bGbQ4PVsO1yca8zfd1Oa 5reg== X-Gm-Message-State: AOAM531RxhGc4wbLmoPm7Wl+9J257Ejac+0R8fPLhGPScO0NOMuu5ZzT kdQsSnJNdftMm7mDABjFIiZkxtibK78JV6XB X-Google-Smtp-Source: ABdhPJxJAWo4ugi121NZgQccpaEIlItxALapeLqAhiE3DiABhmJ2CmiS5JdgfT6Hnv15j4qxkOsrKQ== X-Received: by 2002:a1c:5a54:: with SMTP id o81mr2352219wmb.50.1613465630243; Tue, 16 Feb 2021 00:53:50 -0800 (PST) Received: from naush-laptop.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id e1sm9300369wrd.44.2021.02.16.00.53.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Feb 2021 00:53:49 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Feb 2021 08:53:41 +0000 Message-Id: <20210216085342.1012717-5-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210216085342.1012717-1-naush@raspberrypi.com> References: <20210216085342.1012717-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/5] libcamera: delayed_controls: Remove spurious no-op queued controls X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In DelayedControls::applyControls(), the controls queue would be extended via a no-op control push to fill the intermittent slots with unchanged control values. This is needed so that we read back unchanged control values correctly on every frame. However, there was one additional no-op performed on every frame that is not required, meaning that any controls queued by the pipeline handler would have their write delayed by one further frame. The original StaggeredCtrl did not do this, as it only had one index to manage, whereas DelayedControls uses two. Remove this last no-op push so that the pipeline_handler provided controls would be written on the very next frame if possible. As a consequence, we must mark the control update as completed within the DelayedControls::applyControls() loop, otherwise it might get reused when cycling through the ring buffer. Signed-off-by: Naushir Patuck Reported-by: David Plowman Fixes: 3d4b7b005911 ("libcamera: delayed_controls: Add helper for controls that apply with a delay") Reviewed-by: Paul Elder --- src/libcamera/delayed_controls.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp index 21dc3e164fe9..d1b79dc3570e 100644 --- a/src/libcamera/delayed_controls.cpp +++ b/src/libcamera/delayed_controls.cpp @@ -225,11 +225,11 @@ void DelayedControls::applyControls(uint32_t sequence) * values are set in time to satisfy the sensor delay. */ ControlList out(device_->controls()); - for (const auto &ctrl : values_) { + for (auto &ctrl : values_) { const ControlId *id = ctrl.first; unsigned int delayDiff = maxDelay_ - controlParams_[id].delay; unsigned int index = std::max(0, writeCount_ - delayDiff); - const Info &info = ctrl.second[index]; + Info &info = ctrl.second[index]; if (info.updated) { if (controlParams_[id].priorityWrite) { @@ -252,12 +252,15 @@ void DelayedControls::applyControls(uint32_t sequence) << "Setting " << id->name() << " to " << info.toString() << " at index " << index; + + /* Done with this update, so mark as completed. */ + info.updated = false; } } writeCount_++; - while (writeCount_ >= queueCount_) { + while (writeCount_ > queueCount_) { LOG(DelayedControls, Debug) << "Queue is empty, auto queue no-op."; push({}); From patchwork Tue Feb 16 08:53:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 11304 X-Patchwork-Delegate: niklas.soderlund@ragnatech.se Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id A9913BD1EF for ; Tue, 16 Feb 2021 08:53:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7BBE7637E4; Tue, 16 Feb 2021 09:53:56 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="NqUW8gj3"; dkim-atps=neutral Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A7B4A637E1 for ; Tue, 16 Feb 2021 09:53:51 +0100 (CET) Received: by mail-wr1-x42e.google.com with SMTP id n6so11982424wrv.8 for ; Tue, 16 Feb 2021 00:53:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fyu0xKvfxo3pIJO/KpDt3GBJV8oYCe5aBKHW+vWxN+0=; b=NqUW8gj3o1yG3JdBeRfoXz49gq+oOElIC6F2QuOKP5M7tw7kQb1laMo20HiYeRiFET jk4ZS0YQ9R0zPSFtgXnQurFd28zyMGCaru1PnizfaLaEviCknG7hDhMm/TdcUbD1j5PR MmmUVQCYlrpwzdc24tQoNlLCaIiBqYHSxGJZBPQrv1RAnGMh7L5pj5pjuYMZ1X8fokfL XE+H3+SxLG94Vr+1VV0F/FRCUE0Tk1wkPfOwNwsvjJxmazeD7jboYzGvY2gNaRnRiCJ6 c+adp+wn8qi7McYZ16VJB48B96SJ0zsq62fzFMDyYZX8foD0zUCfRUXU0++9OD83PD4L ZUEg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fyu0xKvfxo3pIJO/KpDt3GBJV8oYCe5aBKHW+vWxN+0=; b=Qli0vS9D8iM1DE/wJGrfAhVyqqUREITsrrgj92pbmjs0Kd1rsq2YSR76bcsRngFSag xMZYOG0tHEM6nlaEARxiRwCTjG8iRGRgNuB2UUDpOErRaaZQdDo6wvQQEkO43eU5HDMj JSuhAo/gVQ2i+Ey54doaCo/v56i8vUtFt1ICc8bQ/iBkPkpfNNLwgKvQWsQUr6xaCTa+ WmwJgAztmNdF0R0FQdp+ax6O+SfKCFdMV2FEsjG9X2pKhIhFLhhnKLSaXjMN/8vkDdLI MBN1m3x/TpcnGr2jVkn/bQBbRdmjbuy0QIZ2g+6h3lQqdSXcGcY+EbqrJBb/xPyF0QXF cE+w== X-Gm-Message-State: AOAM532e52Ovomh+rmPAeWfv2kYADOqrgSj4MQuuPxAHoS1ZcdQeitbU BdWTtpYkcY0CCuIS8s0mBFsKqDHgDYOL7RpA X-Google-Smtp-Source: ABdhPJxrZvd22yS7VmZD9dHGYuxG03iWIlmp0SCffB4N5m2OwjPSUiyoqv+6ZRuSddn1jZRnssybNw== X-Received: by 2002:a5d:4903:: with SMTP id x3mr18244460wrq.95.1613465631132; Tue, 16 Feb 2021 00:53:51 -0800 (PST) Received: from naush-laptop.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id e1sm9300369wrd.44.2021.02.16.00.53.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Feb 2021 00:53:50 -0800 (PST) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Feb 2021 08:53:42 +0000 Message-Id: <20210216085342.1012717-6-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210216085342.1012717-1-naush@raspberrypi.com> References: <20210216085342.1012717-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 5/5] libcamera: delayed_controls: Fix off-by-one error in get() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" There was an off-by-one error in DelayedControls::get() when picking controls from the queue to return back to the pipeline handler. This is only noticeable as small oscillations in brightness when closely viewing frame while AGC is running. The old StaggeredCtrl did not show this error as the startup queuing mechanism has changed in DelayedControls. Fix this by indexing to the correct position in the queue. Signed-off-by: Naushir Patuck Reported-by: David Plowman Fixes: 3d4b7b005911 ("libcamera: delayed_controls: Add helper for controls that apply with a delay") Reviewed-by: Paul Elder --- src/libcamera/delayed_controls.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/delayed_controls.cpp b/src/libcamera/delayed_controls.cpp index d1b79dc3570e..3f829e8c40f2 100644 --- a/src/libcamera/delayed_controls.cpp +++ b/src/libcamera/delayed_controls.cpp @@ -183,7 +183,7 @@ bool DelayedControls::push(const ControlList &controls) */ ControlList DelayedControls::get(uint32_t sequence) { - uint32_t adjustedSeq = sequence - firstSequence_ + 1; + uint32_t adjustedSeq = sequence - firstSequence_; unsigned int index = std::max(0, adjustedSeq - maxDelay_); ControlList out(device_->controls());