From patchwork Fri Mar 14 20:29:29 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22961 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 1CB97C32F7 for ; Fri, 14 Mar 2025 20:30:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4FB6468946; Fri, 14 Mar 2025 21:30:08 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="HMNFeEIH"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 36DAA68777 for ; Fri, 14 Mar 2025 21:30:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984203; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/S2xWvVwFqyo0um4LJ5bkgVbFOmwXjqTH6RNtUr9J2s=; b=HMNFeEIHNowYMAMtvLc3kO7vQXhWggyA3+37PrxnguLTdYKvo6Mpm7SRMnW6LXXJyExB2e dsd5OglDG06OVm9t+srJuyehu2iq3rM4k7yvWkwekYko3m0fhBvorX2dJgwOGHs38nLc2p 1WSjPBU4yjN5iruJRs2EiOb/sk+5b88= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-281-MZsgWWWCPHSpzsJ45JvXeA-1; Fri, 14 Mar 2025 16:30:00 -0400 X-MC-Unique: MZsgWWWCPHSpzsJ45JvXeA-1 X-Mimecast-MFC-AGG-ID: MZsgWWWCPHSpzsJ45JvXeA_1741984199 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8A7F419560AB; Fri, 14 Mar 2025 20:29:59 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 07BD81954B3C; Fri, 14 Mar 2025 20:29:57 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 1/7] apps: common: Fix flipped error condition Date: Fri, 14 Mar 2025 21:29:29 +0100 Message-ID: <20250314202943.112109-2-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 2z77uOCstor1Gg0yEZOn6utYs-BVa_v4kefkIYV42_I_1741984199 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When OptionsParser::childOption encounters an error, it returns nullptr and the corresponding option. The check for a nested parent checks for an error erroneously, leading not only to a wrong behaviour in case there's no error but also to a segmentation error in case of error due to `options' being set to nullptr and accessed later. Signed-off-by: Milan Zamazal --- src/apps/common/options.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/common/options.cpp b/src/apps/common/options.cpp index cae193cc..29a5d9c7 100644 --- a/src/apps/common/options.cpp +++ b/src/apps/common/options.cpp @@ -1095,7 +1095,7 @@ OptionsParser::childOption(const Option *parent, Options *options) std::tie(options, error) = childOption(parent->parent, options); /* Propagate the error all the way back up the call stack. */ - if (!error) + if (error) return { options, error }; } From patchwork Fri Mar 14 20:29:30 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22962 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 36996C32F9 for ; Fri, 14 Mar 2025 20:30:13 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2AA316894C; Fri, 14 Mar 2025 21:30:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="Z6IclDZm"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 1C7D56893D for ; Fri, 14 Mar 2025 21:30:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984204; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/6VRDgNZ6FiWUtw57/iZciACoWNfEv5DGYZ7SovU8/E=; b=Z6IclDZmi17W7h/p9VpGduPTTSrJPSnBxH3VjntJntfz4UW3mCOJ+i6d2Tcd7McL4Ywu0b oBt8oCxM7m2vS5DTZ2lcSJb/Yt36I8OIcPRcRqZfVR8NB1TK42/E9nfRa2l4vDYodnmfMJ 9/8Y6H8SEWzl3faXanxok5Bg4s2VHxU= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-626-dXr0atADNBq5vIBzX6xOSQ-1; Fri, 14 Mar 2025 16:30:02 -0400 X-MC-Unique: dXr0atADNBq5vIBzX6xOSQ-1 X-Mimecast-MFC-AGG-ID: dXr0atADNBq5vIBzX6xOSQ_1741984201 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 939611801A1A; Fri, 14 Mar 2025 20:30:01 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2F1901954B32; Fri, 14 Mar 2025 20:29:59 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 2/7] apps: cam: Formatting fixes Date: Fri, 14 Mar 2025 21:29:30 +0100 Message-ID: <20250314202943.112109-3-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: rhWjfO4Pad3syw2orXQOrcZ8fF1Qhha6cWqktCu4bOo_1741984201 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Let's make the autoformatter happier. Signed-off-by: Milan Zamazal --- src/apps/cam/camera_session.cpp | 7 ++++--- src/apps/cam/kms_sink.cpp | 9 +++++---- src/apps/cam/main.cpp | 3 ++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 9e934827..937a56b5 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -5,6 +5,8 @@ * Camera capture session */ +#include "camera_session.h" + #include #include #include @@ -16,7 +18,6 @@ #include "../common/event_loop.h" #include "../common/stream_options.h" -#include "camera_session.h" #include "capture_script.h" #include "file_sink.h" #ifdef HAVE_KMS @@ -248,8 +249,8 @@ int CameraSession::start() streamNames_.clear(); for (unsigned int index = 0; index < config_->size(); ++index) { StreamConfiguration &cfg = config_->at(index); - streamNames_[cfg.stream()] = "cam" + std::to_string(cameraIndex_) - + "-stream" + std::to_string(index); + streamNames_[cfg.stream()] = "cam" + std::to_string(cameraIndex_) + + "-stream" + std::to_string(index); } camera_->requestCompleted.connect(this, &CameraSession::requestComplete); diff --git a/src/apps/cam/kms_sink.cpp b/src/apps/cam/kms_sink.cpp index aa9459cf..def7878b 100644 --- a/src/apps/cam/kms_sink.cpp +++ b/src/apps/cam/kms_sink.cpp @@ -7,8 +7,8 @@ #include "kms_sink.h" -#include #include +#include #include #include #include @@ -122,7 +122,7 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config) for (const DRM::Mode &mode : modes) { unsigned int modeArea = mode.hdisplay * mode.vdisplay; unsigned int distance = modeArea > cfgArea ? modeArea - cfgArea - : cfgArea - modeArea; + : cfgArea - modeArea; if (distance < bestDistance) { mode_ = &mode; @@ -395,8 +395,9 @@ bool KMSSink::setupComposition(DRM::FrameBuffer *drmBuffer) /* 1. Scale the frame buffer to full screen, preserving aspect ratio. */ libcamera::Rectangle src = framebuffer; - libcamera::Rectangle dst = display.size().boundedToAspectRatio(framebuffer.size()) - .centeredTo(display.center()); + libcamera::Rectangle dst = display.size() + .boundedToAspectRatio(framebuffer.size()) + .centeredTo(display.center()); if (testModeSet(drmBuffer, src, dst)) { std::cout << "KMS: full-screen scaled output, square pixels" diff --git a/src/apps/cam/main.cpp b/src/apps/cam/main.cpp index 460dbc81..fa266eca 100644 --- a/src/apps/cam/main.cpp +++ b/src/apps/cam/main.cpp @@ -5,6 +5,8 @@ * cam - The libcamera swiss army knife */ +#include "main.h" + #include #include #include @@ -19,7 +21,6 @@ #include "../common/stream_options.h" #include "camera_session.h" -#include "main.h" using namespace libcamera; From patchwork Fri Mar 14 20:29:31 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22963 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 94916C32F7 for ; Fri, 14 Mar 2025 20:30:15 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2D2B26894C; Fri, 14 Mar 2025 21:30:15 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="BbrNBAlI"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id ECEA468949 for ; Fri, 14 Mar 2025 21:30:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984207; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+1eeTxAc3etLJP48plHj1awILyyANHtp9dmw2aUu+as=; b=BbrNBAlI1MU2WSsNVPOdQdC8e2vyeJv45hrRICayC9eraWFOuzoZvuMj60bbfG18g6F0EK WNIzxD1oyFHRbbIMaoQeMZTctozVyYkYeH6ccbgUtfZWPN1voljBR5xDAEceM5/E9QnBaw 611LhJp1uG9ZdYJprSuIyWwu1d5oY3k= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-692-HWyx7sKGNUSMAiteJ1nRFg-1; Fri, 14 Mar 2025 16:30:04 -0400 X-MC-Unique: HWyx7sKGNUSMAiteJ1nRFg-1 X-Mimecast-MFC-AGG-ID: HWyx7sKGNUSMAiteJ1nRFg_1741984203 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8DFF51956087; Fri, 14 Mar 2025 20:30:03 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 066E01954B32; Fri, 14 Mar 2025 20:30:01 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 3/7] apps: cam: Remove unused imports Date: Fri, 14 Mar 2025 21:29:31 +0100 Message-ID: <20250314202943.112109-4-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: bvYCUe_3hwmK8JWACrL4NNNd22nopeOdKmbPOqF_EgU_1741984203 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Some imports in `cam' source files are reported by LSP as not directly used, let's remove them. Signed-off-by: Milan Zamazal --- src/apps/cam/kms_sink.cpp | 1 - src/apps/cam/main.cpp | 1 - src/apps/cam/sdl_sink.cpp | 4 ---- 3 files changed, 6 deletions(-) diff --git a/src/apps/cam/kms_sink.cpp b/src/apps/cam/kms_sink.cpp index def7878b..6490a5c0 100644 --- a/src/apps/cam/kms_sink.cpp +++ b/src/apps/cam/kms_sink.cpp @@ -7,7 +7,6 @@ #include "kms_sink.h" -#include #include #include #include diff --git a/src/apps/cam/main.cpp b/src/apps/cam/main.cpp index fa266eca..9d84ef8e 100644 --- a/src/apps/cam/main.cpp +++ b/src/apps/cam/main.cpp @@ -8,7 +8,6 @@ #include "main.h" #include -#include #include #include #include diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp index 8355dd5e..e8a54f7a 100644 --- a/src/apps/cam/sdl_sink.cpp +++ b/src/apps/cam/sdl_sink.cpp @@ -9,11 +9,7 @@ #include #include -#include #include -#include -#include -#include #include #include From patchwork Fri Mar 14 20:29:32 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22964 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 BD2C9C32F7 for ; Fri, 14 Mar 2025 20:30:17 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4D52768956; Fri, 14 Mar 2025 21:30:17 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="QlWpuQ4T"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 112576894E for ; Fri, 14 Mar 2025 21:30:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984210; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mTa4WA1lPtOXS3wfmXBW4JQBLLvsUIU3xGZw/Ji+tP0=; b=QlWpuQ4T/gZ7EJD5pWLuP4csjDe718A3Sd9qikJEWwb+oTwNAY6H+tUe8YhpSbAxZME3ro YaYWUIdpgT9TohJDHs2HBWp+oEhapPIERPrhqcZLryK2TewMgCknzcKmrAqWLMZ4tzqQOP 7FKYYpCLwiu4yZ0CZgDzbEkyLoIKeyg= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-142-a5RqhAKANmipHIMP1M6xxw-1; Fri, 14 Mar 2025 16:30:06 -0400 X-MC-Unique: a5RqhAKANmipHIMP1M6xxw-1 X-Mimecast-MFC-AGG-ID: a5RqhAKANmipHIMP1M6xxw_1741984205 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 885C819560AF; Fri, 14 Mar 2025 20:30:05 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 02C001954B32; Fri, 14 Mar 2025 20:30:03 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 4/7] apps: cam: Add support for multiple sinks Date: Fri, 14 Mar 2025 21:29:32 +0100 Message-ID: <20250314202943.112109-5-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 1nUbPO54ro-I-hizt4eCRgpWSZ63TXjSRk-irIx56SI_1741984205 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" It would be useful if cam supported output to different sinks when run with multiple streams. For example, a processed stream could be displayed while a raw stream would be sent to files. Or a processed stream could be output to PPM files while a raw stream to raw files. Let's start with replacing the single CameraSession::sink_ with a vector of sinks_. We put just the default sink there for now, more functionality will be added in followup patches. Signed-off-by: Milan Zamazal --- src/apps/cam/camera_session.cpp | 51 +++++++++++++++++++++------------ src/apps/cam/camera_session.h | 2 +- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 937a56b5..54073cdf 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -20,6 +20,7 @@ #include "capture_script.h" #include "file_sink.h" +#include "frame_sink.h" #ifdef HAVE_KMS #include "kms_sink.h" #endif @@ -255,14 +256,17 @@ int CameraSession::start() camera_->requestCompleted.connect(this, &CameraSession::requestComplete); + sinks_.clear(); + std::unique_ptr defaultSink; #ifdef HAVE_KMS if (options_.isSet(OptDisplay)) - sink_ = std::make_unique(options_[OptDisplay].toString()); + defaultSink = + std::make_unique(options_[OptDisplay].toString()); #endif #ifdef HAVE_SDL if (options_.isSet(OptSDL)) - sink_ = std::make_unique(); + defaultSink = std::make_unique(); #endif if (options_.isSet(OptFile)) { @@ -275,18 +279,21 @@ int CameraSession::start() return ret; } - sink_ = std::move(sink); + defaultSink = std::move(sink); } - if (sink_) { - ret = sink_->configure(*config_); + if (defaultSink) + sinks_.push_back(std::move(defaultSink)); + + for (auto &sink : sinks_) { + ret = sink->configure(*config_); if (ret < 0) { std::cout << "Failed to configure frame sink" << std::endl; return ret; } - sink_->requestProcessed.connect(this, &CameraSession::sinkRelease); + sink->requestProcessed.connect(this, &CameraSession::sinkRelease); } allocator_ = std::make_unique(camera_); @@ -300,13 +307,14 @@ void CameraSession::stop() if (ret) std::cout << "Failed to stop capture" << std::endl; - if (sink_) { - ret = sink_->stop(); + for (auto &sink : sinks_) { + ret = sink->stop(); if (ret) std::cout << "Failed to stop frame sink" << std::endl; } - sink_.reset(); + for (auto &sink : sinks_) + sink.reset(); requests_.clear(); @@ -355,15 +363,15 @@ int CameraSession::startCapture() return ret; } - if (sink_) - sink_->mapBuffer(buffer.get()); + for (auto &sink : sinks_) + sink->mapBuffer(buffer.get()); } requests_.push_back(std::move(request)); } - if (sink_) { - ret = sink_->start(); + for (auto &sink : sinks_) { + ret = sink->start(); if (ret) { std::cout << "Failed to start frame sink" << std::endl; return ret; @@ -373,8 +381,8 @@ int CameraSession::startCapture() ret = camera_->start(); if (ret) { std::cout << "Failed to start capture" << std::endl; - if (sink_) - sink_->stop(); + for (auto &sink : sinks_) + sink->stop(); return ret; } @@ -383,8 +391,8 @@ int CameraSession::startCapture() if (ret < 0) { std::cerr << "Can't queue request" << std::endl; camera_->stop(); - if (sink_) - sink_->stop(); + for (auto &sink : sinks_) + sink->stop(); return ret; } } @@ -471,9 +479,14 @@ void CameraSession::processRequest(Request *request) } } - if (sink_) { - if (!sink_->processRequest(request)) + for (auto &sink : sinks_) { + if (!sink->processRequest(request)) { + /* + * \todo What happens with the other sinks when the whole request + * gets requeued? + */ requeue = false; + } } std::cout << info.str() << std::endl; diff --git a/src/apps/cam/camera_session.h b/src/apps/cam/camera_session.h index 4442fd9b..056091e5 100644 --- a/src/apps/cam/camera_session.h +++ b/src/apps/cam/camera_session.h @@ -64,7 +64,7 @@ private: std::unique_ptr script_; std::map streamNames_; - std::unique_ptr sink_; + std::vector> sinks_; unsigned int cameraIndex_; uint64_t last_; From patchwork Fri Mar 14 20:29:33 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22965 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 1D22DC32F9 for ; Fri, 14 Mar 2025 20:30:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3A0AA68952; Fri, 14 Mar 2025 21:30:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="i+cF/RN6"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C6CAB6894A for ; Fri, 14 Mar 2025 21:30:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984209; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vgaUImN0wCsNk1ynC8rrqJWeH66K7Oy23vSbw7kLXeo=; b=i+cF/RN606cwrrezQF1INt+u1eXOYgUiSpmrfoxdOS7PGLFWb2GWYYEvJOaKuwJnE0h1l9 vNbNzenmhXQVcj7MPNwgqIJomKzb8/NPdOLnkFRohSEvC6LZIq0qbMF6nIt4l2idqJkF8i 35TMzagWIVHcyaUduU0NxaP6EEuzt5A= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-294-vcXUUOfkN5WuCghSZnxDaw-1; Fri, 14 Mar 2025 16:30:08 -0400 X-MC-Unique: vcXUUOfkN5WuCghSZnxDaw-1 X-Mimecast-MFC-AGG-ID: vcXUUOfkN5WuCghSZnxDaw_1741984207 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 877F1195608B; Fri, 14 Mar 2025 20:30:07 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 006621954B32; Fri, 14 Mar 2025 20:30:05 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 5/7] apps: cam: Report error on multiple default sinks Date: Fri, 14 Mar 2025 21:29:33 +0100 Message-ID: <20250314202943.112109-6-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: lUAg-kvS8NiekhtfwHWYg5BTSU_GInB7X9ArUL-znhY_1741984207 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Multiple default sinks are not really supported, if more than one sink is present then the last one wins and the other ones are just created but not used actually. Let's check for this and report an error in such a case. Signed-off-by: Milan Zamazal --- src/apps/cam/camera_session.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 54073cdf..b1f5209d 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -265,11 +265,21 @@ int CameraSession::start() #endif #ifdef HAVE_SDL - if (options_.isSet(OptSDL)) + if (options_.isSet(OptSDL)) { + if (defaultSink) { + std::cerr << "Multiple default sinks not allowed" << std::endl; + return -EINVAL; + } defaultSink = std::make_unique(); + } #endif if (options_.isSet(OptFile)) { + if (defaultSink) { + std::cerr << "Multiple default sinks not allowed" << std::endl; + return -EINVAL; + } + std::unique_ptr sink = std::make_unique(camera_.get(), streamNames_); From patchwork Fri Mar 14 20:29:34 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22966 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 40460C32F7 for ; Fri, 14 Mar 2025 20:30:20 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5FFE968955; Fri, 14 Mar 2025 21:30:19 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="PpelEAWJ"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EA94368950 for ; Fri, 14 Mar 2025 21:30:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984212; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9fwSjLBWr1oMZz3V0RPmlAXDkKTDuWUYQerCdEJ/8TE=; b=PpelEAWJa7BONBBKmgkM9ltEm7iWPLerDuzSnIjSKUO5oJYKUDoRWr80Aw2OBieL4mloOY g3vTII8g2rB7A8wo0ZX8wAdZgprI2dpzNrLWlyf8+gnZyCa5p7gTyIClfP741yNV6RDQd7 oFukH/VJBfjPh7vy7lZ3UOKLacyuONY= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-34-A9Oi_dspMUG95FoA1n3thQ-1; Fri, 14 Mar 2025 16:30:10 -0400 X-MC-Unique: A9Oi_dspMUG95FoA1n3thQ-1 X-Mimecast-MFC-AGG-ID: A9Oi_dspMUG95FoA1n3thQ_1741984209 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 82C21180025E; Fri, 14 Mar 2025 20:30:09 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 07CB01954B32; Fri, 14 Mar 2025 20:30:07 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 6/7] apps: cam: Track sink streams Date: Fri, 14 Mar 2025 21:29:34 +0100 Message-ID: <20250314202943.112109-7-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: _0zZGioEsa_W0p5eNcFGKEd2n3KNY8CV_Q6aO4B2Imc_1741984209 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" In order to support different sinks for different streams, we must track the relationship between sinks and streams. Let's track the corresponding streams in FrameSink. Different kinds of sinks use different approaches to multiple streams; keeping the sinks to handle that this way is the simplest. Let's add FrameSink class member and some utility methods for the purpose. We still create only one, the default, sink, so all the streams are added to the default sink unconditionally. This will be changed in a followup patch. Operations on each given sink are applied only for streams the sink contains. Signed-off-by: Milan Zamazal --- src/apps/cam/camera_session.cpp | 9 ++++++++- src/apps/cam/file_sink.cpp | 3 ++- src/apps/cam/frame_sink.cpp | 14 ++++++++++++++ src/apps/cam/frame_sink.h | 26 ++++++++++++++++++++++++++ src/apps/cam/kms_sink.cpp | 8 +++++++- src/apps/cam/sdl_sink.cpp | 15 ++++++++------- 6 files changed, 65 insertions(+), 10 deletions(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index b1f5209d..5124029b 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -292,6 +292,12 @@ int CameraSession::start() defaultSink = std::move(sink); } + for (unsigned int i = 0; i < config_->size(); i++) { + const StreamConfiguration &cfg = config_->at(i); + if (defaultSink) + defaultSink->addStream(cfg.stream()); + } + if (defaultSink) sinks_.push_back(std::move(defaultSink)); @@ -374,7 +380,8 @@ int CameraSession::startCapture() } for (auto &sink : sinks_) - sink->mapBuffer(buffer.get()); + if (sink->assignedStream(stream)) + sink->mapBuffer(buffer.get()); } requests_.push_back(std::move(request)); diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp index 76e21db9..9ef4011b 100644 --- a/src/apps/cam/file_sink.cpp +++ b/src/apps/cam/file_sink.cpp @@ -96,7 +96,8 @@ void FileSink::mapBuffer(FrameBuffer *buffer) bool FileSink::processRequest(Request *request) { for (auto [stream, buffer] : request->buffers()) - writeBuffer(stream, buffer, request->metadata()); + if (assignedStream(stream)) + writeBuffer(stream, buffer, request->metadata()); return true; } diff --git a/src/apps/cam/frame_sink.cpp b/src/apps/cam/frame_sink.cpp index 68d6f2c1..51c85124 100644 --- a/src/apps/cam/frame_sink.cpp +++ b/src/apps/cam/frame_sink.cpp @@ -7,6 +7,8 @@ #include "frame_sink.h" +#include + /** * \class FrameSink * \brief Abstract class to model a consumer of frames @@ -65,3 +67,15 @@ int FrameSink::stop() * \return True if the request has been processed synchronously, false if * processing has been queued */ + +const libcamera::StreamConfiguration &FrameSink::findConfiguration( + const libcamera::CameraConfiguration &config) +{ + for (unsigned int i = 0; i < config.size(); i++) + if (assignedStream(config.at(i).stream())) + return config.at(i); + + /* This should never happen. */ + std::cerr << "No camera configuration for frame sink" << std::endl; + return config.at(0); +} diff --git a/src/apps/cam/frame_sink.h b/src/apps/cam/frame_sink.h index 11105c6c..c51db775 100644 --- a/src/apps/cam/frame_sink.h +++ b/src/apps/cam/frame_sink.h @@ -7,8 +7,13 @@ #pragma once +#include + #include +#include +#include + namespace libcamera { class CameraConfiguration; class FrameBuffer; @@ -27,6 +32,27 @@ public: virtual int start(); virtual int stop(); + void addStream(libcamera::Stream *const stream) + { + streams_.push_back(stream); + } + + bool assignedStream(const libcamera::Stream *const stream) + { + return std::find(streams_.begin(), streams_.end(), stream) != streams_.end(); + } + + bool empty() + { + return streams_.empty(); + } + virtual bool processRequest(libcamera::Request *request) = 0; libcamera::Signal requestProcessed; + +protected: + const libcamera::StreamConfiguration &findConfiguration( + const libcamera::CameraConfiguration &config); + + std::vector streams_; }; diff --git a/src/apps/cam/kms_sink.cpp b/src/apps/cam/kms_sink.cpp index 6490a5c0..1fc559ed 100644 --- a/src/apps/cam/kms_sink.cpp +++ b/src/apps/cam/kms_sink.cpp @@ -110,7 +110,7 @@ int KMSSink::configure(const libcamera::CameraConfiguration &config) plane_ = nullptr; mode_ = nullptr; - const libcamera::StreamConfiguration &cfg = config.at(0); + const libcamera::StreamConfiguration &cfg = findConfiguration(config); /* Find the best mode for the stream size. */ const std::vector &modes = connector_->modes(); @@ -456,6 +456,12 @@ bool KMSSink::processRequest(libcamera::Request *camRequest) return true; libcamera::FrameBuffer *buffer = camRequest->buffers().begin()->second; + for (auto [stream, buf] : camRequest->buffers()) { + if (assignedStream(stream)) { + buffer = buf; + break; + } + } auto iter = buffers_.find(buffer); if (iter == buffers_.end()) return true; diff --git a/src/apps/cam/sdl_sink.cpp b/src/apps/cam/sdl_sink.cpp index e8a54f7a..8a7df372 100644 --- a/src/apps/cam/sdl_sink.cpp +++ b/src/apps/cam/sdl_sink.cpp @@ -44,18 +44,17 @@ int SDLSink::configure(const libcamera::CameraConfiguration &config) if (ret < 0) return ret; - if (config.size() > 1) { + if (streams_.size() > 1) { std::cerr - << "SDL sink only supports one camera stream at present, streaming first camera stream" + << "SDL sink only supports one camera stream at present, streaming first stream" << std::endl; - } else if (config.empty()) { + } else if (streams_.empty()) { std::cerr << "Require at least one camera stream to process" << std::endl; return -EINVAL; } - const libcamera::StreamConfiguration &cfg = config.at(0); - rect_.w = cfg.size.width; + const libcamera::StreamConfiguration &cfg = findConfiguration(config); rect_.h = cfg.size.height; switch (cfg.pixelFormat) { @@ -163,8 +162,10 @@ void SDLSink::mapBuffer(FrameBuffer *buffer) bool SDLSink::processRequest(Request *request) { for (auto [stream, buffer] : request->buffers()) { - renderBuffer(buffer); - break; /* to be expanded to launch SDL window per buffer */ + if (assignedStream(stream)) { + renderBuffer(buffer); + break; /* to be expanded to launch SDL window per buffer */ + } } return true; From patchwork Fri Mar 14 20:29:35 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Milan Zamazal X-Patchwork-Id: 22967 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 F39F8C32F7 for ; Fri, 14 Mar 2025 20:30:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id B105968952; Fri, 14 Mar 2025 21:30:31 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.b="itMoM1Uu"; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 480C868950 for ; Fri, 14 Mar 2025 21:30:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1741984228; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cK0ilC9taCY6uIP7kxjRgmSs8FOpljnBJbd+JeDokrs=; b=itMoM1Uuo17HORFnldkCIppE1fLG8c2Az+rdpQUw1qRMssO9ZmlMsxJNVq56tCOd0D+CL2 2K/7RTHQRAN/4FYGqCT3FfARwMT3dpXOVwR0p+9MRbZA2gbcKk7fQXSKLY+yW5+Ve4AyF0 2i+UklbH9wTFoEEvCapELiq5HUnm/FM= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-589-rJ57H-BdNqqmvXaKIukv6w-1; Fri, 14 Mar 2025 16:30:17 -0400 X-MC-Unique: rJ57H-BdNqqmvXaKIukv6w-1 X-Mimecast-MFC-AGG-ID: rJ57H-BdNqqmvXaKIukv6w_1741984211 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8B0D91956080; Fri, 14 Mar 2025 20:30:11 +0000 (UTC) Received: from mzamazal-thinkpadp1gen7.tpbc.com (unknown [10.44.32.19]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 137181954B32; Fri, 14 Mar 2025 20:30:09 +0000 (UTC) From: Milan Zamazal To: libcamera-devel@lists.libcamera.org Cc: Milan Zamazal , Laurent Pinchart Subject: [RFC PATCH 7/7] apps: cam: Add command line options for stream specific outputs Date: Fri, 14 Mar 2025 21:29:35 +0100 Message-ID: <20250314202943.112109-8-mzamazal@redhat.com> In-Reply-To: <20250314202943.112109-1-mzamazal@redhat.com> References: <20250314202943.112109-1-mzamazal@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: e1MLZ808tfl427y7heYgNb45U6vY8jBB48cc3PBkCRg_1741984211 X-Mimecast-Originator: redhat.com content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now, when the support for multiple outputs is ready, let's add command line options to actually use it. To remain backward compatible and to keep the things simple for the user, the original output related command line options work as before. For example, simply running cam -c1 -C -D or cam ... -s role=viewfinder,... -s role=raw,... -Fimage# still works. But the user can also specify a different output for each of the given streams now, for example: cam ... -s role=viewfinder,... --stream-display \ -s role=raw,... --stream-file=raw# or cam ... -s role=viewfinder,... --stream-file=processed#.ppm \ -s role=raw,... --stream-file=raw# To not complicate the implementation more than necessary, it's not allowed to combine the old and the new output options. It is also checked that --stream-display is not used more than once (the KMS output may be used only for a single stream) and that each stream has at most one output assigned. Signed-off-by: Milan Zamazal --- src/apps/cam/camera_session.cpp | 67 ++++++++++++++++++++++++++++++++- src/apps/cam/main.cpp | 23 ++++++++--- src/apps/cam/main.h | 3 ++ 3 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp index 5124029b..5ef0c2fe 100644 --- a/src/apps/cam/camera_session.cpp +++ b/src/apps/cam/camera_session.cpp @@ -7,13 +7,16 @@ #include "camera_session.h" +#include #include #include #include +#include #include #include #include +#include #include "../common/event_loop.h" #include "../common/stream_options.h" @@ -292,10 +295,70 @@ int CameraSession::start() defaultSink = std::move(sink); } +#ifdef HAVE_KMS + bool kmsSinkAssigned = false; +#endif + auto &streamOptions = options_[OptStream]; for (unsigned int i = 0; i < config_->size(); i++) { const StreamConfiguration &cfg = config_->at(i); - if (defaultSink) - defaultSink->addStream(cfg.stream()); + if (streamOptions.empty()) { + if (defaultSink) + defaultSink->addStream(cfg.stream()); + } else { + const OptionsParser::Options &suboptions = streamOptions.toArray()[i].children(); + if (defaultSink) { + if (suboptions.isSet(OptStreamDisplay) || + suboptions.isSet(OptStreamSDL) || + suboptions.isSet(OptStreamFile)) { + std::cerr << "Combining default and stream specific outputs is unsupported" << std::endl; + return -EINVAL; + } + + defaultSink->addStream(cfg.stream()); + continue; + } + + std::unique_ptr sink; +#ifdef HAVE_KMS + if (suboptions.isSet(OptStreamDisplay)) { + if (kmsSinkAssigned) { + std::cerr << "Display doesn't support multiple streams" << std::endl; + return -EINVAL; + } + kmsSinkAssigned = true; + + sink = std::make_unique(suboptions[OptStreamDisplay].toString()); + } +#endif +#ifdef HAVE_SDL + if (suboptions.isSet(OptStreamSDL)) { + if (sink) { + std::cerr << "Single stream cannot have multiple outputs" << std::endl; + return -EINVAL; + } + sink = std::make_unique(); + } +#endif + if (suboptions.isSet(OptStreamFile)) { + if (sink) { + std::cerr << "Single stream cannot have multiple outputs" << std::endl; + return -EINVAL; + } + std::unique_ptr fileSink = + std::make_unique(camera_.get(), streamNames_); + if (!suboptions[OptStreamFile].toString().empty()) { + ret = fileSink->setFilePattern(suboptions[OptStreamFile]); + if (ret) + return ret; + } + sink = std::move(fileSink); + } + + if (sink) { + sink->addStream(cfg.stream()); + sinks_.push_back(std::move(sink)); + } + } } if (defaultSink) diff --git a/src/apps/cam/main.cpp b/src/apps/cam/main.cpp index 9d84ef8e..10b7a33a 100644 --- a/src/apps/cam/main.cpp +++ b/src/apps/cam/main.cpp @@ -138,14 +138,21 @@ int CamApp::parseOptions(int argc, char *argv[]) "Desired image orientation (rot0, rot180, mirror, flip)", "orientation", ArgumentRequired, "orientation", false, OptCamera); + parser.addOption(OptStream, &streamKeyValue, + "Set configuration of a camera stream", "stream", true, + OptCamera); #ifdef HAVE_KMS parser.addOption(OptDisplay, OptionString, - "Display viewfinder through DRM/KMS on specified connector", + "Display viewfinder by default through DRM/KMS on specified connector", "display", ArgumentOptional, "connector", false, OptCamera); + parser.addOption(OptStreamDisplay, OptionString, + "Display viewfinder stream through DRM/KMS on specified connector", + "stream-display", ArgumentOptional, "connector", false, + OptStream); #endif parser.addOption(OptFile, OptionString, - "Write captured frames to disk\n" + "Write captured frames by default to disk\n" "If the file name ends with a '/', it sets the directory in which\n" "to write files, using the default file name. Otherwise it sets the\n" "full file path and name. The first '#' character in the file name\n" @@ -159,13 +166,17 @@ int CamApp::parseOptions(int argc, char *argv[]) "The default file name is 'frame-#.bin'.", "file", ArgumentOptional, "filename", false, OptCamera); + parser.addOption(OptStreamFile, OptionString, + "Write frames captured from a stream to disk\n" + "The file name is of the same format as in --file.", + "stream-file", ArgumentOptional, "filename", false, + OptStream); #ifdef HAVE_SDL - parser.addOption(OptSDL, OptionNone, "Display viewfinder through SDL", + parser.addOption(OptSDL, OptionNone, "Display viewfinder by default through SDL", "sdl", ArgumentNone, "", false, OptCamera); + parser.addOption(OptStreamSDL, OptionNone, "Display stream viewfinder through SDL", + "stream-sdl", ArgumentNone, "", false, OptStream); #endif - parser.addOption(OptStream, &streamKeyValue, - "Set configuration of a camera stream", "stream", true, - OptCamera); parser.addOption(OptStrictFormats, OptionNone, "Do not allow requested stream format(s) to be adjusted", "strict-formats", ArgumentNone, nullptr, false, diff --git a/src/apps/cam/main.h b/src/apps/cam/main.h index 64e6a20e..2f630fbe 100644 --- a/src/apps/cam/main.h +++ b/src/apps/cam/main.h @@ -20,6 +20,9 @@ enum { OptOrientation = 'o', OptSDL = 'S', OptStream = 's', + OptStreamDisplay = 'd', + OptStreamFile = 'f', + OptStreamSDL = 'w', OptListControls = 256, OptStrictFormats = 257, OptMetadata = 258,