From patchwork Tue Feb 18 09:19:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislaw Gruszka X-Patchwork-Id: 22810 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 1759FC3220 for ; Tue, 18 Feb 2025 09:20:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8E2626868D; Tue, 18 Feb 2025 10:20:06 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="lXkRPEqg"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1ADC86032B for ; Tue, 18 Feb 2025 10:20:01 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739870403; x=1771406403; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bV7K+VbTYE28kWMieTanx4R2k3gXPpTQR7bgvSzb37Q=; b=lXkRPEqgWOiQUOTarhsN+hezr80SlRb5whXOhyUMAUTW9w8DuVew1XKV fBH/hBfFLZxldHYj8HXDryAEONJqySxwhc9mGdREnZditwWFrjkaa3Wh8 OhyDO3ouXJrET3nzppj+WLF6LuHq+IRqn/NDVf6CN2aiJtpLBi46OujFb GDXs9GuSPvZude5+iGMfwJ/6KsZAMqt3iXlR3YhFhty0fR6CVM8c4MD2Z zTn+McUHLjdWsbZd87GMczSNWoKQG58BjVkdCuNSPGXYZzXAF7Aa1aB90 5Fi3cJv8qAZpDU6MZWSVjPrc4zwhQ/AmuRB/wsOTGK3bu2CYRni0gRhZJ A==; X-CSE-ConnectionGUID: 1sEAZVVmRti3OSwOp6gLNQ== X-CSE-MsgGUID: 1VDMTcyCRIiACovkmbaMTA== X-IronPort-AV: E=McAfee;i="6700,10204,11348"; a="40692047" X-IronPort-AV: E=Sophos;i="6.13,295,1732608000"; d="scan'208";a="40692047" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Feb 2025 01:20:01 -0800 X-CSE-ConnectionGUID: S/abroGNRO+CVrY2xUqoOA== X-CSE-MsgGUID: WSumBM2JQf+P6M7Kis3cuA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,295,1732608000"; d="scan'208";a="114855859" Received: from sgruszka-mobl.ger.corp.intel.com (HELO localhost) ([10.246.8.237]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Feb 2025 01:19:58 -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 v3 1/2] libcamera: v4l2_device: add frame start event helpers Date: Tue, 18 Feb 2025 10:19:50 +0100 Message-Id: <20250218091951.13017-2-stanislaw.gruszka@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250218091951.13017-1-stanislaw.gruszka@linux.intel.com> References: <20250218091951.13017-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" Add helper to check if frame start event are supported by subdevice. Since kernel does not have interface to query supported events use subscribe interface. Additionally add helper for checking if the event enabled. Will be needed later to proper code flow if enabling the event fail for some reason. Signed-off-by: Stanislaw Gruszka Reviewed-by: Kieran Bingham --- include/libcamera/internal/v4l2_device.h | 2 ++ src/libcamera/v4l2_device.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/libcamera/internal/v4l2_device.h b/include/libcamera/internal/v4l2_device.h index affe52c2..0d807209 100644 --- a/include/libcamera/internal/v4l2_device.h +++ b/include/libcamera/internal/v4l2_device.h @@ -45,6 +45,8 @@ public: const std::string &deviceNode() const { return deviceNode_; } std::string devicePath() const; + bool supportsFrameStartEvent(); + bool frameStartEnabled() { return frameStartEnabled_; } int setFrameStartEnabled(bool enable); Signal frameStart; diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp index 2f65a43a..219c82f6 100644 --- a/src/libcamera/v4l2_device.cpp +++ b/src/libcamera/v4l2_device.cpp @@ -449,6 +449,30 @@ std::string V4L2Device::devicePath() const return path; } +/** + * \brief Check if frame start event is supported + * \return True if frame start event is supported, false otherwise + */ + +bool V4L2Device::supportsFrameStartEvent() +{ + struct v4l2_event_subscription event { + }; + event.type = V4L2_EVENT_FRAME_SYNC; + + int ret = ioctl(VIDIOC_SUBSCRIBE_EVENT, &event); + if (ret == 0) + ioctl(VIDIOC_UNSUBSCRIBE_EVENT, &event); + + return ret == 0; +} + +/** + * \fn V4L2Device::frameStartEnabled() + * \brief Check if frame start event is enabled + * \return True if frame start event is enabled, false otherwise + */ + /** * \brief Enable or disable frame start event notification * \param[in] enable True to enable frame start events, false to disable them From patchwork Tue Feb 18 09:19:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislaw Gruszka X-Patchwork-Id: 22811 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 14BD6C3220 for ; Tue, 18 Feb 2025 09:20:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BE4D868690; Tue, 18 Feb 2025 10:20:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="gXtoOzvm"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.15]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 455296032B for ; Tue, 18 Feb 2025 10:20:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1739870406; x=1771406406; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=LLLmdQO58UaO6l69pODfORzXSSsUZaIhNVtuEthfTaU=; b=gXtoOzvm1WrxqspBQ1CdX9vgrh/Hs/FtJ7vQfGPEUN1zAsKrsk9q06TH Q8epzwSzTVZisI88QJCs10wNyhMbGveHNex0Y/NRaDB2zCVo5+gB/2PlL QW6PqkaPRi3KAd85rpXngPx/UpANx24vUz7ojgYjYc0WJH0SFY3rLs0lq frn3RDEIdKEUO30km2JmNFFw9aaz+OhWynWND04+R25jFenc1ZiwXgj0E vU0HdDY0NlsE5Jaka5I0ZXVllqYeGzF5ZwJOMFEIK0LSt442Ro3DrORE3 LMUn4E42V27XX8darJhtbzVLnFdEDfAFfGa17DXX4MSaQwgXZZIWASnyT Q==; X-CSE-ConnectionGUID: /oHU+ZRlQbevY/0J3XNS3Q== X-CSE-MsgGUID: tvUg6ALqTzWdbAZ02fQYOA== X-IronPort-AV: E=McAfee;i="6700,10204,11348"; a="40692058" X-IronPort-AV: E=Sophos;i="6.13,295,1732608000"; d="scan'208";a="40692058" Received: from fmviesa010.fm.intel.com ([10.60.135.150]) by fmvoesa109.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Feb 2025 01:20:05 -0800 X-CSE-ConnectionGUID: bGbATp/OR6ivdFVtnEbUww== X-CSE-MsgGUID: lTFXM+EeTYG7/MODF/w3nw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.13,295,1732608000"; d="scan'208";a="114855872" Received: from sgruszka-mobl.ger.corp.intel.com (HELO localhost) ([10.246.8.237]) by fmviesa010-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Feb 2025 01:20:02 -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 v3 2/2] pipeline: simple: Use proper device for frame start events Date: Tue, 18 Feb 2025 10:19:51 +0100 Message-Id: <20250218091951.13017-3-stanislaw.gruszka@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250218091951.13017-1-stanislaw.gruszka@linux.intel.com> References: <20250218091951.13017-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. Without DelayedConntrols:applyControls() is possible that we can get call to DelayedControls::get() with frame number that exceed number of saved entries and get below assertion failure: ../src/libcamera/delayed_controls.cpp:227: libcamera::ControlList libcamera::DelayedControls::get(uint32_t): Assertion `info.type() != ControlTypeNone' failed Assertion failure can happen at the beginning of streaming when ControlRingBuffer is not yet filled and there are errors on CSI-2. 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. 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 Signed-off-by: Stanislaw Gruszka Tested-by: Kieran Bingham # Lenovo X13s Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 40 +++++++++++++++++++++--- 1 file changed, 36 insertions(+), 4 deletions(-) -- 2.43.0 diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6e039bf3..ad2167dc 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 *eventEmitter_; std::vector configs_; std::map> formats_; @@ -579,6 +580,19 @@ int SimpleCameraData::init() properties_ = sensor_->properties(); + eventEmitter_ = 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"; + + eventEmitter_ = 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 (!eventEmitter_ || !eventEmitter_->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 *eventEmitter = data->eventEmitter_; 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 (eventEmitter) { + ret = eventEmitter->setFrameStartEnabled(true); + if (ret == 0) + eventEmitter->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 *eventEmitter = data->eventEmitter_; + + if (eventEmitter) { + eventEmitter->setFrameStartEnabled(false); + eventEmitter->frameStart.disconnect(data->delayedCtrls_.get(), + &DelayedControls::applyControls); + } if (data->useConversion_) { if (data->converter_)