[{"id":34421,"web_url":"https://patchwork.libcamera.org/comment/34421/","msgid":"<2r4pekscntpkzzlhdbmfcrpkcictrjlz7gltygvhcntrcvtc3h@t54cloxs64mw>","date":"2025-06-05T07:22:01","subject":"Re: [PATCH v2 3/6] pipeline: ipa: rpi: Split\n\tRPiCameraData::dropFrameCount_","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Naush\n\nOn Thu, May 22, 2025 at 08:48:19AM +0100, Naushir Patuck wrote:\n> Split the pipeline handler drop frame tracking into startup frames and\n> invalid frames, as reported by the IPA.\n>\n> Remove the drop buffer handling logic in the pipeline handler. Now all\n> image buffers are returned out with the appropriate FrameStatus set\n> for startup or invalid frames.\n>\n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> Reviewed-by: David Plowman <david.plowman@raspberrypi.com>\n> ---\n>  .../pipeline/rpi/common/pipeline_base.cpp     | 98 ++++++++-----------\n>  .../pipeline/rpi/common/pipeline_base.h       |  5 +-\n>  2 files changed, 42 insertions(+), 61 deletions(-)\n>\n> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> index 5956485953a2..3f0b7abdc59a 100644\n> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp\n> @@ -659,9 +659,9 @@ int PipelineHandlerBase::start(Camera *camera, const ControlList *controls)\n>  \tif (!result.controls.empty())\n>  \t\tdata->setSensorControls(result.controls);\n>\n> -\t/* Configure the number of dropped frames required on startup. */\n> -\tdata->dropFrameCount_ = data->config_.disableStartupFrameDrops ?\n> -\t\t\t0 : result.startupFrameCount + result.invalidFrameCount;\n> +\t/* Configure the number of startup and invalid frames reported by the IPA. */\n> +\tdata->startupFrameCount_ = result.startupFrameCount;\n> +\tdata->invalidFrameCount_ = result.invalidFrameCount;\n>\n\nThis makes my comment on the previous patch moot\n\n>  \tfor (auto const stream : data->streams_)\n>  \t\tstream->resetBuffers();\n> @@ -678,7 +678,6 @@ int PipelineHandlerBase::start(Camera *camera, const ControlList *controls)\n>  \t\tdata->buffersAllocated_ = true;\n>  \t}\n>\n> -\t/* We need to set the dropFrameCount_ before queueing buffers. */\n>  \tret = queueAllBuffers(camera);\n>  \tif (ret) {\n>  \t\tLOG(RPI, Error) << \"Failed to queue buffers\";\n> @@ -894,28 +893,12 @@ int PipelineHandlerBase::queueAllBuffers(Camera *camera)\n>  \tint ret;\n>\n>  \tfor (auto const stream : data->streams_) {\n> -\t\tif (!(stream->getFlags() & StreamFlag::External)) {\n> -\t\t\tret = stream->queueAllBuffers();\n> -\t\t\tif (ret < 0)\n> -\t\t\t\treturn ret;\n> -\t\t} else {\n> -\t\t\t/*\n> -\t\t\t * For external streams, we must queue up a set of internal\n> -\t\t\t * buffers to handle the number of drop frames requested by\n> -\t\t\t * the IPA. This is done by passing nullptr in queueBuffer().\n> -\t\t\t *\n> -\t\t\t * The below queueBuffer() call will do nothing if there\n> -\t\t\t * are not enough internal buffers allocated, but this will\n> -\t\t\t * be handled by queuing the request for buffers in the\n> -\t\t\t * RPiStream object.\n> -\t\t\t */\n> -\t\t\tunsigned int i;\n> -\t\t\tfor (i = 0; i < data->dropFrameCount_; i++) {\n> -\t\t\t\tret = stream->queueBuffer(nullptr);\n> -\t\t\t\tif (ret)\n> -\t\t\t\t\treturn ret;\n> -\t\t\t}\n> -\t\t}\n> +\t\tif (stream->getFlags() & StreamFlag::External)\n> +\t\t\tcontinue;\n> +\n> +\t\tret = stream->queueAllBuffers();\n> +\t\tif (ret < 0)\n> +\t\t\treturn ret;\n>  \t}\n>\n>  \treturn 0;\n> @@ -1412,7 +1395,15 @@ void CameraData::handleStreamBuffer(FrameBuffer *buffer, RPi::Stream *stream)\n>  \t * buffer back to the stream.\n>  \t */\n>  \tRequest *request = requestQueue_.empty() ? nullptr : requestQueue_.front();\n> -\tif (!dropFrameCount_ && request && request->findBuffer(stream) == buffer) {\n> +\tif (request && request->findBuffer(stream) == buffer) {\n> +\t\tFrameMetadata &md = buffer->_d()->metadata();\n> +\n> +\t\t/* Mark the non-converged and invalid frames in the metadata. */\n> +\t\tif (invalidFrameCount_)\n> +\t\t\tmd.status = FrameMetadata::Status::FrameError;\n> +\t\telse if (startupFrameCount_)\n> +\t\t\tmd.status = FrameMetadata::Status::FrameStartup;\n> +\n>  \t\t/*\n>  \t\t * Tag the buffer as completed, returning it to the\n>  \t\t * application.\n> @@ -1458,42 +1449,31 @@ void CameraData::handleState()\n>\n>  void CameraData::checkRequestCompleted()\n>  {\n> -\tbool requestCompleted = false;\n> -\t/*\n> -\t * If we are dropping this frame, do not touch the request, simply\n> -\t * change the state to IDLE when ready.\n> -\t */\n> -\tif (!dropFrameCount_) {\n> -\t\tRequest *request = requestQueue_.front();\n> -\t\tif (request->hasPendingBuffers())\n> -\t\t\treturn;\n> +\tRequest *request = requestQueue_.front();\n> +\tif (request->hasPendingBuffers())\n> +\t\treturn;\n>\n> -\t\t/* Must wait for metadata to be filled in before completing. */\n> -\t\tif (state_ != State::IpaComplete)\n> -\t\t\treturn;\n> +\t/* Must wait for metadata to be filled in before completing. */\n> +\tif (state_ != State::IpaComplete)\n> +\t\treturn;\n>\n> -\t\tLOG(RPI, Debug) << \"Completing request sequence: \"\n> -\t\t\t\t<< request->sequence();\n> +\tLOG(RPI, Debug) << \"Completing request sequence: \"\n> +\t\t\t<< request->sequence();\n>\n> -\t\tpipe()->completeRequest(request);\n> -\t\trequestQueue_.pop();\n> -\t\trequestCompleted = true;\n> -\t}\n> +\tpipe()->completeRequest(request);\n> +\trequestQueue_.pop();\n>\n> -\t/*\n> -\t * Make sure we have three outputs completed in the case of a dropped\n> -\t * frame.\n> -\t */\n> -\tif (state_ == State::IpaComplete &&\n> -\t    ((ispOutputCount_ == ispOutputTotal_ && dropFrameCount_) ||\n> -\t     requestCompleted)) {\n> -\t\tLOG(RPI, Debug) << \"Going into Idle state\";\n> -\t\tstate_ = State::Idle;\n> -\t\tif (dropFrameCount_) {\n> -\t\t\tdropFrameCount_--;\n> -\t\t\tLOG(RPI, Debug) << \"Dropping frame at the request of the IPA (\"\n> -\t\t\t\t\t<< dropFrameCount_ << \" left)\";\n> -\t\t}\n> +\tLOG(RPI, Debug) << \"Going into Idle state\";\n> +\tstate_ = State::Idle;\n> +\n> +\tif (invalidFrameCount_) {\n> +\t\tinvalidFrameCount_--;\n> +\t\tLOG(RPI, Debug) << \"Decrementing invalid frames to \"\n> +\t\t\t\t<< invalidFrameCount_;\n> +\t} else if (startupFrameCount_) {\n> +\t\tstartupFrameCount_--;\n> +\t\tLOG(RPI, Debug) << \"Decrementing startup frames to \"\n> +\t\t\t\t<< startupFrameCount_;\n>  \t}\n\nThanks, this fixes my comment on the previous version.\n\nReviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>\n\nThanks\n  j\n\n>  }\n>\n> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> index aae0c2f35888..6023f9f9d6b3 100644\n> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h\n> @@ -48,7 +48,7 @@ class CameraData : public Camera::Private\n>  public:\n>  \tCameraData(PipelineHandler *pipe)\n>  \t\t: Camera::Private(pipe), state_(State::Stopped),\n> -\t\t  dropFrameCount_(0), buffersAllocated_(false),\n> +\t\t  startupFrameCount_(0), invalidFrameCount_(0), buffersAllocated_(false),\n>  \t\t  ispOutputCount_(0), ispOutputTotal_(0)\n>  \t{\n>  \t}\n> @@ -151,7 +151,8 @@ public:\n>  \t/* Mapping of CropParams keyed by the output stream order in CameraConfiguration */\n>  \tstd::map<unsigned int, CropParams> cropParams_;\n>\n> -\tunsigned int dropFrameCount_;\n> +\tunsigned int startupFrameCount_;\n> +\tunsigned int invalidFrameCount_;\n>\n>  \t/*\n>  \t * If set, this stores the value that represets a gain of one for\n> --\n> 2.43.0\n>","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 A330BC3237\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu,  5 Jun 2025 07:22:07 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 63FA168DB2;\n\tThu,  5 Jun 2025 09:22:06 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 35FF468DB2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu,  5 Jun 2025 09:22:04 +0200 (CEST)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 8754D6AF;\n\tThu,  5 Jun 2025 09:22:00 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"RVRsX2qK\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1749108120;\n\tbh=AePx5GLGSKKx33qOt64Xuj6Pgx6vGpGc+V/dVZUct5A=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=RVRsX2qKwO4mrbEg02/wIM4uoa7RIEKwDafVJ7q3c90FR/LiOjafw19XtziFts/V7\n\tbJ50LYY3xhw6dLtWfbw/DhWl3k/zNkCptuQO8rpHfmA2FBFhZFP+ZpDYBs5/Ncxjno\n\ts7LbaqPbnk/uOunoS4wH1BGZhQaHNyItG2cHAVaQ=","Date":"Thu, 5 Jun 2025 09:22:01 +0200","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"libcamera-devel@lists.libcamera.org, \n\tDavid Plowman <david.plowman@raspberrypi.com>","Subject":"Re: [PATCH v2 3/6] pipeline: ipa: rpi: Split\n\tRPiCameraData::dropFrameCount_","Message-ID":"<2r4pekscntpkzzlhdbmfcrpkcictrjlz7gltygvhcntrcvtc3h@t54cloxs64mw>","References":"<20250522075244.1198110-1-naush@raspberrypi.com>\n\t<20250522075244.1198110-4-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20250522075244.1198110-4-naush@raspberrypi.com>","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>"}}]