From patchwork Sun Jan 31 22:46:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11080 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 DF673BD808 for ; Sun, 31 Jan 2021 22:47:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ED465683DC; Sun, 31 Jan 2021 23:47:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="RH34UXNz"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E1A48683D0 for ; Sun, 31 Jan 2021 23:47:27 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 63BF68A0; Sun, 31 Jan 2021 23:47:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133247; bh=14wtconu64Dsy+1FTRbga44qZgReUcTY8zTR+TWxIEk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RH34UXNzOM8DdzjkCuKzRmkQRGRF9s6tsFFEkUKvgQoF+GDz9JCGOrG5ju+AE9PRu yS2wA1wylb8ty4agIJ5AwLTKYS/q2yWJmi5GKhxL+2NvAyzQ6X+4ai6Fy+zSI/IAh+ o1qAKpskg6b3/fEYcUXHaEN1m/NAoxG9umW65eQc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:43 +0200 Message-Id: <20210131224702.8838-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 01/20] libcamera: pipeline: simple: Manage converter with std::unique_ptr<> 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Replace manual destruction of the converter with std::unique_ptr<>. This removes the need for the SimplePipelineHandler destructor. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 23320d2687e1..b7aa3d034568 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -116,7 +116,6 @@ class SimplePipelineHandler : public PipelineHandler { public: SimplePipelineHandler(CameraManager *manager); - ~SimplePipelineHandler(); CameraConfiguration *generateConfiguration(Camera *camera, const StreamRoles &roles) override; @@ -132,7 +131,7 @@ public: V4L2VideoDevice *video(const MediaEntity *entity); V4L2Subdevice *subdev(const MediaEntity *entity); - SimpleConverter *converter() { return converter_; } + SimpleConverter *converter() { return converter_.get(); } protected: int queueRequestDevice(Camera *camera, Request *request) override; @@ -151,7 +150,7 @@ private: std::map> videos_; std::map subdevs_; - SimpleConverter *converter_; + std::unique_ptr converter_; bool useConverter_; std::vector> converterBuffers_; std::queue converterQueue_; @@ -507,15 +506,10 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() */ SimplePipelineHandler::SimplePipelineHandler(CameraManager *manager) - : PipelineHandler(manager), converter_(nullptr) + : PipelineHandler(manager) { } -SimplePipelineHandler::~SimplePipelineHandler() -{ - delete converter_; -} - CameraConfiguration *SimplePipelineHandler::generateConfiguration(Camera *camera, const StreamRoles &roles) { @@ -763,12 +757,11 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) /* Open the converter, if any. */ if (converter) { - converter_ = new SimpleConverter(converter); + converter_ = std::make_unique(converter); if (converter_->open() < 0) { LOG(SimplePipeline, Warning) << "Failed to open converter, disabling format conversion"; - delete converter_; - converter_ = nullptr; + converter_.reset(); } else { converter_->bufferReady.connect(this, &SimplePipelineHandler::converterDone); } From patchwork Sun Jan 31 22:46:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11081 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 7DEABBD808 for ; Sun, 31 Jan 2021 22:47:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 71DF9683EC; Sun, 31 Jan 2021 23:47:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="SP5vf8NK"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4CC2E683D0 for ; Sun, 31 Jan 2021 23:47:28 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CC7F08AF; Sun, 31 Jan 2021 23:47:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133248; bh=VXW0sCd0H3wsxlM+tWRBZQt27Lwk6A0o5hrdjQFGq/o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SP5vf8NK5yQN5on+Mptx4ND25oPuAfwN7jyiOdqADLiRmtY4oyV1CL+xXmhVeJNP3 q6KN/yCOjKGUpRW61EkOigTVAmXYSbtvsuNlYwKR/DXQcGWVWDZLhNn5Njg/VIZCu9 DiMJGZZuubVx5Z0+Xiza6cvk+VY2ybVt04Y8M7mM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:44 +0200 Message-Id: <20210131224702.8838-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 02/20] libcamera: pipeline: simple: Don't override stride at configure time 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The stride (and frame size) calculation has been moved from configure time to configuration validate time by commit 89fb1efac240 ("libcamera: simple: Fill stride and frameSize at config validation"). This change has however left one stray setting of the stride when configuring the converter. Fix it. While at it, turn the SimpleConverter::configure() output configuration argument to a const reference to emphasize it can't be null and isn't modified by the function, and rename it from cfg to outputCfg to make its purpose clearer. Fixes: 89fb1efac240 ("libcamera: simple: Fill stride and frameSize at config validation") Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/converter.cpp | 10 ++++------ src/libcamera/pipeline/simple/converter.h | 2 +- src/libcamera/pipeline/simple/simple.cpp | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index a6a8e139cb3e..87d15c781ed8 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -134,7 +134,7 @@ SizeRange SimpleConverter::sizes(const Size &input) } int SimpleConverter::configure(PixelFormat inputFormat, const Size &inputSize, - StreamConfiguration *cfg) + const StreamConfiguration &outputCfg) { V4L2DeviceFormat format; int ret; @@ -157,10 +157,10 @@ int SimpleConverter::configure(PixelFormat inputFormat, const Size &inputSize, } /* Set the pixel format and size on the output. */ - videoFormat = m2m_->capture()->toV4L2PixelFormat(cfg->pixelFormat); + videoFormat = m2m_->capture()->toV4L2PixelFormat(outputCfg.pixelFormat); format = {}; format.fourcc = videoFormat; - format.size = cfg->size; + format.size = outputCfg.size; ret = m2m_->capture()->setFormat(&format); if (ret < 0) { @@ -169,14 +169,12 @@ int SimpleConverter::configure(PixelFormat inputFormat, const Size &inputSize, return ret; } - if (format.fourcc != videoFormat || format.size != cfg->size) { + if (format.fourcc != videoFormat || format.size != outputCfg.size) { LOG(SimplePipeline, Error) << "Output format not supported"; return -EINVAL; } - cfg->stride = format.planes[0].bpl; - return 0; } diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index a3c4d899cfc8..06d66f8caba7 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -37,7 +37,7 @@ public: SizeRange sizes(const Size &input); int configure(PixelFormat inputFormat, const Size &inputSize, - StreamConfiguration *cfg); + const StreamConfiguration &outputCfg); int exportBuffers(unsigned int count, std::vector> *buffers); diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index b7aa3d034568..a97b8442d9a4 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -604,7 +604,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) if (useConverter_) { ret = converter_->configure(pipeConfig.pixelFormat, - pipeConfig.captureSize, &cfg); + pipeConfig.captureSize, cfg); if (ret < 0) { LOG(SimplePipeline, Error) << "Unable to configure converter"; From patchwork Sun Jan 31 22:46:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11082 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 28D2CBD808 for ; Sun, 31 Jan 2021 22:47:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CE2D2683E3; Sun, 31 Jan 2021 23:47:34 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="H9U+01Wh"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C4EE3683E1 for ; Sun, 31 Jan 2021 23:47:28 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 40AA48B5; Sun, 31 Jan 2021 23:47:28 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133248; bh=eJODzAKRKevxslVtydpC+xCmvYO9E7TZ3nYawSGMLjk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=H9U+01Whcbg4t64nUhrwi8KVaUOYaNJwydZaX1fyuHxDLOONaChsHY2GAn+Mufd+/ wwDPYViaNpv7TCyzAhucVgfkytkx1xQiWP+u1ED5NjGgVXXV1hbRcYZFXNHQ7wVJWf hqztL4QrUYK3797ClWq24Sm7X1CX1ULzTMq3RPF0= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:45 +0200 Message-Id: <20210131224702.8838-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 03/20] libcamera: pipeline: simple: converter: Group query functions together 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The SimpleConverter class has different sets of functions, related to static queries, device configuration and runtime operation. Group the query functions together. While at it, swap the arguments to the strideAndFrameSize() function to match the order in which pixel format and size are usually specified. No functional change is included. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/converter.cpp | 30 ++++++++++----------- src/libcamera/pipeline/simple/converter.h | 5 ++-- src/libcamera/pipeline/simple/simple.cpp | 2 +- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 87d15c781ed8..8f54caaca983 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -133,6 +133,21 @@ SizeRange SimpleConverter::sizes(const Size &input) return sizes; } +std::tuple +SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, + const Size &size) +{ + V4L2DeviceFormat format; + format.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat); + format.size = size; + + int ret = m2m_->capture()->tryFormat(&format); + if (ret < 0) + return std::make_tuple(0, 0); + + return std::make_tuple(format.planes[0].bpl, format.planes[0].size); +} + int SimpleConverter::configure(PixelFormat inputFormat, const Size &inputSize, const StreamConfiguration &outputCfg) { @@ -254,19 +269,4 @@ void SimpleConverter::outputBufferReady(FrameBuffer *buffer) } } -std::tuple -SimpleConverter::strideAndFrameSize(const Size &size, - const PixelFormat &pixelFormat) -{ - V4L2DeviceFormat format; - format.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat); - format.size = size; - - int ret = m2m_->capture()->tryFormat(&format); - if (ret < 0) - return std::make_tuple(0, 0); - - return std::make_tuple(format.planes[0].bpl, format.planes[0].size); -} - } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index 06d66f8caba7..07a632abd8f6 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -35,6 +35,8 @@ public: std::vector formats(PixelFormat input); SizeRange sizes(const Size &input); + std::tuple + strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size); int configure(PixelFormat inputFormat, const Size &inputSize, const StreamConfiguration &outputCfg); @@ -46,9 +48,6 @@ public: int queueBuffers(FrameBuffer *input, FrameBuffer *output); - std::tuple - strideAndFrameSize(const Size &size, const PixelFormat &pixelFormat); - Signal bufferReady; private: diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index a97b8442d9a4..4e3127814b89 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -494,7 +494,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() SimpleConverter *converter = pipe->converter(); std::tie(cfg.stride, cfg.frameSize) = - converter->strideAndFrameSize(cfg.size, cfg.pixelFormat); + converter->strideAndFrameSize(cfg.pixelFormat, cfg.size); if (cfg.stride == 0) return Invalid; From patchwork Sun Jan 31 22:46:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11083 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 1B40DBD808 for ; Sun, 31 Jan 2021 22:47:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B89E2683E0; Sun, 31 Jan 2021 23:47:35 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="D9it4Glh"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 296D0683E6 for ; Sun, 31 Jan 2021 23:47:29 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A7ACB8EC; Sun, 31 Jan 2021 23:47:28 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133248; bh=XcnYxUCHJg5ctwjJ37SV0l3szVn/PcayYP781pv6gBc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=D9it4GlhrODCWtTf6BRD05gWR2zJI0QM8t1i9W1TImcEgSGIN3V7KvUE7hdAVcPKO 8ebyUwKf0kOSb4DFEaNTp23xZ+Xhi2mBKUbKWqW9amBta7/YyFFtG+1hXjrxEc//VQ k9Vm9FvzhLgkyVE8vu6I7yojzW8Y6MXK29zoMyiA= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:46 +0200 Message-Id: <20210131224702.8838-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 04/20] libcamera: pipeline: simple: converter: Use StreamConfiguration for input configuration 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Group the configuration parameters for the converter input in a StreamConfiguration instance. This makes the configure() function signature cleaner, and will allow passing additional parameters (such as stride and buffer count). Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/converter.cpp | 12 +++++++----- src/libcamera/pipeline/simple/converter.h | 2 +- src/libcamera/pipeline/simple/simple.cpp | 7 +++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 8f54caaca983..6f4e41db2e00 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -148,15 +148,17 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, return std::make_tuple(format.planes[0].bpl, format.planes[0].size); } -int SimpleConverter::configure(PixelFormat inputFormat, const Size &inputSize, +int SimpleConverter::configure(const StreamConfiguration &inputCfg, const StreamConfiguration &outputCfg) { - V4L2DeviceFormat format; int ret; - V4L2PixelFormat videoFormat = m2m_->output()->toV4L2PixelFormat(inputFormat); + V4L2PixelFormat videoFormat = + m2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat); + + V4L2DeviceFormat format; format.fourcc = videoFormat; - format.size = inputSize; + format.size = inputCfg.size; ret = m2m_->output()->setFormat(&format); if (ret < 0) { @@ -165,7 +167,7 @@ int SimpleConverter::configure(PixelFormat inputFormat, const Size &inputSize, return ret; } - if (format.fourcc != videoFormat || format.size != inputSize) { + if (format.fourcc != videoFormat || format.size != inputCfg.size) { LOG(SimplePipeline, Error) << "Input format not supported"; return -EINVAL; diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index 07a632abd8f6..47a056e582d6 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -38,7 +38,7 @@ public: std::tuple strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size); - int configure(PixelFormat inputFormat, const Size &inputSize, + int configure(const StreamConfiguration &inputCfg, const StreamConfiguration &outputCfg); int exportBuffers(unsigned int count, std::vector> *buffers); diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 4e3127814b89..0a53fa934261 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -603,8 +603,11 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) useConverter_ = config->needConversion(); if (useConverter_) { - ret = converter_->configure(pipeConfig.pixelFormat, - pipeConfig.captureSize, cfg); + StreamConfiguration inputCfg; + inputCfg.pixelFormat = pipeConfig.pixelFormat; + inputCfg.size = pipeConfig.captureSize; + + ret = converter_->configure(inputCfg, cfg); if (ret < 0) { LOG(SimplePipeline, Error) << "Unable to configure converter"; From patchwork Sun Jan 31 22:46:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11084 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 0F381BD808 for ; Sun, 31 Jan 2021 22:47:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B09E268401; Sun, 31 Jan 2021 23:47:36 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="i2MHfw5g"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 950DB683D9 for ; Sun, 31 Jan 2021 23:47:29 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1D7D88F1; Sun, 31 Jan 2021 23:47:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133249; bh=H1qIVCyOhiIrEzzsoNBN34FbiBDaspLhH6VLpFXQn9w=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=i2MHfw5gUx9ax9q/Lf1eJrZq4Wlhr7zuid4kg2R9Ovj03oINy5Q1zEXOamYMJ3d32 ElIdly5Ss3WKGA7e8mdWCWDfOasAvHEq2fDTSblcuf11n6AZw1enUTORTstxhiTvwm tydHXeiqIzLxLYDnG76lzzN0rMv1183VXx0i6ZhI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:47 +0200 Message-Id: <20210131224702.8838-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 05/20] libcamera: pipeline: simple: converter: Configure input stride 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Use the stride of the video capture device to configure the converter input. This ensures that no stride mismatch occurs inadvertently along the pipeline. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/converter.cpp | 5 ++++- src/libcamera/pipeline/simple/simple.cpp | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 6f4e41db2e00..550b2bcfb001 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -159,6 +159,8 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, V4L2DeviceFormat format; format.fourcc = videoFormat; format.size = inputCfg.size; + format.planesCount = 1; + format.planes[0].bpl = inputCfg.stride; ret = m2m_->output()->setFormat(&format); if (ret < 0) { @@ -167,7 +169,8 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, return ret; } - if (format.fourcc != videoFormat || format.size != inputCfg.size) { + if (format.fourcc != videoFormat || format.size != inputCfg.size || + format.planes[0].bpl != inputCfg.stride) { LOG(SimplePipeline, Error) << "Input format not supported"; return -EINVAL; diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 0a53fa934261..1ed67bcec490 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -606,6 +606,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) StreamConfiguration inputCfg; inputCfg.pixelFormat = pipeConfig.pixelFormat; inputCfg.size = pipeConfig.captureSize; + inputCfg.stride = captureFormat.planes[0].bpl; ret = converter_->configure(inputCfg, cfg); if (ret < 0) { From patchwork Sun Jan 31 22:46:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11085 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 C8D63BD808 for ; Sun, 31 Jan 2021 22:47:37 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 89D80683F0; Sun, 31 Jan 2021 23:47:37 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rKsc6uU4"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 08890683E3 for ; Sun, 31 Jan 2021 23:47:30 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 87D53144C; Sun, 31 Jan 2021 23:47:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133249; bh=DzYvlXA+EbM9lCOtKu+NO+jfA8Dcz6NpNaNgMQh4Nlo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=rKsc6uU4hwWRefUMHVG6cSl90EOhN1ehut/lo0Yh5c8ui8Bzy0Iy2qmFPlEJuFnVf q7VTegezOuCzmwh6qTHb3r8pD+BEqiwcV730SopDslmWwGuLFKdAgdasknVJkCa3wM 9/xIvo+QvG3KEie/xf9LOxt7Qm5Hv5h1sDUVk/BU= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:48 +0200 Message-Id: <20210131224702.8838-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 06/20] libcamera: pipeline: simple: converter: Differentiate input and output buffers count 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The number of buffers on the input and output of the converter don't necessarily need to match. Use the buffer count from the input and output configuration respectively. This removes the need to pass the buffer count to the start() function, which brings it closer to the pipeline handler API. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/converter.cpp | 9 ++++++--- src/libcamera/pipeline/simple/converter.h | 5 ++++- src/libcamera/pipeline/simple/simple.cpp | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 550b2bcfb001..6b3249ea92b0 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -195,6 +195,9 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, return -EINVAL; } + inputBufferCount_ = inputCfg.bufferCount; + outputBufferCount_ = outputCfg.bufferCount; + return 0; } @@ -204,13 +207,13 @@ int SimpleConverter::exportBuffers(unsigned int count, return m2m_->capture()->exportBuffers(count, buffers); } -int SimpleConverter::start(unsigned int count) +int SimpleConverter::start() { - int ret = m2m_->output()->importBuffers(count); + int ret = m2m_->output()->importBuffers(inputBufferCount_); if (ret < 0) return ret; - ret = m2m_->capture()->importBuffers(count); + ret = m2m_->capture()->importBuffers(outputBufferCount_); if (ret < 0) { stop(); return ret; diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index 47a056e582d6..a1503a6099ff 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -43,7 +43,7 @@ public: int exportBuffers(unsigned int count, std::vector> *buffers); - int start(unsigned int count); + int start(); void stop(); int queueBuffers(FrameBuffer *input, FrameBuffer *output); @@ -58,6 +58,9 @@ private: std::queue captureDoneQueue_; std::queue outputDoneQueue_; + + unsigned int inputBufferCount_; + unsigned int outputBufferCount_; }; } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 1ed67bcec490..8c0bca36bbfb 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -607,6 +607,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) inputCfg.pixelFormat = pipeConfig.pixelFormat; inputCfg.size = pipeConfig.captureSize; inputCfg.stride = captureFormat.planes[0].bpl; + inputCfg.bufferCount = cfg.bufferCount; ret = converter_->configure(inputCfg, cfg); if (ret < 0) { @@ -660,7 +661,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *c } if (useConverter_) { - ret = converter_->start(count); + ret = converter_->start(); if (ret < 0) { stop(camera); return ret; From patchwork Sun Jan 31 22:46:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11086 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 9ECDDBD808 for ; Sun, 31 Jan 2021 22:47:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4B511683F5; Sun, 31 Jan 2021 23:47:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="E8zaFpn/"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7EEF2683E7 for ; Sun, 31 Jan 2021 23:47:30 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F4017145B; Sun, 31 Jan 2021 23:47:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133250; bh=G9q7k/ellxmM5flEfJJTPlrdY8qbq6/u+UXrzKmEW5o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E8zaFpn/yAh65Uol+dv8Nqt3HAUwT2gCkE88V4J7copkLQICUXj6ab33mZv3RTKyH FiD4FWEqgYAFpJYyFXM2jwdLDV9KYaKPLkBYXFvcGY5dm7TymJiDxAeg8vo2j41zzh e3TFuyySqANTcdhZJYTBtk9vqdlOzHQ3MjGjf3Kg= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:49 +0200 Message-Id: <20210131224702.8838-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 07/20] libcamera: pipeline: simple: converter: Replace open() with isValid() 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Simplify the SimpleConverter interface by opening the M2M device in the constructor. The explicit call to open() is replaced by a check through a new isValid() function, and the unused close() function is removed. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/converter.cpp | 20 ++++++-------------- src/libcamera/pipeline/simple/converter.h | 3 +-- src/libcamera/pipeline/simple/simple.cpp | 4 ++-- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 6b3249ea92b0..f782fbc63b09 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -39,24 +39,16 @@ SimpleConverter::SimpleConverter(MediaDevice *media) m2m_ = std::make_unique((*it)->deviceNode()); + int ret = m2m_->open(); + if (ret < 0) { + m2m_.reset(); + return; + } + m2m_->output()->bufferReady.connect(this, &SimpleConverter::outputBufferReady); m2m_->capture()->bufferReady.connect(this, &SimpleConverter::captureBufferReady); } -int SimpleConverter::open() -{ - if (!m2m_) - return -ENODEV; - - return m2m_->open(); -} - -void SimpleConverter::close() -{ - if (m2m_) - m2m_->close(); -} - std::vector SimpleConverter::formats(PixelFormat input) { if (!m2m_) diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index a1503a6099ff..780bfa8f7832 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -30,8 +30,7 @@ class SimpleConverter public: SimpleConverter(MediaDevice *media); - int open(); - void close(); + bool isValid() const { return m2m_ != nullptr; } std::vector formats(PixelFormat input); SizeRange sizes(const Size &input); diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 8c0bca36bbfb..20a4ebca94fd 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -763,9 +763,9 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) /* Open the converter, if any. */ if (converter) { converter_ = std::make_unique(converter); - if (converter_->open() < 0) { + if (!converter_->isValid()) { LOG(SimplePipeline, Warning) - << "Failed to open converter, disabling format conversion"; + << "Failed to create converter, disabling format conversion"; converter_.reset(); } else { converter_->bufferReady.connect(this, &SimplePipelineHandler::converterDone); From patchwork Sun Jan 31 22:46:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11087 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 3635EBD808 for ; Sun, 31 Jan 2021 22:47:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id ECE46683F9; Sun, 31 Jan 2021 23:47:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kJ5KPWd0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E5E2F683DD for ; Sun, 31 Jan 2021 23:47:30 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6DA07145C; Sun, 31 Jan 2021 23:47:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133250; bh=u+pC3266rubsngdrw/0GegTHaDvdoizTRyIRuXLKRt8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kJ5KPWd0R1zq4f78HOA4lZ13q9kERZZLjQ4APuxgxUbtr3pUuVo/2YNo8axKXRJZR /vyP4GXSHtlTwxYQPsKBoWfmP/RZf/UzH0kZBSBMxbFs7VTiZRKhQ1kWf3ycg4CN6S Etu/mX0LSfHdFzr25bWewTC0xaqQ9CZ9WZ+uUzWI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:50 +0200 Message-Id: <20210131224702.8838-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 08/20] libcamera: pipeline: simple: converter: Decouple input and output completion 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The SimpleConverter API signals completion of input and output buffer pairs. This unnecessarily delays requeueing the input buffer to the video capture queue until the output buffer completes, and also delays signalling request completion until the input buffer completes. While this shouldn't cause large delays in practice, it will also not scale when multi-stream support will be added to the converter class. To address the current issue and prepare for the future, decouple signalling of input and output buffers completion. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/converter.cpp | 24 +++++-------------- src/libcamera/pipeline/simple/converter.h | 11 ++++----- src/libcamera/pipeline/simple/simple.cpp | 26 +++++++++++++-------- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index f782fbc63b09..8324baedc198 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -45,8 +45,8 @@ SimpleConverter::SimpleConverter(MediaDevice *media) return; } - m2m_->output()->bufferReady.connect(this, &SimpleConverter::outputBufferReady); - m2m_->capture()->bufferReady.connect(this, &SimpleConverter::captureBufferReady); + m2m_->output()->bufferReady.connect(this, &SimpleConverter::m2mInputBufferReady); + m2m_->capture()->bufferReady.connect(this, &SimpleConverter::m2mOutputBufferReady); } std::vector SimpleConverter::formats(PixelFormat input) @@ -247,26 +247,14 @@ int SimpleConverter::queueBuffers(FrameBuffer *input, FrameBuffer *output) return 0; } -void SimpleConverter::captureBufferReady(FrameBuffer *buffer) +void SimpleConverter::m2mInputBufferReady(FrameBuffer *buffer) { - if (!outputDoneQueue_.empty()) { - FrameBuffer *other = outputDoneQueue_.front(); - outputDoneQueue_.pop(); - bufferReady.emit(other, buffer); - } else { - captureDoneQueue_.push(buffer); - } + inputBufferReady.emit(buffer); } -void SimpleConverter::outputBufferReady(FrameBuffer *buffer) +void SimpleConverter::m2mOutputBufferReady(FrameBuffer *buffer) { - if (!captureDoneQueue_.empty()) { - FrameBuffer *other = captureDoneQueue_.front(); - captureDoneQueue_.pop(); - bufferReady.emit(buffer, other); - } else { - outputDoneQueue_.push(buffer); - } + outputBufferReady.emit(buffer); } } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index 780bfa8f7832..739b24df0200 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -9,7 +9,6 @@ #define __LIBCAMERA_PIPELINE_SIMPLE_CONVERTER_H__ #include -#include #include #include @@ -47,17 +46,15 @@ public: int queueBuffers(FrameBuffer *input, FrameBuffer *output); - Signal bufferReady; + Signal inputBufferReady; + Signal outputBufferReady; private: - void captureBufferReady(FrameBuffer *buffer); - void outputBufferReady(FrameBuffer *buffer); + void m2mInputBufferReady(FrameBuffer *buffer); + void m2mOutputBufferReady(FrameBuffer *buffer); std::unique_ptr m2m_; - std::queue captureDoneQueue_; - std::queue outputDoneQueue_; - unsigned int inputBufferCount_; unsigned int outputBufferCount_; }; diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 20a4ebca94fd..7f9c57234256 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -144,7 +144,8 @@ private: } void bufferReady(FrameBuffer *buffer); - void converterDone(FrameBuffer *input, FrameBuffer *output); + void converterInputDone(FrameBuffer *buffer); + void converterOutputDone(FrameBuffer *buffer); MediaDevice *media_; std::map> videos_; @@ -768,7 +769,8 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) << "Failed to create converter, disabling format conversion"; converter_.reset(); } else { - converter_->bufferReady.connect(this, &SimplePipelineHandler::converterDone); + converter_->inputBufferReady.connect(this, &SimplePipelineHandler::converterInputDone); + converter_->outputBufferReady.connect(this, &SimplePipelineHandler::converterOutputDone); } } @@ -925,19 +927,23 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) completeRequest(request); } -void SimplePipelineHandler::converterDone(FrameBuffer *input, - FrameBuffer *output) +void SimplePipelineHandler::converterInputDone(FrameBuffer *buffer) { ASSERT(activeCamera_); SimpleCameraData *data = cameraData(activeCamera_); - /* Complete the request. */ - Request *request = output->request(); - completeBuffer(request, output); - completeRequest(request); - /* Queue the input buffer back for capture. */ - data->video_->queueBuffer(input); + data->video_->queueBuffer(buffer); +} + +void SimplePipelineHandler::converterOutputDone(FrameBuffer *buffer) +{ + ASSERT(activeCamera_); + + /* Complete the request. */ + Request *request = buffer->request(); + completeBuffer(request, buffer); + completeRequest(request); } REGISTER_PIPELINE_HANDLER(SimplePipelineHandler) From patchwork Sun Jan 31 22:46:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11088 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 DD64CBD808 for ; Sun, 31 Jan 2021 22:47:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A7ECB68411; Sun, 31 Jan 2021 23:47:40 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ut8M1lRa"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4F0CD683E0 for ; Sun, 31 Jan 2021 23:47:31 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D68641460; Sun, 31 Jan 2021 23:47:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133251; bh=yFBWlz+JxVm2MSv9YLIAxbCUWjk9/213xueQ6ccIxbY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ut8M1lRa479kizbaWf0KULpMU9H4W6D8+tuh4/usdw5/Qe9cpo4rsJIlIVXXZqdhW xxEVnBlw2uTXmG+/9r4AGvf4L5O5khr7WM/9wEtO+nawzDfMVj2c2ivO6DHqTh6PV8 k0By56RyUUM2q2ac8aTLWt2fI2PPZ6JNgGVhEBuM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:51 +0200 Message-Id: <20210131224702.8838-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 09/20] libcamera: pipeline: simple: converter: Add multi-stream support 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" While the M2M device backing the converter doesn't support multiple streams natively, it can be run once per stream to produce multiple outputs from the same input, with different output formats and sizes. To support this, create a class to model a stream and move control of the M2M device to the Stream class. The SimpleConverter class then creates stream instances and iterates over them. Each stream needs its own instance of the V4L2M2MDevice, to support different output configurations. The SimpleConverter class retains a device instance to support the query operations. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/converter.cpp | 294 ++++++++++++++------ src/libcamera/pipeline/simple/converter.h | 44 ++- src/libcamera/pipeline/simple/simple.cpp | 6 +- 3 files changed, 250 insertions(+), 94 deletions(-) diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/pipeline/simple/converter.cpp index 8324baedc198..3db162d9edb8 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/pipeline/simple/converter.cpp @@ -17,12 +17,157 @@ #include "libcamera/internal/log.h" #include "libcamera/internal/media_device.h" +#include "libcamera/internal/utils.h" #include "libcamera/internal/v4l2_videodevice.h" namespace libcamera { LOG_DECLARE_CATEGORY(SimplePipeline) +/* ----------------------------------------------------------------------------- + * SimpleConverter::Stream + */ + +SimpleConverter::Stream::Stream(SimpleConverter *converter) + : converter_(converter) +{ + m2m_ = std::make_unique(converter->deviceNode_); + + m2m_->output()->bufferReady.connect(this, &Stream::outputBufferReady); + m2m_->capture()->bufferReady.connect(this, &Stream::captureBufferReady); + + int ret = m2m_->open(); + if (ret < 0) + m2m_.reset(); +} + +int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg) +{ + V4L2PixelFormat videoFormat = + m2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat); + + V4L2DeviceFormat format; + format.fourcc = videoFormat; + format.size = inputCfg.size; + format.planesCount = 1; + format.planes[0].bpl = inputCfg.stride; + + int ret = m2m_->output()->setFormat(&format); + if (ret < 0) { + LOG(SimplePipeline, Error) + << "Failed to set input format: " << strerror(-ret); + return ret; + } + + if (format.fourcc != videoFormat || format.size != inputCfg.size || + format.planes[0].bpl != inputCfg.stride) { + LOG(SimplePipeline, Error) + << "Input format not supported"; + return -EINVAL; + } + + /* Set the pixel format and size on the output. */ + videoFormat = m2m_->capture()->toV4L2PixelFormat(outputCfg.pixelFormat); + format = {}; + format.fourcc = videoFormat; + format.size = outputCfg.size; + + ret = m2m_->capture()->setFormat(&format); + if (ret < 0) { + LOG(SimplePipeline, Error) + << "Failed to set output format: " << strerror(-ret); + return ret; + } + + if (format.fourcc != videoFormat || format.size != outputCfg.size) { + LOG(SimplePipeline, Error) + << "Output format not supported"; + return -EINVAL; + } + + inputBufferCount_ = inputCfg.bufferCount; + outputBufferCount_ = outputCfg.bufferCount; + + return 0; +} + +int SimpleConverter::Stream::exportBuffers(unsigned int count, + std::vector> *buffers) +{ + return m2m_->capture()->exportBuffers(count, buffers); +} + +int SimpleConverter::Stream::start() +{ + int ret = m2m_->output()->importBuffers(inputBufferCount_); + if (ret < 0) + return ret; + + ret = m2m_->capture()->importBuffers(outputBufferCount_); + if (ret < 0) { + stop(); + return ret; + } + + ret = m2m_->output()->streamOn(); + if (ret < 0) { + stop(); + return ret; + } + + ret = m2m_->capture()->streamOn(); + if (ret < 0) { + stop(); + return ret; + } + + return 0; +} + +void SimpleConverter::Stream::stop() +{ + m2m_->capture()->streamOff(); + m2m_->output()->streamOff(); + m2m_->capture()->releaseBuffers(); + m2m_->output()->releaseBuffers(); +} + +int SimpleConverter::Stream::queueBuffers(FrameBuffer *input, + FrameBuffer *output) +{ + int ret = m2m_->output()->queueBuffer(input); + if (ret < 0) + return ret; + + ret = m2m_->capture()->queueBuffer(output); + if (ret < 0) + return ret; + + return 0; +} + +void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer) +{ + auto it = converter_->queue_.find(buffer); + if (it == converter_->queue_.end()) + return; + + if (!--it->second) { + converter_->inputBufferReady.emit(buffer); + converter_->queue_.erase(it); + } +} + +void SimpleConverter::Stream::captureBufferReady(FrameBuffer *buffer) +{ + converter_->outputBufferReady.emit(buffer); +} + +/* ----------------------------------------------------------------------------- + * SimpleConverter + */ + SimpleConverter::SimpleConverter(MediaDevice *media) { /* @@ -37,16 +182,14 @@ SimpleConverter::SimpleConverter(MediaDevice *media) if (it == entities.end()) return; - m2m_ = std::make_unique((*it)->deviceNode()); + deviceNode_ = (*it)->deviceNode(); + m2m_ = std::make_unique(deviceNode_); int ret = m2m_->open(); if (ret < 0) { m2m_.reset(); return; } - - m2m_->output()->bufferReady.connect(this, &SimpleConverter::m2mInputBufferReady); - m2m_->capture()->bufferReady.connect(this, &SimpleConverter::m2mOutputBufferReady); } std::vector SimpleConverter::formats(PixelFormat input) @@ -141,86 +284,54 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, } int SimpleConverter::configure(const StreamConfiguration &inputCfg, - const StreamConfiguration &outputCfg) + const std::vector> &outputCfgs) { - int ret; + int ret = 0; - V4L2PixelFormat videoFormat = - m2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat); + streams_.clear(); + streams_.reserve(outputCfgs.size()); - V4L2DeviceFormat format; - format.fourcc = videoFormat; - format.size = inputCfg.size; - format.planesCount = 1; - format.planes[0].bpl = inputCfg.stride; + for (const StreamConfiguration &outputCfg : outputCfgs) { + Stream &stream = streams_.emplace_back(this); - ret = m2m_->output()->setFormat(&format); - if (ret < 0) { - LOG(SimplePipeline, Error) - << "Failed to set input format: " << strerror(-ret); - return ret; - } + if (!stream.isValid()) { + LOG(SimplePipeline, Error) << "Failed to create stream"; + ret = -EINVAL; + break; + } - if (format.fourcc != videoFormat || format.size != inputCfg.size || - format.planes[0].bpl != inputCfg.stride) { - LOG(SimplePipeline, Error) - << "Input format not supported"; - return -EINVAL; + ret = stream.configure(inputCfg, outputCfg); + if (ret < 0) + break; } - /* Set the pixel format and size on the output. */ - videoFormat = m2m_->capture()->toV4L2PixelFormat(outputCfg.pixelFormat); - format = {}; - format.fourcc = videoFormat; - format.size = outputCfg.size; - - ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) - << "Failed to set output format: " << strerror(-ret); + streams_.clear(); return ret; } - if (format.fourcc != videoFormat || format.size != outputCfg.size) { - LOG(SimplePipeline, Error) - << "Output format not supported"; - return -EINVAL; - } - - inputBufferCount_ = inputCfg.bufferCount; - outputBufferCount_ = outputCfg.bufferCount; - return 0; } -int SimpleConverter::exportBuffers(unsigned int count, +int SimpleConverter::exportBuffers(unsigned int output, unsigned int count, std::vector> *buffers) { - return m2m_->capture()->exportBuffers(count, buffers); + if (output >= streams_.size()) + return -EINVAL; + + return streams_[output].exportBuffers(count, buffers); } int SimpleConverter::start() { - int ret = m2m_->output()->importBuffers(inputBufferCount_); - if (ret < 0) - return ret; + int ret; - ret = m2m_->capture()->importBuffers(outputBufferCount_); - if (ret < 0) { - stop(); - return ret; - } - - ret = m2m_->output()->streamOn(); - if (ret < 0) { - stop(); - return ret; - } - - ret = m2m_->capture()->streamOn(); - if (ret < 0) { - stop(); - return ret; + for (Stream &stream : utils::reverse(streams_)) { + ret = stream.start(); + if (ret < 0) { + stop(); + return ret; + } } return 0; @@ -228,33 +339,48 @@ int SimpleConverter::start() void SimpleConverter::stop() { - m2m_->capture()->streamOff(); - m2m_->output()->streamOff(); - m2m_->capture()->releaseBuffers(); - m2m_->output()->releaseBuffers(); + for (Stream &stream : utils::reverse(streams_)) + stream.stop(); } -int SimpleConverter::queueBuffers(FrameBuffer *input, FrameBuffer *output) +int SimpleConverter::queueBuffers(FrameBuffer *input, + const std::map &outputs) { - int ret = m2m_->output()->queueBuffer(input); - if (ret < 0) - return ret; + unsigned int mask = 0; + int ret; - ret = m2m_->capture()->queueBuffer(output); - if (ret < 0) - return ret; + /* Validate the outputs as a sanity check. */ + if (outputs.empty()) + return -EINVAL; + + for (auto [index, buffer] : outputs) { + if (index >= streams_.size()) + return -EINVAL; + if (mask & (1 << index)) + return -EINVAL; + if (!buffer) + return -EINVAL; + + mask |= 1 << index; + } + + /* Queue the input and output buffers to all the streams. */ + for (auto [index, buffer] : outputs) { + ret = streams_[index].queueBuffers(input, buffer); + if (ret < 0) + return ret; + } + + /* + * Add the input buffer to the queue, with the number of streams as a + * reference count. Completion of the input buffer will be signalled by + * the stream that releases the last reference. + */ + queue_.emplace(std::piecewise_construct, + std::forward_as_tuple(input), + std::forward_as_tuple(outputs.size())); return 0; } -void SimpleConverter::m2mInputBufferReady(FrameBuffer *buffer) -{ - inputBufferReady.emit(buffer); -} - -void SimpleConverter::m2mOutputBufferReady(FrameBuffer *buffer) -{ - outputBufferReady.emit(buffer); -} - } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/converter.h b/src/libcamera/pipeline/simple/converter.h index 739b24df0200..176978eefe48 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/src/libcamera/pipeline/simple/converter.h @@ -8,7 +8,10 @@ #ifndef __LIBCAMERA_PIPELINE_SIMPLE_CONVERTER_H__ #define __LIBCAMERA_PIPELINE_SIMPLE_CONVERTER_H__ +#include +#include #include +#include #include #include @@ -37,26 +40,53 @@ public: strideAndFrameSize(const PixelFormat &pixelFormat, const Size &size); int configure(const StreamConfiguration &inputCfg, - const StreamConfiguration &outputCfg); - int exportBuffers(unsigned int count, + const std::vector> &outputCfg); + int exportBuffers(unsigned int ouput, unsigned int count, std::vector> *buffers); int start(); void stop(); - int queueBuffers(FrameBuffer *input, FrameBuffer *output); + int queueBuffers(FrameBuffer *input, + const std::map &outputs); Signal inputBufferReady; Signal outputBufferReady; private: - void m2mInputBufferReady(FrameBuffer *buffer); - void m2mOutputBufferReady(FrameBuffer *buffer); + class Stream + { + public: + Stream(SimpleConverter *converter); + bool isValid() const { return m2m_ != nullptr; } + + int configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg); + int exportBuffers(unsigned int count, + std::vector> *buffers); + + int start(); + void stop(); + + int queueBuffers(FrameBuffer *input, FrameBuffer *output); + + private: + void captureBufferReady(FrameBuffer *buffer); + void outputBufferReady(FrameBuffer *buffer); + + SimpleConverter *converter_; + std::unique_ptr m2m_; + + unsigned int inputBufferCount_; + unsigned int outputBufferCount_; + }; + + std::string deviceNode_; std::unique_ptr m2m_; - unsigned int inputBufferCount_; - unsigned int outputBufferCount_; + std::vector streams_; + std::map queue_; }; } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 7f9c57234256..b7a890ab772e 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -610,7 +610,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) inputCfg.stride = captureFormat.planes[0].bpl; inputCfg.bufferCount = cfg.bufferCount; - ret = converter_->configure(inputCfg, cfg); + ret = converter_->configure(inputCfg, { cfg }); if (ret < 0) { LOG(SimplePipeline, Error) << "Unable to configure converter"; @@ -636,7 +636,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * whether the converter is used or not. */ if (useConverter_) - return converter_->exportBuffers(count, buffers); + return converter_->exportBuffers(0, count, buffers); else return data->video_->exportBuffers(count, buffers); } @@ -917,7 +917,7 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) FrameBuffer *output = converterQueue_.front(); converterQueue_.pop(); - converter_->queueBuffers(buffer, output); + converter_->queueBuffers(buffer, { { 0, output } }); return; } From patchwork Sun Jan 31 22:46:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11089 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 77921BD808 for ; Sun, 31 Jan 2021 22:47:41 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 315B3683F0; Sun, 31 Jan 2021 23:47:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="GM3vk86b"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DB572683EE for ; Sun, 31 Jan 2021 23:47:31 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4C368163C; Sun, 31 Jan 2021 23:47:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133251; bh=c4oPxFmw6lLgdArqv9i4qy63kIjhfJYW+rlHSU0uIQU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GM3vk86broaLMOx7ffpDYsVVf0vduwI2iBwY8/vr4SU6gtDWBKyh3ehai2OUWdxZj GU9s3DhdMQIJeKDIOG5XK5pE3bhO+/8FvqplRVbHc2LJHku+FLMMQOBbiJaceNPFIl 0+bcRrS5IRuvbVoF6FSr6OmRoIe3/QhqNgkKd5/o= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:52 +0200 Message-Id: <20210131224702.8838-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 10/20] libcamera: pipeline: simple: Store streams in a vector 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" To prepare for multiple streams support, store the streams in a vector in the SimpleCameraData class. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/simple.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index b7a890ab772e..390c87ba74d8 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -61,7 +61,6 @@ public: SimpleCameraData(SimplePipelineHandler *pipe, MediaEntity *sensor); bool isValid() const { return sensor_ != nullptr; } - std::set streams() { return { &stream_ }; } int init(); int setupLinks(); @@ -80,7 +79,7 @@ public: SizeRange outputSizes; }; - Stream stream_; + std::vector streams_; std::unique_ptr sensor_; std::list entities_; V4L2VideoDevice *video_; @@ -169,6 +168,8 @@ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, { int ret; + streams_.resize(1); + /* * Walk the pipeline towards the video node and store all entities * along the way. @@ -620,7 +621,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) LOG(SimplePipeline, Debug) << "Using format converter"; } - cfg.setStream(&data->stream_); + cfg.setStream(&data->streams_[0]); return 0; } @@ -645,7 +646,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *c { SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; - unsigned int count = data->stream_.configuration().bufferCount; + unsigned int count = data->streams_[0].configuration().bufferCount; int ret; if (useConverter_) @@ -696,7 +697,7 @@ void SimplePipelineHandler::stop(Camera *camera) int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) { SimpleCameraData *data = cameraData(camera); - Stream *stream = &data->stream_; + Stream *stream = &data->streams_[0]; FrameBuffer *buffer = request->findBuffer(stream); if (!buffer) { @@ -825,9 +826,13 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) if (ret < 0) continue; + std::set streams; + std::transform(data->streams_.begin(), data->streams_.end(), + std::inserter(streams, streams.end()), + [](Stream &stream) { return &stream; }); + std::shared_ptr camera = - Camera::create(this, data->sensor_->id(), - data->streams()); + Camera::create(this, data->sensor_->id(), streams); registerCamera(std::move(camera), std::move(data)); registered = true; } From patchwork Sun Jan 31 22:46:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11090 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 037B8BD808 for ; Sun, 31 Jan 2021 22:47:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B40DE683F5; Sun, 31 Jan 2021 23:47:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="SBMdySvR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4D61A683EF for ; Sun, 31 Jan 2021 23:47:32 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id CC8EA163D; Sun, 31 Jan 2021 23:47:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133252; bh=SU9OhxbM7NK3Aw7pyUS4R74PWXHV4+VAjU78cMSDa2c=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SBMdySvRL5HXlyH6AERnTZGMlTHQDEnPX0F4uArhmI2H9+PBRIv5fTfhCQDc+SALs S4sepfwyeo7rJne7EsQcEt2Wlj7ZPVv7MleaRN+wN04kFjbH1Jjg6YoVtRg/hJNcBZ Kp9JTmqzXJ38mRtBb+IeXgrfYx1L0rxpAmK449OY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:53 +0200 Message-Id: <20210131224702.8838-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 11/20] libcamera: pipeline: simple: Drop unused members of configuration 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The SimpleCameraConfiguration class has a sensorFormat_ member variable and a corresponding accessor that are never used. Drop them. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/simple.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 390c87ba74d8..f072e0f1fa81 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -94,8 +94,6 @@ public: Status validate() override; - const V4L2SubdeviceFormat &sensorFormat() { return sensorFormat_; } - bool needConversion() const { return needConversion_; } private: @@ -107,7 +105,6 @@ private: std::shared_ptr camera_; const SimpleCameraData *data_; - V4L2SubdeviceFormat sensorFormat_; bool needConversion_; }; From patchwork Sun Jan 31 22:46:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11091 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 89CCBBD808 for ; Sun, 31 Jan 2021 22:47:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4F59968408; Sun, 31 Jan 2021 23:47:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mlhY4Srw"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id ACD35683E6 for ; Sun, 31 Jan 2021 23:47:32 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3DC108A0; Sun, 31 Jan 2021 23:47:32 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133252; bh=ZY2jarT0TsSLPyvDzZtj+FVF6KM2VIUroJRj8LLakB8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mlhY4SrwoUN5hvzEMQh4oPI6yuk1ADL1r2Rf6RIVwlLhNliiNL+jDPrSHlQt/kdqf SwTXn7vq6gxS/ZZMWeLG5IbAdqSmaRVSDwOXFgmlU/UR+jvo86Kh0wglrrSeX8pt1w t/rj5+eMY7a6hx5TGdHQbkGeiNIbR/Zj0UMZCfTc= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:54 +0200 Message-Id: <20210131224702.8838-13-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 12/20] libcamera: pipeline: simple: Document the pipeline handler design 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The simple pipeline handler has grown over time, and isn't that simple anymore that it can easily be understood by an unfamiliar reader. Document the design to explicitly state the expectations of the pipeline handler, and to explain how it operates. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/simple.cpp | 83 ++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index f072e0f1fa81..7c5a56a2f395 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -38,6 +38,89 @@ namespace libcamera { LOG_DEFINE_CATEGORY(SimplePipeline) +/* ----------------------------------------------------------------------------- + * + * Overview + * -------- + * + * The SimplePipelineHandler relies on generic kernel APIs to control a camera + * device, without any device-specific code and with limited device-specific + * static data. + * + * To quality for support by the simple pipeline handler, a device shall + * + * - be supported by V4L2 drivers, exposing the Media Controller API, the V4L2 + * subdev APIs and the media bus format-based enumeration extension for the + * VIDIOC_ENUM_FMT ioctl ; + * - not expose any device-specific API from drivers to userspace ; + * - include one or more camera sensor media entities and one or more video + * capture devices ; + * - have a capture pipeline with linear paths from the camera sensors to the + * video capture devices ; and + * - have an optional memory-to-memory device to perform format conversion + * and/or scaling, exposed as a V4L2 M2M device. + * + * As devices that require a specific pipeline handler may still match the + * above characteristics, the simple pipeline handler doesn't attempt to + * automatically determine which devices it can support. It instead relies on + * an explicit list of supported devices, provided in the supportedDevices + * array. + * + * When matching a device, the pipeline handler enumerates all camera sensors + * and attempts, for each of them, to find a path to a video captude video node. + * It does so by traversing the media graph, following the first non permanently + * disabled downstream link. If such a path is found, the pipeline handler + * creates a corresponding SimpleCameraData instance, and stores the media graph + * path in its entities_ list. + * + * A more complex graph search algorithm could be implemented if a device that + * would otherwise be compatible with the pipeline handler isn't correctly + * handled by this heuristic. + * + * Once the camera data instances have been created, the match() function + * creates a V4L2Subdevice instance for each entity used by any of the cameras + * and stores the instances in SimplePipelineHandler::subdevs_, accessible by + * the SimpleCameraData class through the SimplePipelineHandler::subdev() + * function. This avoids duplication of subdev instances between different + * cameras when the same entity is used in multiple paths. A similar mechanism + * is used for V4L2VideoDevice instances, but instances are in this case created + * on demand when access through SimplePipelineHandler::video() instead of all + * in one go at initialization time. + * + * Finally, all camera data instances are initialized to gather information + * about the possible pipeline configurations for the corresponding camera. If + * valid pipeline configurations are found, a Camera is registered for the + * SimpleCameraData instance. + * + * Pipeline Configuration + * ---------------------- + * + * The simple pipeline handler configures the pipeline by propagating V4L2 + * subdev formats from the camera sensor to the video node. The format is first + * set on the camera sensor's output, using the native camera sensor + * resolution. Then, on every link in the pipeline, the format is retrieved on + * the link source and set unmodified on the link sink. + * + * When initializating the camera data, this above procedure is repeated for + * every media bus format supported by the camera sensor. Upon reaching the + * video node, the pixel formats compatible with the media bus format are + * enumerated. Each of those pixel formats correspond to one possible pipeline + * configuration, stored as an intsance of SimpleCameraData::Configuration in + * the SimpleCameraData::formats_ map. + * + * Format Conversion and Scaling + * ----------------------------- + * + * The capture pipeline isn't expected to include a scaler, and if a scaler is + * available, it is ignored when configuring the pipeline. However, the simple + * pipeline handler supports optional memory-to-memory converters to scale the + * image and convert it to a different pixel format. If such a converter is + * present, the pipeline handler enumerates, for each pipeline configuration, + * the pixel formats and sizes that the converter can produce for the output of + * the capture video node, and stores the information in the outputFormats and + * outputSizes of the SimpleCameraData::Configuration structure. + */ + class SimplePipelineHandler; struct SimplePipelineInfo { From patchwork Sun Jan 31 22:46:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11092 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 132E8BD808 for ; Sun, 31 Jan 2021 22:47:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D5F5D68407; Sun, 31 Jan 2021 23:47:42 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Lrd7D9U8"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 268EC683F0 for ; Sun, 31 Jan 2021 23:47:33 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A56A4813; Sun, 31 Jan 2021 23:47:32 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133252; bh=fonE0GucruxFPXXcNqlmLbRBju4Gc3HNXtuLFHyP8e8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Lrd7D9U8lRjrWLrg4KYRpmNEdzIQ4jPr5kz2JUy4NScz7x/5nWBS0iESLh+/D/iHQ YxOQ1dcL7+88XxXRd5kIpL3Mm63qeaHjeYFHylT8fOBynSlY6sbctGGQRM+bYb1C2T YGhJ3+A0IuaqBUC5sJG3UFQXDrybw301b+r1xbLY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:55 +0200 Message-Id: <20210131224702.8838-14-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 13/20] libcamera: pipeline: simple: Rename Configuration::pixelFormat 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The Configuration::pixelFormat field stores the pixel format at the output of the capture part of the pipeline. Rename it to captureFormat, to match the related captureSize field. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/libcamera/pipeline/simple/simple.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 7c5a56a2f395..72a18cc0b97f 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -157,7 +157,7 @@ public: struct Configuration { uint32_t code; - PixelFormat pixelFormat; + PixelFormat captureFormat; Size captureSize; SizeRange outputSizes; }; @@ -379,7 +379,7 @@ int SimpleCameraData::init() Configuration config; config.code = code; - config.pixelFormat = pixelFormat; + config.captureFormat = pixelFormat; config.captureSize = format.size; if (!converter) { @@ -551,7 +551,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() status = Adjusted; } - needConversion_ = cfg.pixelFormat != pipeConfig.pixelFormat + needConversion_ = cfg.pixelFormat != pipeConfig.captureFormat || cfg.size != pipeConfig.captureSize; cfg.bufferCount = 3; @@ -656,7 +656,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) return ret; /* Configure the video node. */ - V4L2PixelFormat videoFormat = video->toV4L2PixelFormat(pipeConfig.pixelFormat); + V4L2PixelFormat videoFormat = video->toV4L2PixelFormat(pipeConfig.captureFormat); V4L2DeviceFormat captureFormat; captureFormat.fourcc = videoFormat; @@ -686,7 +686,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) if (useConverter_) { StreamConfiguration inputCfg; - inputCfg.pixelFormat = pipeConfig.pixelFormat; + inputCfg.pixelFormat = pipeConfig.captureFormat; inputCfg.size = pipeConfig.captureSize; inputCfg.stride = captureFormat.planes[0].bpl; inputCfg.bufferCount = cfg.bufferCount; From patchwork Sun Jan 31 22:46:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11093 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 933ABBD808 for ; Sun, 31 Jan 2021 22:47:43 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5FA6F683D9; Sun, 31 Jan 2021 23:47:43 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="eEdTs/Dq"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8B138683E3 for ; Sun, 31 Jan 2021 23:47:33 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 184EB182D; Sun, 31 Jan 2021 23:47:33 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133253; bh=jigumEo2DE/9bxKJVy7h3VHqG3W5V3REGWObfLeKwMg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eEdTs/Dq9pMvoA8xZ1MTqFdhJ+0lsUsooYdEfdISLnvQ6cGCzp25GkKpJ0EQJYkZ1 zPq7S+icEMkd6L5CICOAUoQOh4a6IZm/QFhITchcb9TCZG/WVRL8IVrpU7vq4r1SlO qsFyVTeB+00OxSBfssUQEG28kD7WevGONGV9mRU0= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:56 +0200 Message-Id: <20210131224702.8838-15-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 14/20] libcamera: pipeline: simple: Cache pipeline config in SimpleCameraConfiguration 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" As the pipeline configuration is selected in SimpleCameraConfiguration::validate() already, cache it in the SimpleCameraConfiguration instead of looking it up in SimplePipelineHandler::configure(). This makes little difference at the moment, but will save duplication of more complex logic between validate() and configure() when adding support for multiple streams. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 38 +++++++++++++----------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 72a18cc0b97f..c44fa9ee28ed 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -177,6 +177,11 @@ public: Status validate() override; + const SimpleCameraData::Configuration *pipeConfig() const + { + return pipeConfig_; + } + bool needConversion() const { return needConversion_; } private: @@ -188,6 +193,7 @@ private: std::shared_ptr camera_; const SimpleCameraData *data_; + const SimpleCameraData::Configuration *pipeConfig_; bool needConversion_; }; @@ -506,7 +512,7 @@ int SimpleCameraData::setupFormats(V4L2SubdeviceFormat *format, SimpleCameraConfiguration::SimpleCameraConfiguration(Camera *camera, SimpleCameraData *data) : CameraConfiguration(), camera_(camera->shared_from_this()), - data_(data) + data_(data), pipeConfig_(nullptr) { } @@ -542,17 +548,17 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() status = Adjusted; } - const SimpleCameraData::Configuration &pipeConfig = it->second; - if (!pipeConfig.outputSizes.contains(cfg.size)) { + pipeConfig_ = &it->second; + if (!pipeConfig_->outputSizes.contains(cfg.size)) { LOG(SimplePipeline, Debug) << "Adjusting size from " << cfg.size.toString() - << " to " << pipeConfig.captureSize.toString(); - cfg.size = pipeConfig.captureSize; + << " to " << pipeConfig_->captureSize.toString(); + cfg.size = pipeConfig_->captureSize; status = Adjusted; } - needConversion_ = cfg.pixelFormat != pipeConfig.captureFormat - || cfg.size != pipeConfig.captureSize; + needConversion_ = cfg.pixelFormat != pipeConfig_->captureFormat + || cfg.size != pipeConfig_->captureSize; cfg.bufferCount = 3; @@ -646,21 +652,19 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) if (ret < 0) return ret; - const SimpleCameraData::Configuration &pipeConfig = - data->formats_[cfg.pixelFormat]; - - V4L2SubdeviceFormat format{ pipeConfig.code, data->sensor_->resolution() }; + const SimpleCameraData::Configuration *pipeConfig = config->pipeConfig(); + V4L2SubdeviceFormat format{ pipeConfig->code, data->sensor_->resolution() }; ret = data->setupFormats(&format, V4L2Subdevice::ActiveFormat); if (ret < 0) return ret; /* Configure the video node. */ - V4L2PixelFormat videoFormat = video->toV4L2PixelFormat(pipeConfig.captureFormat); + V4L2PixelFormat videoFormat = video->toV4L2PixelFormat(pipeConfig->captureFormat); V4L2DeviceFormat captureFormat; captureFormat.fourcc = videoFormat; - captureFormat.size = pipeConfig.captureSize; + captureFormat.size = pipeConfig->captureSize; ret = video->setFormat(&captureFormat); if (ret) @@ -673,10 +677,10 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) } if (captureFormat.fourcc != videoFormat || - captureFormat.size != pipeConfig.captureSize) { + captureFormat.size != pipeConfig->captureSize) { LOG(SimplePipeline, Error) << "Unable to configure capture in " - << pipeConfig.captureSize.toString() << "-" + << pipeConfig->captureSize.toString() << "-" << videoFormat.toString(); return -EINVAL; } @@ -686,8 +690,8 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) if (useConverter_) { StreamConfiguration inputCfg; - inputCfg.pixelFormat = pipeConfig.captureFormat; - inputCfg.size = pipeConfig.captureSize; + inputCfg.pixelFormat = pipeConfig->captureFormat; + inputCfg.size = pipeConfig->captureSize; inputCfg.stride = captureFormat.planes[0].bpl; inputCfg.bufferCount = cfg.bufferCount; From patchwork Sun Jan 31 22:46:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11094 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 166A7BD808 for ; Sun, 31 Jan 2021 22:47:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D4FC9683E5; Sun, 31 Jan 2021 23:47:43 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="t5fF9UbN"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 01794683F7 for ; Sun, 31 Jan 2021 23:47:34 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7F2481830; Sun, 31 Jan 2021 23:47:33 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133253; bh=2SAvivIhcxfowTyvt/rn9nFkZARojyA8NX8axkOSUWg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=t5fF9UbNbvKlKn6pbSaB+rt3CBEN4I4Mmypz8ZbYG7OCYAZsSXLb6YGr5lDpKLNck aYBRpHvlB0H3eRLXH6Qu3gUcMoYmr6Bfpy7weLAzy97EDA/LrRTlGwc49fZSyVQ34T bX5W1vDN63qOIXHa0q+gvTiSxtJijBrrpJeM0Ezk= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:57 +0200 Message-Id: <20210131224702.8838-16-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 15/20] libcamera: pipeline: simple: Add output formats to Configuration 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Store the list of converter output formats in the Configuration structure, to be used to implement multi-stream support. As the Configuration structure grows bigger, avoid duplicating it in the formats_ map for each supported pixel format by storing it in a configs_ vector instead, and storing pointers only in the map. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 40 ++++++++++++++---------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index c44fa9ee28ed..6a8253101a61 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -159,6 +159,7 @@ public: uint32_t code; PixelFormat captureFormat; Size captureSize; + std::vector outputFormats; SizeRange outputSizes; }; @@ -167,7 +168,8 @@ public: std::list entities_; V4L2VideoDevice *video_; - std::map formats_; + std::vector configs_; + std::map formats_; }; class SimpleCameraConfiguration : public CameraConfiguration @@ -371,13 +373,6 @@ int SimpleCameraData::init() }) << " ]"; - /* - * Store the configuration in the formats_ map, mapping the - * PixelFormat to the corresponding configuration. Any - * previously stored value is overwritten, as the pipeline - * handler currently doesn't care about how a particular - * PixelFormat is achieved. - */ for (const auto &videoFormat : videoFormats) { PixelFormat pixelFormat = videoFormat.first.toPixelFormat(); if (!pixelFormat) @@ -389,23 +384,34 @@ int SimpleCameraData::init() config.captureSize = format.size; if (!converter) { + config.outputFormats = { pixelFormat }; config.outputSizes = config.captureSize; - formats_[pixelFormat] = config; - continue; + } else { + config.outputFormats = converter->formats(pixelFormat); + config.outputSizes = converter->sizes(format.size); } - config.outputSizes = converter->sizes(format.size); - - for (PixelFormat fmt : converter->formats(pixelFormat)) - formats_[fmt] = config; + configs_.push_back(config); } } - if (formats_.empty()) { + if (configs_.empty()) { LOG(SimplePipeline, Error) << "No valid configuration found"; return -EINVAL; } + /* + * Map the pixel formats to configurations. Any previously stored value + * is overwritten, as the pipeline handler currently doesn't care about + * how a particular PixelFormat is achieved. + */ + for (const Configuration &config : configs_) { + formats_[config.captureFormat] = &config; + + for (PixelFormat fmt : config.outputFormats) + formats_[fmt] = &config; + } + properties_ = sensor_->properties(); return 0; @@ -548,7 +554,7 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() status = Adjusted; } - pipeConfig_ = &it->second; + pipeConfig_ = it->second; if (!pipeConfig_->outputSizes.contains(cfg.size)) { LOG(SimplePipeline, Debug) << "Adjusting size from " << cfg.size.toString() @@ -614,7 +620,7 @@ CameraConfiguration *SimplePipelineHandler::generateConfiguration(Camera *camera std::inserter(formats, formats.end()), [](const auto &format) -> decltype(formats)::value_type { const PixelFormat &pixelFormat = format.first; - const Size &size = format.second.captureSize; + const Size &size = format.second->captureSize; return { pixelFormat, { size } }; }); From patchwork Sun Jan 31 22:46:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11095 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 A0C63BD808 for ; Sun, 31 Jan 2021 22:47:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 64E5D683F0; Sun, 31 Jan 2021 23:47:44 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DnljjMWc"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 68D8E683E0 for ; Sun, 31 Jan 2021 23:47:34 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id E6832E04; Sun, 31 Jan 2021 23:47:33 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133254; bh=68rngc+q0/iNYmw88fLcyYaXd5/7OCNEnogt2/chMEo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DnljjMWcOg8kGWeJfD6fkiE9TD4060iLCTWptBuiDGaCadrJ4iHh+QQBnnMzkpK/v w8FqNwwEFc9zL8HHQXRdJNG1TSHWpmzgHsI9DKaAzMj8HRNOSvNHrSf8dsVEtgliEy 2wOEbckMPd3Hz/l4YDw1hvTxHGwncEl8R97e+8Ao= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:58 +0200 Message-Id: <20210131224702.8838-17-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 16/20] libcamera: pipeline: simple: Move converter data to camera data 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Converter usage is a per-camera property, move its data to the SimpleCameraData class. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 46 ++++++++++++------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 6a8253101a61..9dffe64ee870 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -170,6 +170,10 @@ public: std::vector configs_; std::map formats_; + + std::vector> converterBuffers_; + bool useConverter_; + std::queue converterQueue_; }; class SimpleCameraConfiguration : public CameraConfiguration @@ -239,9 +243,6 @@ private: std::map subdevs_; std::unique_ptr converter_; - bool useConverter_; - std::vector> converterBuffers_; - std::queue converterQueue_; Camera *activeCamera_; }; @@ -692,9 +693,8 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) } /* Configure the converter if required. */ - useConverter_ = config->needConversion(); - - if (useConverter_) { + data->useConverter_ = config->needConversion(); + if (data->useConverter_) { StreamConfiguration inputCfg; inputCfg.pixelFormat = pipeConfig->captureFormat; inputCfg.size = pipeConfig->captureSize; @@ -726,7 +726,7 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * Export buffers on the converter or capture video node, depending on * whether the converter is used or not. */ - if (useConverter_) + if (data->useConverter_) return converter_->exportBuffers(0, count, buffers); else return data->video_->exportBuffers(count, buffers); @@ -739,8 +739,8 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *c unsigned int count = data->streams_[0].configuration().bufferCount; int ret; - if (useConverter_) - ret = video->allocateBuffers(count, &converterBuffers_); + if (data->useConverter_) + ret = video->allocateBuffers(count, &data->converterBuffers_); else ret = video->importBuffers(count); if (ret < 0) @@ -752,7 +752,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *c return ret; } - if (useConverter_) { + if (data->useConverter_) { ret = converter_->start(); if (ret < 0) { stop(camera); @@ -760,7 +760,7 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *c } /* Queue all internal buffers for capture. */ - for (std::unique_ptr &buffer : converterBuffers_) + for (std::unique_ptr &buffer : data->converterBuffers_) video->queueBuffer(buffer.get()); } @@ -774,13 +774,13 @@ void SimplePipelineHandler::stop(Camera *camera) SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; - if (useConverter_) + if (data->useConverter_) converter_->stop(); video->streamOff(); video->releaseBuffers(); - converterBuffers_.clear(); + data->converterBuffers_.clear(); activeCamera_ = nullptr; } @@ -800,8 +800,8 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) * If conversion is needed, push the buffer to the converter queue, it * will be handed to the converter in the capture completion handler. */ - if (useConverter_) { - converterQueue_.push(buffer); + if (data->useConverter_) { + data->converterQueue_.push(buffer); return 0; } @@ -977,7 +977,7 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) * point converting an erroneous buffer. */ if (buffer->metadata().status != FrameMetadata::FrameSuccess) { - if (useConverter_) { + if (data->useConverter_) { /* Requeue the buffer for capture. */ data->video_->queueBuffer(buffer); @@ -985,11 +985,11 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) * Get the next user-facing buffer to complete the * request. */ - if (converterQueue_.empty()) + if (data->converterQueue_.empty()) return; - buffer = converterQueue_.front(); - converterQueue_.pop(); + buffer = data->converterQueue_.front(); + data->converterQueue_.pop(); } Request *request = buffer->request(); @@ -1003,14 +1003,14 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) * conversion is needed. If there's no queued request, just requeue the * captured buffer for capture. */ - if (useConverter_) { - if (converterQueue_.empty()) { + if (data->useConverter_) { + if (data->converterQueue_.empty()) { data->video_->queueBuffer(buffer); return; } - FrameBuffer *output = converterQueue_.front(); - converterQueue_.pop(); + FrameBuffer *output = data->converterQueue_.front(); + data->converterQueue_.pop(); converter_->queueBuffers(buffer, { { 0, output } }); return; From patchwork Sun Jan 31 22:46:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11096 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 154C7BD808 for ; Sun, 31 Jan 2021 22:47:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D6B5B68405; Sun, 31 Jan 2021 23:47:46 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="P8+x1yF3"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D0601683FB for ; Sun, 31 Jan 2021 23:47:34 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5B0B71837; Sun, 31 Jan 2021 23:47:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133254; bh=M6YJCT5HNDQZjXGdDinaNuEli/O+JV1gaSEG9v1m1RA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=P8+x1yF3HqglBT11dDT6oc+tmSESlQsEF2N2rFts3Hzh/mQ44wn0Sio989k7eb09M TqReggXTuqUBGIyWzMRfMFadu85xH5e8xqwrQD8TUIDYKclNXnc+w6H4QS09aVT8sk jlv36YPhMuFpSrWgFSbFnHaGVY9w/4ya4PglT1/E= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:46:59 +0200 Message-Id: <20210131224702.8838-18-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 17/20] libcamera: pipeline: simple: Hardcode the number of internal buffers 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The number of internal buffers, used between the capture device and the converter, doesn't need to depend on the number of buffers allocated for the output stream of the pipeline. Hardcode it to a fixed value. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 9dffe64ee870..c987e1a0d9cb 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -228,6 +228,8 @@ protected: int queueRequestDevice(Camera *camera, Request *request) override; private: + static constexpr unsigned int kNumInternalBuffers = 3; + SimpleCameraData *cameraData(const Camera *camera) { return static_cast( @@ -699,7 +701,7 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) inputCfg.pixelFormat = pipeConfig->captureFormat; inputCfg.size = pipeConfig->captureSize; inputCfg.stride = captureFormat.planes[0].bpl; - inputCfg.bufferCount = cfg.bufferCount; + inputCfg.bufferCount = kNumInternalBuffers; ret = converter_->configure(inputCfg, { cfg }); if (ret < 0) { @@ -736,13 +738,20 @@ int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *c { SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; - unsigned int count = data->streams_[0].configuration().bufferCount; int ret; - if (data->useConverter_) - ret = video->allocateBuffers(count, &data->converterBuffers_); - else - ret = video->importBuffers(count); + if (data->useConverter_) { + /* + * When using the converter allocate a fixed number of internal + * buffers. + */ + ret = video->allocateBuffers(kNumInternalBuffers, + &data->converterBuffers_); + } else { + /* Otherwise, prepare for using buffers from the only stream. */ + Stream *stream = &data->streams_[0]; + ret = video->importBuffers(stream->configuration().bufferCount); + } if (ret < 0) return ret; From patchwork Sun Jan 31 22:47:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11097 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 8F3C8BD808 for ; Sun, 31 Jan 2021 22:47:47 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5304D683F7; Sun, 31 Jan 2021 23:47:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZKjDDOx4"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6BDAB683F0 for ; Sun, 31 Jan 2021 23:47:35 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id C19B41838; Sun, 31 Jan 2021 23:47:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133255; bh=c8JhsNI3GFEXO5I0AruI7LmSmioJBCP29agTnw6OfwA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZKjDDOx4hX34YNSAgYRqozEIU1j6YuIheZe1knDtcWhZ2f0O3dJjRzAvAtLy5HhvW D80Epu5WkJEM47mmrvM2VipN6QNZhsR2MCm2hOHev0iOxWXzaWJRwMNUu5lk3CP9pS 3Og32jtHq6oQ1O//Zus1Cmi6xMDya4fo1Tc87+nw= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:47:00 +0200 Message-Id: <20210131224702.8838-19-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 18/20] libcamera: pipeline: simple: Support configuration of multiple streams 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Extend the SimpleCameraConfiguration to support multiple streams, using the multi-stream capability of the SimpleConverter class. Wiring up multi-stream support in the other pipeline handler operations will come in further commits. To keep the code simple, require all streams to use the converter if any stream needs it. It would be possible to generate one stream without conversion (provided the format and size match what the capture device can generate), and this is left as a future optimization. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 174 ++++++++++++++--------- 1 file changed, 104 insertions(+), 70 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index c987e1a0d9cb..58e5f0d23139 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -538,62 +538,94 @@ CameraConfiguration::Status SimpleCameraConfiguration::validate() } /* Cap the number of entries to the available streams. */ - if (config_.size() > 1) { - config_.resize(1); + if (config_.size() > data_->streams_.size()) { + config_.resize(data_->streams_.size()); status = Adjusted; } - StreamConfiguration &cfg = config_[0]; - - /* Adjust the pixel format. */ - auto it = data_->formats_.find(cfg.pixelFormat); - if (it == data_->formats_.end()) - it = data_->formats_.begin(); - - PixelFormat pixelFormat = it->first; - if (cfg.pixelFormat != pixelFormat) { - LOG(SimplePipeline, Debug) << "Adjusting pixel format"; - cfg.pixelFormat = pixelFormat; - status = Adjusted; - } - - pipeConfig_ = it->second; - if (!pipeConfig_->outputSizes.contains(cfg.size)) { - LOG(SimplePipeline, Debug) - << "Adjusting size from " << cfg.size.toString() - << " to " << pipeConfig_->captureSize.toString(); - cfg.size = pipeConfig_->captureSize; - status = Adjusted; - } - - needConversion_ = cfg.pixelFormat != pipeConfig_->captureFormat - || cfg.size != pipeConfig_->captureSize; - - cfg.bufferCount = 3; - - /* Set the stride and frameSize. */ - if (!needConversion_) { - V4L2DeviceFormat format; - format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); - format.size = cfg.size; - - int ret = data_->video_->tryFormat(&format); - if (ret < 0) - return Invalid; - - cfg.stride = format.planes[0].bpl; - cfg.frameSize = format.planes[0].size; - - return status; + /* + * Pick a configuration for the pipeline based on the pixel format for + * the streams (ordered from highest to lowest priority). Default to + * the first pipeline configuration if no streams requests a supported + * pixel format. + */ + pipeConfig_ = data_->formats_.begin()->second; + + for (const StreamConfiguration &cfg : config_) { + auto it = data_->formats_.find(cfg.pixelFormat); + if (it != data_->formats_.end()) { + pipeConfig_ = it->second; + break; + } } + /* Adjust the requested streams. */ SimplePipelineHandler *pipe = static_cast(data_->pipe_); SimpleConverter *converter = pipe->converter(); - std::tie(cfg.stride, cfg.frameSize) = - converter->strideAndFrameSize(cfg.pixelFormat, cfg.size); - if (cfg.stride == 0) - return Invalid; + /* + * Enable usage of the converter when producing multiple streams, as + * the video capture device can't capture to multiple buffers. + * + * It is possible to produce up to one stream without conversion + * (provided the format and size match), at the expense of more complex + * buffer handling (including allocation of internal buffers to be used + * when a request doesn't contain a buffer for the stream that doesn't + * require any conversion, similar to raw capture use cases). This is + * left as a future improvement. + */ + needConversion_ = config_.size() > 1; + + for (unsigned int i = 0; i < config_.size(); ++i) { + StreamConfiguration &cfg = config_[i]; + + /* Adjust the pixel format and size. */ + auto it = std::find(pipeConfig_->outputFormats.begin(), + pipeConfig_->outputFormats.end(), + cfg.pixelFormat); + if (it == pipeConfig_->outputFormats.end()) + it = pipeConfig_->outputFormats.begin(); + + PixelFormat pixelFormat = *it; + if (cfg.pixelFormat != pixelFormat) { + LOG(SimplePipeline, Debug) << "Adjusting pixel format"; + cfg.pixelFormat = pixelFormat; + status = Adjusted; + } + + if (!pipeConfig_->outputSizes.contains(cfg.size)) { + LOG(SimplePipeline, Debug) + << "Adjusting size from " << cfg.size.toString() + << " to " << pipeConfig_->captureSize.toString(); + cfg.size = pipeConfig_->captureSize; + status = Adjusted; + } + + if (cfg.pixelFormat != pipeConfig_->captureFormat || + cfg.size != pipeConfig_->captureSize) + needConversion_ = true; + + /* Set the stride, frameSize and bufferCount. */ + if (needConversion_) { + std::tie(cfg.stride, cfg.frameSize) = + converter->strideAndFrameSize(cfg.pixelFormat, cfg.size); + if (cfg.stride == 0) + return Invalid; + } else { + V4L2DeviceFormat format; + format.fourcc = data_->video_->toV4L2PixelFormat(cfg.pixelFormat); + format.size = cfg.size; + + int ret = data_->video_->tryFormat(&format); + if (ret < 0) + return Invalid; + + cfg.stride = format.planes[0].bpl; + cfg.frameSize = format.planes[0].size; + } + + cfg.bufferCount = 3; + } return status; } @@ -628,16 +660,18 @@ CameraConfiguration *SimplePipelineHandler::generateConfiguration(Camera *camera }); /* - * Create the stream configuration. Take the first entry in the formats + * Create the stream configurations. Take the first entry in the formats * map as the default, for lack of a better option. * * \todo Implement a better way to pick the default format */ - StreamConfiguration cfg{ StreamFormats{ formats } }; - cfg.pixelFormat = formats.begin()->first; - cfg.size = formats.begin()->second[0].max; + for ([[maybe_unused]] StreamRole role : roles) { + StreamConfiguration cfg{ StreamFormats{ formats } }; + cfg.pixelFormat = formats.begin()->first; + cfg.size = formats.begin()->second[0].max; - config->addConfiguration(cfg); + config->addConfiguration(cfg); + } config->validate(); @@ -650,7 +684,6 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) static_cast(c); SimpleCameraData *data = cameraData(camera); V4L2VideoDevice *video = data->video_; - StreamConfiguration &cfg = config->at(0); int ret; /* @@ -694,28 +727,29 @@ int SimplePipelineHandler::configure(Camera *camera, CameraConfiguration *c) return -EINVAL; } - /* Configure the converter if required. */ + /* Configure the converter if needed. */ + std::vector> outputCfgs; data->useConverter_ = config->needConversion(); - if (data->useConverter_) { - StreamConfiguration inputCfg; - inputCfg.pixelFormat = pipeConfig->captureFormat; - inputCfg.size = pipeConfig->captureSize; - inputCfg.stride = captureFormat.planes[0].bpl; - inputCfg.bufferCount = kNumInternalBuffers; - ret = converter_->configure(inputCfg, { cfg }); - if (ret < 0) { - LOG(SimplePipeline, Error) - << "Unable to configure converter"; - return ret; - } + for (unsigned int i = 0; i < config->size(); ++i) { + StreamConfiguration &cfg = config->at(i); - LOG(SimplePipeline, Debug) << "Using format converter"; + cfg.setStream(&data->streams_[i]); + + if (data->useConverter_) + outputCfgs.push_back(cfg); } - cfg.setStream(&data->streams_[0]); + if (outputCfgs.empty()) + return 0; - return 0; + StreamConfiguration inputCfg; + inputCfg.pixelFormat = pipeConfig->captureFormat; + inputCfg.size = pipeConfig->captureSize; + inputCfg.stride = captureFormat.planes[0].bpl; + inputCfg.bufferCount = kNumInternalBuffers; + + return converter_->configure(inputCfg, outputCfgs); } int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, From patchwork Sun Jan 31 22:47:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11098 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 0D71BBD808 for ; Sun, 31 Jan 2021 22:47:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CC293683EF; Sun, 31 Jan 2021 23:47:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="sqBTzKzL"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E13E2683FF for ; Sun, 31 Jan 2021 23:47:35 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6669315CF; Sun, 31 Jan 2021 23:47:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133255; bh=RfDpVTg62cT7shPfh0FX8KWfZyRzyHyYDgH3Dy37xWE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sqBTzKzLvrIx/0M0H8Nmt3pzV5fQaahHiQg/FWyDP82GVt1uyV9sGavgegBSntdOf hUEulFsJaZpY4qd9BqbvzkTGS8tlGJlnCnm77h25Gef/QmlRQkyUdsivJrUaxOXEmH FpekhaCLuSLb3ePRQXIFtVe9tZaCEGboFlHL4/x8= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:47:01 +0200 Message-Id: <20210131224702.8838-20-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 19/20] libcamera: pipeline: simple: Support usage of multiple streams 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" To extend the multi-stream support to runtime operation of the pipeline, expand the converter queue to store multiple output buffers, and update the request queuing and buffer completion handlers accordingly. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 93 ++++++++++++++---------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 58e5f0d23139..55a5528611c8 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -173,7 +173,7 @@ public: std::vector> converterBuffers_; bool useConverter_; - std::queue converterQueue_; + std::queue> converterQueue_; }; class SimpleCameraConfiguration : public CameraConfiguration @@ -762,10 +762,12 @@ int SimplePipelineHandler::exportFrameBuffers(Camera *camera, Stream *stream, * Export buffers on the converter or capture video node, depending on * whether the converter is used or not. */ - if (data->useConverter_) - return converter_->exportBuffers(0, count, buffers); - else + if (data->useConverter_) { + unsigned int index = stream - &data->streams_.front(); + return converter_->exportBuffers(index, count, buffers); + } else { return data->video_->exportBuffers(count, buffers); + } } int SimplePipelineHandler::start(Camera *camera, [[maybe_unused]] ControlList *controls) @@ -830,25 +832,30 @@ void SimplePipelineHandler::stop(Camera *camera) int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) { SimpleCameraData *data = cameraData(camera); - Stream *stream = &data->streams_[0]; + int ret; - FrameBuffer *buffer = request->findBuffer(stream); - if (!buffer) { - LOG(SimplePipeline, Error) - << "Attempt to queue request with invalid stream"; - return -ENOENT; - } + std::map buffers; - /* - * If conversion is needed, push the buffer to the converter queue, it - * will be handed to the converter in the capture completion handler. - */ - if (data->useConverter_) { - data->converterQueue_.push(buffer); - return 0; + for (auto &[stream, buffer] : request->buffers()) { + /* + * If conversion is needed, push the buffer to the converter + * queue, it will be handed to the converter in the capture + * completion handler. + */ + if (data->useConverter_) { + unsigned int index = stream - &data->streams_.front(); + buffers.emplace(index, buffer); + } else { + ret = data->video_->queueBuffer(buffer); + if (ret < 0) + return ret; + } } - return data->video_->queueBuffer(buffer); + if (data->useConverter_) + data->converterQueue_.push(std::move(buffers)); + + return 0; } /* ----------------------------------------------------------------------------- @@ -1020,24 +1027,34 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) * point converting an erroneous buffer. */ if (buffer->metadata().status != FrameMetadata::FrameSuccess) { - if (data->useConverter_) { - /* Requeue the buffer for capture. */ - data->video_->queueBuffer(buffer); + if (!data->useConverter_) { + /* No conversion, just complete the request. */ + Request *request = buffer->request(); + completeBuffer(request, buffer); + completeRequest(request); + return; + } + + /* + * The converter is in use. Requeue the internal buffer for + * capture, and complete the request with all the user-facing + * buffers. + */ + data->video_->queueBuffer(buffer); - /* - * Get the next user-facing buffer to complete the - * request. - */ - if (data->converterQueue_.empty()) - return; + if (data->converterQueue_.empty()) + return; - buffer = data->converterQueue_.front(); - data->converterQueue_.pop(); + Request *request = nullptr; + for (auto &item : data->converterQueue_.front()) { + FrameBuffer *outputBuffer = item.second; + request = outputBuffer->request(); + completeBuffer(request, outputBuffer); } + data->converterQueue_.pop(); - Request *request = buffer->request(); - completeBuffer(request, buffer); - completeRequest(request); + if (request) + completeRequest(request); return; } @@ -1052,10 +1069,8 @@ void SimplePipelineHandler::bufferReady(FrameBuffer *buffer) return; } - FrameBuffer *output = data->converterQueue_.front(); + converter_->queueBuffers(buffer, data->converterQueue_.front()); data->converterQueue_.pop(); - - converter_->queueBuffers(buffer, { { 0, output } }); return; } @@ -1078,10 +1093,10 @@ void SimplePipelineHandler::converterOutputDone(FrameBuffer *buffer) { ASSERT(activeCamera_); - /* Complete the request. */ + /* Complete the buffer and the request. */ Request *request = buffer->request(); - completeBuffer(request, buffer); - completeRequest(request); + if (completeBuffer(request, buffer)) + completeRequest(request); } REGISTER_PIPELINE_HANDLER(SimplePipelineHandler) From patchwork Sun Jan 31 22:47:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11099 X-Patchwork-Delegate: laurent.pinchart@ideasonboard.com 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 8756EBD808 for ; Sun, 31 Jan 2021 22:47:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 53FCD6840E; Sun, 31 Jan 2021 23:47:48 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="hcoGpm93"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9E342683FF for ; Sun, 31 Jan 2021 23:47:37 +0100 (CET) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D12531850; Sun, 31 Jan 2021 23:47:35 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1612133256; bh=veZtHrkAHVBklEY0+Sz5xGy72xisPX77x1nnWAKUZQE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hcoGpm93r3xZdktSxVEguXJPxzX6zVa4Y0szpFtEEJiHJaxqj8CZqSL4amDWcsBez r/kQkophXYXonp0NzfsgO3lOCt7aRjViaw08RrD0obcHamnq8qEukvv9anc/z0/YE6 pdj0VKE5GmzYKCeqMYpgMf4o1nwfZajCDCBQFFsI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Mon, 1 Feb 2021 00:47:02 +0200 Message-Id: <20210131224702.8838-21-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> References: <20210131224702.8838-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH 20/20] libcamera: pipeline: simple: Enable multiple streams for compatible devices 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: , Cc: Phi-Bang Nguyen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Allow support for multiple streams on a per-device basis. The decision should be made based on the ability of the converter to run multiple times within the duration of one frame. Hardcode it in SimplePipelineInfo for now. We may later compute the number of supported streams dynamically based on the requested configuration, using converter bandwidth information instead of a hardcoded fixed value. All platforms are currently limited to a single stream until they get successfully tested with multiple streams. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Kieran Bingham --- src/libcamera/pipeline/simple/simple.cpp | 39 +++++++++++++----------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index 55a5528611c8..4a8a7ed24960 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -126,14 +126,15 @@ class SimplePipelineHandler; struct SimplePipelineInfo { const char *driver; const char *converter; + unsigned int numStreams; }; namespace { static const SimplePipelineInfo supportedDevices[] = { - { "imx7-csi", "pxp" }, - { "qcom-camss", nullptr }, - { "sun6i-csi", nullptr }, + { "imx7-csi", "pxp", 1 }, + { "qcom-camss", nullptr, 1 }, + { "sun6i-csi", nullptr, 1 }, }; } /* namespace */ @@ -141,7 +142,9 @@ static const SimplePipelineInfo supportedDevices[] = { class SimpleCameraData : public CameraData { public: - SimpleCameraData(SimplePipelineHandler *pipe, MediaEntity *sensor); + SimpleCameraData(SimplePipelineHandler *pipe, + const SimplePipelineInfo *info, + MediaEntity *sensor); bool isValid() const { return sensor_ != nullptr; } @@ -254,13 +257,12 @@ private: */ SimpleCameraData::SimpleCameraData(SimplePipelineHandler *pipe, + const SimplePipelineInfo *info, MediaEntity *sensor) - : CameraData(pipe) + : CameraData(pipe), streams_(info->numStreams) { int ret; - streams_.resize(1); - /* * Walk the pipeline towards the video node and store all entities * along the way. @@ -864,25 +866,26 @@ int SimplePipelineHandler::queueRequestDevice(Camera *camera, Request *request) bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) { + const SimplePipelineInfo *info = nullptr; MediaDevice *converter = nullptr; - for (const SimplePipelineInfo &info : supportedDevices) { - DeviceMatch dm(info.driver); + for (const SimplePipelineInfo &inf : supportedDevices) { + DeviceMatch dm(inf.driver); media_ = acquireMediaDevice(enumerator, dm); - if (!media_) - continue; - - if (!info.converter) + if (media_) { + info = &inf; break; - - DeviceMatch converterMatch(info.converter); - converter = acquireMediaDevice(enumerator, converterMatch); - break; + } } if (!media_) return false; + if (info->converter) { + DeviceMatch converterMatch(info->converter); + converter = acquireMediaDevice(enumerator, converterMatch); + } + /* Locate the sensors. */ std::vector sensors; @@ -926,7 +929,7 @@ bool SimplePipelineHandler::match(DeviceEnumerator *enumerator) for (MediaEntity *sensor : sensors) { std::unique_ptr data = - std::make_unique(this, sensor); + std::make_unique(this, info, sensor); if (!data->isValid()) { LOG(SimplePipeline, Error) << "No valid pipeline for sensor '"