From patchwork Tue Nov 15 12:59:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xavier Roumegue X-Patchwork-Id: 17802 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 99887C3285 for ; Tue, 15 Nov 2022 13:00:12 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8B2EB63091; Tue, 15 Nov 2022 14:00:11 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1668517211; bh=NNRm5ysaW9aOkU/3+UmSo4hHHR9ERYJho/lw0z0JnQs=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=djZ6Q/PixYCnvczjhDCesDs1U8v/Gny/KFXYCKPXSS0LA6Ke1QgCupyy60UKNz7eq RVBLr0c1NrE4pBMUwzalzTIu9Grehm4eH75/jKhaf7WnSUOZs8b27TWbcHEmmX7WsS ygbF9JoegLjvxRueOIYg1PEQnSLVB8CsSCanNwEP315wYsUAPPU/atsd4g2JBWTaQS vdBjxlSwQFlIPrBkzUaJHuFEUZz3geZSOP0z7kxjw443IwqPgUvuWRHWecxAeZGkKV M4DJ0jooJFdv1q27d2l6+kkRAtEmriV4jhm/DcIQUW+2Ck6dOMoGtVmUPhAGbRXxq/ 9LEDC+4DsY5UA== Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on0613.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe0d::613]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 363FC63086 for ; Tue, 15 Nov 2022 14:00:09 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=NXP1.onmicrosoft.com header.i=@NXP1.onmicrosoft.com header.b="XIXh4v0A"; dkim-atps=neutral ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d2ij4oGkyk01ifuebutlSUqop2ykWvifeKOkyS/672GXPE03SHBZropnC2GTRb/DtGYePPEMn9NnLrlTM8Ih1JaMKG6TczG/03AzBVmXCTUt7868Me1KJzbn/eEjvFR3GJwOZ97dszv4rQDEqb0CISWNXC6lhEuR1OmtizduLcyHXchkIzvSjCMU9YQ/BHj2Zp3NpVI0doecPj7jVn9fZFPpRgKy/vrKWngrgFIvibLsu3P3Cve3RHZ/jkrY2hsNMdPgHN9jwTw2fV0lBg5Z1bPO57xeQ7kiQTVb9zNCo4moFrD5NU7sFvbcwOFRRPUFn2DHb/79dvM+MQHIK8THRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=KAUDWq3MJRyC2i5jOYmMmBF+MtZu4kl74ng2Y39O4pI=; b=NA/FRiWlvjCjkC5zDota7hqEhnqE6fZK6PbxxOePVXkC23bPK277zpaO1/FmYgIgKSL16FeziFNpMnCfEJ/gXyZ2IgYPLsU9TouD2srj8EaNzxJnDy6AebZdaUO/OraB1BcJ0PmqWgePwuGx248wivZyjaLBO2QCtyf3BCe1E2lBg1E+u3fWlHVri/heV40ODfuCIqvD2WuyIQp8J/MtxQF9GZGuy7MSNqgeSraLsOZPhi5SR4BxLIAOmE2F7v+Zh86+Zs+D/sdUQ32BjbpL34zgV0KLCaON+2s4GlsGXtX0c+9rgRcvTWiq2ronlSAM7wo/iCs5gfz2VBzwRQrrNQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=oss.nxp.com; dmarc=pass action=none header.from=oss.nxp.com; dkim=pass header.d=oss.nxp.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=NXP1.onmicrosoft.com; s=selector2-NXP1-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=KAUDWq3MJRyC2i5jOYmMmBF+MtZu4kl74ng2Y39O4pI=; b=XIXh4v0A7Y6jDwC09KY3qsV0ddO78EFm4uqSwhwPh+EX1G+Mnbr1m1bNL1Rk2Gbl0xJpSFQEj+K6dl1ZXafzlkFaXFMVpOwA+8n5hKi8V0ElSut65bkC+6AocJN72uDrEKkO75caZtafSd+oi+nMAoW9DuX0kJAccf2sVnrt+kM= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=oss.nxp.com; Received: from PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) by PAXPR04MB8639.eurprd04.prod.outlook.com (2603:10a6:102:21e::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5813.13; Tue, 15 Nov 2022 13:00:06 +0000 Received: from PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::14d3:8e4:cf07:810d]) by PAXPR04MB8703.eurprd04.prod.outlook.com ([fe80::14d3:8e4:cf07:810d%3]) with mapi id 15.20.5813.018; Tue, 15 Nov 2022 13:00:06 +0000 To: jacopo@jmondi.org, laurent.pinchart@ideasonboard.com Date: Tue, 15 Nov 2022 13:59:34 +0100 Message-Id: <20221115125935.1196138-2-xavier.roumegue@oss.nxp.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221115125935.1196138-1-xavier.roumegue@oss.nxp.com> References: <20221115125935.1196138-1-xavier.roumegue@oss.nxp.com> X-ClientProxiedBy: PR3P189CA0080.EURP189.PROD.OUTLOOK.COM (2603:10a6:102:b4::25) To PAXPR04MB8703.eurprd04.prod.outlook.com (2603:10a6:102:21e::22) MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PAXPR04MB8703:EE_|PAXPR04MB8639:EE_ X-MS-Office365-Filtering-Correlation-Id: 30763b04-1832-4458-5e60-08dac70951a5 X-MS-Exchange-SharedMailbox-RoutingAgent-Processed: True X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PpfY3H6wuzEAoN4m4u4/Qelxw/ODJ5a6f1eg83ToNh8Cmwf6FTPAzymymzkmFoO61HKO5Jl0DPdFiLEyqP9lZobKbZBYC5zRV3l2QlZYJbDmcoIj/PZjw4b7ruDdLj+K0OlbRiHeZgQSu+nC5VK/lw7sqpzvNCyYX/7irykx5wj2MEyz4dI1Zi+qRTexzEfeTQXf6fx4LvkiqmF3/z8f56vBk1ZCqMetS/5LaC2FVNdgUtfwkGTK/NWW6e444Tr/9+zhr7/mE35uGu9X+UBr6+IvhgHMHKEFK4k5BiPKZCHnG0gWxoCj4Gz5fx9PrM+gPD1lZ3oey+dm62srzWUNiqIjdrWT8IXxfIoWEUdnWc8IESjCKWDk+IuOVW+nU9q3UdBUN/XT9DZCfEseaeyx5WXUcHuqUIb2yLEWk/4Yt1fjuEzlaY/DGUP80KqfpE9TWSxDsS/Nw1ZlI7NS8wxBtU7jHu8QpV2gMHMxkuKTF08JnujtiE2SynJrlWZ5iz3xn4VTpYiPhjAsrL58jpd70WN9zJ/R69ubRRqs4/moO1t2pGPsp1lkrRXTFCtrVoIT8pI/RX2lUnGteIFZobkOj0O0EIonGqQ5STG8kNluW81sC3+Sm7zxUI2wM/fvSa56ze8RNmmbrCNjSJM5sYHph2/swxR6c/x0dWJLnu+gpYHkKj/xdKjc2x2jlDw52lkkoTGPGKblld4VV0d89m1dqnxCha9iXev3b2rqgqsEhE8daALYRyQ6z/zZgNh/sn4L X-Forefront-Antispam-Report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:PAXPR04MB8703.eurprd04.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230022)(4636009)(136003)(396003)(366004)(376002)(39860400002)(346002)(451199015)(6512007)(86362001)(316002)(38100700002)(52116002)(83380400001)(44832011)(2906002)(41300700001)(8676002)(4326008)(66946007)(8936002)(66556008)(1076003)(66476007)(186003)(30864003)(5660300002)(2616005)(6486002)(6506007)(478600001)(6666004)(41533002); DIR:OUT; SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: wY1bj1gMk2IbyYyKSvToFS6S9m3oGxsZ9CQULwOHwwYDYRymfnPXDe3TTmxFtKFkpVAJBEmBSlLuEkd12UNJonbMMqk5MmmBPQ4fftBprKNdXmDgyadcDZbM5mDPqCBLG7PH9Zmk9jobbKN+mgn38KW7Nbg4oK+MIh63p3nkS28qyzLuhRpvCddSBItwffiPshb9EhUzzO4Rg+arGTGhYGqmrtaDpR5/jwUuW7eDSrUOpWrl6hVqgrplfgLEGoeX+qNSNzFTDbJZnZHHLmDSLnces9Lb3q0U0r4NigFMgBcnyl41dJUCIrdMFUqkyclu3c9RuGtJyK9mWa9hfMGNhxhQMG/f55dV9uhWwWhZhPW6jFNu/KrN68RNIUy73sFnpvE1CZZQeHTlhQJRC6ioF8rMk2/Af/e6gXSxEPSznlmimBnV7tAHqylErDAlAoJRomjsuGEypo138PqDcaR22ydb4GHmqOEV3ThNjUBOVouv/9VjBBGLAqWAmMIoP1D00fXOgtKvfL0MigZYo5ZDbmU6/LkwsqQO9eSeaFL/GoUMaxeaqKW29mxSD7XixHuxkQmwTwaV95KC9j+nSRB87awkFGaqzcFvSGaSK/U+ToQOKblmSH91zLq+XmZjLoRxeVB2k4CZPVwlsbFUek45V9qrEGnS3O0attRYWMwx2qfd4DstNRV5htxNVLb44jTO3LFD5jkx5esuV4Y392vRy5knIlowxk05wthjDjUOqcBEVCrUeDX6+9VDeGwAQwbzXjaT0QWDPurX35ncT9AHVSDs3UHCrwWxNaz1MCmkQBTK8jIWiAPx7IPspslMVlLL5wXxo1CIBmHQev4ieDP3H+L9NXKaAEkMb93KEUWmjKEP12ueWUafd93kQfCj3yA3HUsD7GomV/WjlEbE0x7cwVgLJNwU1FmZKj0Lk2WMIwWtFNo0jwpSnTqXoadrrCwcU26TBrOZGDsg8TrAoY7yMwfte/wSQXoIGnwN2qjoXh/+i98HT7oilpaqYB/YoandcWfxqD4VYg2J+IicKXwIUVXX7jlAsl3d8KoxsMPtIkHBRvD/vGr02wdYMW/b3qDPsoqLW729Z5X2ykHnCtUxyq8XEfgSqSYQ+iqPAlmXcMqcO3TO6L1fX3ODn9zaOxFxAF704Y4XPggtLEef8ZKHqTvRUEDQg4/Dfzgv+IJL98pGdo382kNjhx9hRhOB0OEHVAMrD0IYYdOCsFt/hMsg0+hmdTT3mh5Winw47FeQ2nfza+jTFLn52WCtSwa5Pq7HdY/X6w4DjleU3OmRLjrB+OU8wN4B0He5EkCQtiOA6aqjPjUrjM/Wfdl3ZYRfs+4JQegdK0u9yY/CirPoAoI/8j5c3yO8GlJH7vp4GEtkuK/IRsts9N9PJ27yNmiqjBeuClGAHANtcROmXmfLbz7U8fB9IkRgkeuterYJLkbbjOXBwx+e1eFRho2T0lM3ptYmdSFj8+KTgCNVNsoWC/R6iUC8y2Mt4tppRxhj5YmQTwTXRj6he9/EoBoB+yEj0ppDsuRDig6ePpk6XRg2yMyvuEsvp7IsC2xqWRRQ+1dOK3AXyPtMsE3X++gIH+qw2l709xTBibo+06Os9ILHnw6uQqhk6cXC0Z3lJIAOEPMO6XSYblCBEGTZHiwU2vddUuaS6oOS4CVpBTqyZNVvOOC6gA== X-OriginatorOrg: oss.nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 30763b04-1832-4458-5e60-08dac70951a5 X-MS-Exchange-CrossTenant-AuthSource: PAXPR04MB8703.eurprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Nov 2022 13:00:06.7896 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: EVzmsturS0DK5pDgwvc7l8vQWYsHuOfrk99xCWKSsIvfn/bk1GKcTV54Wuls4olohaFVrEV+Wk8NAuMkYQDtUg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAXPR04MB8639 Subject: [libcamera-devel] [PATCH v2 2/2] libcamera: pipeline: simple: converter: Use generic converter interface 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: , X-Patchwork-Original-From: Xavier Roumegue via libcamera-devel From: Xavier Roumegue Reply-To: Xavier Roumegue Cc: libcamera-devel@lists.libcamera.org Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Move the simple converter implementation to a generic V4L2 M2M class derived from the converter interface. This latter could be used by other pipeline implementations and as base class for customized V4L2 M2M converters. Signed-off-by: Xavier Roumegue Reviewed-by: Jacopo Mondi --- .../internal/converter/converter_v4l2_m2m.h | 18 +-- .../libcamera/internal/converter/meson.build | 5 + include/libcamera/internal/meson.build | 2 + .../converter_v4l2_m2m.cpp} | 153 +++++++++++------- src/libcamera/converter/meson.build | 5 + src/libcamera/meson.build | 1 + src/libcamera/pipeline/simple/meson.build | 1 - src/libcamera/pipeline/simple/simple.cpp | 6 +- 8 files changed, 123 insertions(+), 68 deletions(-) rename src/libcamera/pipeline/simple/converter.h => include/libcamera/internal/converter/converter_v4l2_m2m.h (83%) create mode 100644 include/libcamera/internal/converter/meson.build rename src/libcamera/{pipeline/simple/converter.cpp => converter/converter_v4l2_m2m.cpp} (68%) create mode 100644 src/libcamera/converter/meson.build diff --git a/src/libcamera/pipeline/simple/converter.h b/include/libcamera/internal/converter/converter_v4l2_m2m.h similarity index 83% rename from src/libcamera/pipeline/simple/converter.h rename to include/libcamera/internal/converter/converter_v4l2_m2m.h index f0ebe2e0..ef31eeba 100644 --- a/src/libcamera/pipeline/simple/converter.h +++ b/include/libcamera/internal/converter/converter_v4l2_m2m.h @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Laurent Pinchart + * Copyright 2022 NXP * - * converter.h - Format converter for simple pipeline handler + * converter_v4l2_m2m.h - V4l2 M2M Format converter interface */ #pragma once @@ -19,6 +20,8 @@ #include #include +#include "libcamera/internal/converter.h" + namespace libcamera { class FrameBuffer; @@ -28,11 +31,12 @@ class SizeRange; struct StreamConfiguration; class V4L2M2MDevice; -class SimpleConverter +class V4L2M2MConverter : public Converter { public: - SimpleConverter(MediaDevice *media); + V4L2M2MConverter(MediaDevice *media); + int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } bool isValid() const { return m2m_ != nullptr; } std::vector formats(PixelFormat input); @@ -52,14 +56,11 @@ public: int queueBuffers(FrameBuffer *input, const std::map &outputs); - Signal inputBufferReady; - Signal outputBufferReady; - private: class Stream : protected Loggable { public: - Stream(SimpleConverter *converter, unsigned int index); + Stream(V4L2M2MConverter *converter, unsigned int index); bool isValid() const { return m2m_ != nullptr; } @@ -80,7 +81,7 @@ private: void captureBufferReady(FrameBuffer *buffer); void outputBufferReady(FrameBuffer *buffer); - SimpleConverter *converter_; + V4L2M2MConverter *converter_; unsigned int index_; std::unique_ptr m2m_; @@ -88,7 +89,6 @@ private: unsigned int outputBufferCount_; }; - std::string deviceNode_; std::unique_ptr m2m_; std::vector streams_; diff --git a/include/libcamera/internal/converter/meson.build b/include/libcamera/internal/converter/meson.build new file mode 100644 index 00000000..891e79e7 --- /dev/null +++ b/include/libcamera/internal/converter/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_internal_headers += files([ + 'converter_v4l2_m2m.h', +]) diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 8f50d755..b9db5a8c 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -45,3 +45,5 @@ libcamera_internal_headers = files([ 'v4l2_videodevice.h', 'yaml_parser.h', ]) + +subdir('converter') diff --git a/src/libcamera/pipeline/simple/converter.cpp b/src/libcamera/converter/converter_v4l2_m2m.cpp similarity index 68% rename from src/libcamera/pipeline/simple/converter.cpp rename to src/libcamera/converter/converter_v4l2_m2m.cpp index acaaa64c..31acb048 100644 --- a/src/libcamera/pipeline/simple/converter.cpp +++ b/src/libcamera/converter/converter_v4l2_m2m.cpp @@ -1,12 +1,11 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2020, Laurent Pinchart + * Copyright 2022 NXP * - * converter.cpp - Format converter for simple pipeline handler + * converter_v4l2_m2m.cpp - V4L2 M2M Format converter */ -#include "converter.h" - #include #include @@ -20,19 +19,25 @@ #include "libcamera/internal/media_device.h" #include "libcamera/internal/v4l2_videodevice.h" +#include "libcamera/internal/converter/converter_v4l2_m2m.h" + +/** + * \file internal/converter/converter_v4l2_m2m.h + * \brief V4L2 M2M based converter + */ namespace libcamera { -LOG_DECLARE_CATEGORY(SimplePipeline) +LOG_DECLARE_CATEGORY(Converter) /* ----------------------------------------------------------------------------- - * SimpleConverter::Stream + * V4L2M2MConverter::Stream */ -SimpleConverter::Stream::Stream(SimpleConverter *converter, unsigned int index) +V4L2M2MConverter::Stream::Stream(V4L2M2MConverter *converter, unsigned int index) : converter_(converter), index_(index) { - m2m_ = std::make_unique(converter->deviceNode_); + m2m_ = std::make_unique(converter->deviceNode()); m2m_->output()->bufferReady.connect(this, &Stream::outputBufferReady); m2m_->capture()->bufferReady.connect(this, &Stream::captureBufferReady); @@ -42,8 +47,8 @@ SimpleConverter::Stream::Stream(SimpleConverter *converter, unsigned int index) m2m_.reset(); } -int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, - const StreamConfiguration &outputCfg) +int V4L2M2MConverter::Stream::configure(const StreamConfiguration &inputCfg, + const StreamConfiguration &outputCfg) { V4L2PixelFormat videoFormat = m2m_->output()->toV4L2PixelFormat(inputCfg.pixelFormat); @@ -56,14 +61,14 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, int ret = m2m_->output()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, 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) + LOG(Converter, Error) << "Input format not supported (requested " << inputCfg.size << "-" << videoFormat << ", got " << format << ")"; @@ -78,13 +83,13 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set output format: " << strerror(-ret); return ret; } if (format.fourcc != videoFormat || format.size != outputCfg.size) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Output format not supported"; return -EINVAL; } @@ -95,13 +100,13 @@ int SimpleConverter::Stream::configure(const StreamConfiguration &inputCfg, return 0; } -int SimpleConverter::Stream::exportBuffers(unsigned int count, - std::vector> *buffers) +int V4L2M2MConverter::Stream::exportBuffers(unsigned int count, + std::vector> *buffers) { return m2m_->capture()->exportBuffers(count, buffers); } -int SimpleConverter::Stream::start() +int V4L2M2MConverter::Stream::start() { int ret = m2m_->output()->importBuffers(inputBufferCount_); if (ret < 0) @@ -128,7 +133,7 @@ int SimpleConverter::Stream::start() return 0; } -void SimpleConverter::Stream::stop() +void V4L2M2MConverter::Stream::stop() { m2m_->capture()->streamOff(); m2m_->output()->streamOff(); @@ -136,8 +141,7 @@ void SimpleConverter::Stream::stop() m2m_->output()->releaseBuffers(); } -int SimpleConverter::Stream::queueBuffers(FrameBuffer *input, - FrameBuffer *output) +int V4L2M2MConverter::Stream::queueBuffers(FrameBuffer *input, FrameBuffer *output) { int ret = m2m_->output()->queueBuffer(input); if (ret < 0) @@ -150,12 +154,12 @@ int SimpleConverter::Stream::queueBuffers(FrameBuffer *input, return 0; } -std::string SimpleConverter::Stream::logPrefix() const +std::string V4L2M2MConverter::Stream::logPrefix() const { return "stream" + std::to_string(index_); } -void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer) +void V4L2M2MConverter::Stream::outputBufferReady(FrameBuffer *buffer) { auto it = converter_->queue_.find(buffer); if (it == converter_->queue_.end()) @@ -167,32 +171,34 @@ void SimpleConverter::Stream::outputBufferReady(FrameBuffer *buffer) } } -void SimpleConverter::Stream::captureBufferReady(FrameBuffer *buffer) +void V4L2M2MConverter::Stream::captureBufferReady(FrameBuffer *buffer) { converter_->outputBufferReady.emit(buffer); } /* ----------------------------------------------------------------------------- - * SimpleConverter + * V4L2M2MConverter + */ + +/** + * \class libcamera::V4L2M2MConverter + * \brief The V4L2 M2M converter implements the converter interface based on + * V4L2 M2M device. +*/ + +/** + * \fn V4L2M2MConverter::V4L2M2MConverter + * \brief Construct a V4L2M2MConverter instance + * \param[in] media The media device implementing the converter */ -SimpleConverter::SimpleConverter(MediaDevice *media) +V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media) + : Converter(media) { - /* - * Locate the video node. There's no need to validate the pipeline - * further, the caller guarantees that this is a V4L2 mem2mem device. - */ - const std::vector &entities = media->entities(); - auto it = std::find_if(entities.begin(), entities.end(), - [](MediaEntity *entity) { - return entity->function() == MEDIA_ENT_F_IO_V4L; - }); - if (it == entities.end()) + if (deviceNode().empty()) return; - deviceNode_ = (*it)->deviceNode(); - - m2m_ = std::make_unique(deviceNode_); + m2m_ = std::make_unique(deviceNode()); int ret = m2m_->open(); if (ret < 0) { m2m_.reset(); @@ -200,7 +206,21 @@ SimpleConverter::SimpleConverter(MediaDevice *media) } } -std::vector SimpleConverter::formats(PixelFormat input) +/** + * \fn libcamera::V4L2M2MConverter::loadConfiguration + * \details \copydetails libcamera::Converter::loadConfiguration + */ + +/** + * \fn libcamera::V4L2M2MConverter::isValid + * \details \copydetails libcamera::Converter::isValid + */ + +/** + * \fn libcamera::V4L2M2MConverter::formats + * \details \copydetails libcamera::Converter::formats + */ +std::vector V4L2M2MConverter::formats(PixelFormat input) { if (!m2m_) return {}; @@ -215,13 +235,13 @@ std::vector SimpleConverter::formats(PixelFormat input) int ret = m2m_->output()->setFormat(&v4l2Format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } if (v4l2Format.fourcc != m2m_->output()->toV4L2PixelFormat(input)) { - LOG(SimplePipeline, Debug) + LOG(Converter, Debug) << "Input format " << input << " not supported."; return {}; } @@ -237,7 +257,10 @@ std::vector SimpleConverter::formats(PixelFormat input) return pixelFormats; } -SizeRange SimpleConverter::sizes(const Size &input) +/** + * \copydoc libcamera::Converter::sizes + */ +SizeRange V4L2M2MConverter::sizes(const Size &input) { if (!m2m_) return {}; @@ -252,7 +275,7 @@ SizeRange SimpleConverter::sizes(const Size &input) int ret = m2m_->output()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } @@ -262,7 +285,7 @@ SizeRange SimpleConverter::sizes(const Size &input) format.size = { 1, 1 }; ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } @@ -272,7 +295,7 @@ SizeRange SimpleConverter::sizes(const Size &input) format.size = { UINT_MAX, UINT_MAX }; ret = m2m_->capture()->setFormat(&format); if (ret < 0) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to set format: " << strerror(-ret); return {}; } @@ -282,9 +305,12 @@ SizeRange SimpleConverter::sizes(const Size &input) return sizes; } +/** + * \copydoc libcamera::Converter::strideAndFrameSize + */ std::tuple -SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, - const Size &size) +V4L2M2MConverter::strideAndFrameSize(const PixelFormat &pixelFormat, + const Size &size) { V4L2DeviceFormat format; format.fourcc = m2m_->capture()->toV4L2PixelFormat(pixelFormat); @@ -297,8 +323,11 @@ SimpleConverter::strideAndFrameSize(const PixelFormat &pixelFormat, return std::make_tuple(format.planes[0].bpl, format.planes[0].size); } -int SimpleConverter::configure(const StreamConfiguration &inputCfg, - const std::vector> &outputCfgs) +/** + * \copydoc libcamera::Converter::configure + */ +int V4L2M2MConverter::configure(const StreamConfiguration &inputCfg, + const std::vector> &outputCfgs) { int ret = 0; @@ -309,7 +338,7 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, Stream &stream = streams_.emplace_back(this, i); if (!stream.isValid()) { - LOG(SimplePipeline, Error) + LOG(Converter, Error) << "Failed to create stream " << i; ret = -EINVAL; break; @@ -328,8 +357,11 @@ int SimpleConverter::configure(const StreamConfiguration &inputCfg, return 0; } -int SimpleConverter::exportBuffers(unsigned int output, unsigned int count, - std::vector> *buffers) +/** + * \copydoc libcamera::Converter::exportBuffers + */ +int V4L2M2MConverter::exportBuffers(unsigned int output, unsigned int count, + std::vector> *buffers) { if (output >= streams_.size()) return -EINVAL; @@ -337,7 +369,10 @@ int SimpleConverter::exportBuffers(unsigned int output, unsigned int count, return streams_[output].exportBuffers(count, buffers); } -int SimpleConverter::start() +/** + * \copydoc libcamera::Converter::start + */ +int V4L2M2MConverter::start() { int ret; @@ -352,14 +387,20 @@ int SimpleConverter::start() return 0; } -void SimpleConverter::stop() +/** + * \copydoc libcamera::Converter::stop + */ +void V4L2M2MConverter::stop() { for (Stream &stream : utils::reverse(streams_)) stream.stop(); } -int SimpleConverter::queueBuffers(FrameBuffer *input, - const std::map &outputs) +/** + * \copydoc libcamera::Converter::queueBuffers + */ +int V4L2M2MConverter::queueBuffers(FrameBuffer *input, + const std::map &outputs) { unsigned int mask = 0; int ret; @@ -402,4 +443,6 @@ int SimpleConverter::queueBuffers(FrameBuffer *input, return 0; } +REGISTER_CONVERTER("v4l2_m2m", V4L2M2MConverter, "pxp") + } /* namespace libcamera */ diff --git a/src/libcamera/converter/meson.build b/src/libcamera/converter/meson.build new file mode 100644 index 00000000..2aa72fe4 --- /dev/null +++ b/src/libcamera/converter/meson.build @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: CC0-1.0 + +libcamera_sources += files([ + 'converter_v4l2_m2m.cpp' +]) diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index e9d0324e..ffc294f3 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -62,6 +62,7 @@ libatomic = cc.find_library('atomic', required : false) libthreads = dependency('threads') subdir('base') +subdir('converter') subdir('ipa') subdir('pipeline') subdir('proxy') diff --git a/src/libcamera/pipeline/simple/meson.build b/src/libcamera/pipeline/simple/meson.build index 9c99b32f..42b0896d 100644 --- a/src/libcamera/pipeline/simple/meson.build +++ b/src/libcamera/pipeline/simple/meson.build @@ -1,6 +1,5 @@ # SPDX-License-Identifier: CC0-1.0 libcamera_sources += files([ - 'converter.cpp', 'simple.cpp', ]) diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp index a32de7f3..24ded4db 100644 --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -30,13 +30,13 @@ #include "libcamera/internal/camera.h" #include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/converter.h" #include "libcamera/internal/device_enumerator.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" -#include "converter.h" namespace libcamera { @@ -266,7 +266,7 @@ public: std::vector configs_; std::map> formats_; - std::unique_ptr converter_; + std::unique_ptr converter_; std::vector> converterBuffers_; bool useConverter_; std::queue> converterQueue_; @@ -492,7 +492,7 @@ int SimpleCameraData::init() /* Open the converter, if any. */ MediaDevice *converter = pipe->converter(); if (converter) { - converter_ = std::make_unique(converter); + converter_ = ConverterFactoryBase::create(converter); if (!converter_->isValid()) { LOG(SimplePipeline, Warning) << "Failed to create converter, disabling format conversion";