From patchwork Tue Sep 8 07:49:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9517 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 3828CBDB1C for ; Tue, 8 Sep 2020 07:49:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 050C762BF5; Tue, 8 Sep 2020 09:49:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="AZEb9+Vb"; dkim-atps=neutral Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EEE1362B90 for ; Tue, 8 Sep 2020 09:49:19 +0200 (CEST) Received: by mail-wr1-x430.google.com with SMTP id k15so17970850wrn.10 for ; Tue, 08 Sep 2020 00:49:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=RwctxmJSFTe6+XjCaT5M2+31UMCk6sU6+3dJg6rPVGI=; b=AZEb9+VbC5YpRupQB13g2fuOxqlsjLFYL/RG/gFAV4lddWS+BMyGnCZmU8P5lGU8iS 3L00omceOIPR/JVgkz7KOD8PKV809ki2aAI/Oqaa5NRcHGRV+t3HSBE0k8L5cxt2KKtG p7SZtXsbDA3kRJ9KkxrvmsbTjrLvTmCsIDT2YVXhE8tCy+5DkteaDPvrV6G4eoefECtg 3S5qovPmWhkYuKnQbasFbidMNEMGTXJiDOUUXCfnZf798tDCK0UHKWVPVqR5U9IatmFF JZryTf4ZFh+CV5doClUYATyKn9HNnoQkkL4iKPCP7uozEqvIsJMhNnxhrNKY5MY8YzyW 27NQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=RwctxmJSFTe6+XjCaT5M2+31UMCk6sU6+3dJg6rPVGI=; b=gsBNiVRczHzSjlltIeQymzfJKc7WUf2iXkqIkW20JAlebPoF5LCEi4glSeN+bioSTO Jy92T3SAgChKP/WtGjIk/wIdawDYt8U/wcnxaPyYK9FSoMUVEaoz0agiXod3llbzwvc+ uvkKncoFFXJ5J7pUG3QEVQO8JX/bFpXowOCRKn86icP0XgJ81807vIXPdKisjWweF6Nx NE7gqc6YZcfJHE8hIlDoDbuhKUDCrkmbE2wmkBvhnK3UsaMgKv64LGvAzL3nDpcWqOul i+vokB81eVuS3e0AhGUopsnEc/V4LOGHyY9fv5IIH8EmRDQlUnY7HcvtFdVhAliKY3Dy nrcg== X-Gm-Message-State: AOAM532Ak2d4qi6IXhkKKnGC63DGsb1bbRvl6jo8L6uZlN+T2a9hnfyy omoPKYocPyLWnGgjzyw3Ixy5fSZPAggtgw== X-Google-Smtp-Source: ABdhPJyY608CXKUWraEMJRo87FSjIDREnIrmn+mwlyrIDYH/8hwgR3viCx7pw6IKmpRzgkP18rbyfw== X-Received: by 2002:adf:df0f:: with SMTP id y15mr25175184wrl.127.1599551358952; Tue, 08 Sep 2020 00:49:18 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:18 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:01 +0100 Message-Id: <20200908074913.109244-2-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 01/12] libcamera: pipeline: raspberrypi: Move RPiStream into a separate file 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" Put RPiStream into the RPi namespace and add a new log category (RPISTREAM). Reorder methods into logical groups for readability. There are no functional changes in this commit. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Tested-by: David Plowman --- .../pipeline/raspberrypi/meson.build | 1 + .../pipeline/raspberrypi/raspberrypi.cpp | 193 ++---------------- .../pipeline/raspberrypi/rpi_stream.cpp | 116 +++++++++++ .../pipeline/raspberrypi/rpi_stream.h | 107 ++++++++++ 4 files changed, 243 insertions(+), 174 deletions(-) create mode 100644 src/libcamera/pipeline/raspberrypi/rpi_stream.cpp create mode 100644 src/libcamera/pipeline/raspberrypi/rpi_stream.h diff --git a/src/libcamera/pipeline/raspberrypi/meson.build b/src/libcamera/pipeline/raspberrypi/meson.build index ae0aed3b..7c5b6ff7 100644 --- a/src/libcamera/pipeline/raspberrypi/meson.build +++ b/src/libcamera/pipeline/raspberrypi/meson.build @@ -3,5 +3,6 @@ libcamera_sources += files([ 'dma_heaps.cpp', 'raspberrypi.cpp', + 'rpi_stream.cpp', 'staggered_ctrl.cpp', ]) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index ce43af34..3d94b3ed 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include @@ -33,6 +32,7 @@ #include "libcamera/internal/v4l2_videodevice.h" #include "dma_heaps.h" +#include "rpi_stream.h" #include "staggered_ctrl.h" namespace libcamera { @@ -122,165 +122,10 @@ V4L2DeviceFormat findBestMode(V4L2VideoDevice::Formats &formatsMap, return bestMode; } -} /* namespace */ - -/* - * Device stream abstraction for either an internal or external stream. - * Used for both Unicam and the ISP. - */ -class RPiStream : public Stream -{ -public: - RPiStream() - { - } - - RPiStream(const char *name, MediaEntity *dev, bool importOnly = false) - : external_(false), importOnly_(importOnly), name_(name), - dev_(std::make_unique(dev)) - { - } - - V4L2VideoDevice *dev() const - { - return dev_.get(); - } - - void setExternal(bool external) - { - external_ = external; - } - - bool isExternal() const - { - /* - * Import streams cannot be external. - * - * RAW capture is a special case where we simply copy the RAW - * buffer out of the request. All other buffer handling happens - * as if the stream is internal. - */ - return external_ && !importOnly_; - } - - bool isImporter() const - { - return importOnly_; - } - - void reset() - { - external_ = false; - internalBuffers_.clear(); - } - - std::string name() const - { - return name_; - } - - void setExternalBuffers(std::vector> *buffers) - { - externalBuffers_ = buffers; - } - - const std::vector> *getBuffers() const - { - return external_ ? externalBuffers_ : &internalBuffers_; - } - - void releaseBuffers() - { - dev_->releaseBuffers(); - if (!external_ && !importOnly_) - internalBuffers_.clear(); - } - - int importBuffers(unsigned int count) - { - return dev_->importBuffers(count); - } - - int allocateBuffers(unsigned int count) - { - return dev_->allocateBuffers(count, &internalBuffers_); - } - - int queueBuffers() - { - if (external_) - return 0; - - for (auto &b : internalBuffers_) { - int ret = dev_->queueBuffer(b.get()); - if (ret) { - LOG(RPI, Error) << "Failed to queue buffers for " - << name_; - return ret; - } - } - - return 0; - } - - bool findFrameBuffer(FrameBuffer *buffer) const - { - auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin(); - auto end = external_ ? externalBuffers_->end() : internalBuffers_.end(); - - if (importOnly_) - return false; - - if (std::find_if(start, end, - [buffer](std::unique_ptr const &ref) { return ref.get() == buffer; }) != end) - return true; - - return false; - } - -private: - /* - * Indicates that this stream is active externally, i.e. the buffers - * are provided by the application. - */ - bool external_; - /* Indicates that this stream only imports buffers, e.g. ISP input. */ - bool importOnly_; - /* Stream name identifier. */ - std::string name_; - /* The actual device stream. */ - std::unique_ptr dev_; - /* Internally allocated framebuffers associated with this device stream. */ - std::vector> internalBuffers_; - /* Externally allocated framebuffers associated with this device stream. */ - std::vector> *externalBuffers_; -}; - -/* - * The following class is just a convenient (and typesafe) array of device - * streams indexed with an enum class. - */ enum class Unicam : unsigned int { Image, Embedded }; enum class Isp : unsigned int { Input, Output0, Output1, Stats }; -template -class RPiDevice : public std::array -{ -private: - constexpr auto index(E e) const noexcept - { - return static_cast>(e); - } -public: - RPiStream &operator[](E e) - { - return std::array::operator[](index(e)); - } - const RPiStream &operator[](E e) const - { - return std::array::operator[](index(e)); - } -}; +} /* namespace */ class RPiCameraData : public CameraData { @@ -304,15 +149,15 @@ public: void ispOutputDequeue(FrameBuffer *buffer); void clearIncompleteRequests(); - void handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream); + void handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream); void handleState(); CameraSensor *sensor_; /* Array of Unicam and ISP device streams and associated buffers/streams. */ - RPiDevice unicam_; - RPiDevice isp_; + RPi::RPiDevice unicam_; + RPi::RPiDevice isp_; /* The vector below is just for convenience when iterating over all streams. */ - std::vector streams_; + std::vector streams_; /* Buffers passed to the IPA. */ std::vector ipaBuffers_; @@ -761,7 +606,7 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stream *stream, std::vector> *buffers) { - RPiStream *s = static_cast(stream); + RPi::RPiStream *s = static_cast(stream); unsigned int count = stream->configuration().bufferCount; int ret = s->dev()->exportBuffers(count, buffers); @@ -908,14 +753,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator) return false; /* Locate and open the unicam video streams. */ - data->unicam_[Unicam::Embedded] = RPiStream("Unicam Embedded", unicam_->getEntityByName("unicam-embedded")); - data->unicam_[Unicam::Image] = RPiStream("Unicam Image", unicam_->getEntityByName("unicam-image")); + data->unicam_[Unicam::Embedded] = RPi::RPiStream("Unicam Embedded", unicam_->getEntityByName("unicam-embedded")); + data->unicam_[Unicam::Image] = RPi::RPiStream("Unicam Image", unicam_->getEntityByName("unicam-image")); /* Tag the ISP input stream as an import stream. */ - data->isp_[Isp::Input] = RPiStream("ISP Input", isp_->getEntityByName("bcm2835-isp0-output0"), true); - data->isp_[Isp::Output0] = RPiStream("ISP Output0", isp_->getEntityByName("bcm2835-isp0-capture1")); - data->isp_[Isp::Output1] = RPiStream("ISP Output1", isp_->getEntityByName("bcm2835-isp0-capture2")); - data->isp_[Isp::Stats] = RPiStream("ISP Stats", isp_->getEntityByName("bcm2835-isp0-capture3")); + data->isp_[Isp::Input] = RPi::RPiStream("ISP Input", isp_->getEntityByName("bcm2835-isp0-output0"), true); + data->isp_[Isp::Output0] = RPi::RPiStream("ISP Output0", isp_->getEntityByName("bcm2835-isp0-capture1")); + data->isp_[Isp::Output1] = RPi::RPiStream("ISP Output1", isp_->getEntityByName("bcm2835-isp0-capture2")); + data->isp_[Isp::Stats] = RPi::RPiStream("ISP Stats", isp_->getEntityByName("bcm2835-isp0-capture3")); /* This is just for convenience so that we can easily iterate over all streams. */ for (auto &stream : data->unicam_) @@ -1013,7 +858,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) */ unsigned int maxBuffers = 0; for (const Stream *s : camera->streams()) - if (static_cast(s)->isExternal()) + if (static_cast(s)->isExternal()) maxBuffers = std::max(maxBuffers, s->configuration().bufferCount); for (auto const stream : data->streams_) { @@ -1257,12 +1102,12 @@ done: void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer) { - const RPiStream *stream = nullptr; + const RPi::RPiStream *stream = nullptr; if (state_ == State::Stopped) return; - for (RPiStream const &s : unicam_) { + for (RPi::RPiStream const &s : unicam_) { if (s.findFrameBuffer(buffer)) { stream = &s; break; @@ -1318,12 +1163,12 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer) void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) { - const RPiStream *stream = nullptr; + const RPi::RPiStream *stream = nullptr; if (state_ == State::Stopped) return; - for (RPiStream const &s : isp_) { + for (RPi::RPiStream const &s : isp_) { if (s.findFrameBuffer(buffer)) { stream = &s; break; @@ -1404,7 +1249,7 @@ void RPiCameraData::clearIncompleteRequests() } } -void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream) +void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream) { if (stream->isExternal()) { if (!dropFrame_) { diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp new file mode 100644 index 00000000..2e52bd5c --- /dev/null +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Raspberry Pi (Trading) Ltd. + * + * rpi_stream.cpp - Raspberry Pi device stream abstraction class. + */ +#include "rpi_stream.h" + +#include "libcamera/internal/log.h" + +namespace libcamera { + +LOG_DEFINE_CATEGORY(RPISTREAM) + +namespace RPi { + +V4L2VideoDevice *RPiStream::dev() const +{ + return dev_.get(); +} + +std::string RPiStream::name() const +{ + return name_; +} + +void RPiStream::reset() +{ + external_ = false; + internalBuffers_.clear(); +} + +bool RPiStream::isImporter() const +{ + return importOnly_; +} + +void RPiStream::setExternal(bool external) +{ + external_ = external; +} + +bool RPiStream::isExternal() const +{ + /* + * Import streams cannot be external. + * + * RAW capture is a special case where we simply copy the RAW + * buffer out of the request. All other buffer handling happens + * as if the stream is internal. + */ + return external_ && !importOnly_; +} + +void RPiStream::setExternalBuffers(std::vector> *buffers) +{ + externalBuffers_ = buffers; +} + +const std::vector> *RPiStream::getBuffers() const +{ + return external_ ? externalBuffers_ : &internalBuffers_; +} + +bool RPiStream::findFrameBuffer(FrameBuffer *buffer) const +{ + auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin(); + auto end = external_ ? externalBuffers_->end() : internalBuffers_.end(); + + if (importOnly_) + return false; + + if (std::find_if(start, end, + [buffer](std::unique_ptr const &ref) { return ref.get() == buffer; }) != end) + return true; + + return false; +} + +int RPiStream::importBuffers(unsigned int count) +{ + return dev_->importBuffers(count); +} + +int RPiStream::allocateBuffers(unsigned int count) +{ + return dev_->allocateBuffers(count, &internalBuffers_); +} + +int RPiStream::queueBuffers() +{ + if (external_) + return 0; + + for (auto &b : internalBuffers_) { + int ret = dev_->queueBuffer(b.get()); + if (ret) { + LOG(RPISTREAM, Error) << "Failed to queue buffers for " + << name_; + return ret; + } + } + + return 0; +} + +void RPiStream::releaseBuffers() +{ + dev_->releaseBuffers(); + if (!external_ && !importOnly_) + internalBuffers_.clear(); +} + +} /* namespace RPi */ + +} /* namespace libcamera */ diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h new file mode 100644 index 00000000..8fcf522b --- /dev/null +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2020, Raspberry Pi (Trading) Ltd. + * + * rpi_stream.h - Raspberry Pi device stream abstraction class. + */ +#ifndef __LIBCAMERA_PIPELINE_RPI_STREAM_H__ +#define __LIBCAMERA_PIPELINE_RPI_STREAM_H__ + +#include +#include +#include + +#include + +#include "libcamera/internal/v4l2_videodevice.h" + +namespace libcamera { + +namespace RPi { + +/* + * Device stream abstraction for either an internal or external stream. + * Used for both Unicam and the ISP. + */ +class RPiStream : public Stream +{ +public: + RPiStream() + { + } + + RPiStream(const char *name, MediaEntity *dev, bool importOnly = false) + : external_(false), importOnly_(importOnly), name_(name), + dev_(std::make_unique(dev)) + { + } + + V4L2VideoDevice *dev() const; + std::string name() const; + bool isImporter() const; + void reset(); + + void setExternal(bool external); + bool isExternal() const; + + void setExternalBuffers(std::vector> *buffers); + const std::vector> *getBuffers() const; + bool findFrameBuffer(FrameBuffer *buffer) const; + + int importBuffers(unsigned int count); + int allocateBuffers(unsigned int count); + + int queueBuffers(); + void releaseBuffers(); + +private: + /* + * Indicates that this stream is active externally, i.e. the buffers + * are provided by the application. + */ + bool external_; + + /* Indicates that this stream only imports buffers, e.g. ISP input. */ + bool importOnly_; + + /* Stream name identifier. */ + std::string name_; + + /* The actual device stream. */ + std::unique_ptr dev_; + + /* Internally allocated framebuffers associated with this device stream. */ + std::vector> internalBuffers_; + + /* Externally allocated framebuffers associated with this device stream. */ + std::vector> *externalBuffers_; +}; + +/* + * The following class is just a convenient (and typesafe) array of device + * streams indexed with an enum class. + */ +template +class RPiDevice : public std::array +{ +private: + constexpr auto index(E e) const noexcept + { + return static_cast>(e); + } +public: + RPiStream &operator[](E e) + { + return std::array::operator[](index(e)); + } + const RPiStream &operator[](E e) const + { + return std::array::operator[](index(e)); + } +}; + +} /* namespace RPi */ + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_PIPELINE_RPI_STREAM_H__ */ From patchwork Tue Sep 8 07:49:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9518 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 EB7AFBDB1C for ; Tue, 8 Sep 2020 07:49:22 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5F46F62931; Tue, 8 Sep 2020 09:49:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="j7ntiKSw"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9CC8162931 for ; Tue, 8 Sep 2020 09:49:20 +0200 (CEST) Received: by mail-wr1-x42c.google.com with SMTP id j2so18009088wrx.7 for ; Tue, 08 Sep 2020 00:49:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3WK0rRdnEn+I4wH+SGznB3/njHWyIksYVpF7BQwluB4=; b=j7ntiKSwcrpRqeoYMxUWqsvPdMaLR4fi+q8hYJp0c6nFY/OnqSoQI+RfNOGB+RCiSh Z2AXyoM+3yimHyMPjiZr6hUwcgqhNlJoEo+jFg+mUQTpekcU/sDGJlcQ/nZxfPzv6bJ5 i8eKulZ/uG6HqUJaRFwCdIDKZV/rFCI4Kv4aZjnQx78Q5inyZyd7FQxsNVxvaGadrnGa tSALS6Lw4RY0aUCvv5g1e+nsEnN46SekyxNYlsOwwuJl4IdRC6JnMLDqfiSpt5OAs1LU OrOM4stezfkJNHmngOH7SrV8hF5LqMx/0HAMn3vtupN5RMiSPy2/pYYJrDQtw/9tQxm9 tfGA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3WK0rRdnEn+I4wH+SGznB3/njHWyIksYVpF7BQwluB4=; b=nkiybcOPPPl/oRpSkW6GYfzmSFNvwP+z1wc4Wb3B9BZDLbumGPIYZTk+1H1Y1InsiX rmWwDFuEY8h45W7Mcg3LTvqIBaYuK1F9Eh0/IGT+Rzm7s91x0eiXIKruPLQFXyAM5jzY /0XUEq2L4MdPVJXF97eRPh01kJUmZGqrHeo1rE6qARZ70jDRxAiTnzW2DLauPtqlASal we0jOoG+mBmluA/RqNvoiwP25/l/Y29rHm2CmCIQo1BIh6lg+bKShxpzp0yXAB+7FxI3 nAZK2rOBSR9wlqsjiIbZUOj/M+JGiaBEzATUmKRWKDDjj+6gjT5ulVB8EAc36OwCR1R7 XRvA== X-Gm-Message-State: AOAM532UNVCC1qoQfERf/UP0AQizK7GA5ecTK7gB8P/UT7Bg2Z6LIAJW DTKWNLEuynhTAUBxPWZTHdAi1pIWtRH+3Q== X-Google-Smtp-Source: ABdhPJx3ScM4Ivf7znHKDBDoOJOzN3bXs+r80rFav7dA0XDACxTO4IlwXbAf2NaCc7YPQZfKy2JJIw== X-Received: by 2002:a05:6000:83:: with SMTP id m3mr25114860wrx.165.1599551359936; Tue, 08 Sep 2020 00:49:19 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:19 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:02 +0100 Message-Id: <20200908074913.109244-3-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 02/12] libcamera: pipeline: ipa: raspberrypi: Rework drop frame signalling 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" The IPA now signals up front how many frames it wants the pipeline handler to drop. This makes it easier to handle up-coming changes to the buffer handling for import/export buffers. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Tested-by: David Plowman --- include/libcamera/ipa/raspberrypi.h | 2 +- src/ipa/raspberrypi/raspberrypi.cpp | 20 +++++------ .../pipeline/raspberrypi/raspberrypi.cpp | 36 +++++++++++-------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h index ca62990e..262fc6f3 100644 --- a/include/libcamera/ipa/raspberrypi.h +++ b/include/libcamera/ipa/raspberrypi.h @@ -14,6 +14,7 @@ enum RPiConfigParameters { RPI_IPA_CONFIG_LS_TABLE = (1 << 0), RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1), RPI_IPA_CONFIG_SENSOR = (1 << 2), + RPI_IPA_CONFIG_DROP_FRAMES = (1 << 3), }; enum RPiOperations { @@ -21,7 +22,6 @@ enum RPiOperations { RPI_IPA_ACTION_V4L2_SET_ISP, RPI_IPA_ACTION_STATS_METADATA_COMPLETE, RPI_IPA_ACTION_RUN_ISP, - RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME, RPI_IPA_ACTION_EMBEDDED_COMPLETE, RPI_IPA_EVENT_SIGNAL_STAT_READY, RPI_IPA_EVENT_SIGNAL_ISP_PREPARE, diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 4557016c..688d2efc 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -65,8 +65,8 @@ class IPARPi : public IPAInterface public: IPARPi() : lastMode_({}), controller_(), controllerInit_(false), - frame_count_(0), check_count_(0), hide_count_(0), - mistrust_count_(0), lsTable_(nullptr) + frame_count_(0), check_count_(0), mistrust_count_(0), + lsTable_(nullptr) { } @@ -137,8 +137,6 @@ private: uint64_t frame_count_; /* For checking the sequencing of Prepare/Process calls. */ uint64_t check_count_; - /* How many frames the pipeline handler should hide, or "drop". */ - unsigned int hide_count_; /* How many frames we should avoid running control algos on. */ unsigned int mistrust_count_; /* LS table allocation passed in from the pipeline handler. */ @@ -242,14 +240,18 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo, */ frame_count_ = 0; check_count_ = 0; + unsigned int drop_frame = 0; if (controllerInit_) { - hide_count_ = helper_->HideFramesModeSwitch(); + drop_frame = helper_->HideFramesModeSwitch(); mistrust_count_ = helper_->MistrustFramesModeSwitch(); } else { - hide_count_ = helper_->HideFramesStartup(); + drop_frame = helper_->HideFramesStartup(); mistrust_count_ = helper_->MistrustFramesStartup(); } + result->data.push_back(drop_frame); + result->operation |= RPI_IPA_CONFIG_DROP_FRAMES; + struct AgcStatus agcStatus; /* These zero values mean not program anything (unless overwritten). */ agcStatus.shutter_time = 0.0; @@ -366,13 +368,11 @@ void IPARPi::processEvent(const IPAOperationData &event) * they are "unreliable". */ prepareISP(embeddedbufferId); + frame_count_++; /* Ready to push the input buffer into the ISP. */ IPAOperationData op; - if (++frame_count_ > hide_count_) - op.operation = RPI_IPA_ACTION_RUN_ISP; - else - op.operation = RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME; + op.operation = RPI_IPA_ACTION_RUN_ISP; op.data = { bayerbufferId & RPiIpaMask::ID }; queueFrameAction.emit(0, op); break; diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 3d94b3ed..4c878003 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -132,7 +132,7 @@ class RPiCameraData : public CameraData public: RPiCameraData(PipelineHandler *pipe) : CameraData(pipe), sensor_(nullptr), state_(State::Stopped), - dropFrame_(false), ispOutputCount_(0) + dropFrameCount_(0), ispOutputCount_(0) { } @@ -180,14 +180,15 @@ public: std::queue embeddedQueue_; std::deque requestQueue_; + unsigned int dropFrameCount_; + private: void checkRequestCompleted(); void tryRunPipeline(); void tryFlushQueues(); FrameBuffer *updateQueue(std::queue &q, uint64_t timestamp, V4L2VideoDevice *dev); - bool dropFrame_; - int ispOutputCount_; + unsigned int ispOutputCount_; }; class RPiCameraConfiguration : public CameraConfiguration @@ -1007,6 +1008,7 @@ int RPiCameraData::configureIPA() ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig, &result); + unsigned int resultIdx = 0; if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) { /* * Setup our staggered control writer with the sensor default @@ -1014,9 +1016,9 @@ int RPiCameraData::configureIPA() */ if (!staggeredCtrl_) { staggeredCtrl_.init(unicam_[Unicam::Image].dev(), - { { V4L2_CID_ANALOGUE_GAIN, result.data[0] }, - { V4L2_CID_EXPOSURE, result.data[1] } }); - sensorMetadata_ = result.data[2]; + { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] }, + { V4L2_CID_EXPOSURE, result.data[resultIdx++] } }); + sensorMetadata_ = result.data[resultIdx++]; } } @@ -1026,6 +1028,11 @@ int RPiCameraData::configureIPA() LOG(RPI, Error) << "V4L2 staggered set failed"; } + if (result.operation & RPI_IPA_CONFIG_DROP_FRAMES) { + /* Configure the number of dropped frames required on startup. */ + dropFrameCount_ = result.data[resultIdx++]; + } + return 0; } @@ -1077,7 +1084,6 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, break; } - case RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME: case RPI_IPA_ACTION_RUN_ISP: { unsigned int bufferId = action.data[0]; FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers()->at(bufferId).get(); @@ -1086,7 +1092,6 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, << ", timestamp: " << buffer->metadata().timestamp; isp_[Isp::Input].dev()->queueBuffer(buffer); - dropFrame_ = (action.operation == RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME) ? true : false; ispOutputCount_ = 0; break; } @@ -1252,7 +1257,7 @@ void RPiCameraData::clearIncompleteRequests() void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream) { if (stream->isExternal()) { - if (!dropFrame_) { + if (!dropFrameCount_) { Request *request = buffer->request(); pipe_->completeBuffer(camera_, request, buffer); } @@ -1264,7 +1269,7 @@ void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream * simply memcpy to the Request buffer and requeue back to the * device. */ - if (stream == &unicam_[Unicam::Image] && !dropFrame_) { + if (stream == &unicam_[Unicam::Image] && !dropFrameCount_) { const Stream *rawStream = static_cast(&isp_[Isp::Input]); Request *request = requestQueue_.front(); FrameBuffer *raw = request->findBuffer(const_cast(rawStream)); @@ -1309,7 +1314,7 @@ void RPiCameraData::checkRequestCompleted() * If we are dropping this frame, do not touch the request, simply * change the state to IDLE when ready. */ - if (!dropFrame_) { + if (!dropFrameCount_) { Request *request = requestQueue_.front(); if (request->hasPendingBuffers()) return; @@ -1328,10 +1333,13 @@ void RPiCameraData::checkRequestCompleted() * frame. */ if (state_ == State::IpaComplete && - ((ispOutputCount_ == 3 && dropFrame_) || requestCompleted)) { + ((ispOutputCount_ == 3 && dropFrameCount_) || requestCompleted)) { state_ = State::Idle; - if (dropFrame_) - LOG(RPI, Info) << "Dropping frame at the request of the IPA"; + if (dropFrameCount_) { + dropFrameCount_--; + LOG(RPI, Info) << "Dropping frame at the request of the IPA (" + << dropFrameCount_ << " left)"; + } } } From patchwork Tue Sep 8 07:49:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9519 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 773EABDB1C for ; Tue, 8 Sep 2020 07:49:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EEFA362C01; Tue, 8 Sep 2020 09:49:22 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="RPpVGnLH"; dkim-atps=neutral Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A1AC262931 for ; Tue, 8 Sep 2020 09:49:21 +0200 (CEST) Received: by mail-wm1-x343.google.com with SMTP id b79so16132342wmb.4 for ; Tue, 08 Sep 2020 00:49:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7z1YhK/QItKgF24LCdggoTXw9ex8XokQHsbkI0ox0fs=; b=RPpVGnLHnwjNVgW5lQ8QI0Xj8zAdQdLY8BbrhJ2Fim4zZsIjIspx/DtCWRTSYqAWkJ iY1pUYt+XT3EVsiydR8qWxfj6mi+aHZfd6iYWrpupCvUTtPy8DQe+zCjHhLNReugqMlW 6gn/eESoeKRhqGZCkmX+7o+IFthJm6/Eb+d/JHvx69wQYOxC/BVP3gSEa4GE7X8hxo5N EiRUfdxhuNxwsxa+nMtwB7ADYV/UbzJ5Fr/WnRsltXa1HtjJ8V9DBzP/H73UtBiuGei4 uaSOq2P5idSfRGXyRJckyBawL2Wj6XieadBsYqCgUgsZpWGhFsj+0xTy2RpDFtrYU9yX 2WCg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7z1YhK/QItKgF24LCdggoTXw9ex8XokQHsbkI0ox0fs=; b=kKBxyV5jJQ9lcUjTV1K4LRHospTYilLLP66joq5aMEZrAC3rvl6uvwAlQtG5kzOJWo 08BH7ne8WYftIqncBXvUOJIB9GQIDylEpfks4ePzGtS7TbnoqZlHJNs+/85gTORPEp2E JvAL9huS413DWVUc0EbQ0ndwddLvE/JY/f3npOwIeelXubVBtd4QDR3/5zatSGw9Ciie DZHQFCLPxgtpe6pGq74kxoeniuhiTngpL07d6gu4hdZ8X0VDirJz0EvclnYRgNfINehf 2DvMIZTb9BLqYOEyaOqCK1fJFrIW8hk8Re6hdQ8mZoJqaXqpMqu5B/NVBXOT6KQIuYyF OlEg== X-Gm-Message-State: AOAM533EKb/H1W1VGm+AGPh50Sp8G8WvHXmxWjc0QtMF4REXcZOqoX/L OMGnzaBSkiK0QGBo2frcmImeGCPgZ9buLg== X-Google-Smtp-Source: ABdhPJxqg3KhnoF5g1Ljl+P7o6u2Chz+i3zBjtU21OA2TUuw5uA7N1sAtDkYYm3AjJAARWlC3LHjgQ== X-Received: by 2002:a7b:c210:: with SMTP id x16mr2890062wmi.76.1599551361089; Tue, 08 Sep 2020 00:49:21 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:20 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:03 +0100 Message-Id: <20200908074913.109244-4-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 03/12] libcamera: pipeline: raspberrypi: Add some debug logging 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" No functional changes, only added some more trace points. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Tested-by: David Plowman --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 4c878003..f15345ea 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -1162,6 +1162,11 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer) if (state_ == State::Stopped) return; + LOG(RPI, Debug) << "Stream ISP Input buffer complete" + << ", buffer id " << buffer->cookie() + << ", timestamp: " << buffer->metadata().timestamp; + + /* The ISP input buffer gets re-queued into Unicam. */ handleStreamBuffer(buffer, &unicam_[Unicam::Image]); handleState(); } @@ -1464,7 +1469,7 @@ FrameBuffer *RPiCameraData::updateQueue(std::queue &q, uint64_t t if (b->metadata().timestamp < timestamp) { q.pop(); dev->queueBuffer(b); - LOG(RPI, Error) << "Dropping input frame!"; + LOG(RPI, Warning) << "Dropping input frame!"; } else if (b->metadata().timestamp == timestamp) { /* The calling function will pop the item from the queue. */ return b; From patchwork Tue Sep 8 07:49:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9520 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 776C5BDB1C for ; Tue, 8 Sep 2020 07:49:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 4585562C15; Tue, 8 Sep 2020 09:49:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="spNUbmYh"; dkim-atps=neutral Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C4FC562C08 for ; Tue, 8 Sep 2020 09:49:22 +0200 (CEST) Received: by mail-wr1-x441.google.com with SMTP id c18so17982922wrm.9 for ; Tue, 08 Sep 2020 00:49:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nE/emN/9YQ8F/OJCPwpwoa+soM6JSc3SLzfzjKB3NuU=; b=spNUbmYhTqbIIgGx3pTJrmVoC0A/ArDmmJMDZmmVQHr24H2GjGjdhg0hf1bDT6Xhd8 29BE4gL8y4pIP4r4OV8V+7oD/+3HbtNidQrSxgFXId4/y90oG754zQnImRCnyuBEboQL YuKEM28KejS3BozmBQNX7NzRtthJBPvz4QjoM98gS0I+HBuL3VEbjCQn5NjK+3GFnFJa kLbOHY+EX2TLZNOAIR/UwcLoe8bGjVjZSEiLOzoeFOtie7HHVnMYlwDHYuc3cr4aRpYu 4sPCg8Gyisjby/sydVdu9R0zZe4ax3/ujWC899rUmXpjw+2Pum+savK+Ua14rT7KPYuN gWOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nE/emN/9YQ8F/OJCPwpwoa+soM6JSc3SLzfzjKB3NuU=; b=mEu2gdRgDpoAhzg3X1d+b7bsooWDvi+X2eXouU66v6muzwpjw72IOXhLCJVfOmShSP lw2SnSpTKiluL0H4Y5taucHIKV9p2EmF7eCA7y+701RT7q0HiPDxYYej6P8YwrsCqEef aqSu8yApr7YaMZpzru1aaTOezUgdDOekVQHR60Vn1RDkOIqh5ObtkibKpGzjspJZXADU 0ZuBFoSIThprPqtamCIkekvOZwB4BmbbeZCzRjWgNR+FXepnQj5+UP+PwX9CV3j4nPLp eNBmJuruuKDE2lptZO5OVhVm//Q3XPLkxwHlYHooNzi5lSQK+rTJMQCpUHik9nN5iEbM B2jg== X-Gm-Message-State: AOAM531dhBwQ7qgTupp40gJhEYMA0fxiM6zGh7vlHYCsbikvu0jXDWAx 3Uz4H4JdHjp+EPB0TjBDop8X3bphY+HtlA== X-Google-Smtp-Source: ABdhPJwL0HIGJUrg765TS8ROGeAU8GJYU/2TLHoxcG1NlQLU3P+K2vOJ6tl/Z4khXIlHEI3k8zcpWA== X-Received: by 2002:adf:b306:: with SMTP id j6mr24317671wrd.279.1599551362253; Tue, 08 Sep 2020 00:49:22 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:21 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:04 +0100 Message-Id: <20200908074913.109244-5-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 04/12] libcamera: pipeline: raspberrypi: Increase the number of RAW buffers X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Increase the number of expected RAW buffers in the stream configuration to 2. This will avoid dropping Unicam frames when exporting RAW streams. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Tested-by: David Plowman --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index f15345ea..ed83a2c6 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -378,7 +378,7 @@ CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera, sensorFormat = findBestMode(fmts, size); pixelFormat = sensorFormat.fourcc.toPixelFormat(); ASSERT(pixelFormat.isValid()); - bufferCount = 1; + bufferCount = 2; rawCount++; break; From patchwork Tue Sep 8 07:49:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9521 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 CC582BDB1E for ; Tue, 8 Sep 2020 07:49:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 988CA62C08; Tue, 8 Sep 2020 09:49:24 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="T15ngFA2"; dkim-atps=neutral Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D5E0160534 for ; Tue, 8 Sep 2020 09:49:23 +0200 (CEST) Received: by mail-wr1-x434.google.com with SMTP id m6so18050422wrn.0 for ; Tue, 08 Sep 2020 00:49:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2HZNXIdwEKmIQyD2h2XM7I6cmzMuhwlSR4pJrDGbzE4=; b=T15ngFA24+SyNpSvFhubxpCqtiLU9sT0x2chP0sihXxfhepCxnatAvxG+UydojmFVT 2PfW9qDQtSsRJfuieqjwTy89+NrGFoVXzjFiV5WUNkrf/8nbaFwks5uQw0KeuI4WL37E COO+nUTLLOEtDys2hRIJf/k0pXqv32/xlcOzAgHl/hsHwKN9ayCp7ni+DWcbU4az6ofz 9DUFonwOB9BGESeY5dCc7TkCMgQVaumSC4Ali4ex6o4y4Y6PYZIj9PEZ0t3BSd0Nzntt Kg0Lz/ELLSbT7QAIhOvG4IdB3C56BIyK5iex3fdxgBM0G5H1EIwHk6IZBeeSps1mf6Ll FEUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2HZNXIdwEKmIQyD2h2XM7I6cmzMuhwlSR4pJrDGbzE4=; b=pEKIBh4ifb2lcfoRKpY0vpLL0+wxbvQ5RC8CKcldsU72umyumLFjUHJRQnjMzhvrJj 9RVnz5Vosj8Vfjhb/P5Vjg/pdrsC08SNiP6hqdSLQ0YsMWUhivxUwvbZn0yZszq7zdsv 6JaY+7MV6ZTtEVnuXk9O2bAdCdYlT5Ox78iSghK26JFfp/I9oprl4PYRhCgRaSjC6aqh iH2o4qKbRugVqGdDp2F5OOaAAmktoLx1OaPQXpmDy7O2oij0aCRTKNG656sGaMbi1bNu oeACQpIumkxOODzuHven3fukGE0MC15+mZ8lLC9roWHsQT7Q4lyqxCDvCfC25HXgAcwW gcpg== X-Gm-Message-State: AOAM533ZdDVj6dazYsYixERWTaPr4NDZzsaQS3P2eXthX1+6VVoJa4mY Cs0lyDSztew9ImNR4NLjgNy11mULOk3toQ== X-Google-Smtp-Source: ABdhPJw3aBYsR8TJC9O6fT1fKVlyZV4krclR/Fn0yc0Y7UXMtz+hAmi1s5Hp5oZz3t/9KRw2R1VxXQ== X-Received: by 2002:a5d:6852:: with SMTP id o18mr24997882wrw.113.1599551363324; Tue, 08 Sep 2020 00:49:23 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:22 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:05 +0100 Message-Id: <20200908074913.109244-6-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 05/12] libcamera: pipeline: raspberrypi: Remove const qualifier from RPiStream 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" For the zero-copy RAW capture feature, the RPiStream will have to be modified. Remove the const qualifier in anticipation of the future commits for this feature. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Tested-by: David Plowman --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index ed83a2c6..6b9de029 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -149,7 +149,7 @@ public: void ispOutputDequeue(FrameBuffer *buffer); void clearIncompleteRequests(); - void handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream); + void handleStreamBuffer(FrameBuffer *buffer, RPi::RPiStream *stream); void handleState(); CameraSensor *sensor_; @@ -1107,12 +1107,12 @@ done: void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer) { - const RPi::RPiStream *stream = nullptr; + RPi::RPiStream *stream = nullptr; if (state_ == State::Stopped) return; - for (RPi::RPiStream const &s : unicam_) { + for (RPi::RPiStream &s : unicam_) { if (s.findFrameBuffer(buffer)) { stream = &s; break; @@ -1173,12 +1173,12 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer) void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) { - const RPi::RPiStream *stream = nullptr; + RPi::RPiStream *stream = nullptr; if (state_ == State::Stopped) return; - for (RPi::RPiStream const &s : isp_) { + for (RPi::RPiStream &s : isp_) { if (s.findFrameBuffer(buffer)) { stream = &s; break; @@ -1259,7 +1259,7 @@ void RPiCameraData::clearIncompleteRequests() } } -void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, const RPi::RPiStream *stream) +void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, RPi::RPiStream *stream) { if (stream->isExternal()) { if (!dropFrameCount_) { From patchwork Tue Sep 8 07:49:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9522 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 34239BDB1C for ; Tue, 8 Sep 2020 07:49:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F171A62C20; Tue, 8 Sep 2020 09:49:26 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="ri8SiQ8Q"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A31F260534 for ; Tue, 8 Sep 2020 09:49:25 +0200 (CEST) Received: by mail-wr1-x42c.google.com with SMTP id z4so18025365wrr.4 for ; Tue, 08 Sep 2020 00:49:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JNwsFLK7aZHVpqGiH2+p1BCd0OBDsiMuVtgz7GPAsF8=; b=ri8SiQ8Q5gmzn28fJNjgo6ACmAFabmyTwDfTomRxnR3rpj+8sBXC21KXk6Ele1DVXB HvUeSMXeJahwSIuMm0mEURyrNij2X5X2dLwDyu4g3uF7YvZ+Io/pEhuqo+/sVQRWBfjp 7zIJfQCIxod+85E7BziogceX0oCh+N4IkOJevV635aaQXx6Gs92KtVrD4ZIsFFzeA85g AIdvoQMA/6OqCAOWP6I+sHDQmHmCQLlHcF/qKY23/anXqaP+R2HFVvj1yYss/+BZJdHW iITW4vHCLJlLc6UX5DllSUudNIbGZT0vFgmvM4/+O0Fma3Uh865lWw6XYXwyaQPTsHoL hkJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JNwsFLK7aZHVpqGiH2+p1BCd0OBDsiMuVtgz7GPAsF8=; b=OEMbWDy5zR+b9Wzt7LAMHnkXy+E3WrDvgn7r3ZWydJJylvj0qTZPuhLkDGglAAIKUl HVcNs7/FAlWAOGcLzGMoWEqqm/YGFYshfDCxiWcwh1y/2W5GqzqqTS+V9blhriIJ43mM vV3qmR2L8iARNSYtdIUlTBAnnWgz8fur/tbIGff6/sN5Cmw1m9w0zeW2i3GZbqn2t4dT IkchenOhadJZnyUH6r4ptLnQteMaNwoxtHkwlZ+lMGx++PGUdRmSOPtAdvmPyQllYt+U rqqznofGJ923I0dXn55CUFOLkJ1Tmldsc8WjSXMCCD1/YBjlXmJU6kath3ewQDtfnF8I S5eQ== X-Gm-Message-State: AOAM5311nbUsNgleN9ZAmN44zOWuR7/iyfZRc9VDDpj9iHEUEZ7a0F5c 6wJN2s+DmPcDaexkiKINK+arAsVPtfUzgA== X-Google-Smtp-Source: ABdhPJyDF7fracAZzrS2cC2NLGcXIYk8Je+Xzh/YCIn9Ig1LOAkNHBXJCy4F1GYuKc2//VEHUGhoFw== X-Received: by 2002:adf:a48d:: with SMTP id g13mr25036485wrb.212.1599551364494; Tue, 08 Sep 2020 00:49:24 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:23 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:06 +0100 Message-Id: <20200908074913.109244-7-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 06/12] libcamera: pipeline: raspberrypi: Rework stream buffer logic for zero-copy 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" Stop using v4l2_videodevice::allocateBuffer() for internal buffers and instead export/import all buffers. This allows the pipeline to return any stream buffer requested by the application as zero-copy. Advertise the Unicam Image stream as the RAW capture stream now. The RPiStream object now maintains a new list of buffers that are available to queue into a device. This is needed to distinguish between FrameBuffers allocated for internal use vs externally provided buffers. When a Request comes in, if a buffer is not provided for an exported stream, we re-use a buffer from this list. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Tested-by: David Plowman --- .../pipeline/raspberrypi/raspberrypi.cpp | 231 ++++++++++-------- .../pipeline/raspberrypi/rpi_stream.cpp | 118 ++++++--- .../pipeline/raspberrypi/rpi_stream.h | 33 ++- 3 files changed, 231 insertions(+), 151 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 6b9de029..ea61df27 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -186,7 +186,8 @@ private: void checkRequestCompleted(); void tryRunPipeline(); void tryFlushQueues(); - FrameBuffer *updateQueue(std::queue &q, uint64_t timestamp, V4L2VideoDevice *dev); + FrameBuffer *updateQueue(std::queue &q, uint64_t timestamp, + RPi::RPiStream *stream); unsigned int ispOutputCount_; }; @@ -507,8 +508,15 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config) StreamConfiguration &cfg = config->at(i); if (isRaw(cfg.pixelFormat)) { - cfg.setStream(&data->isp_[Isp::Input]); - data->isp_[Isp::Input].setExternal(true); + cfg.setStream(&data->unicam_[Unicam::Image]); + /* + * We must set both Unicam streams as external, even + * though the application may only request RAW frames. + * This is because we match timestamps on both streams + * to synchronise buffers. + */ + data->unicam_[Unicam::Image].setExternal(true); + data->unicam_[Unicam::Embedded].setExternal(true); continue; } @@ -611,7 +619,7 @@ int PipelineHandlerRPi::exportFrameBuffers([[maybe_unused]] Camera *camera, Stre unsigned int count = stream->configuration().bufferCount; int ret = s->dev()->exportBuffers(count, buffers); - s->setExternalBuffers(buffers); + s->setExportedBuffers(buffers); return ret; } @@ -625,6 +633,7 @@ int PipelineHandlerRPi::start(Camera *camera) ret = prepareBuffers(camera); if (ret) { LOG(RPI, Error) << "Failed to allocate buffers"; + stop(camera); return ret; } @@ -710,14 +719,26 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request) if (data->state_ == RPiCameraData::State::Stopped) return -EINVAL; - /* Ensure all external streams have associated buffers! */ - for (auto &stream : data->isp_) { - if (!stream.isExternal()) - continue; + LOG(RPI, Debug) << "queueRequestDevice: New request."; - if (!request->findBuffer(&stream)) { - LOG(RPI, Error) << "Attempt to queue request with invalid stream."; - return -ENOENT; + /* Push all buffers supplied in the Request to the respective streams. */ + for (auto stream : data->streams_) { + if (stream->isExternal()) { + FrameBuffer *buffer = request->findBuffer(stream); + /* + * If no buffer is provided by the request for this stream, we + * queue a nullptr to the stream to signify that it must use an + * internally allocated buffer for this capture request. This + * buffer will not be given back to the application, but is used + * to support the internal pipeline flow. + * + * The below queueBuffer() call will do nothing if there are not + * enough internal buffers allocated, but this will be handled by + * queuing the request for buffers in the RPiStream object. + */ + int ret = stream->queueBuffer(buffer); + if (ret) + return ret; } } @@ -816,14 +837,14 @@ bool PipelineHandlerRPi::match(DeviceEnumerator *enumerator) data->unicam_[Unicam::Image].dev()->setControls(&ctrls); /* - * List the available output streams. - * Currently cannot do Unicam streams! + * List the available streams an application may request. At present, we + * do not advertise Unicam Embedded and ISP Statistics streams, as there + * is no mechanism for the application to request non-image buffer formats. */ std::set streams; - streams.insert(&data->isp_[Isp::Input]); + streams.insert(&data->unicam_[Unicam::Image]); streams.insert(&data->isp_[Isp::Output0]); streams.insert(&data->isp_[Isp::Output1]); - streams.insert(&data->isp_[Isp::Stats]); /* Create and register the camera. */ std::shared_ptr camera = @@ -839,9 +860,28 @@ int PipelineHandlerRPi::queueAllBuffers(Camera *camera) int ret; for (auto const stream : data->streams_) { - ret = stream->queueBuffers(); - if (ret < 0) - return ret; + if (!stream->isExternal()) { + ret = stream->queueAllBuffers(); + if (ret < 0) + return ret; + } else { + /* + * For external streams, we must queue up a set of internal + * buffers to handle the number of drop frames requested by + * the IPA. This is done by passing nullptr in queueBuffer(). + * + * The below queueBuffer() call will do nothing if there + * are not enough internal buffers allocated, but this will + * be handled by queuing the request for buffers in the + * RPiStream object. + */ + unsigned int i; + for (i = 0; i < data->dropFrameCount_; i++) { + int ret = stream->queueBuffer(nullptr); + if (ret) + return ret; + } + } } return 0; @@ -855,7 +895,8 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) /* * Decide how many internal buffers to allocate. For now, simply look * at how many external buffers will be provided. Will need to improve - * this logic. + * this logic. However, we really must have all streams allocate the same + * number of buffers to simplify error handling in queueRequestDevice(). */ unsigned int maxBuffers = 0; for (const Stream *s : camera->streams()) @@ -863,33 +904,9 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) maxBuffers = std::max(maxBuffers, s->configuration().bufferCount); for (auto const stream : data->streams_) { - if (stream->isExternal() || stream->isImporter()) { - /* - * If a stream is marked as external reserve memory to - * prepare to import as many buffers are requested in - * the stream configuration. - * - * If a stream is an internal stream with importer - * role, reserve as many buffers as possible. - */ - unsigned int count = stream->isExternal() - ? stream->configuration().bufferCount - : maxBuffers; - ret = stream->importBuffers(count); - if (ret < 0) - return ret; - } else { - /* - * If the stream is an internal exporter allocate and - * export as many buffers as possible to its internal - * pool. - */ - ret = stream->allocateBuffers(maxBuffers); - if (ret < 0) { - freeBuffers(camera); - return ret; - } - } + ret = stream->prepareBuffers(maxBuffers); + if (ret < 0) + return ret; } /* @@ -897,7 +914,7 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) * the IPA and RPI_IPA_EVENT_SIGNAL_ISP_PREPARE event. */ count = 0; - for (auto const &b : *data->unicam_[Unicam::Image].getBuffers()) { + for (auto const &b : data->unicam_[Unicam::Image].getBuffers()) { b->setCookie(count++); } @@ -906,14 +923,14 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) * the IPA. */ count = 0; - for (auto const &b : *data->isp_[Isp::Stats].getBuffers()) { + for (auto const &b : data->isp_[Isp::Stats].getBuffers()) { b->setCookie(count++); data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | b->cookie(), .planes = b->planes() }); } count = 0; - for (auto const &b : *data->unicam_[Unicam::Embedded].getBuffers()) { + for (auto const &b : data->unicam_[Unicam::Embedded].getBuffers()) { b->setCookie(count++); data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | b->cookie(), .planes = b->planes() }); @@ -1068,7 +1085,7 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, switch (action.operation) { case RPI_IPA_ACTION_STATS_METADATA_COMPLETE: { unsigned int bufferId = action.data[0]; - FrameBuffer *buffer = isp_[Isp::Stats].getBuffers()->at(bufferId).get(); + FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId); handleStreamBuffer(buffer, &isp_[Isp::Stats]); /* Fill the Request metadata buffer with what the IPA has provided */ @@ -1079,19 +1096,19 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, case RPI_IPA_ACTION_EMBEDDED_COMPLETE: { unsigned int bufferId = action.data[0]; - FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers()->at(bufferId).get(); + FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId); handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]); break; } case RPI_IPA_ACTION_RUN_ISP: { unsigned int bufferId = action.data[0]; - FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers()->at(bufferId).get(); + FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId); LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << buffer->cookie() << ", timestamp: " << buffer->metadata().timestamp; - isp_[Isp::Input].dev()->queueBuffer(buffer); + isp_[Isp::Input].queueBuffer(buffer); ispOutputCount_ = 0; break; } @@ -1192,22 +1209,26 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) << ", buffer id " << buffer->cookie() << ", timestamp: " << buffer->metadata().timestamp; - handleStreamBuffer(buffer, stream); - /* - * Increment the number of ISP outputs generated. - * This is needed to track dropped frames. + * ISP statistics buffer must not be re-queued or sent back to the + * application until after the IPA signals so. */ - ispOutputCount_++; - - /* If this is a stats output, hand it to the IPA now. */ if (stream == &isp_[Isp::Stats]) { IPAOperationData op; op.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY; op.data = { RPiIpaMask::STATS | buffer->cookie() }; ipa_->processEvent(op); + } else { + /* Any other ISP output can be handed back to the application now. */ + handleStreamBuffer(buffer, stream); } + /* + * Increment the number of ISP outputs generated. + * This is needed to track dropped frames. + */ + ispOutputCount_++; + handleState(); } @@ -1220,8 +1241,12 @@ void RPiCameraData::clearIncompleteRequests() */ for (auto const request : requestQueue_) { for (auto const stream : streams_) { - if (stream->isExternal()) - stream->dev()->queueBuffer(request->findBuffer(stream)); + if (!stream->isExternal()) + continue; + + FrameBuffer *buffer = request->findBuffer(stream); + if (buffer) + stream->queueBuffer(buffer); } } @@ -1250,7 +1275,7 @@ void RPiCameraData::clearIncompleteRequests() * Has the buffer already been handed back to the * request? If not, do so now. */ - if (buffer->request()) + if (buffer && buffer->request()) pipe_->completeBuffer(camera_, request, buffer); } @@ -1262,30 +1287,24 @@ void RPiCameraData::clearIncompleteRequests() void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, RPi::RPiStream *stream) { if (stream->isExternal()) { - if (!dropFrameCount_) { - Request *request = buffer->request(); + Request *request = requestQueue_.front(); + + if (!dropFrameCount_ && request->findBuffer(stream) == buffer) { + /* + * Tag the buffer as completed, returning it to the + * application. + */ pipe_->completeBuffer(camera_, request, buffer); + } else { + /* + * This buffer was not part of the Request, so we can + * recycle it. + */ + stream->returnBuffer(buffer); } } else { - /* Special handling for RAW buffer Requests. - * - * The ISP input stream is alway an import stream, but if the - * current Request has been made for a buffer on the stream, - * simply memcpy to the Request buffer and requeue back to the - * device. - */ - if (stream == &unicam_[Unicam::Image] && !dropFrameCount_) { - const Stream *rawStream = static_cast(&isp_[Isp::Input]); - Request *request = requestQueue_.front(); - FrameBuffer *raw = request->findBuffer(const_cast(rawStream)); - if (raw) { - raw->copyFrom(buffer); - pipe_->completeBuffer(camera_, request, raw); - } - } - - /* Simply requeue the buffer. */ - stream->dev()->queueBuffer(buffer); + /* Simply re-queue the buffer to the requested stream. */ + stream->queueBuffer(buffer); } } @@ -1367,7 +1386,7 @@ void RPiCameraData::tryRunPipeline() * current bayer buffer will be removed and re-queued to the driver. */ embeddedBuffer = updateQueue(embeddedQueue_, bayerBuffer->metadata().timestamp, - unicam_[Unicam::Embedded].dev()); + &unicam_[Unicam::Embedded]); if (!embeddedBuffer) { LOG(RPI, Debug) << "Could not find matching embedded buffer"; @@ -1386,7 +1405,7 @@ void RPiCameraData::tryRunPipeline() embeddedBuffer = embeddedQueue_.front(); bayerBuffer = updateQueue(bayerQueue_, embeddedBuffer->metadata().timestamp, - unicam_[Unicam::Image].dev()); + &unicam_[Unicam::Image]); if (!bayerBuffer) { LOG(RPI, Debug) << "Could not find matching bayer buffer - ending."; @@ -1394,11 +1413,7 @@ void RPiCameraData::tryRunPipeline() } } - /* - * Take the first request from the queue and action the IPA. - * Unicam buffers for the request have already been queued as they come - * in. - */ + /* Take the first request from the queue and action the IPA. */ Request *request = requestQueue_.front(); /* @@ -1410,12 +1425,6 @@ void RPiCameraData::tryRunPipeline() op.controls = { request->controls() }; ipa_->processEvent(op); - /* Queue up any ISP buffers passed into the request. */ - for (auto &stream : isp_) { - if (stream.isExternal()) - stream.dev()->queueBuffer(request->findBuffer(&stream)); - } - /* Ready to use the buffers, pop them off the queue. */ bayerQueue_.pop(); embeddedQueue_.pop(); @@ -1445,32 +1454,42 @@ void RPiCameraData::tryFlushQueues() * and give a chance for the hardware to return to lock-step. We do have * to drop all interim frames. */ - if (unicam_[Unicam::Image].getBuffers()->size() == bayerQueue_.size() && - unicam_[Unicam::Embedded].getBuffers()->size() == embeddedQueue_.size()) { + if (unicam_[Unicam::Image].getBuffers().size() == bayerQueue_.size() && + unicam_[Unicam::Embedded].getBuffers().size() == embeddedQueue_.size()) { + /* This cannot happen when Unicam streams are external. */ + assert(!unicam_[Unicam::Image].isExternal()); + LOG(RPI, Warning) << "Flushing all buffer queues!"; while (!bayerQueue_.empty()) { - unicam_[Unicam::Image].dev()->queueBuffer(bayerQueue_.front()); + unicam_[Unicam::Image].queueBuffer(bayerQueue_.front()); bayerQueue_.pop(); } while (!embeddedQueue_.empty()) { - unicam_[Unicam::Embedded].dev()->queueBuffer(embeddedQueue_.front()); + unicam_[Unicam::Embedded].queueBuffer(embeddedQueue_.front()); embeddedQueue_.pop(); } } } FrameBuffer *RPiCameraData::updateQueue(std::queue &q, uint64_t timestamp, - V4L2VideoDevice *dev) + RPi::RPiStream *stream) { + /* + * If the unicam streams are external (both have be to the same), then we + * can only return out the top buffer in the queue, and assume they have + * been synced by queuing at the same time. We cannot drop these frames, + * as they may have been provided externally. + */ while (!q.empty()) { FrameBuffer *b = q.front(); - if (b->metadata().timestamp < timestamp) { + if (!stream->isExternal() && b->metadata().timestamp < timestamp) { q.pop(); - dev->queueBuffer(b); - LOG(RPI, Warning) << "Dropping input frame!"; - } else if (b->metadata().timestamp == timestamp) { + stream->queueBuffer(b); + LOG(RPI, Warning) << "Dropping unmatched input frame in stream " + << stream->name(); + } else if (stream->isExternal() || b->metadata().timestamp == timestamp) { /* The calling function will pop the item from the queue. */ return b; } else { diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp index 2e52bd5c..b4d737db 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp @@ -27,78 +27,120 @@ std::string RPiStream::name() const void RPiStream::reset() { external_ = false; - internalBuffers_.clear(); -} - -bool RPiStream::isImporter() const -{ - return importOnly_; + clearBuffers(); } void RPiStream::setExternal(bool external) { + /* Import streams cannot be external. */ + ASSERT(!external || !importOnly_); external_ = external; } bool RPiStream::isExternal() const { - /* - * Import streams cannot be external. - * - * RAW capture is a special case where we simply copy the RAW - * buffer out of the request. All other buffer handling happens - * as if the stream is internal. - */ - return external_ && !importOnly_; + return external_; } -void RPiStream::setExternalBuffers(std::vector> *buffers) +void RPiStream::setExportedBuffers(std::vector> *buffers) { - externalBuffers_ = buffers; + std::transform(buffers->begin(), buffers->end(), std::back_inserter(bufferList_), + [](std::unique_ptr &b) { return b.get(); }); } -const std::vector> *RPiStream::getBuffers() const +const std::vector &RPiStream::getBuffers() const { - return external_ ? externalBuffers_ : &internalBuffers_; + return bufferList_; } bool RPiStream::findFrameBuffer(FrameBuffer *buffer) const { - auto start = external_ ? externalBuffers_->begin() : internalBuffers_.begin(); - auto end = external_ ? externalBuffers_->end() : internalBuffers_.end(); - if (importOnly_) return false; - if (std::find_if(start, end, - [buffer](std::unique_ptr const &ref) { return ref.get() == buffer; }) != end) + if (std::find(bufferList_.begin(), bufferList_.end(), buffer) != bufferList_.end()) return true; return false; } -int RPiStream::importBuffers(unsigned int count) +int RPiStream::prepareBuffers(unsigned int count) { + int ret; + + if (!importOnly_) { + if (count) { + /* Export some frame buffers for internal use. */ + ret = dev_->exportBuffers(count, &internalBuffers_); + if (ret < 0) + return ret; + + /* Add these exported buffers to the internal/external buffer list. */ + setExportedBuffers(&internalBuffers_); + + /* Add these buffers to the queue of internal usable buffers. */ + for (auto const &buffer : internalBuffers_) + availableBuffers_.push(buffer.get()); + } + + /* We must import all internal/external exported buffers. */ + count = bufferList_.size(); + } + return dev_->importBuffers(count); } -int RPiStream::allocateBuffers(unsigned int count) +int RPiStream::queueBuffer(FrameBuffer *buffer) +{ + /* + * A nullptr buffer implies an external stream, but no external + * buffer has been supplied. So, pick one from the availableBuffers_ + * queue. + */ + if (!buffer) { + if (availableBuffers_.empty()) { + LOG(RPISTREAM, Warning) << "No buffers available for " + << name_; + return -EINVAL; + } + + buffer = availableBuffers_.front(); + availableBuffers_.pop(); + } + + LOG(RPISTREAM, Debug) << "Queuing buffer " << buffer->cookie() + << " for " << name_; + + int ret = dev_->queueBuffer(buffer); + if (ret) { + LOG(RPISTREAM, Error) << "Failed to queue buffer for " + << name_; + } + + return ret; +} + +void RPiStream::returnBuffer(FrameBuffer *buffer) { - return dev_->allocateBuffers(count, &internalBuffers_); + /* This can only be called for external streams. */ + assert(external_); + + availableBuffers_.push(buffer); } -int RPiStream::queueBuffers() +int RPiStream::queueAllBuffers() { + int ret; + if (external_) return 0; - for (auto &b : internalBuffers_) { - int ret = dev_->queueBuffer(b.get()); - if (ret) { - LOG(RPISTREAM, Error) << "Failed to queue buffers for " - << name_; + while (!availableBuffers_.empty()) { + ret = queueBuffer(availableBuffers_.front()); + if (ret < 0) return ret; - } + + availableBuffers_.pop(); } return 0; @@ -107,8 +149,14 @@ int RPiStream::queueBuffers() void RPiStream::releaseBuffers() { dev_->releaseBuffers(); - if (!external_ && !importOnly_) - internalBuffers_.clear(); + clearBuffers(); +} + +void RPiStream::clearBuffers() +{ + availableBuffers_ = std::queue{}; + internalBuffers_.clear(); + bufferList_.clear(); } } /* namespace RPi */ diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h index 8fcf522b..73954ec7 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h @@ -44,20 +44,23 @@ public: void setExternal(bool external); bool isExternal() const; - void setExternalBuffers(std::vector> *buffers); - const std::vector> *getBuffers() const; + void setExportedBuffers(std::vector> *buffers); + const std::vector &getBuffers() const; bool findFrameBuffer(FrameBuffer *buffer) const; - int importBuffers(unsigned int count); - int allocateBuffers(unsigned int count); + int prepareBuffers(unsigned int count); + int queueBuffer(FrameBuffer *buffer); + void returnBuffer(FrameBuffer *buffer); - int queueBuffers(); + int queueAllBuffers(); void releaseBuffers(); private: + void clearBuffers(); + /* * Indicates that this stream is active externally, i.e. the buffers - * are provided by the application. + * might be provided by (and returned to) the application. */ bool external_; @@ -70,11 +73,21 @@ private: /* The actual device stream. */ std::unique_ptr dev_; - /* Internally allocated framebuffers associated with this device stream. */ - std::vector> internalBuffers_; + /* All framebuffers associated with this device stream. */ + std::vector bufferList_; + + /* + * List of frame buffers that we can use if none have been provided by + * the application for external streams. This is populated by the + * buffers exported internally. + */ + std::queue availableBuffers_; - /* Externally allocated framebuffers associated with this device stream. */ - std::vector> *externalBuffers_; + /* + * This is a list of buffers exported internally. Need to keep this around + * as the stream needs to maintain ownership of these buffers. + */ + std::vector> internalBuffers_; }; /* From patchwork Tue Sep 8 07:49:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9523 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 EB8F2BDB1C for ; Tue, 8 Sep 2020 07:49:27 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8133D62C11; Tue, 8 Sep 2020 09:49:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="ak0IohM9"; dkim-atps=neutral Received: from mail-wr1-x441.google.com (mail-wr1-x441.google.com [IPv6:2a00:1450:4864:20::441]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 04FAC60534 for ; Tue, 8 Sep 2020 09:49:26 +0200 (CEST) Received: by mail-wr1-x441.google.com with SMTP id z4so18025383wrr.4 for ; Tue, 08 Sep 2020 00:49:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HY410+IGo+p0b3nplNTrR4E7HZ5Bkkrqd9Tftr8OvXc=; b=ak0IohM92t0pdyKbWRuv3xwnmC6CSCrYJTkHCGjDuWzxuXz6ehvlsObnfxS4dVKl1i O8qHwaQbIi5C0scgopOz47P94T8daHy6kKVeL5+foovcWv9iwcr8P0j9A8Q5oL6f/pPs WTMq4lT1D2mDAZNSzBmeE6Irv4stq8zJhCQMlAuy+gLlMYBrfsgI2TIY1AnjbnMyU7vH 6eKkmb4ifMauS1/yGTt+kpJCKM8EB/z4UOybVKBZNTofRuXRjIEdIBWPxFwWnJL07SX5 BSAKXGMcLnZKvdvlInyKNEUvnGnS1H8XHh/2vh/49sXmcUnJYyp+H8p0+NRlOEyqioNd SZfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HY410+IGo+p0b3nplNTrR4E7HZ5Bkkrqd9Tftr8OvXc=; b=Tli8vgF6ToOiSlkK1Af1Tv9zY1Vtk0iGo2o8mJ0Rrbz8HiXmjGVUQD2RLevWdCBTp6 YL5iMV013FYrThIenLv2qB4aQskdVxlv0EOkGWQFZ/N7AVnrvG6DW0SfQN29QkXNGuPA sEi8VPESkApnk9BVhRT3RS6FXZCAsKLtNNfe5Euang9TRy0z6O3dzOaiDpktr8gBU6aX bCYaEiMBXEf/2pZ+iwZ8DP9VYwidbqTQ+a9J+57neU8xwf3lDvbohpE35RMudwiwD09h AqIL8K0knQZWROSgWNkMKW+JZRSVdVeW1qYx5wkTmaWEFivyGrkV6EfjwltS9YIQjS42 /48A== X-Gm-Message-State: AOAM531SqAuHd9iLBWIchk4q4vf/2iM1z6Vdv3C1s/WryxHDv6nfXRg1 BnWVCC248Ka7nbiLrzVNUrjFMdsfzl9Y5Q== X-Google-Smtp-Source: ABdhPJxeXupKueWC12zhsxHP4BMPEg6SHIN6BtpOUkHnHby6YJ11vKx0HJKJdj1PpjpIsn+27shO/A== X-Received: by 2002:a5d:50c3:: with SMTP id f3mr24915254wrt.125.1599551365417; Tue, 08 Sep 2020 00:49:25 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:24 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:07 +0100 Message-Id: <20200908074913.109244-8-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 07/12] libcamera: pipeline: raspberrypi: Fix bug in passing configuration to IPA 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" The counter was not incremented, so multiple streams would only pass the last stream config to the IPA. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Tested-by: David Plowman --- src/libcamera/pipeline/raspberrypi/raspberrypi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index ea61df27..2a876c3e 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -992,12 +992,13 @@ int RPiCameraData::configureIPA() unsigned int i = 0; for (auto const &stream : isp_) { if (stream.isExternal()) { - streamConfig[i] = { + streamConfig[i++] = { .pixelFormat = stream.configuration().pixelFormat, .size = stream.configuration().size }; } } + entityControls.emplace(0, unicam_[Unicam::Image].dev()->controls()); entityControls.emplace(1, isp_[Isp::Input].dev()->controls()); From patchwork Tue Sep 8 07:49:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9524 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 2639DBDB1C for ; Tue, 8 Sep 2020 07:49:29 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EA84E62BBA; Tue, 8 Sep 2020 09:49:28 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="LTX/wby/"; dkim-atps=neutral Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9299D62C13 for ; Tue, 8 Sep 2020 09:49:27 +0200 (CEST) Received: by mail-wm1-x336.google.com with SMTP id w2so16277950wmi.1 for ; Tue, 08 Sep 2020 00:49:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pO9m/3WEaO+YsGGYT5406UzcJktNRpMQ9mP+ggh1N14=; b=LTX/wby/ZkHuV92Ph+JDEJ751L3hh3Ruye4NiDeRA+EctvY+JjagSz6T34S7p5VPje S4Jrl+N1PIdxvVDtWn4RftxtADofxPyJeUDhMBNrv41BTvoXPVAhKhamNL6D8DOMjbG+ FbIbAYP/BqW+vbDV0o62SRYLjAYH8VVTswhxVwG9ERgyUcsjt6NHg2KyK5kTUGjU/ULt ns5Grb9XYpECV1TVmZl7iSvrZFUwlsp/gldt1BanV8ClaDhsCHvqnP13HlF11/5hYmZu CmWP9Om3tQRfYEqGeKLARoa2iSR1YgsibfFCQMKV2baRp3Hn1dyMRNLDhErn97XHzwRF fRAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pO9m/3WEaO+YsGGYT5406UzcJktNRpMQ9mP+ggh1N14=; b=qW8Q3S1SQ5mVwLRxIZdZz08XPT4vnjA/Ytw1+Yi4Nbzy0pbwPGqK6H/fKW2SIlXIX3 JMaszBFfefz095yKRJWCWK0NnWvR9sd3k61CJdlPDSIc4B1L8uHsFkr8FAXR5Ct0BlFt Xw2t1TxQzR8l/cS/XMisRSycLVp+MPDn45qLWtZ2X7fxu9/KxKpnqT66EfHDmGrksxoX 7Is340KbCGgAlYih+V2zNdXHCkn+PxyDT6VnJQ2LBW6oiUjtasMWJ3+EAL093e2cOLUH w9oepyhTxYrl2PacnadPJTMMqJwOBK2/ZZed0UgfKXur+NfWVd2uqO0HbkUE4268ZQTj qgag== X-Gm-Message-State: AOAM531y9y6gonwRmG1M2Y1dDoRdgwBWi6QDdbHyo3ZSJ2Nt4WyO3qbn 1/9z6/d/fIaAsl7nVo7nEIQ06vX8S+jBFg== X-Google-Smtp-Source: ABdhPJxsPEBwWORaVVhGKhRj2gwhFQGCLftKiQNMM+RvdRrPpis7G/mDxCa/Dvd+FNgPgGElVnUlUQ== X-Received: by 2002:a7b:c5c6:: with SMTP id n6mr2940968wmk.120.1599551366892; Tue, 08 Sep 2020 00:49:26 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:26 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:08 +0100 Message-Id: <20200908074913.109244-9-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 08/12] libcamera: pipeline: raspberrypi: Add more robust stream buffer logic 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 further queueing into the RPiStream object to ensure that we always follow the buffer ordering (be it internal or external) given by incoming Requests. This is essential, otherwise we risk dropping frames that are meant to be part of a Request, and can cause the pipeline to stall indefinitely. This also prevents any possibility of mismatched frame buffers going through the pipeline and out to the application. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Tested-by: David Plowman Reviewed-by: Kieran Bingham --- .../pipeline/raspberrypi/rpi_stream.cpp | 76 +++++++++++++++---- .../pipeline/raspberrypi/rpi_stream.h | 13 +++- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp index b4d737db..b2a5dfa7 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp @@ -94,38 +94,75 @@ int RPiStream::queueBuffer(FrameBuffer *buffer) { /* * A nullptr buffer implies an external stream, but no external - * buffer has been supplied. So, pick one from the availableBuffers_ - * queue. + * buffer has been supplied in the Request. So, pick one from the + * availableBuffers_ queue. */ if (!buffer) { if (availableBuffers_.empty()) { - LOG(RPISTREAM, Warning) << "No buffers available for " + LOG(RPISTREAM, Info) << "No buffers available for " << name_; - return -EINVAL; + /* + * Note that we need to queue an internal buffer as soon + * as one becomes available. + */ + requestBuffers_.push(nullptr); + return 0; } buffer = availableBuffers_.front(); availableBuffers_.pop(); } - LOG(RPISTREAM, Debug) << "Queuing buffer " << buffer->cookie() - << " for " << name_; + /* + * If no earlier requests are pending to be queued we can go ahead and + * queue this buffer into the device. + */ + if (requestBuffers_.empty()) + return queueToDevice(buffer); - int ret = dev_->queueBuffer(buffer); - if (ret) { - LOG(RPISTREAM, Error) << "Failed to queue buffer for " - << name_; - } + /* + * There are earlier Request buffers to be queued, so this buffer must go + * on the waiting list. + */ + requestBuffers_.push(buffer); - return ret; + return 0; } void RPiStream::returnBuffer(FrameBuffer *buffer) { /* This can only be called for external streams. */ - assert(external_); + ASSERT(external_); + /* Push this buffer back into the queue to be used again. */ availableBuffers_.push(buffer); + + /* + * Do we have any Request buffers that are waiting to be queued? + * If so, do it now as availableBuffers_ will not be empty. + */ + while (!requestBuffers_.empty()) { + FrameBuffer *buffer = requestBuffers_.front(); + + if (!buffer) { + /* + * We want to queue an internal buffer, but none + * are available. Can't do anything, quit the loop. + */ + if (availableBuffers_.empty()) + break; + + /* + * We want to queue an internal buffer, and at least one + * is available. + */ + buffer = availableBuffers_.front(); + availableBuffers_.pop(); + } + + requestBuffers_.pop(); + queueToDevice(buffer); + } } int RPiStream::queueAllBuffers() @@ -155,10 +192,23 @@ void RPiStream::releaseBuffers() void RPiStream::clearBuffers() { availableBuffers_ = std::queue{}; + requestBuffers_ = std::queue{}; internalBuffers_.clear(); bufferList_.clear(); } +int RPiStream::queueToDevice(FrameBuffer *buffer) +{ + LOG(RPISTREAM, Debug) << "Queuing buffer " << buffer->cookie() + << " for " << name_; + + int ret = dev_->queueBuffer(buffer); + if (ret) + LOG(RPISTREAM, Error) << "Failed to queue buffer for " + << name_; + return ret; +} + } /* namespace RPi */ } /* namespace libcamera */ diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h index 73954ec7..f42e25b9 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h @@ -57,6 +57,7 @@ public: private: void clearBuffers(); + int queueToDevice(FrameBuffer *buffer); /* * Indicates that this stream is active externally, i.e. the buffers @@ -73,7 +74,7 @@ private: /* The actual device stream. */ std::unique_ptr dev_; - /* All framebuffers associated with this device stream. */ + /* All frame buffers associated with this device stream. */ std::vector bufferList_; /* @@ -83,6 +84,16 @@ private: */ std::queue availableBuffers_; + /* + * List of frame buffers that are to be queued into the device from a Request. + * A nullptr indicates any internal buffer can be used (from availableBuffers_), + * whereas a valid pointer indicates an external buffer to be queued. + * + * Ordering buffers to be queued is important here as it must match the + * requests coming from the application. + */ + std::queue requestBuffers_; + /* * This is a list of buffers exported internally. Need to keep this around * as the stream needs to maintain ownership of these buffers. From patchwork Tue Sep 8 07:49:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9525 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 7574EBDB1C for ; Tue, 8 Sep 2020 07:49:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 3E43B62C29; Tue, 8 Sep 2020 09:49:30 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="OtkAeQze"; dkim-atps=neutral Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C327962C28 for ; Tue, 8 Sep 2020 09:49:28 +0200 (CEST) Received: by mail-wr1-x42c.google.com with SMTP id c15so17966604wrs.11 for ; Tue, 08 Sep 2020 00:49:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aQctSJDUSP0lrSRo64RqJJLJn/Iv5Ck1Sjm3aQ3f7b8=; b=OtkAeQzeEqwziFqN3I9VeTgTBIpuiWAalJslqPUVrUcGgBVxIY4OGCIXqjgA3rWO3r TB5zCIP9E+vsBwIcf4eww9gu3BobtLtdAHYClUxatAUFVRIqsirJQIeA0t5gQlp9g4ZW EtnKHJ4wbpLrDyDfnowe5q7wVc6EHAvqWqLWlLFp2usL7JDiKNmnFF94vbm0OHRsyLee /fKfnoUloZDU4zZK+X9Y1KVZ6hX6JyWRhSzaFyfC/RLHU/OhFw4/jjLCkUPk/Wq8lJlI KTsSpJT2em0UpGjFJGAVlyDCwmXmrsKsxhejRKiQAtcaLDtS9Y3LeGPolrQPV/wW1KQb QPew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aQctSJDUSP0lrSRo64RqJJLJn/Iv5Ck1Sjm3aQ3f7b8=; b=H76qISpGAl4+MaOzhJC9yqHZY8uyaxoLB/zw6QuWGwmS1CbMPIdg3Bhnx0t/fyBJxY 6DcRobamnAa2DbJYqD9CF9HAKo4SosNwowhxN6cU3GqLzf5bSaLtRob3pwspZXJq4gf/ w+cdueV87K/X/UBqwqIPlpX9WyVGKX3ex5KatuC6nNYPukh9BrwcEsMZWpeCfnt0BwFX 3HtOYwGuGiZYWhNiyceEHk0e/gT4MCB9N1tICRlJ8myES2H1QBcg8JaMfWZ3X+o5IKYg b6eQcoxQ95DxJfhZhY9RCrcyGZ/K6fMqyooLVZxFS3GMIbsziXCVtXVrz3iI8Sb9IXEJ qmCA== X-Gm-Message-State: AOAM533f7xNTMnGAnDHoRD2gYiT9UW7lIuRJqIPWlxewUxUN5Nn8bPh5 UgKDdnKS5R/gS8OnEsYH/RFGsfzOyttQyg== X-Google-Smtp-Source: ABdhPJy8I00wyyu/2AuMWzZMakjNDYjVUUJ5v0X8y9lVGWcd0ZTaxwdswznkGVD/5nXdiiuoQwq8Tg== X-Received: by 2002:a5d:6cd4:: with SMTP id c20mr24449574wrc.234.1599551368078; Tue, 08 Sep 2020 00:49:28 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:27 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:09 +0100 Message-Id: <20200908074913.109244-10-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 09/12] libcamera: pipeline: ipa: raspberrypi: Remove use of FrameBuffer cookie 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" The FrameBuffer cookie may be set by the application, so this cannot be set by the pipeline handler as well. Revert to using a simple index into the buffer list to identify buffers passing to and from the IPA. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham Tested-by: David Plowman --- .../pipeline/raspberrypi/raspberrypi.cpp | 60 ++++++++++--------- .../pipeline/raspberrypi/rpi_stream.cpp | 14 +++-- .../pipeline/raspberrypi/rpi_stream.h | 2 +- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 2a876c3e..341ee6ce 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -890,7 +890,8 @@ int PipelineHandlerRPi::queueAllBuffers(Camera *camera) int PipelineHandlerRPi::prepareBuffers(Camera *camera) { RPiCameraData *data = cameraData(camera); - int count, ret; + unsigned int index; + int ret; /* * Decide how many internal buffers to allocate. For now, simply look @@ -910,30 +911,24 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) } /* - * Add cookies to the ISP Input buffers so that we can link them with - * the IPA and RPI_IPA_EVENT_SIGNAL_ISP_PREPARE event. - */ - count = 0; - for (auto const &b : data->unicam_[Unicam::Image].getBuffers()) { - b->setCookie(count++); - } - - /* - * Add cookies to the stats and embedded data buffers and link them with - * the IPA. + * Link the FrameBuffers with the index of their position in the vector + * stored in the RPi stream object. + * + * This will allow us to identify buffers passed between the pipeline + * handler and the IPA. */ - count = 0; + index = 0; for (auto const &b : data->isp_[Isp::Stats].getBuffers()) { - b->setCookie(count++); - data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | b->cookie(), + data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | index, .planes = b->planes() }); + index++; } - count = 0; + index = 0; for (auto const &b : data->unicam_[Unicam::Embedded].getBuffers()) { - b->setCookie(count++); - data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | b->cookie(), + data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | index, .planes = b->planes() }); + index++; } data->ipa_->mapBuffers(data->ipaBuffers_); @@ -1106,7 +1101,7 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, unsigned int bufferId = action.data[0]; FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId); - LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << buffer->cookie() + LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId << ", timestamp: " << buffer->metadata().timestamp; isp_[Isp::Input].queueBuffer(buffer); @@ -1126,12 +1121,14 @@ done: void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer) { RPi::RPiStream *stream = nullptr; + int index; if (state_ == State::Stopped) return; for (RPi::RPiStream &s : unicam_) { - if (s.findFrameBuffer(buffer)) { + index = s.getBufferIndex(buffer); + if (index != -1) { stream = &s; break; } @@ -1141,7 +1138,7 @@ void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer) ASSERT(stream); LOG(RPI, Debug) << "Stream " << stream->name() << " buffer dequeue" - << ", buffer id " << buffer->cookie() + << ", buffer id " << index << ", timestamp: " << buffer->metadata().timestamp; if (stream == &unicam_[Unicam::Image]) { @@ -1181,7 +1178,7 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer) return; LOG(RPI, Debug) << "Stream ISP Input buffer complete" - << ", buffer id " << buffer->cookie() + << ", buffer id " << unicam_[Unicam::Image].getBufferIndex(buffer) << ", timestamp: " << buffer->metadata().timestamp; /* The ISP input buffer gets re-queued into Unicam. */ @@ -1192,12 +1189,14 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer) void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) { RPi::RPiStream *stream = nullptr; + int index; if (state_ == State::Stopped) return; for (RPi::RPiStream &s : isp_) { - if (s.findFrameBuffer(buffer)) { + index = s.getBufferIndex(buffer); + if (index != -1) { stream = &s; break; } @@ -1207,7 +1206,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) ASSERT(stream); LOG(RPI, Debug) << "Stream " << stream->name() << " buffer complete" - << ", buffer id " << buffer->cookie() + << ", buffer id " << index << ", timestamp: " << buffer->metadata().timestamp; /* @@ -1217,7 +1216,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) if (stream == &isp_[Isp::Stats]) { IPAOperationData op; op.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY; - op.data = { RPiIpaMask::STATS | buffer->cookie() }; + op.data = { RPiIpaMask::STATS | static_cast(index) }; ipa_->processEvent(op); } else { /* Any other ISP output can be handed back to the application now. */ @@ -1433,13 +1432,16 @@ void RPiCameraData::tryRunPipeline() /* Set our state to say the pipeline is active. */ state_ = State::Busy; + unsigned int bayerIndex = unicam_[Unicam::Image].getBufferIndex(bayerBuffer); + unsigned int embeddedIndex = unicam_[Unicam::Embedded].getBufferIndex(embeddedBuffer); + LOG(RPI, Debug) << "Signalling RPI_IPA_EVENT_SIGNAL_ISP_PREPARE:" - << " Bayer buffer id: " << bayerBuffer->cookie() - << " Embedded buffer id: " << embeddedBuffer->cookie(); + << " Bayer buffer id: " << bayerIndex + << " Embedded buffer id: " << embeddedIndex; op.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE; - op.data = { RPiIpaMask::EMBEDDED_DATA | embeddedBuffer->cookie(), - RPiIpaMask::BAYER_DATA | bayerBuffer->cookie() }; + op.data = { RPiIpaMask::EMBEDDED_DATA | embeddedIndex, + RPiIpaMask::BAYER_DATA | bayerIndex }; ipa_->processEvent(op); } diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp index b2a5dfa7..80170d64 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp @@ -53,15 +53,17 @@ const std::vector &RPiStream::getBuffers() const return bufferList_; } -bool RPiStream::findFrameBuffer(FrameBuffer *buffer) const +int RPiStream::getBufferIndex(FrameBuffer *buffer) const { if (importOnly_) - return false; + return -1; - if (std::find(bufferList_.begin(), bufferList_.end(), buffer) != bufferList_.end()) - return true; + /* Find the buffer in the list, and return the index position. */ + auto it = std::find(bufferList_.begin(), bufferList_.end(), buffer); + if (it != bufferList_.end()) + return std::distance(bufferList_.begin(), it); - return false; + return -1; } int RPiStream::prepareBuffers(unsigned int count) @@ -199,7 +201,7 @@ void RPiStream::clearBuffers() int RPiStream::queueToDevice(FrameBuffer *buffer) { - LOG(RPISTREAM, Debug) << "Queuing buffer " << buffer->cookie() + LOG(RPISTREAM, Debug) << "Queuing buffer " << getBufferIndex(buffer) << " for " << name_; int ret = dev_->queueBuffer(buffer); diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h index f42e25b9..959e9147 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h @@ -46,7 +46,7 @@ public: void setExportedBuffers(std::vector> *buffers); const std::vector &getBuffers() const; - bool findFrameBuffer(FrameBuffer *buffer) const; + int getBufferIndex(FrameBuffer *buffer) const; int prepareBuffers(unsigned int count); int queueBuffer(FrameBuffer *buffer); From patchwork Tue Sep 8 07:49:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9526 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 BEA59BDB1C for ; Tue, 8 Sep 2020 07:49:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8AF4462C2F; Tue, 8 Sep 2020 09:49:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="UZh1fpPP"; dkim-atps=neutral Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EDD9462BAA for ; Tue, 8 Sep 2020 09:49:29 +0200 (CEST) Received: by mail-wr1-x429.google.com with SMTP id z4so18025562wrr.4 for ; Tue, 08 Sep 2020 00:49:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MR4GBDeEwsdkEea4GUgguWUuMoirZnEcLbA3FTMTiIg=; b=UZh1fpPPIj7NPrzFXHye7bekiPQsAj0XVd9w49PuuGCURXda6AHGjzJ/Uxx7tLdHpZ C+NkmrnJUGFs1uC2q4/C4JfeqJdk8aOiN/QFaha45yzDIyyE1745kVceecHgAZxgj36S HtqgfpNVgoZWGAItPvfrsGgxMpYBI46jnfEByCrWoWuySbL7R+PaOIhziqLMj6jt4mx8 Eu5mq+aNN23faKDG4UvPDAd+pAOeDGn5axsyyUpVC9sDw4Es5ZcqVQZ5ZtFIpPgkOo1B A+rTu4p9ZAk2bvc3ptX8RrASkL/1L6nZ3vnnTOZD7n7oBh6pqwj5k1EsqupybcYxfYyW Vjyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MR4GBDeEwsdkEea4GUgguWUuMoirZnEcLbA3FTMTiIg=; b=seVF6+awmL2C2JlkqfvaBzphnCjLhmpgFIljgwUjPPvZXay3OZdUiCXx+rDN5l9vX8 bBOqmSWc0k4WzN5k+r32S2KtLuO9XFu8WxDNb7u1jnz7UOn6JFDvbmiEnUlReBkMlhK8 YISM5yslXY5eqFxDfNKUpgLioWVQu1U9BoSRGdW9OaRp9ap2REpXKT2WjJUkEIFEBgBc RrMyZUD0cbDYUO1V+kH+zZu+qIZJ3LKSaPPDRFNv3CDq7BhO1VMlm2ACLsNFZejDFrtB qGJaVOcqOdUUv2W2zLRa/FdkXjB+0AN0odPeiO0rPYNCvB5I2rJdabcPxBvSA7EhJuD7 uFLQ== X-Gm-Message-State: AOAM532EMoJXxGNncl/QD0cEGfg/Pe5cXfvXjFwaLBGXyJk79qCqkK1C uvDJ4nrkhLpjISgjBF72tJiO4gW1fofsSw== X-Google-Smtp-Source: ABdhPJyRyGRprEoHdhJ45RxLjIRC4WLvr6opPkT8+Cv3yPQqREF1t6x0qqXMDSFp60ZPG3V0JFUjng== X-Received: by 2002:a5d:4c88:: with SMTP id z8mr25302827wrs.218.1599551369311; Tue, 08 Sep 2020 00:49:29 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:28 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:10 +0100 Message-Id: <20200908074913.109244-11-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 10/12] pipeline: raspberrypi: Use an unordered_map for the stream buffer list 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" By using a map container, we can easily insert/remove buffers from the buffer list. This will be required to track buffers allocated externally and passed to the pipeline handler through a Request. Replace the buffer index tracking with an id generated internally by the stream object. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- .../pipeline/raspberrypi/raspberrypi.cpp | 23 ++++++--------- .../pipeline/raspberrypi/rpi_stream.cpp | 28 ++++++++++--------- .../pipeline/raspberrypi/rpi_stream.h | 14 +++++++--- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 341ee6ce..6aa13034 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -890,7 +890,6 @@ int PipelineHandlerRPi::queueAllBuffers(Camera *camera) int PipelineHandlerRPi::prepareBuffers(Camera *camera) { RPiCameraData *data = cameraData(camera); - unsigned int index; int ret; /* @@ -917,18 +916,14 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) * This will allow us to identify buffers passed between the pipeline * handler and the IPA. */ - index = 0; for (auto const &b : data->isp_[Isp::Stats].getBuffers()) { - data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | index, - .planes = b->planes() }); - index++; + data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | b.first, + .planes = b.second->planes() }); } - index = 0; for (auto const &b : data->unicam_[Unicam::Embedded].getBuffers()) { - data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | index, - .planes = b->planes() }); - index++; + data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | b.first, + .planes = b.second->planes() }); } data->ipa_->mapBuffers(data->ipaBuffers_); @@ -1127,7 +1122,7 @@ void RPiCameraData::unicamBufferDequeue(FrameBuffer *buffer) return; for (RPi::RPiStream &s : unicam_) { - index = s.getBufferIndex(buffer); + index = s.getBufferId(buffer); if (index != -1) { stream = &s; break; @@ -1178,7 +1173,7 @@ void RPiCameraData::ispInputDequeue(FrameBuffer *buffer) return; LOG(RPI, Debug) << "Stream ISP Input buffer complete" - << ", buffer id " << unicam_[Unicam::Image].getBufferIndex(buffer) + << ", buffer id " << unicam_[Unicam::Image].getBufferId(buffer) << ", timestamp: " << buffer->metadata().timestamp; /* The ISP input buffer gets re-queued into Unicam. */ @@ -1195,7 +1190,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) return; for (RPi::RPiStream &s : isp_) { - index = s.getBufferIndex(buffer); + index = s.getBufferId(buffer); if (index != -1) { stream = &s; break; @@ -1432,8 +1427,8 @@ void RPiCameraData::tryRunPipeline() /* Set our state to say the pipeline is active. */ state_ = State::Busy; - unsigned int bayerIndex = unicam_[Unicam::Image].getBufferIndex(bayerBuffer); - unsigned int embeddedIndex = unicam_[Unicam::Embedded].getBufferIndex(embeddedBuffer); + unsigned int bayerIndex = unicam_[Unicam::Image].getBufferId(bayerBuffer); + unsigned int embeddedIndex = unicam_[Unicam::Embedded].getBufferId(embeddedBuffer); LOG(RPI, Debug) << "Signalling RPI_IPA_EVENT_SIGNAL_ISP_PREPARE:" << " Bayer buffer id: " << bayerIndex diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp index 80170d64..879e25ba 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp @@ -44,26 +44,28 @@ bool RPiStream::isExternal() const void RPiStream::setExportedBuffers(std::vector> *buffers) { - std::transform(buffers->begin(), buffers->end(), std::back_inserter(bufferList_), - [](std::unique_ptr &b) { return b.get(); }); + for (auto const &buffer : *buffers) + bufferMap_.emplace(id_++, buffer.get()); } -const std::vector &RPiStream::getBuffers() const +const BufferMap &RPiStream::getBuffers() const { - return bufferList_; + return bufferMap_; } -int RPiStream::getBufferIndex(FrameBuffer *buffer) const +int RPiStream::getBufferId(FrameBuffer *buffer) const { if (importOnly_) return -1; - /* Find the buffer in the list, and return the index position. */ - auto it = std::find(bufferList_.begin(), bufferList_.end(), buffer); - if (it != bufferList_.end()) - return std::distance(bufferList_.begin(), it); + /* Find the buffer in the map, and return the buffer id. */ + auto it = std::find_if(bufferMap_.begin(), bufferMap_.end(), + [&buffer](auto const &p) { return p.second == buffer; }); - return -1; + if (it == bufferMap_.end()) + return -1; + + return it->first; } int RPiStream::prepareBuffers(unsigned int count) @@ -86,7 +88,7 @@ int RPiStream::prepareBuffers(unsigned int count) } /* We must import all internal/external exported buffers. */ - count = bufferList_.size(); + count = bufferMap_.size(); } return dev_->importBuffers(count); @@ -196,12 +198,12 @@ void RPiStream::clearBuffers() availableBuffers_ = std::queue{}; requestBuffers_ = std::queue{}; internalBuffers_.clear(); - bufferList_.clear(); + bufferMap_.clear(); } int RPiStream::queueToDevice(FrameBuffer *buffer) { - LOG(RPISTREAM, Debug) << "Queuing buffer " << getBufferIndex(buffer) + LOG(RPISTREAM, Debug) << "Queuing buffer " << getBufferId(buffer) << " for " << name_; int ret = dev_->queueBuffer(buffer); diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h index 959e9147..ed517c22 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -19,6 +20,8 @@ namespace libcamera { namespace RPi { +using BufferMap = std::unordered_map; + /* * Device stream abstraction for either an internal or external stream. * Used for both Unicam and the ISP. @@ -32,7 +35,7 @@ public: RPiStream(const char *name, MediaEntity *dev, bool importOnly = false) : external_(false), importOnly_(importOnly), name_(name), - dev_(std::make_unique(dev)) + dev_(std::make_unique(dev)), id_(0) { } @@ -45,8 +48,8 @@ public: bool isExternal() const; void setExportedBuffers(std::vector> *buffers); - const std::vector &getBuffers() const; - int getBufferIndex(FrameBuffer *buffer) const; + const BufferMap &getBuffers() const; + int getBufferId(FrameBuffer *buffer) const; int prepareBuffers(unsigned int count); int queueBuffer(FrameBuffer *buffer); @@ -74,8 +77,11 @@ private: /* The actual device stream. */ std::unique_ptr dev_; + /* Tracks a unique id key for the bufferMap_ */ + unsigned int id_; + /* All frame buffers associated with this device stream. */ - std::vector bufferList_; + BufferMap bufferMap_; /* * List of frame buffers that we can use if none have been provided by From patchwork Tue Sep 8 07:49:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9527 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 29077BDB1E for ; Tue, 8 Sep 2020 07:49:32 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E50D262C31; Tue, 8 Sep 2020 09:49:31 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="J3qecZdC"; dkim-atps=neutral Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 0751D62C27 for ; Tue, 8 Sep 2020 09:49:31 +0200 (CEST) Received: by mail-wr1-x444.google.com with SMTP id c18so17983310wrm.9 for ; Tue, 08 Sep 2020 00:49:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DXlCmLR+6xccYNyuaOP6y9KyOurPOW50qeSaoIlpP0U=; b=J3qecZdCdqzu4aTjuSiWiujdiDxwvaMFQ0RL1U0jlH4M+isLA0FXAdQ3TLF3nZLpp3 THNsv9D2T8OfiMZUFY1iMqs85jfbm6GLsE+Pyi8xskj/djVdcKyCE9P9vbFkIpIB+KMG JbGoVnnfjvN4sjFOB/Cg0m0Vzq9E0fjMT2o+JN9fT039PvC1IPQmA1yxS07+cchiOdae AJybdGpIBChYJwDGRg06bht0x2rHEvF673skikXT7kHcN95IU5uov2fU9gn+S+9a+UE2 R2F8vWruGpvq9Dhao6s5NKqugUHnjuQvH74NDwNycweSSXMb00wc/0iq91ER8eRfuasX noXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DXlCmLR+6xccYNyuaOP6y9KyOurPOW50qeSaoIlpP0U=; b=t9kUTa9d9a8hTQsGsSel+P2BU7sNdxWoMGFkIVfc76NbL8pWFebWAk72HJK/SiJeWq nYeZJiO13yEziojOzHz5rbR1PrHMGW2fomptrNccRms5RsKzTj4wshqYPb+d2GCMAA4B MsQ1zrBltfjCum7l46/hgTZIb3IGm9UaHy0IUOK6cMoGn7FNRPNegC+NH8RG3gWnJ0Nw nEyiCp+z6kDNLUS8ukyX0AiLR9v69iJiQyETVmXe/Jo5WoI+o48iGwmWr/gcseoyDKD/ na3Q0vALuWhWvPlB6vVClBcZQmYrer8854VU+eo7OGhFSQnQnPPZgrsPBR1t9xoq8bue 84ZA== X-Gm-Message-State: AOAM532G/57jSVCTFSXmiwPzhKBbTvZ3DnlhOjaXJ+xzFRmhVD1D2Ju7 DEuFGUcGNR4Bl+AhFnk01wVcqy1JeJZmeA== X-Google-Smtp-Source: ABdhPJxK6sXfE5f4/mo4nxcSvi1JHTSv/LqPIgmo2VzgzpjW5vILEfiuJWeLupxpW3fXonsKkRmCsg== X-Received: by 2002:adf:81c6:: with SMTP id 64mr24475854wra.176.1599551370455; Tue, 08 Sep 2020 00:49:30 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:29 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:11 +0100 Message-Id: <20200908074913.109244-12-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 11/12] pipeline: raspberrypi: Use an unordered_set to store IPA buffer ids 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" By using a set container, we can easily insert/remove buffer ids that have been mmaped by the IPA. This will be required to track buffers allocated externally and passed to the pipeline handler through a Request. Move the IPA buffer mapping code into a function to remove duplicated code. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- .../pipeline/raspberrypi/raspberrypi.cpp | 48 +++++++++++-------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 6aa13034..5621f182 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -158,8 +159,8 @@ public: RPi::RPiDevice isp_; /* The vector below is just for convenience when iterating over all streams. */ std::vector streams_; - /* Buffers passed to the IPA. */ - std::vector ipaBuffers_; + /* Stores the ids of the buffers mapped in the IPA. */ + std::unordered_set ipaBuffers_; /* DMAHEAP allocation helper. */ RPi::DmaHeap dmaHeap_; @@ -230,6 +231,7 @@ private: int queueAllBuffers(Camera *camera); int prepareBuffers(Camera *camera); void freeBuffers(Camera *camera); + void mapBuffers(Camera *camera, const RPi::BufferMap &buffers, unsigned int mask); MediaDevice *unicam_; MediaDevice *isp_; @@ -910,36 +912,42 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) } /* - * Link the FrameBuffers with the index of their position in the vector - * stored in the RPi stream object. + * Pass the stats and embedded data buffers to the IPA. No other + * buffers need to be passed. + */ + mapBuffers(camera, data->isp_[Isp::Stats].getBuffers(), RPiIpaMask::STATS); + mapBuffers(camera, data->unicam_[Unicam::Embedded].getBuffers(), RPiIpaMask::EMBEDDED_DATA); + + return 0; +} + +void PipelineHandlerRPi::mapBuffers(Camera *camera, const RPi::BufferMap &buffers, unsigned int mask) +{ + RPiCameraData *data = cameraData(camera); + std::vector ipaBuffers; + /* + * Link the FrameBuffers with the id (key value) in the map stored in + * the RPi stream object - along with an identifer mask. * * This will allow us to identify buffers passed between the pipeline * handler and the IPA. */ - for (auto const &b : data->isp_[Isp::Stats].getBuffers()) { - data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | b.first, - .planes = b.second->planes() }); - } - - for (auto const &b : data->unicam_[Unicam::Embedded].getBuffers()) { - data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | b.first, - .planes = b.second->planes() }); + for (auto const &it : buffers) { + ipaBuffers.push_back({ .id = mask | it.first, + .planes = it.second->planes() }); + data->ipaBuffers_.insert(mask | it.first); } - data->ipa_->mapBuffers(data->ipaBuffers_); - - return 0; + data->ipa_->mapBuffers(ipaBuffers); } void PipelineHandlerRPi::freeBuffers(Camera *camera) { RPiCameraData *data = cameraData(camera); - std::vector ids; - for (IPABuffer &ipabuf : data->ipaBuffers_) - ids.push_back(ipabuf.id); - - data->ipa_->unmapBuffers(ids); + /* Copy the buffer ids from the unordered_set to a vector to pass to the IPA. */ + std::vector ipaBuffers(data->ipaBuffers_.begin(), data->ipaBuffers_.end()); + data->ipa_->unmapBuffers(ipaBuffers); data->ipaBuffers_.clear(); for (auto const stream : data->streams_) From patchwork Tue Sep 8 07:49:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Naushir Patuck X-Patchwork-Id: 9528 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 2AFD6BDB1C for ; Tue, 8 Sep 2020 07:49:34 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E5B2F62BF5; Tue, 8 Sep 2020 09:49:33 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=raspberrypi.com header.i=@raspberrypi.com header.b="ENwqRFOz"; dkim-atps=neutral Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 330CC62C33 for ; Tue, 8 Sep 2020 09:49:32 +0200 (CEST) Received: by mail-wr1-x42d.google.com with SMTP id j2so18009734wrx.7 for ; Tue, 08 Sep 2020 00:49:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=raspberrypi.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+m5t4oaBhjXCa+YRQlZGE+0h7+DM3PcY0Gkj/7069Pc=; b=ENwqRFOzC4AsjjUKYk2VRb1WII4cACJa1ivp2Hvw5u/6JyaezQLeTbZDuaFa1VApp5 Up3FUnVo2LLHs06mAPJMXAknnyqx2Uf25Ek7sw1t1jmIpFIXLmOCd51ej8oh+sKnrqIC JCCG7rAK/ZA8wb6PyQ7vNIGVKlMXDOnsvUdY57vdccCrOv1chk+lHSlD7UMgUXoykzGJ YQmWYWTlH4MbLocI8XyaHkEFnuofOVCpfwQAYmDYND8H8+pZv7OoWFeiQn5ysS5doALa S1TipXJaClQpFRIzhgQpDRaB8T3xnHXpvQ57HqhDYPdxiAs07jdrBhPVeDPylXiitn6s 0XVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+m5t4oaBhjXCa+YRQlZGE+0h7+DM3PcY0Gkj/7069Pc=; b=OTZ6sbZiRkt1oJGZinWywHuLITWjExOHF6ocBK/D7rGP+gWh/+nAoc2DbGb1SCYDio yyUiCBCHBJ62udvBNOEZDJpQsjmsc8ht82moaEDVVXF1LJGuMhXJ1Bz6y10NhRZbhY5I iol70w8pph2Y719sUuyGibSHL8BAjpdU4VhjjjhJtVkqo7z7pnGycIIHogdA4ofckFh7 bCTEdA20y5nWnY15fTGp3elC8HFd8shL/ARu07vUOMypcay7jTNvHxHPMcqtEK6WrKSX biH4BtxuZIXA69cYMRJ0el7r9nAMFTVTibbnxx1M+Bv1JqNwjO0Tg/YOVagXdD7VSDR0 fgoQ== X-Gm-Message-State: AOAM531E/FnyOiIiJbcu7Y2V7wLMqlnCqYusKUNmIRKojodXrFR4yGx/ /xs8EuF5sLsyBF1W7EubrCeNNaJpj3V+5g== X-Google-Smtp-Source: ABdhPJwbG03oopFsfkS3PwwegOOA4HNTLgWrZbGhqsrg5iPJbJFLxWAlThJJqs+ytv5v5y++e1uWDw== X-Received: by 2002:adf:f750:: with SMTP id z16mr24305171wrp.377.1599551371491; Tue, 08 Sep 2020 00:49:31 -0700 (PDT) Received: from naushir-VirtualBox.patuck.local ([88.97.76.4]) by smtp.gmail.com with ESMTPSA id q15sm32534502wrr.8.2020.09.08.00.49.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Sep 2020 00:49:30 -0700 (PDT) From: Naushir Patuck To: libcamera-devel@lists.libcamera.org Date: Tue, 8 Sep 2020 08:49:12 +0100 Message-Id: <20200908074913.109244-13-naush@raspberrypi.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200908074913.109244-1-naush@raspberrypi.com> References: <20200908074913.109244-1-naush@raspberrypi.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 12/12] pipeline: ipa: raspberrypi: Handle any externally allocated FrameBuffer 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" Handle the case where a FrameBuffer that has been externally allocated (i.e. not through the v4l2 video device) is passed into a Request. We must store the buffer pointer in the stream internal buffer list to identify when used. Signed-off-by: Naushir Patuck Reviewed-by: Niklas Söderlund Reviewed-by: Kieran Bingham --- include/libcamera/ipa/raspberrypi.h | 11 ++-- src/ipa/raspberrypi/raspberrypi.cpp | 6 +- .../pipeline/raspberrypi/raspberrypi.cpp | 64 +++++++++++++------ .../pipeline/raspberrypi/rpi_stream.cpp | 30 ++++++++- .../pipeline/raspberrypi/rpi_stream.h | 3 + 5 files changed, 85 insertions(+), 29 deletions(-) diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h index 262fc6f3..dd6ebeac 100644 --- a/include/libcamera/ipa/raspberrypi.h +++ b/include/libcamera/ipa/raspberrypi.h @@ -28,11 +28,12 @@ enum RPiOperations { RPI_IPA_EVENT_QUEUE_REQUEST, }; -enum RPiIpaMask { - ID = 0x0ffff, - STATS = 0x10000, - EMBEDDED_DATA = 0x20000, - BAYER_DATA = 0x40000 +enum RPiBufferMask { + ID = 0x00ffff, + STATS = 0x010000, + EMBEDDED_DATA = 0x020000, + BAYER_DATA = 0x040000, + EXTERNAL_BUFFER = 0x100000, }; /* Size of the LS grid allocation. */ diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp index 688d2efc..0555cc4e 100644 --- a/src/ipa/raspberrypi/raspberrypi.cpp +++ b/src/ipa/raspberrypi/raspberrypi.cpp @@ -352,7 +352,7 @@ void IPARPi::processEvent(const IPAOperationData &event) IPAOperationData op; op.operation = RPI_IPA_ACTION_STATS_METADATA_COMPLETE; - op.data = { bufferId & RPiIpaMask::ID }; + op.data = { bufferId & RPiBufferMask::ID }; op.controls = { libcameraMetadata_ }; queueFrameAction.emit(0, op); break; @@ -373,7 +373,7 @@ void IPARPi::processEvent(const IPAOperationData &event) /* Ready to push the input buffer into the ISP. */ IPAOperationData op; op.operation = RPI_IPA_ACTION_RUN_ISP; - op.data = { bayerbufferId & RPiIpaMask::ID }; + op.data = { bayerbufferId & RPiBufferMask::ID }; queueFrameAction.emit(0, op); break; } @@ -700,7 +700,7 @@ void IPARPi::returnEmbeddedBuffer(unsigned int bufferId) { IPAOperationData op; op.operation = RPI_IPA_ACTION_EMBEDDED_COMPLETE; - op.data = { bufferId & RPiIpaMask::ID }; + op.data = { bufferId & RPiBufferMask::ID }; queueFrameAction.emit(0, op); } diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 5621f182..f5e0d1cd 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -151,6 +151,7 @@ public: void clearIncompleteRequests(); void handleStreamBuffer(FrameBuffer *buffer, RPi::RPiStream *stream); + void handleExternalBuffer(FrameBuffer *buffer, RPi::RPiStream *stream); void handleState(); CameraSensor *sensor_; @@ -725,23 +726,32 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request) /* Push all buffers supplied in the Request to the respective streams. */ for (auto stream : data->streams_) { - if (stream->isExternal()) { - FrameBuffer *buffer = request->findBuffer(stream); + if (!stream->isExternal()) + continue; + + FrameBuffer *buffer = request->findBuffer(stream); + if (buffer && stream->getBufferId(buffer) == -1) { /* - * If no buffer is provided by the request for this stream, we - * queue a nullptr to the stream to signify that it must use an - * internally allocated buffer for this capture request. This - * buffer will not be given back to the application, but is used - * to support the internal pipeline flow. - * - * The below queueBuffer() call will do nothing if there are not - * enough internal buffers allocated, but this will be handled by - * queuing the request for buffers in the RPiStream object. + * This buffer is not recognised, so it must have been allocated + * outside the v4l2 device. Store it in the stream buffer list + * so we can track it. */ - int ret = stream->queueBuffer(buffer); - if (ret) - return ret; + stream->setExternalBuffer(buffer); } + /* + * If no buffer is provided by the request for this stream, we + * queue a nullptr to the stream to signify that it must use an + * internally allocated buffer for this capture request. This + * buffer will not be given back to the application, but is used + * to support the internal pipeline flow. + * + * The below queueBuffer() call will do nothing if there are not + * enough internal buffers allocated, but this will be handled by + * queuing the request for buffers in the RPiStream object. + */ + int ret = stream->queueBuffer(buffer); + if (ret) + return ret; } /* Push the request to the back of the queue. */ @@ -915,8 +925,8 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera) * Pass the stats and embedded data buffers to the IPA. No other * buffers need to be passed. */ - mapBuffers(camera, data->isp_[Isp::Stats].getBuffers(), RPiIpaMask::STATS); - mapBuffers(camera, data->unicam_[Unicam::Embedded].getBuffers(), RPiIpaMask::EMBEDDED_DATA); + mapBuffers(camera, data->isp_[Isp::Stats].getBuffers(), RPiBufferMask::STATS); + mapBuffers(camera, data->unicam_[Unicam::Embedded].getBuffers(), RPiBufferMask::EMBEDDED_DATA); return 0; } @@ -1219,7 +1229,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) if (stream == &isp_[Isp::Stats]) { IPAOperationData op; op.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY; - op.data = { RPiIpaMask::STATS | static_cast(index) }; + op.data = { RPiBufferMask::STATS | static_cast(index) }; ipa_->processEvent(op); } else { /* Any other ISP output can be handed back to the application now. */ @@ -1293,6 +1303,11 @@ void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, RPi::RPiStream *stre Request *request = requestQueue_.front(); if (!dropFrameCount_ && request->findBuffer(stream) == buffer) { + /* + * Check if this is an externally provided buffer, and if + * so, we must stop tracking it in the pipeline handler. + */ + handleExternalBuffer(buffer, stream); /* * Tag the buffer as completed, returning it to the * application. @@ -1311,6 +1326,17 @@ void RPiCameraData::handleStreamBuffer(FrameBuffer *buffer, RPi::RPiStream *stre } } +void RPiCameraData::handleExternalBuffer(FrameBuffer *buffer, RPi::RPiStream *stream) +{ + unsigned int id = stream->getBufferId(buffer); + + if (!(id & RPiBufferMask::EXTERNAL_BUFFER)) + return; + + /* Stop the Stream object from tracking the buffer. */ + stream->removeExternalBuffer(buffer); +} + void RPiCameraData::handleState() { switch (state_) { @@ -1443,8 +1469,8 @@ void RPiCameraData::tryRunPipeline() << " Embedded buffer id: " << embeddedIndex; op.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE; - op.data = { RPiIpaMask::EMBEDDED_DATA | embeddedIndex, - RPiIpaMask::BAYER_DATA | bayerIndex }; + op.data = { RPiBufferMask::EMBEDDED_DATA | embeddedIndex, + RPiBufferMask::BAYER_DATA | bayerIndex }; ipa_->processEvent(op); } diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp index 879e25ba..c09f14c9 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp @@ -6,6 +6,8 @@ */ #include "rpi_stream.h" +#include + #include "libcamera/internal/log.h" namespace libcamera { @@ -44,8 +46,13 @@ bool RPiStream::isExternal() const void RPiStream::setExportedBuffers(std::vector> *buffers) { - for (auto const &buffer : *buffers) - bufferMap_.emplace(id_++, buffer.get()); + /* Ensure we are using a sensible number of buffers. */ + ASSERT(id_ < RPiBufferMask::ID); + + for (auto const &buffer : *buffers) { + bufferMap_.emplace(id_ & RPiBufferMask::ID, buffer.get()); + id_++; + } } const BufferMap &RPiStream::getBuffers() const @@ -68,6 +75,25 @@ int RPiStream::getBufferId(FrameBuffer *buffer) const return it->first; } +void RPiStream::setExternalBuffer(FrameBuffer *buffer) +{ + /* Ensure we are using a sensible number of buffers. */ + ASSERT(id_ < RPiBufferMask::ID); + + bufferMap_.emplace(RPiBufferMask::EXTERNAL_BUFFER | (id_ & RPiBufferMask::ID), + buffer); + id_++; +} + +void RPiStream::removeExternalBuffer(FrameBuffer *buffer) +{ + int id = getBufferId(buffer); + + /* Ensure we have this buffer in the stream, and it is marked external. */ + ASSERT(id != -1 && (id & RPiBufferMask::EXTERNAL_BUFFER)); + bufferMap_.erase(id); +} + int RPiStream::prepareBuffers(unsigned int count) { int ret; diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h index ed517c22..8b23c4b2 100644 --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h @@ -51,6 +51,9 @@ public: const BufferMap &getBuffers() const; int getBufferId(FrameBuffer *buffer) const; + void setExternalBuffer(FrameBuffer *buffer); + void removeExternalBuffer(FrameBuffer *buffer); + int prepareBuffers(unsigned int count); int queueBuffer(FrameBuffer *buffer); void returnBuffer(FrameBuffer *buffer);