From patchwork Fri Feb 21 11:26:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislaw Gruszka X-Patchwork-Id: 22820 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 CA316BEFBE for ; Fri, 21 Feb 2025 11:26:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7EBD1686B0; Fri, 21 Feb 2025 12:26:27 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="gRLZZ7Se"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.14]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 40C0D68686 for ; Fri, 21 Feb 2025 12:26:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1740137185; x=1771673185; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=54fDOP/oX+p7uk9qUdPX4gcO8WT9ItyPgz8hgCSpXnk=; b=gRLZZ7SeAtsheTBvykQGUg0LHCXVvGk8A9bJbBcmbD07MVUutqMsvntf ZVsMH9vTIpzRkDdK6FTKN7rhIinTsZu6tPGaUbp6mt2yZr8OZhnBPS8k+ JuXnrP67QvUMcZp2p/g3qHMWAWbTvGrrXsY4IRTzIbKxbSJBRyIKlKuFH b3iHKx1Qa/yO5n/x/O4noX5rOTF4qk/UTb5K4kM6ZUg9wOnPb1SojcGZa SLqYe6p4VfsgLaG72oodTjJF/SaOGmUyoaiVBsFeDLmmzme5NNfUSV9P/ z58gTTNQkNqTXd+xqXEz/WDGIXkLVQgtG85h2D8H3IF3JN6tswccNCDdw w==; X-CSE-ConnectionGUID: YFK/fOXWTda+hK94WcyUKQ== X-CSE-MsgGUID: tLGkB/oeR+aLjr0Lw/vG5g== X-IronPort-AV: E=McAfee;i="6700,10204,11351"; a="44738605" X-IronPort-AV: E=Sophos;i="6.13,304,1732608000"; d="scan'208";a="44738605" Received: from fmviesa009.fm.intel.com ([10.60.135.149]) by orvoesa106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:24 -0800 X-CSE-ConnectionGUID: Zvjl0p+1ROCQY+uX4ykN8Q== X-CSE-MsgGUID: cOi0Kly2QqiFqTttwx4srQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,304,1732608000"; d="scan'208";a="115990715" Received: from sgruszka-mobl.ger.corp.intel.com (HELO localhost) ([10.245.97.15]) by fmviesa009-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Feb 2025 03:26:21 -0800 From: Stanislaw Gruszka To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart , Kieran Bingham , Naushir Patuck , Sakari Ailus , Hans de Goede Subject: [PATCH v4 2/2] pipeline: simple: Use proper device for frame start events 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 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" Currently we use frame start event from video capture device to apply controls. But the capture device might not generate the events. Usually CSI-2 receiver is proper device to subscribe for start frame events. To fix, loop over devices in the pipeline (starting from the last one), find one that emits start frame events and connect applyControls() to it. Additionally remove direct call to sensor_->setControls() if the emitter device was found. This also fixes the assertion like below: ../src/libcamera/delayed_controls.cpp:227: libcamera::ControlList libcamera::DelayedControls::get(uint32_t): Assertion `info.type() != ControlTypeNone' failed which can happen rarely at the beginning of streaming when ControlRingBuffer is not yet filled and there are errors on CSI-2. In such rare scenario we can have call to DelayedControls::get() with frame number that exceed number of saved entries. Handing frame start signal assures we do DelayedConntrols::applyControls() with (possibly out of sequence) frame number and later call to DelayedControls::get() will get proper not-empty control entry. Bug: https://bugs.libcamera.org/show_bug.cgi?id=241 Co-developed-by: Hans de Goede Signed-off-by: Hans de Goede Reviewed-by: Hans de Goede # v2 Tested-by: Hans de Goede # Lenovo X1 Yoga IPU6 + ov2740 # v2 Reviewed-by: Milan Zamazal # v2 Reviewed-by: Kieran Bingham # v3 Signed-off-by: Stanislaw Gruszka --- src/libcamera/pipeline/simple/simple.cpp | 40 +++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6e039bf3..088b9156 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -277,6 +277,7 @@ public: std::list entities_; std::unique_ptr sensor_; V4L2VideoDevice *video_; + V4L2Subdevice *frameStartEmitter_; std::vector configs_; std::map> formats_; @@ -579,6 +580,19 @@ int SimpleCameraData::init() properties_ = sensor_->properties(); + frameStartEmitter_ = nullptr; + for (auto it = entities_.rbegin(); it != entities_.rend(); ++it) { + V4L2Subdevice *sd = pipe->subdev(it->entity); + if (!sd || !sd->supportsFrameStartEvent()) + continue; + + LOG(SimplePipeline, Debug) + << "Using " << it->entity->name() << " frameStart signal"; + + frameStartEmitter_ = sd; + break; + } + return 0; } @@ -897,8 +911,11 @@ void SimpleCameraData::ispStatsReady(uint32_t frame, uint32_t bufferId) void SimpleCameraData::setSensorControls(const ControlList &sensorControls) { delayedCtrls_->push(sensorControls); - ControlList ctrls(sensorControls); - sensor_->setControls(&ctrls); + /* Directly apply controls now if there is no frameStart signal */ + if (!frameStartEmitter_ || !frameStartEmitter_->frameStartEnabled()) { + ControlList ctrls(sensorControls); + sensor_->setControls(&ctrls); + } } /* Retrieve all source pads connected to a sink pad through active routes. */ @@ -1285,8 +1302,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) data->delayedCtrls_ = std::make_unique(data->sensor_->device(), params); - data->video_->frameStart.connect(data->delayedCtrls_.get(), - &DelayedControls::applyControls); StreamConfiguration inputCfg; inputCfg.pixelFormat = pipeConfig->captureFormat; @@ -1325,6 +1340,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL { SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; + V4L2Subdevice *frameStartEmitter = data->frameStartEmitter_; int ret; const MediaPad *pad = acquirePipeline(data); @@ -1354,6 +1370,15 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] const ControlL video->bufferReady.connect(data, &SimpleCameraData::imageBufferReady); + if (frameStartEmitter) { + ret = frameStartEmitter->setFrameStartEnabled(true); + if (ret == 0) + frameStartEmitter->frameStart.connect(data->delayedCtrls_.get(), + &DelayedControls::applyControls); + } + + data->delayedCtrls_->reset(); + ret = video->streamOn(); if (ret < 0) { stop(camera); @@ -1385,6 +1410,13 @@ void SimplePipelineHandler::stopDevice(Camera *camera) { SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; + V4L2Subdevice *frameStartEmitter = data->frameStartEmitter_; + + if (frameStartEmitter) { + frameStartEmitter->setFrameStartEnabled(false); + frameStartEmitter->frameStart.disconnect(data->delayedCtrls_.get(), + &DelayedControls::applyControls); + } if (data->useConversion_) { if (data->converter_)