From patchwork Thu Oct 29 15:20:53 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28709 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 D700CC324C for ; Thu, 29 Oct 2026 15:21:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 94A0B690D0; Thu, 29 Oct 2026 16:21:56 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="beYjyKPs"; dkim-atps=neutral Received: from mail-vs1-xe2b.google.com (mail-vs1-xe2b.google.com [IPv6:2607:f8b0:4864:20::e2b]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AA5BB690A0 for ; Thu, 29 Oct 2026 16:21:54 +0100 (CET) Received: by mail-vs1-xe2b.google.com with SMTP id ada2fe7eead31-7bec5112765so1252803137.1 for ; Thu, 29 Oct 2026 08:21:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1793287313; x=1793892113; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=QyZ8thwMCGw70fPVVwaP3ssbbEYD7uBXQJer8IqBj/I=; b=beYjyKPsiwDUy6KvoIqDkcQ3EndubiyqBnppGvAvipnN0ACtp11y3/QMD90JyfSXka KNsM/qZXLHPXA17OZyXkO4LOAGhfvgb9hyU2SPqnJXgwYgSAtJjOrcGuzi+Cr/dWEf/1 bi6VlqVWDAPSXIv7Ap8IuYrWBLw75LWPnNQa6ZfUEdKHN8DKBE3XFP7UKzkel4chLmlH cvKuw+sd4SD28LW+MIz1R00oqVG3KKA8bcwJSalXPwvwuvyoC3oN0ozX/oYzXq4m1+IV BBHy4oJJn+I52eK2Cba23PAP+U5TJx0S6B0Ig/7oylXGIPPm0PEw8XZdwbFmiX+3NNaJ zWHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793287313; x=1793892113; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=QyZ8thwMCGw70fPVVwaP3ssbbEYD7uBXQJer8IqBj/I=; b=JzdlSeIZT+f0cvTnP/tuOwIpcjSpX/mJfWiE4zcc4rl2DsiXLSE6EaFBPFsx5zG/KC qx0xNsPcWjoon7+WdriTVZTiIv6/KRPOhNgnLIcrKGiV7AiuXg8X8p1DeLV63MDxsuCP XuQfIyBZu6+k6mWXIVEDjjwlSX1atfbEe31NFRdQ4N5RMRXw0A/z8azFoLI+nJn+KX+I o93Jxbm9GXBiuiPefpDNmXH2ZaVnpe72AkJWbpl/fYdjw8IEzpTrNIMdYC83R05NiCCN b3bWtkGlxtxkSUoGU6dnp/DgcS50DpGo8xv0o1fZVOZHyFXwTuqhq8cN/xsiTcT+RnsH rz5Q== X-Gm-Message-State: AFq9FYLMu5He4IpYBOsUt9I4+YA+BoTxQbQpGF3lr7VoTU31v0VVTYbH rWNlZFijmBOXtHc4vXgONJXc6fxNMRAxq+xJnlcj+3LEH229qvR9IqUNIH/rkIvSgnE= X-Gm-Gg: AYBFou2s9BGtzUt927szBb7EVQAG9Nc84RToDwfMv+44y3uxL2PrpO0t0dpzCDijjYA 0626xp5jPFVdaCMM+DsFUeI6L8ZODgiYMGgHtD/yMw2s+MtBYTILNIsy+d5tvrM7Ns45x/2n9Xe z2Ws4UXfAOE5ezq517NVWgDmDFkhTmikmRxuPxVhwCYt8l+OP48jxGil6y7yt3SuWdQ3uVWVZIn o9tNVx2TZ+ax/ti6E3FNDml5ZYvgVxZDXTBS6XhQWZfpV9IkpP9mY8e+NcKfFQOPyvwv9rfp2uW MX5K8h7cKzZd90ycT1PiW/y8XbSCPgDTOqNUib9Z+WocFIzWhbHwtPI2m1rgHxDh49MNFqMftrD 7lZSY6zMpRWzA9IJXEIA4W06+KHappPJYkLI7E8s5IWLL1Sxj1S5hz4IQbIuTwdggXGjaeieYyL o/vgAYvwhaFlmpRwvFocJwcwS/4ACP2FZOw4W/6CP/ORKqS3eQbS/whTeNo3Mgn7XN5QMovwknN MMemYdUYEJ3OpzBhVJ2u1JOKio1RWQW4DZxMY3mW3tw0E4wSUyblHHVbTIbxPwxEwvh9M4EFDOP BiQ3hloQEIX9QAtdklGfT2OQJCjDARXEpBDFCJygMUFWSNbjof8TxTCp X-Received: by 2002:a05:6102:3c83:b0:7c3:7286:c291 with SMTP id ada2fe7eead31-7d03a4846c0mr2739269137.19.1793287313433; Thu, 29 Oct 2026 08:21:53 -0700 (PDT) Received: from localhost ([144.121.52.163]) by smtp.gmail.com with ESMTPSA id a1e0cc1a2514c-991f74e5e22sm206563241.4.2026.10.29.08.21.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Oct 2026 08:21:52 -0700 (PDT) From: Ray Strode To: libcamera-devel@lists.libcamera.org Cc: kieran.bingham@ideasonboard.com, bod.linux@nxsw.ie, laurent.pinchart@ideasonboard.com, stefan.klug@ideasonboard.com, martincarvalho@gmail.com Subject: [PATCH v5 06/11] software-isp: Expose the configured image crop Date: Thu, 29 Oct 2026 11:20:53 -0400 Message-ID: <20261029152058.896209-7-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261029152058.896209-1-halfline@gmail.com> References: <20261029152058.896209-1-halfline@gmail.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Ray Strode This commit makes the image region selected by the debayer available to the pipeline handler, so ScalerCrop metadata can describe the processed output. The CPU and EGL backends crop input differently. CPU debayering keeps an output-sized window whose origin depends on the Bayer pattern and output channel order, while EGL scales a centered crop to fill the output. Each backend returns its actual configured image crop in input-buffer coordinates. The EGL crop is retained before statistics alignment, so the returned rectangle describes the image rather than its metering samples. Signed-off-by: Ray Strode --- .../libcamera/internal/software_isp/software_isp.h | 1 + src/libcamera/software_isp/debayer.cpp | 11 +++++++++++ src/libcamera/software_isp/debayer.h | 1 + src/libcamera/software_isp/debayer_cpu.h | 4 ++++ src/libcamera/software_isp/debayer_egl.cpp | 3 ++- src/libcamera/software_isp/debayer_egl.h | 2 ++ src/libcamera/software_isp/software_isp.cpp | 14 ++++++++++++++ 7 files changed, 35 insertions(+), 1 deletion(-) diff --git a/include/libcamera/internal/software_isp/software_isp.h b/include/libcamera/internal/software_isp/software_isp.h index b6491063..d32bb7d2 100644 --- a/include/libcamera/internal/software_isp/software_isp.h +++ b/include/libcamera/internal/software_isp/software_isp.h @@ -40,60 +40,61 @@ class Debayer; class FrameBuffer; class PixelFormat; class Stream; struct StreamConfiguration; LOG_DECLARE_CATEGORY(SoftwareIsp) class SoftwareIsp : public Object { public: SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor, ControlInfoMap *ipaControls); ~SoftwareIsp(); int loadConfiguration([[maybe_unused]] const std::string &filename) { return 0; } bool isValid() const; std::vector formats(PixelFormat input); SizeRange sizes(PixelFormat inputFormat, const Size &inputSize); std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size); uint32_t preferredInputStride(const PixelFormat &inputFormat, const Size &size); int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, const ipa::softisp::IPAConfigInfo &configInfo, ControlInfoMap *ipaControls); + Rectangle inputCrop() const; int exportBuffers(const Stream *stream, unsigned int count, std::vector> *buffers); void processStats(const uint32_t frame, const uint32_t bufferId, const ControlList &sensorControls); int start(); void stop(); void queueRequest(const uint32_t frame, const ControlList &controls); int queueBuffers(uint32_t frame, FrameBuffer *input, const std::map &outputs); void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output); Signal inputBufferReady; Signal outputBufferReady; Signal ispStatsReady; Signal metadataReady; Signal setSensorControls; private: void saveIspParams(uint32_t frame); void setSensorCtrls(const ControlList &sensorControls); void statsReady(uint32_t frame, uint32_t bufferId); void inputReady(FrameBuffer *input); void outputReady(FrameBuffer *output); std::unique_ptr debayer_; Thread ispWorkerThread_; diff --git a/src/libcamera/software_isp/debayer.cpp b/src/libcamera/software_isp/debayer.cpp index 4f665900..c7b1b2b3 100644 --- a/src/libcamera/software_isp/debayer.cpp +++ b/src/libcamera/software_isp/debayer.cpp @@ -79,60 +79,71 @@ namespace libcamera { * not apply any real lens shading correction. */ /** * \var DebayerParams::lscLutVersion * \brief Incremented on each \a lscLut change */ /** * \class Debayer * \brief Base debayering class * * Base class that provides functions for setting up the debayering process. */ LOG_DEFINE_CATEGORY(Debayer) /** * \brief Construct a Debayer object * \param[in] cm The camera manager */ Debayer::Debayer(const CameraManager &cm) : bench_(cm, "Debayer") { } Debayer::~Debayer() { } +/** + * \fn Rectangle Debayer::inputCrop() const + * \brief Retrieve the input region visible in the configured output + * + * The rectangle is in input-buffer coordinates and excludes any additional + * alignment performed for statistics sampling. It is valid after a successful + * configure() call. + * + * \return The configured image crop + */ + /** * \fn int Debayer::configure() * \brief Configure the debayer object according to the passed in parameters * \param[in] inputCfg The input configuration * \param[in] outputCfgs The output configurations * \param[in] ccmEnabled Whether a color correction matrix is applied * \param[in] lscEnabled Whether lens shading correction grid is provided * * \return 0 on success, a negative errno on failure */ /** * \fn Size Debayer::patternSize(PixelFormat inputFormat) * \brief Get the width and height at which the bayer pattern repeats * \param[in] inputFormat The input format * * Valid sizes are: 2x2, 4x2 or 4x4. * * \return Pattern size or an empty size for unsupported inputFormats */ /** * \fn std::vector Debayer::formats(PixelFormat inputFormat) * \brief Get the supported output formats * \param[in] inputFormat The input format * * \return All supported output formats or an empty vector if there are none */ /** diff --git a/src/libcamera/software_isp/debayer.h b/src/libcamera/software_isp/debayer.h index e30a0527..ef36f3c8 100644 --- a/src/libcamera/software_isp/debayer.h +++ b/src/libcamera/software_isp/debayer.h @@ -27,60 +27,61 @@ namespace libcamera { class CameraManager; class FrameBuffer; LOG_DECLARE_CATEGORY(Debayer) class Debayer : public Object { public: Debayer(const CameraManager &cm); virtual ~Debayer() = 0; virtual int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, bool ccmEnabled, bool lscEnabled) = 0; virtual std::vector formats(PixelFormat inputFormat) = 0; virtual std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) = 0; virtual uint32_t preferredInputStride([[maybe_unused]] const PixelFormat &inputFormat, [[maybe_unused]] const Size &size) { return 0; } virtual void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) = 0; virtual int start() { return 0; } virtual void stop() {} virtual SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) = 0; + virtual Rectangle inputCrop() const = 0; virtual const SharedFD &getStatsFD() = 0; unsigned int frameSize() { return outputConfig_.frameSize; } Signal inputBufferReady; Signal outputBufferReady; struct DebayerInputConfig { Size patternSize; unsigned int bpp; unsigned int stride; std::vector outputFormats; }; struct DebayerOutputConfig { unsigned int stride; unsigned int frameSize; }; DebayerInputConfig inputConfig_; DebayerOutputConfig outputConfig_; Size outputSize_; PixelFormat inputPixelFormat_; PixelFormat outputPixelFormat_; bool swapRedBlueGains_; Benchmark bench_; private: virtual Size patternSize(PixelFormat inputFormat) = 0; diff --git a/src/libcamera/software_isp/debayer_cpu.h b/src/libcamera/software_isp/debayer_cpu.h index ae570893..0c025b75 100644 --- a/src/libcamera/software_isp/debayer_cpu.h +++ b/src/libcamera/software_isp/debayer_cpu.h @@ -20,60 +20,64 @@ #include #include "libcamera/internal/bayer_format.h" #include "libcamera/internal/software_isp/debayer_params.h" #include "libcamera/internal/software_isp/swstats_cpu.h" #include "debayer.h" namespace libcamera { class DebayerCpuThread; class DebayerCpu : public Debayer { public: DebayerCpu(std::unique_ptr stats, const CameraManager &cm); ~DebayerCpu(); int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, bool ccmEnabled, bool lscEnabled) override; Size patternSize(PixelFormat inputFormat) override; std::vector formats(PixelFormat input) override; std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override; void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) override; int start() override; void stop() override; SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override; + Rectangle inputCrop() const override + { + return window_.translatedBy({ static_cast(xShift_), 0 }); + } const SharedFD &getStatsFD() override { return stats_->getStatsFD(); } private: friend class DebayerCpuThread; /** * \brief Called to debayer 1 line of Bayer input data to output format * \param[out] dst Pointer to the start of the output line to write * \param[in] src The input data * * Input data is an array of (patternSize_.height + 1) src * pointers each pointing to a line in the Bayer source. The middle * element of the array will point to the actual line being processed. * Earlier element(s) will point to the previous line(s) and later * element(s) to the next line(s). * * These functions take an array of src pointers, rather than * a single src pointer + a stride for the source, so that when the src * is slow uncached memory it can be copied to faster memory before * debayering. Debayering a standard 2x2 Bayer pattern requires access * to the previous and next src lines for interpolating the missing * colors. To allow copying the src lines only once 3 temporary buffers * each holding a single line are used, re-using the oldest buffer for * the next line and the pointers are swizzled so that: * src[0] = previous-line, src[1] = currrent-line, src[2] = next-line. * This way the 3 pointers passed to the debayer functions form * a sliding window over the src avoiding the need to copy each * line more than once. * * Similarly for bayer patterns which repeat every 4 lines, 5 src diff --git a/src/libcamera/software_isp/debayer_egl.cpp b/src/libcamera/software_isp/debayer_egl.cpp index 5a27a38d..d6636302 100644 --- a/src/libcamera/software_isp/debayer_egl.cpp +++ b/src/libcamera/software_isp/debayer_egl.cpp @@ -309,61 +309,62 @@ int DebayerEGL::configure(const StreamConfiguration &inputCfg, height_ = inputCfg.size.height; if (outputCfgs.size() != 1) { LOG(Debayer, Error) << "Unsupported number of output streams: " << outputCfgs.size(); return -EINVAL; } const StreamConfiguration &outputCfg = outputCfgs[0]; SizeRange outSizeRange = sizes(inputCfg.pixelFormat, inputCfg.size); std::tie(outputConfig_.stride, outputConfig_.frameSize) = strideAndFrameSize(outputCfg.pixelFormat, outputCfg.size); if (!outSizeRange.contains(outputCfg.size) || outputConfig_.stride != outputCfg.stride) { LOG(Debayer, Error) << "Invalid output size/stride: " << "\n " << outputCfg.size << " (" << outSizeRange << ")" << "\n " << outputCfg.stride << " (" << outputConfig_.stride << ")"; return -EINVAL; } outputPixelFormat_ = outputCfg.pixelFormat; outputSize_ = outputCfg.size; nativeOutputSize_ = outSizeRange.max; /* * The GPU scales the visible sensor crop to outputSize_. Statistics * consume the original input buffer, so use sensor coordinates here. */ - stats_->setWindow(debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_)); + inputCrop_ = debayerCrop(inputCfg.size, nativeOutputSize_, outputSize_); + stats_->setWindow(inputCrop_); inputBufferCount_ = inputCfg.bufferCount; outputBufferCount_ = outputCfg.bufferCount; return 0; } Size DebayerEGL::patternSize(PixelFormat inputFormat) { DebayerEGL::DebayerInputConfig config; if (getInputConfig(inputFormat, config) != 0) return {}; return config.patternSize; } std::vector DebayerEGL::formats(PixelFormat inputFormat) { DebayerEGL::DebayerInputConfig config; if (getInputConfig(inputFormat, config) != 0) return std::vector(); return config.outputFormats; } std::tuple DebayerEGL::strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) { diff --git a/src/libcamera/software_isp/debayer_egl.h b/src/libcamera/software_isp/debayer_egl.h index 6910fa49..90e361ce 100644 --- a/src/libcamera/software_isp/debayer_egl.h +++ b/src/libcamera/software_isp/debayer_egl.h @@ -34,99 +34,101 @@ namespace libcamera { #define DEBAYER_EGL_MIN_SIMPLE_RGB_GAIN_TEXTURE_UNITS 4 #define DEBAYER_OPENGL_COORDS 4 class CameraManager; class DebayerEGL : public Debayer { public: DebayerEGL(std::unique_ptr stats, const CameraManager &cm, EGLDisplay display); ~DebayerEGL(); int configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, bool ccmEnabled, bool lscEnabled) override; Size patternSize(PixelFormat inputFormat) override; std::vector formats(PixelFormat input) override; std::tuple strideAndFrameSize(const PixelFormat &outputFormat, const Size &size) override; uint32_t preferredInputStride(const PixelFormat &inputFormat, const Size &size) override; void process(uint32_t frame, FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms) override; int start() override; void stop() override; const SharedFD &getStatsFD() override { return stats_->getStatsFD(); } SizeRange sizes(PixelFormat inputFormat, const Size &inputSize) override; + Rectangle inputCrop() const override { return inputCrop_; } private: static int getInputConfig(PixelFormat inputFormat, DebayerInputConfig &config); int initBayerShaders(PixelFormat inputFormat, PixelFormat outputFormat); int getShaderVariableLocations(); void setShaderVariableValues(eGLImage &eGLImageIn, const DebayerParams ¶ms); int debayerGPU(FrameBuffer *input, FrameBuffer *output, const DebayerParams ¶ms, std::optional *mappedInputBuffer, std::optional *inputBufferDmaSyncer); eGLImage *getCachedInputFrameBuffer(FrameBuffer *input, std::optional *inMapped, std::optional *inDmaSyncer); eGLImage *getCachedOutputFrameBuffer(FrameBuffer *output); /* Shader program identifiers */ GLuint vertexShaderId_ = 0; GLuint fragmentShaderId_ = 0; GLuint programId_ = 0; /* Pointer to object representing input texture */ std::deque>> eglImageInCache_; std::deque>> eglImageOutCache_; unsigned int inputBufferCount_; unsigned int outputBufferCount_; /* LSC lookup table */ bool lscEnabled_; std::optional eglImageLscLookup_; std::optional lscLutVersion_; /* Shader parameters */ float firstRed_x_; float firstRed_y_; GLint attributeVertex_; GLint attributeTexture_; GLint textureUniformStep_; GLint textureUniformSize_; GLint textureUniformStrideFactor_; GLint textureUniformBayerFirstRed_; GLint textureUniformProjMatrix_; GLint textureUniformBayerDataIn_; /* Per-frame AWB gains */ GLint awbUniformDataIn_; /* Lens shading correction */ GLint textureUniformLsc_; /* Represent per-frame CCM as a uniform vector of floats 3 x 3 */ GLint ccmUniformDataIn_; /* Black Level compensation */ GLint blackLevelUniformDataIn_; /* Gamma */ GLint gammaUniformDataIn_; /* Contrast */ GLint contrastExpUniformDataIn_; Size nativeOutputSize_; + Rectangle inputCrop_; std::unique_ptr stats_; eGL egl_; uint32_t width_; uint32_t height_; GLint glFormat_; unsigned int bytesPerPixel_; uint32_t shaderStridePixels_; }; } /* namespace libcamera */ diff --git a/src/libcamera/software_isp/software_isp.cpp b/src/libcamera/software_isp/software_isp.cpp index 627625b4..8a06e53d 100644 --- a/src/libcamera/software_isp/software_isp.cpp +++ b/src/libcamera/software_isp/software_isp.cpp @@ -279,60 +279,74 @@ uint32_t SoftwareIsp::preferredInputStride(const PixelFormat &inputFormat, const * \brief Configure the SoftwareIsp object according to the passed in parameters * \param[in] inputCfg The input configuration * \param[in] outputCfgs The output configurations * \param[in] configInfo The IPA configuration data, received from the pipeline handler * \param[out] ipaControls The IPA controls to update * \return 0 on success, a negative errno on failure */ int SoftwareIsp::configure(const StreamConfiguration &inputCfg, const std::vector> &outputCfgs, const ipa::softisp::IPAConfigInfo &configInfo, ControlInfoMap *ipaControls) { ASSERT(ipa_ && debayer_); int ret = ipa_->configure(configInfo, ipaControls); if (ret < 0) return ret; ret = debayer_->configure(inputCfg, outputCfgs, ccmEnabled_, lscEnabled_); if (ret < 0) return ret; LOG(SoftwareIsp, Info) << "Input " << inputCfg.size << "-" << BayerFormat::fromPixelFormat(inputCfg.pixelFormat) << " stride " << inputCfg.stride; return 0; } +/** + * \brief Retrieve the input region used to produce the configured output + * + * The rectangle is expressed in input-buffer pixels, before any Bayer + * alignment applied by the statistics engine. It is valid after configure() + * succeeds and describes the selected CPU or EGL debayer backend. + * + * \return The configured input crop + */ +Rectangle SoftwareIsp::inputCrop() const +{ + return debayer_->inputCrop(); +} + /** * \brief Export the buffers from the Software ISP * \param[in] stream Output stream exporting the buffers * \param[in] count Number of buffers to allocate * \param[out] buffers Vector to store the allocated buffers * \return The number of allocated buffers on success or a negative error code * otherwise */ int SoftwareIsp::exportBuffers(const Stream *stream, unsigned int count, std::vector> *buffers) { ASSERT(debayer_ != nullptr); /* single output for now */ if (stream == nullptr) return -EINVAL; return dmaHeap_.exportBuffers(count, { debayer_->frameSize() }, buffers); } /** * \brief Queue a request and process the control list from the application * \param[in] frame The number of the frame which will be processed next * \param[in] controls The controls for the \a frame */ void SoftwareIsp::queueRequest(const uint32_t frame, const ControlList &controls) { ipa_->queueRequest(frame, controls); }