From patchwork Wed Oct 9 07:41:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harvey Yang X-Patchwork-Id: 21553 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 F09F7C32DE for ; Wed, 9 Oct 2024 07:46:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 65DF06536A; Wed, 9 Oct 2024 09:46:52 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="K3IoTonb"; dkim-atps=neutral Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 94C1B6353B for ; Wed, 9 Oct 2024 09:46:50 +0200 (CEST) Received: by mail-pj1-x1031.google.com with SMTP id 98e67ed59e1d1-2e09f67bc39so5423308a91.1 for ; Wed, 09 Oct 2024 00:46:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728460009; x=1729064809; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tIeh9OOzrh2fB+2XUMZ2I8IIwRldeYy5fiX65sGidRY=; b=K3IoTonbKXVZVnCTps3bei1Av+yL3ND3XuYBB67RjM7JqcyNCR5AC2NI9+x6VtRFFc c2qrsUSaHmysUHHEEVCl+6RaJR5DDx+EvW56W9TXODQQJJWP9M2pc4C1W4paSOal+/0g 7lsMC1e59Kh/sd1cK+lBoR+ssCShN8vDRtuO8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728460009; x=1729064809; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tIeh9OOzrh2fB+2XUMZ2I8IIwRldeYy5fiX65sGidRY=; b=xBrBWaXWycfdGUMdfVOxjksOu7mSSP2uUW7533Txm4ztqDgc4tbIAbVkiN53G0RMRO UXpf9clNrXLmxH0Xdpk2CzndoomiU0IbUUtWnjGYdmz/bXNKTCRYvg9CEQ17zf9c+CO6 DOWCT7QbyylL/nx8nWwwsKrb0M7yhmp6NWBr8fbpNgO1A6L5s4NQ0wYIUZRovvsWuXzr UvAIfcp+ucJw+s5NBphgzkdX5EFXPN07twVJ2n6t/R8gbGnnk3DsAyUZMYozpyRyJ0Ep QYZs4FUj0zxEN+qtswzS9mp0ROlQwjrLR7MGdt8u5wk3jWrgBSsWcQ8//yNqZnfGFjdP wVxQ== X-Gm-Message-State: AOJu0YzaV6yqH390UcE71BUyfQ0DXYz8fUSR/T+zMsH1+6TFrif5f9A/ 4PhP7YWnD74WlWR4UbqYAbX3jecooJ58W1WPq5z3hNuvxo/bExFxL0Skax3FMZrqGapU/w5XX2o = X-Google-Smtp-Source: AGHT+IE1MbJ1uLEKY4uI/8OoZeYfydbkVINyPrZ/at025/EE0D2okHXPplA6juoqYHbAhWt5Iw423Q== X-Received: by 2002:a17:90a:46ca:b0:2d3:cd27:c480 with SMTP id 98e67ed59e1d1-2e2a25519aamr2098551a91.33.1728460008755; Wed, 09 Oct 2024 00:46:48 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (199.211.81.34.bc.googleusercontent.com. [34.81.211.199]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2a57077c2sm944414a91.17.2024.10.09.00.46.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 00:46:48 -0700 (PDT) From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Han-Lin Chen , Harvey Yang Subject: [PATCH 1/5] libcamera: Add mailbox template helper Date: Wed, 9 Oct 2024 07:41:19 +0000 Message-ID: <20241009074642.2965791-2-chenghaoyang@chromium.org> X-Mailer: git-send-email 2.47.0.rc0.187.ge670bccf7e-goog In-Reply-To: <20241009074642.2965791-1-chenghaoyang@chromium.org> References: <20241009074642.2965791-1-chenghaoyang@chromium.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Han-Lin Chen MailBox is designed to be used to shares data, usually a frame buffer, among tasks. A Mailbox can store a data which the producer task should set into, and multiple consumer tasks could read the data from it. The data could be set only once, i.e., there should be only one producer. All tasks shares the Mailbox with share_ptr and the data it contains should be recycled when all tasks are finished. Signed-off-by: Han-Lin Chen Co-developed-by: Harvey Yang Signed-off-by: Harvey Yang --- include/libcamera/internal/mailbox.h | 75 ++++++++++++++++++++++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/mailbox.cpp | 60 +++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 137 insertions(+) create mode 100644 include/libcamera/internal/mailbox.h create mode 100644 src/libcamera/mailbox.cpp diff --git a/include/libcamera/internal/mailbox.h b/include/libcamera/internal/mailbox.h new file mode 100644 index 000000000..4c76eade9 --- /dev/null +++ b/include/libcamera/internal/mailbox.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * mailbox.h - Template class for generic mailbox + */ + +#pragma once + +#include +#include +#include + +#include + +namespace libcamera { + +template +class MailBox +{ +public: + using Recycler = std::function; + + MailBox() + : valid_(false) {} + ~MailBox() + { + if (valid_ && recycler_) + recycler_(item_); + } + + void put(const T &item, Recycler recycler) + { + ASSERT(!valid_); + + valid_ = true; + recycler_ = recycler; + item_ = item; + } + + const T &get() + { + ASSERT(valid_); + return item_; + } + + bool valid() { return valid_; } + +private: + T item_; + bool valid_; + std::function recycler_; +}; + +template +using SharedMailBox = std::shared_ptr>; + +template +SharedMailBox makeMailBox() +{ + return std::make_shared>(); +} + +template +std::vector> makeMailBoxVector(const unsigned int count) +{ + std::vector> mailBoxes; + mailBoxes.resize(count); + for (unsigned int i = 0; i < count; i++) + mailBoxes[i] = makeMailBox(); + + return mailBoxes; +} + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 1c5eef9ca..4c1228b95 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -27,6 +27,7 @@ libcamera_internal_headers = files([ 'ipa_proxy.h', 'ipc_pipe.h', 'ipc_unixsocket.h', + 'mailbox.h', 'mapped_framebuffer.h', 'media_device.h', 'media_object.h', diff --git a/src/libcamera/mailbox.cpp b/src/libcamera/mailbox.cpp new file mode 100644 index 000000000..7335122e3 --- /dev/null +++ b/src/libcamera/mailbox.cpp @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * mailbox.cpp - Template class for generic mailbox + */ + +/** + * \class libcamera::MailBox + * \brief MailBox of data + * + * A MailBox contains a block of data that has a single producer, and one or + * multiple consumers. It's often used as a shared_ptr (SharedMailBox) and + * being held by different tasks in pipelines. + */ + +/** + * \typedef MailBox::Recycler + * \brief A function that recycles the data when the mailbox is destructed + */ + +/** + * \fn MailBox::put(const T &item, MailBox::Recycler recycler) + * \brief Set the data as the producer. Should be called only once + * \param[in] item The data to be stored + * \param[in] recycler The function that recycles \a data when destructing the + * mailbox. Mostly used for recycling buffers. + */ + +/** + * \fn MailBox::get() + * \brief Get the data as a consumer. put() function should be called ahead + * + * \return The stored data + */ + +/** + * \fn MailBox::valid() + * \return True if put() function has been called + */ + +/** + * \typedef libcamera::SharedMailBox + * \brief A mailbox as a shared_ptr + */ + +/** + * \fn libcamera::makeMailBox() + * \brief A helper function to create a SharedMailBox + * + * \return A mailbox as a SharedMailBox + */ + +/** + * \fn libcamera::makeMailBoxVector(const unsigned int count) + * \brief A helper function to create a list of mailboxes + * \param[in] count The number of mailboxes requested + * + * \return Mailboxes as a vector + */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index aa9ab0291..6c3ef5377 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -38,6 +38,7 @@ libcamera_internal_sources = files([ 'ipc_pipe.cpp', 'ipc_pipe_unixsocket.cpp', 'ipc_unixsocket.cpp', + 'mailbox.cpp', 'mapped_framebuffer.cpp', 'media_device.cpp', 'media_object.cpp', From patchwork Wed Oct 9 07:41:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harvey Yang X-Patchwork-Id: 21554 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 77108C32E7 for ; Wed, 9 Oct 2024 07:46:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 52EAE6536F; Wed, 9 Oct 2024 09:46:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="GXEC7gYw"; dkim-atps=neutral Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F17D56536F for ; Wed, 9 Oct 2024 09:46:51 +0200 (CEST) Received: by mail-pj1-x102f.google.com with SMTP id 98e67ed59e1d1-2e199b1d157so4773870a91.2 for ; Wed, 09 Oct 2024 00:46:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728460010; x=1729064810; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=KTpmD1L4y0v1O2KJieH/lIMmNmwARc2tg5l3xqlLN5k=; b=GXEC7gYwNyE0EdxSlxG8V+hoLMuJAIz3f0ggY8IY770BnZ+8u1WCWu93oQIVzvMvyG eGd9K7xdD5YKWw85hqI/8ibvolXm2uHpVDKcGBU4yNu/1NA/l4rLENRBCbCxDryRhTe6 VmLKEqksoAuFAjdhGcWrRKewjmvK2EOWkV8Rc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728460010; x=1729064810; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KTpmD1L4y0v1O2KJieH/lIMmNmwARc2tg5l3xqlLN5k=; b=ss7mk/Edg2Z6Sr2gtfEQKt/5xZ6JyMjcnHKQvgd0NOHkUcvH0wZja0XI8HwNS0LTSu 2oSOxt4ZsEsZ6/oG17TVbNdQgbks1Hy8l7GgjV+vqzQg4t0J4ibqUYGymTsWYS/0zEqN 2xqr8lYY0mooK1He+2ckq7r1SSFvK5TCz601m7FZ1molQdy78/X/T6//L1y+rr3hXrlK o4JOFqvk7kn0ucXK0OeYPeX9k1h8sXCl6YR+Dq0HHoNG+hxEt8pEcxFvGgHNrGqIgBaj 90bv+aQQKwvQlo5gkiwamptGfs1/q4z/oRfdrAfzTbv213R7LMzPpdn88O96DBDIQ4z8 5puw== X-Gm-Message-State: AOJu0YwzH/cF6b4zDF5rBUWzxaSlsLQsHBrH2/bzldQTr+zKj7NNJLS2 6raa2Uw3P7OQlNfUCwGczoaqaIlss3LFfouBTT5UP/zLjmYt3RnsPYUvhjIqRKkL9x5DMCAqCtI = X-Google-Smtp-Source: AGHT+IEJ0Tjw06HXoNrNo4fgOVUUvOOBohGqPp62OkvEdQ4WaOAkT8/2erOwp3jlgvr66Eb+rsqIKg== X-Received: by 2002:a17:90b:fc8:b0:2d8:f7c6:e1dd with SMTP id 98e67ed59e1d1-2e2a25a04e1mr1904759a91.37.1728460010206; Wed, 09 Oct 2024 00:46:50 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (199.211.81.34.bc.googleusercontent.com. [34.81.211.199]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2a57077c2sm944414a91.17.2024.10.09.00.46.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 00:46:49 -0700 (PDT) From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Harvey Yang , Han-Lin Chen Subject: [PATCH 2/5] libcamera: Add template for pool implementation Date: Wed, 9 Oct 2024 07:41:20 +0000 Message-ID: <20241009074642.2965791-3-chenghaoyang@chromium.org> X-Mailer: git-send-email 2.47.0.rc0.187.ge670bccf7e-goog In-Reply-To: <20241009074642.2965791-1-chenghaoyang@chromium.org> References: <20241009074642.2965791-1-chenghaoyang@chromium.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add a template helper class as a Pool, which owns a list of objects that allows requesting and recycling objects. Mostly used as buffer pools. Signed-off-by: Han-Lin Chen Co-developed-by: Harvey Yang Signed-off-by: Harvey Yang --- include/libcamera/internal/meson.build | 1 + include/libcamera/internal/pool.h | 119 +++++++++++++++++++++++++ src/libcamera/meson.build | 1 + src/libcamera/pool.cpp | 70 +++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 include/libcamera/internal/pool.h create mode 100644 src/libcamera/pool.cpp diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index 4c1228b95..b78e51d0b 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -32,6 +32,7 @@ libcamera_internal_headers = files([ 'media_device.h', 'media_object.h', 'pipeline_handler.h', + 'pool.h', 'process.h', 'pub_key.h', 'request.h', diff --git a/include/libcamera/internal/pool.h b/include/libcamera/internal/pool.h new file mode 100644 index 000000000..578c6dd12 --- /dev/null +++ b/include/libcamera/internal/pool.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * pool.h - Template class for generic pool + * + * Common usage: + * + * Unique tokens: + * Pool>; + * + * Auto closed Fds: + * Pool; + * + * Auto destructed FrameBuffers: + * Pool>; + */ + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include + +namespace libcamera { + +LOG_DEFINE_CATEGORY(Pool) + +template +class Pool : public Loggable +{ +public: + Pool() = default; + ~Pool() = default; + + /* Loggable */ + std::string logPrefix() const override { return "Pool"; } + + void setData(std::vector &pool) + { + pool_.swap(pool); + free_.clear(); + inUse_.clear(); + + for (auto &fd : pool_) { + free_.emplace_back(fd.get()); + } + } + + void release() + { + pool_.clear(); + free_.clear(); + inUse_.clear(); + } + + std::vector &content() + { + return pool_; + } + + size_t size() + { + return pool_.size(); + } + + T get() + { + std::scoped_lock lock(mutex_); + + if (free_.empty()) + LOG(Pool, Fatal) << "not enough data in the Pool"; + + T fd = free_.front(); + free_.pop_front(); + inUse_.emplace(fd); + + return fd; + } + + void put(T data) + { + std::scoped_lock lock(mutex_); + + auto iter = std::find(inUse_.begin(), inUse_.end(), data); + if (iter == inUse_.end()) + LOG(Pool, Fatal) << "return data not belonging to the pool"; + + inUse_.erase(iter); + free_.emplace_front(data); + } + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(Pool) + + std::vector pool_; + std::deque free_; + std::set inUse_; + Mutex mutex_; +}; + +template +class BasicContainer +{ +public: + BasicContainer(T &value) + : value_(value) {} + T get() { return value_; } + +private: + T value_; +}; + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index 6c3ef5377..f4403687a 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -43,6 +43,7 @@ libcamera_internal_sources = files([ 'media_device.cpp', 'media_object.cpp', 'pipeline_handler.cpp', + 'pool.cpp', 'process.cpp', 'pub_key.cpp', 'shared_mem_object.cpp', diff --git a/src/libcamera/pool.cpp b/src/libcamera/pool.cpp new file mode 100644 index 000000000..122b025d1 --- /dev/null +++ b/src/libcamera/pool.cpp @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Google Inc. + * + * pool.cpp - Template class for generic pool + */ + +/** + * \class libcamera::Pool + * \brief Pool that owns a list of objects + * + * A Pool that owns a list of objects, and allows users to request objects and + * recycle them. It's mostly used as a buffer pool, holding a list of buffers + * as std::unique_ptr. + */ + +/** + * \fn Pool::setData(std::vector &pool) + * \brief Set and claim ownership of objects. Swap the previously owned objects + * not empty. + * \param[inout] pool The objects to be set and the swapped out ones + */ + +/** + * \fn Pool::release() + * \brief Release the ownership of objects and reset states + */ + +/** + * \fn Pool::content() + * \return The reference of objects + */ + +/** + * \fn Pool::size() + * \brief The size of objects + */ + +/** + * \fn Pool::get() + * \brief Get one object. Fatal if there's none available + * + * \return An available object + */ + +/** + * \fn Pool::put(T data) + * \brief Recycle one object that was retrieved by get() + * \param[in] data The object to be recycled + */ + +/** + * \class libcamera::BasicContainer + * \brief A container for basic types + * + * When using Pool with a basic type (e.g. `int`), it'd be easier to get an + * object by value instead of by pointer. BasicContainer makes it possible as a + * helper class. + */ + +/** + * \fn BasicContainer::BasicContainer(T &value) + * \brief Create a BasicContainer with a value + * \param[in] value The value to be contained + */ + +/** + * \fn BasicContainer::get() + * \return Return the object by value + */ From patchwork Wed Oct 9 07:41:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harvey Yang X-Patchwork-Id: 21555 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 885A4C32DE for ; Wed, 9 Oct 2024 07:46:57 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1B73A65376; Wed, 9 Oct 2024 09:46:57 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="R46HTvBU"; dkim-atps=neutral Received: from mail-pg1-x535.google.com (mail-pg1-x535.google.com [IPv6:2607:f8b0:4864:20::535]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id CF26263527 for ; Wed, 9 Oct 2024 09:46:53 +0200 (CEST) Received: by mail-pg1-x535.google.com with SMTP id 41be03b00d2f7-7ea16c7759cso1696474a12.1 for ; Wed, 09 Oct 2024 00:46:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728460012; x=1729064812; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LARBt1OC+m6EqoRtLJGDk6jJj2R9CzZ07H1YfA0LEvs=; b=R46HTvBUl0wCud2I1sRj+WIU9iwtjprdwWPCdAgvtQsyGBbOR2bFxhnI9AXYcEgneG fN5RXYaw3bpZhzhHn+e8jE0bHr747+GyQXqoT3jJdP/Spx7SGODNyT2pv0HRs6qJcOnF HfUXToVkZVjF3qXWZ7Z1x63HvKsf+Xq8ZyWAQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728460012; x=1729064812; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LARBt1OC+m6EqoRtLJGDk6jJj2R9CzZ07H1YfA0LEvs=; b=OAEk3IeuihIy3Mt3X3ug5u/C9tBrBU+Lrb1bIR3OadskkZHyZEHRYiKhqL77EzwOu1 uLOLEj5hID51r1642PG+R5LsW9p1tu8xX0/qeXUATMiaQ6VKJotuvrLDGhzDuc8m1uWn epWSQQWMO1l8I+Jx7O6x8ndMMfUuKrEdCoTWZxW/kDVAM5Mj8q+sGVhsErjrONx09gK5 nwfP038sYNS9yIg16LiGXFURQBuqVmBSx6Zrf8I6eXrq+E0aT5Lam3CmJVjfRstTwgsd 9Rp7HQWpAV3eZeFc3jfMkxZIxUBtwpyihjZlGzVuFvsxx56nhH1IZNH66NGCa6VV4U4/ WflA== X-Gm-Message-State: AOJu0Yxk7/rQ8LWO3lhm2CjmMhwVW+bctgCPKLKvJmbIEqEjLYLWf/2m G81221Tv+UG0hnooko8SBi51c5nf4pJlTp0u1Dufv3WMu4dW9UzGGMIwzZXeLauce+YaNk2nH88 71g== X-Google-Smtp-Source: AGHT+IFlQW9SdLiLmSVXsMQl5d7eA+0gtc1T3oyPHEBuDJqJY0vRxjNjYuhlgfRwVJjZVaaRLTgMSQ== X-Received: by 2002:a05:6a21:3944:b0:1d3:42f3:ff6d with SMTP id adf61e73a8af0-1d8a3c3a455mr2357609637.31.1728460012051; Wed, 09 Oct 2024 00:46:52 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (199.211.81.34.bc.googleusercontent.com. [34.81.211.199]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2a57077c2sm944414a91.17.2024.10.09.00.46.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 00:46:51 -0700 (PDT) From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Han-Lin Chen , Harvey Yang Subject: [PATCH 3/5] libcamera: format: Extend plane size calculation to accept scanline alignment Date: Wed, 9 Oct 2024 07:41:21 +0000 Message-ID: <20241009074642.2965791-4-chenghaoyang@chromium.org> X-Mailer: git-send-email 2.47.0.rc0.187.ge670bccf7e-goog In-Reply-To: <20241009074642.2965791-1-chenghaoyang@chromium.org> References: <20241009074642.2965791-1-chenghaoyang@chromium.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Han-Lin Chen As some platforms need alignment on scanline, this patch extends the format::planeSize() method to accept scanline alignment. Signed-off-by: Han-Lin Chen Co-developed-by: Harvey Yang Signed-off-by: Harvey Yang --- include/libcamera/internal/formats.h | 5 +++-- src/libcamera/formats.cpp | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/libcamera/internal/formats.h b/include/libcamera/internal/formats.h index 6a3e9c16a..143ab1dce 100644 --- a/include/libcamera/internal/formats.h +++ b/include/libcamera/internal/formats.h @@ -40,10 +40,11 @@ public: unsigned int stride(unsigned int width, unsigned int plane, unsigned int align = 1) const; unsigned int planeSize(const Size &size, unsigned int plane, - unsigned int align = 1) const; + unsigned int align = 1, unsigned scanAlign = 1) const; unsigned int planeSize(unsigned int height, unsigned int plane, unsigned int stride) const; - unsigned int frameSize(const Size &size, unsigned int align = 1) const; + unsigned int frameSize(const Size &size, unsigned int align = 1, + unsigned scanAlign = 1) const; unsigned int frameSize(const Size &size, const std::array &strides) const; diff --git a/src/libcamera/formats.cpp b/src/libcamera/formats.cpp index dbefb0947..7643a5a23 100644 --- a/src/libcamera/formats.cpp +++ b/src/libcamera/formats.cpp @@ -1093,6 +1093,7 @@ unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane, * \param[in] size The size of the frame, in pixels * \param[in] plane The plane index * \param[in] align The stride alignment, in bytes (1 for default alignment) + * \param[in] scanAlign The scanline alignment, in bytes (1 for default alignment) * * The plane size is computed by multiplying the line stride and the frame * height, taking subsampling and other format characteristics into account. @@ -1105,13 +1106,19 @@ unsigned int PixelFormatInfo::stride(unsigned int width, unsigned int plane, * format */ unsigned int PixelFormatInfo::planeSize(const Size &size, unsigned int plane, - unsigned int align) const + unsigned int align, unsigned scanAlign) const { unsigned int stride = PixelFormatInfo::stride(size.width, plane, align); if (!stride) return 0; - return planeSize(size.height, plane, stride); + unsigned int vertSubSample = planes[plane].verticalSubSampling; + if (!vertSubSample) + return 0; + + unsigned int planeHeight = (size.height + vertSubSample - 1) / vertSubSample; + + return stride * ((planeHeight + scanAlign - 1) / scanAlign * scanAlign); } /** @@ -1143,6 +1150,7 @@ unsigned int PixelFormatInfo::planeSize(unsigned int height, unsigned int plane, * \brief Compute the number of bytes necessary to store a frame * \param[in] size The size of the frame, in pixels * \param[in] align The stride alignment, in bytes (1 for default alignment) + * \param[in] scanAlign The scanline alignment, in bytes (1 for default alignment) * * The frame size is computed by adding the size of all planes, as computed by * planeSize(), using the specified alignment constraints for all planes. For @@ -1154,7 +1162,8 @@ unsigned int PixelFormatInfo::planeSize(unsigned int height, unsigned int plane, * \return The number of bytes necessary to store the frame, or 0 if the * PixelFormatInfo instance is not valid */ -unsigned int PixelFormatInfo::frameSize(const Size &size, unsigned int align) const +unsigned int PixelFormatInfo::frameSize(const Size &size, unsigned int align, + unsigned scanAlign) const { unsigned int sum = 0; @@ -1162,7 +1171,7 @@ unsigned int PixelFormatInfo::frameSize(const Size &size, unsigned int align) co if (plane.bytesPerGroup == 0) break; - sum += planeSize(size, i, align); + sum += planeSize(size, i, align, scanAlign); } return sum; From patchwork Wed Oct 9 07:41:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harvey Yang X-Patchwork-Id: 21556 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 ADBE8C32E7 for ; Wed, 9 Oct 2024 07:47:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 488DE63527; Wed, 9 Oct 2024 09:47:01 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="gJXAPL2e"; dkim-atps=neutral Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 75E0365373 for ; Wed, 9 Oct 2024 09:46:55 +0200 (CEST) Received: by mail-pj1-x102e.google.com with SMTP id 98e67ed59e1d1-2e29522f0f1so954000a91.0 for ; Wed, 09 Oct 2024 00:46:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728460014; x=1729064814; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hIYRjwA8UoGnGjd32bbuoBgeCFx8Qw8gErvHW8Wrnvw=; b=gJXAPL2eqGNQoQrB8Dp6ApUz9n6luulWraxZ45AXh4Z4uBf0H5+rxLOkPLJoMddl6Q aYw5HTv45hYctIJlpRjyAN3IDlFAXM/ZeqmBWL9fKN3ET3XgCxTpwio0DiVPJC0yfolI +Fe12ytUHDb+uG01YUi/j7IB/GzPnBdH0bYY4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728460014; x=1729064814; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hIYRjwA8UoGnGjd32bbuoBgeCFx8Qw8gErvHW8Wrnvw=; b=E+9sPZrkjHdRifQ/zv/Jt79aUT0lhmQ3y/r3Oex87TUyEA30Ig/azBXJGF/pldAH6I k1vpk7BUi6Ex78xMfRVExt8xV++CShJWhaF51iH5mUsOwATGDsB78oKbScrFJSgkSrBB Tu7rIiW1lqgt+RfNNoGkKhYftXiboyVae56Nr8IwdWipNQiJw4kMhwMNvMLTjQ8xvtl6 WwX+hLbZuEwQ+3bak15lzhrSRREUkEEQmMQw7ruzC4iWRhgrA6shH5/u59dxeXSbq4rY djGLTx1IgVqHxaIOuhRNnY64F42wgxVI4CSW+wAGJHAb7Ps1W386C/kImjh64eNw6IjX lcfg== X-Gm-Message-State: AOJu0Yy1+gWY+Fx1nTN6SR9cGPBK0Wgtk58oUTnhDr3ExA7FCyEvWUP3 /I+WOV/d2XwoZPvyMFrTc3pf7JzKXaFeEs0KOZRc14/R7Naw75pwFuv7GdhPMciXIi9+hgV4WtE jdw== X-Google-Smtp-Source: AGHT+IGhpAn5NpRtGtKjEr8o4YFApr6aKAtH2EF99znKPWIMSgohChmotRBfaLeiXwS43nFjDpYd2g== X-Received: by 2002:a17:90b:1288:b0:2e0:7012:335a with SMTP id 98e67ed59e1d1-2e2a21eb985mr1820248a91.6.1728460013686; Wed, 09 Oct 2024 00:46:53 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (199.211.81.34.bc.googleusercontent.com. [34.81.211.199]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2a57077c2sm944414a91.17.2024.10.09.00.46.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 00:46:53 -0700 (PDT) From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Harvey Yang Subject: [PATCH 4/5] libcamera: Add stride in FrameBuffer::Plane Date: Wed, 9 Oct 2024 07:41:22 +0000 Message-ID: <20241009074642.2965791-5-chenghaoyang@chromium.org> X-Mailer: git-send-email 2.47.0.rc0.187.ge670bccf7e-goog In-Reply-To: <20241009074642.2965791-1-chenghaoyang@chromium.org> References: <20241009074642.2965791-1-chenghaoyang@chromium.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Some platforms, like mtkisp7, need the stride information in a FrameBuffer. This patch adds the member variable in FrameBuffer::Plane, and appends the member variable in IPA (de)serializer. Signed-off-by: Harvey Yang --- include/libcamera/framebuffer.h | 1 + src/libcamera/dma_buf_allocator.cpp | 3 ++- src/libcamera/framebuffer.cpp | 5 +++++ src/libcamera/ipa_data_serializer.cpp | 3 +++ 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/libcamera/framebuffer.h b/include/libcamera/framebuffer.h index ff8392430..059c66f31 100644 --- a/include/libcamera/framebuffer.h +++ b/include/libcamera/framebuffer.h @@ -55,6 +55,7 @@ public: SharedFD fd; unsigned int offset = kInvalidOffset; unsigned int length; + unsigned int stride; }; FrameBuffer(const std::vector &planes, unsigned int cookie = 0); diff --git a/src/libcamera/dma_buf_allocator.cpp b/src/libcamera/dma_buf_allocator.cpp index 262eb53a0..e6a29c2d7 100644 --- a/src/libcamera/dma_buf_allocator.cpp +++ b/src/libcamera/dma_buf_allocator.cpp @@ -255,7 +255,8 @@ DmaBufAllocator::createBuffer(std::string name, return nullptr; for (auto planeSize : planeSizes) { - planes.emplace_back(FrameBuffer::Plane{ fd, offset, planeSize }); + /* \todo Invalid stride information. Consider adding strides as input. */ + planes.emplace_back(FrameBuffer::Plane{ fd, offset, planeSize, 0 }); offset += planeSize; } diff --git a/src/libcamera/framebuffer.cpp b/src/libcamera/framebuffer.cpp index 826848f75..61a3cc024 100644 --- a/src/libcamera/framebuffer.cpp +++ b/src/libcamera/framebuffer.cpp @@ -282,6 +282,11 @@ FrameBuffer::Private::~Private() * \brief The plane length in bytes */ +/** + * \var FrameBuffer::Plane::stride + * \brief The plane stride in bytes + */ + namespace { ino_t fileDescriptorInode(const SharedFD &fd) diff --git a/src/libcamera/ipa_data_serializer.cpp b/src/libcamera/ipa_data_serializer.cpp index 2189a2466..d9d76c57c 100644 --- a/src/libcamera/ipa_data_serializer.cpp +++ b/src/libcamera/ipa_data_serializer.cpp @@ -572,6 +572,7 @@ SharedFD IPADataSerializer::deserialize(const std::vector &da * 4 byte - SharedFD * 4 bytes - uint32_t Offset * 4 bytes - uint32_t Length + * 4 bytes - uint32_t Stride */ template<> std::tuple, std::vector> @@ -590,6 +591,7 @@ IPADataSerializer::serialize(const FrameBuffer::Plane &data, appendPOD(dataVec, data.offset); appendPOD(dataVec, data.length); + appendPOD(dataVec, data.stride); return { dataVec, fdsVec }; } @@ -608,6 +610,7 @@ IPADataSerializer::deserialize(std::vector::const_i fdsBegin, fdsBegin + 1); ret.offset = readPOD(dataBegin, 4, dataEnd); ret.length = readPOD(dataBegin, 8, dataEnd); + ret.stride = readPOD(dataBegin, 12, dataEnd); return ret; } From patchwork Wed Oct 9 07:41:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Harvey Yang X-Patchwork-Id: 21557 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 1C62CC32DE for ; Wed, 9 Oct 2024 07:47:03 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C72A265372; Wed, 9 Oct 2024 09:47:02 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="Cemb5dEo"; dkim-atps=neutral Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 06CD965372 for ; Wed, 9 Oct 2024 09:46:57 +0200 (CEST) Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-20c593d6b1cso13713525ad.0 for ; Wed, 09 Oct 2024 00:46:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1728460015; x=1729064815; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1jCHNJHRlUl6YhNHIyh2oLEZ9RXC+uN9lCYMqUib2tg=; b=Cemb5dEonj3IEN+YjMNCfHX/6XdFUsWBS1/4rElENluycL9cxuscImQAi9CYTzW1h+ XORyGeuyx7fwGmoHo7pE9nMTzxCi48pujZdSZdZDGx5THUoEmKo8wc41wspZaZ17YdWr vBRABNNH8eYOjruK2ClLY5l2MTzXSni/W5s+s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728460015; x=1729064815; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1jCHNJHRlUl6YhNHIyh2oLEZ9RXC+uN9lCYMqUib2tg=; b=YMidVPThteqatbB+rpEiYsyNViCxbTrc1QNNlx70/Nxs0PWBcdgsKPLpBYUQAJxqM2 tvckko+o8hFa7Sh+BbCY/2iXxU6WdtLHFN6Qch1xWx6h+K20R0eeDx+/NBLxdI9daLJz QUTfhIv43y1zfYQmmysjNbNmOXWlkqXU7uWKuVe8Dtz6aLvaiDOKLHFBLCfXxLWLIcue naXbW/Y1flIMH3gzn26PQcdibKELchDCtzs1DeiyM1cvuE2D1ICdaIsmUbXX1ts7bvyd n7/TkWvPLGidZW2XQDhLUWiR2EO7JF3Ik6KXouauR7c55kTUAEs2MMuntSnWlm6S8rl1 x+/A== X-Gm-Message-State: AOJu0YzxmtDRHPdFGIyJCK+hUuK1PdzVOpA+Xv327N6ASjVBov3ukWyP SdfriyvhWBRpJDbvgcJ/LDAe7ETrvrcKiiyJgLyK54IrnxkSzNVCWWGndsTDxCSrl0unppJxpl8 W/A== X-Google-Smtp-Source: AGHT+IEZf+5PvCmrrbWy3OGP1dJ6Kf3KUG1/Dh5z8gwbe1pQAGZeDHFQgp8JVnlK9gX4w6uFMFuXDQ== X-Received: by 2002:a17:902:f68a:b0:206:aac4:b844 with SMTP id d9443c01a7336-20c636dcbf4mr22252365ad.6.1728460015087; Wed, 09 Oct 2024 00:46:55 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (199.211.81.34.bc.googleusercontent.com. [34.81.211.199]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2e2a57077c2sm944414a91.17.2024.10.09.00.46.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Oct 2024 00:46:54 -0700 (PDT) From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Harvey Yang , Han-Lin Chen Subject: [PATCH 5/5] libcamera: Add InfoFrame implememtation Date: Wed, 9 Oct 2024 07:41:23 +0000 Message-ID: <20241009074642.2965791-6-chenghaoyang@chromium.org> X-Mailer: git-send-email 2.47.0.rc0.187.ge670bccf7e-goog In-Reply-To: <20241009074642.2965791-1-chenghaoyang@chromium.org> References: <20241009074642.2965791-1-chenghaoyang@chromium.org> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" InfoFrame consists of an InfoFrame class which is used as an extension of FrameBuffer, with extra information of pixel format, size, and memory address if it's mmapped. InfoFramePool is introduced to handle InfoFrames more easily, which supports a pool implementation of InfoFrames, creates frames by DmaBufAllocator, and mmap/munmap all frames of the pool. Signed-off-by: Han-Lin Chen Co-developed-by: Harvey Yang Signed-off-by: Harvey Yang --- include/libcamera/internal/info_frame.h | 105 ++++++++ include/libcamera/internal/meson.build | 1 + src/libcamera/info_frame.cpp | 302 ++++++++++++++++++++++++ src/libcamera/meson.build | 1 + 4 files changed, 409 insertions(+) create mode 100644 include/libcamera/internal/info_frame.h create mode 100644 src/libcamera/info_frame.cpp diff --git a/include/libcamera/internal/info_frame.h b/include/libcamera/internal/info_frame.h new file mode 100644 index 000000000..29b445bb3 --- /dev/null +++ b/include/libcamera/internal/info_frame.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2023, Google Inc. + * + * info_frame.h - InfoFrame and InfoFramePool + */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include "libcamera/internal/dma_buf_allocator.h" +#include "libcamera/internal/mailbox.h" +#include "libcamera/internal/pool.h" + +namespace libcamera { + +class InfoFrame +{ +public: + struct Plane { + uint8_t *address; + }; + + InfoFrame(); + InfoFrame(const PixelFormat &format, const Size &size, FrameBuffer *buffers, + unsigned int strideAlign = 1, unsigned int scanAlign = 1, + std::array planes = {}); + + uint8_t *address(unsigned int plane) const; + + PixelFormat format() const { return format_; } + Size size() const { return size_; } + FrameBuffer *buffer() const { return buffer_; } + unsigned int numPlanes() const { return buffer_ ? buffer_->planes().size() : 0; } + unsigned int strideAlign() const { return strideAlign_; } + unsigned int scanAlign() const { return scanAlign_; } + +private: + Size size_; + PixelFormat format_; + FrameBuffer *buffer_ = nullptr; + + unsigned int strideAlign_ = 1; + unsigned int scanAlign_ = 1; + + std::array planes_; +}; + +class InfoFramePool +{ +public: + struct MappedBufferInfo { + uint8_t *address = nullptr; + size_t dmabufLength = 0; + }; + + InfoFramePool(); + ~InfoFramePool(); + + int createBuffers(DmaBufAllocator *dmaHeap, const PixelFormat &format, + const Size &size, uint32_t count, + unsigned int strideAlign = 1, unsigned scanAlign = 1); + + void release(); + + void fetch(SharedMailBox &mailBox); + + int mmap(); + int munmap(); + + bool mapped() const { return 0 != mappedBuffers_.size(); } + + size_t size() { return pool_.size(); } + std::vector> &content() + { + return pool_.content(); + } + +private: + LIBCAMERA_DISABLE_COPY_AND_MOVE(InfoFramePool) + + void setBuffers(const PixelFormat &format, const Size &size, + std::vector> &buffers, + unsigned int align, unsigned int scanAlign); + + InfoFrame get(); + void put(InfoFrame &frameInfo); + + Size size_; + PixelFormat format_; + Pool> pool_; + unsigned int strideAlign_; + unsigned int scanAlign_; + + std::unordered_map mappedBuffers_; +}; + +} /* namespace libcamera */ diff --git a/include/libcamera/internal/meson.build b/include/libcamera/internal/meson.build index b78e51d0b..8983bcd21 100644 --- a/include/libcamera/internal/meson.build +++ b/include/libcamera/internal/meson.build @@ -21,6 +21,7 @@ libcamera_internal_headers = files([ 'dma_buf_allocator.h', 'formats.h', 'framebuffer.h', + 'info_frame.h', 'ipa_data_serializer.h', 'ipa_manager.h', 'ipa_module.h', diff --git a/src/libcamera/info_frame.cpp b/src/libcamera/info_frame.cpp new file mode 100644 index 000000000..5407fadd9 --- /dev/null +++ b/src/libcamera/info_frame.cpp @@ -0,0 +1,302 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023, Google Inc. + * + * info_frame.cpp - InfoFrame and InfoFramePool + */ + +#include "libcamera/internal/info_frame.h" + +#include +#include + +#include "libcamera/internal/dma_buf_allocator.h" +#include "libcamera/internal/formats.h" +#include "libcamera/internal/pool.h" + +namespace libcamera { + +LOG_DEFINE_CATEGORY(InfoFrame) + +/** + * \class InfoFrame + * \brief A wrapper class that consists of a FrameBuffer and extra information, + * including PixelFormat, size, and memory address if it's mmap'ed. + */ + +/** + * \class InfoFrame::Plane + * \brief Per-plane frame mmap'ed address + * + * Frames are stored in memory in one or multiple planes. The + * InfoFrame::Plane structure stores per-plane mmap'ed address. + */ + +/** + * \var InfoFrame::Plane::address + * \brief mmap'ed address of a plane + */ + +InfoFrame::InfoFrame() = default; + +/** + * \brief Create an InfoFrame instance + * \param[in] format PixelFormat of the frame + * \param[in] size Size of the frame + * \param[in] buffer Pointer to the buffer. InfoFrame doesn't take the ownership + * \param[in] strideAlign The stride alignment, in bytes (1 for default alignment) + * \param[in] scanAlign The scanline alignment, in bytes (1 for default alignment) + * \param[in] planes mmap'ed addresses of planes + */ +InfoFrame::InfoFrame(const PixelFormat &format, const Size &size, + FrameBuffer *buffer, unsigned int strideAlign, + unsigned int scanAlign, std::array planes) + : size_(size), format_(format), buffer_(buffer), + strideAlign_(strideAlign), scanAlign_(scanAlign), + planes_(planes) + +{ +} + +/** + * \brief Get the mmap'ed address of \a plane + * \param[in] plane The \a plane'th plane + * \return Return the mmap'ed address of the plane + */ +uint8_t *InfoFrame::address(unsigned int plane) const +{ + return (plane < numPlanes()) ? planes_[plane].address : nullptr; +} + +/** + * \fn InfoFrame::format() + * \return Return the PixelFormat of the frame + */ + +/** + * \fn InfoFrame::size() + * \return Return the size of the frame + */ + +/** + * \fn InfoFrame::buffer() + * \return Return the pointer to the buffer + */ + +/** + * \fn InfoFrame::numPlanes() + * \return Return the number of planes of the buffer + */ + +/** + * \fn InfoFrame::strideAlign() + * \return Return the stride alignment, in bytes (1 for default alignment) + */ + +/** + * \fn InfoFrame::scanAlign() + * \return Return the scanline alignment, in bytes (1 for default alignment) + */ + +/** + * \class InfoFramePool + * \brief A buffer pool that allows users to allocate and request InfoFrame + * buffers from DmaBufAllocator + */ + +/** + * \struct InfoFramePool::MappedBufferInfo + * \brief Contains the information of the mmap'ed buffers, including address + * and length + */ + +/** + * \var InfoFramePool::MappedBufferInfo::address + * \brief mmap'ed address of a buffer + */ + +/** + * \var InfoFramePool::MappedBufferInfo::dmabufLength + * \brief Length of the DMA buffer + */ + +InfoFramePool::InfoFramePool() = default; + +InfoFramePool::~InfoFramePool() +{ + release(); +} + +/** + * \brief Create DMA buffers + * \param[in] dmaHeap The DmaBufAllocator to allocate buffers from + * \param[in] format PixelFormat of each frame + * \param[in] size Size of each frame + * \param[in] count Number of frames to create + * \param[in] strideAlign The stride alignment, in bytes (1 for default alignment) + * \param[in] scanAlign The scanline alignment, in bytes (1 for default alignment) + * + * \return 0 on success or a negative error code otherwise + */ +int InfoFramePool::createBuffers(DmaBufAllocator *dmaHeap, + const PixelFormat &format, const Size &size, + unsigned int count, + unsigned int strideAlign, unsigned scanAlign) +{ + release(); + + const PixelFormatInfo &info = PixelFormatInfo::info(format); + uint32_t frameSize = info.frameSize(size, strideAlign, scanAlign); + + std::vector> buffers; + buffers.reserve(count); + for (unsigned int i = 0; i < count; i++) { + SharedFD fd(dmaHeap->alloc(("frame-" + std::to_string(i)).c_str(), + frameSize)); + if (!fd.isValid()) { + buffers.clear(); + return -EBUSY; + } + + uint32_t offset = 0; + std::vector planes; + + for (unsigned int j = 0; j < info.numPlanes(); j++) { + planes.emplace_back(FrameBuffer::Plane{ + fd, offset, + info.planeSize(size, j, strideAlign, scanAlign), + info.stride(size.width, j, strideAlign) }); + offset += planes.back().length; + } + + buffers.emplace_back(std::make_unique(planes)); + } + + setBuffers(format, size, buffers, strideAlign, scanAlign); + + return 0; +} + +/** + * \brief Release all allocated buffers. InfoFramePool can create another set + * of buffers again. + */ +void InfoFramePool::release() +{ + if (munmap()) + LOG(InfoFrame, Error) << "Failed to unmap mapped buffers"; + + pool_.release(); +} + +/** + * \brief Fetch an available InfoFrame from the pool + * \param[out] mailBox The shared pointer of MailBox to store the fetched + * InfoFrame + * + * When \a mailBox is reset, the recycler will return the InfoFrame back to the + * InfoFramePool. + */ +void InfoFramePool::fetch(SharedMailBox &mailBox) +{ + auto recycler = [this](InfoFrame &info) { + this->put(info); + }; + + mailBox->put(get(), recycler); +} + +/** + * \brief mmap all allocated buffers and set the addresses in `InfoFrame`s + */ +int InfoFramePool::mmap() +{ + if (!mappedBuffers_.empty()) + return 0; + + for (auto &buffer : pool_.content()) { + for (const FrameBuffer::Plane &plane : buffer->planes()) { + const int fd = plane.fd.get(); + if (mappedBuffers_.find(fd) == mappedBuffers_.end()) { + const size_t length = lseek(fd, 0, SEEK_END); + mappedBuffers_[fd] = MappedBufferInfo{ nullptr, length }; + } + } + } + + for (auto &[fd, info] : mappedBuffers_) { + void *address = ::mmap(nullptr, info.dmabufLength, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + info.address = static_cast(address); + } + return 0; +} + +/** + * \brief munmap all allocated buffers and reset addresses + */ +int InfoFramePool::munmap() +{ + if (mappedBuffers_.empty()) + return 0; + + for (auto &[_, info] : mappedBuffers_) { + ::munmap(info.address, info.dmabufLength); + info.address = nullptr; + } + + mappedBuffers_.clear(); + return 0; +} + +/** + * \fn InfoFramePool::mapped() + * \return True if mmap() was called on the allocated buffers, false otherwise + */ + +/** + * \fn InfoFramePool::size() + * \return Return the number of `InfoFrame`s allocated + */ + +/** + * \fn InfoFramePool::content() + * \return Return frame buffers allocated in the pool + */ + +void InfoFramePool::setBuffers(const PixelFormat &format, const Size &size, + std::vector> &buffers, + unsigned int strideAlign, unsigned int scanAlign) +{ + if (munmap()) + LOG(InfoFrame, Error) << "Failed to unmap buffers"; + + size_ = size; + format_ = format; + pool_.setData(buffers); + strideAlign_ = strideAlign; + scanAlign_ = scanAlign; +} + +InfoFrame InfoFramePool::get() +{ + FrameBuffer *buffer = pool_.get(); + + std::array planes; + for (size_t i = 0; i < buffer->planes().size() && i < 3; i++) { + const int fd = buffer->planes()[i].fd.get(); + const unsigned int offset = buffer->planes()[i].offset; + + if (mappedBuffers_.count(fd)) + planes[i].address = mappedBuffers_[fd].address + offset; + } + + return InfoFrame(format_, size_, buffer, strideAlign_, scanAlign_, planes); +} + +void InfoFramePool::put(InfoFrame &info) +{ + pool_.put(info.buffer()); +} + +} /* namespace libcamera */ diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build index f4403687a..39483b458 100644 --- a/src/libcamera/meson.build +++ b/src/libcamera/meson.build @@ -29,6 +29,7 @@ libcamera_internal_sources = files([ 'device_enumerator_sysfs.cpp', 'dma_buf_allocator.cpp', 'formats.cpp', + 'info_frame.cpp', 'ipa_controls.cpp', 'ipa_data_serializer.cpp', 'ipa_interface.cpp',