From patchwork Thu Oct 29 13:26:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ray Strode X-Patchwork-Id: 28696 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 BB713C3261 for ; Thu, 29 Oct 2026 13:27:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 71C05690BF; Thu, 29 Oct 2026 14:27:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="I4cDCnCF"; dkim-atps=neutral Received: from mail-vs1-xe2c.google.com (mail-vs1-xe2c.google.com [IPv6:2607:f8b0:4864:20::e2c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BB43B68E07 for ; Thu, 29 Oct 2026 14:27:09 +0100 (CET) Received: by mail-vs1-xe2c.google.com with SMTP id ada2fe7eead31-78fb1fb9508so602339137.1 for ; Thu, 29 Oct 2026 06:27:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20260707; t=1793280428; x=1793885228; 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=I4cDCnCF5bNRsHjJef+tGIuPFXx5aU88ZY5E0OBL1MXNbTofT6Mx+dFMiKIQ3lDzG9 J0oImVs45TjDB/zD4Xx7ecCoedhuQgHNX33ARtJex8Ukym/2aXy0zTj4RzbpjHiqdMri mU2+u1IqkxWiZreWUhlxsA5yr14i0S0Gcv5nA0ruKz3DHcWp30LoyT8/3I7T7OGtSM9Q mdLSp5dGf0dR2QgeyXDMgimlK7T/6faExKJ+/l7y2JD7edKKC8jV9/JLRb7wTa4xkZVD yAwcWWMqR5ta2Ovy4ewOTpYOz5W1NApwcuKvdJyqWoiwN6bPo5fseHOXhLgQUpwe+1qQ Fn/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793280428; x=1793885228; 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=LCgf8qLlWaAX2p9xsNjcsAqKOQ74Lj/kGcET8f7ye3JqlPmefocTwEbPut84WDQ4GB 73zY3lkHyonH0R1rAFe3XPIlvn2UHdMCCLXM7ZkghOCHTMjP072a1tODppFtjnHueq+6 BBIlCiKHmjSSyzCjPC5vy3gwGWT+nfwYPxRbxj38w+SuVcAX5OInpw8+xLYG/uJul09n dGc9zj/o9TmEEFLudiPkjVL4acqKcxS3qR5HuG6tDG6iIsjNv5il7keHAu78NP4onDU/ paHciP0/rhRsS/0fEAknQTtBGY3yUq8dOHi1YwydTIzbe2f4UuDyjSyZrKddPG0JlNaE dHTg== X-Gm-Message-State: AFq9FYJ/VX/v5d8yK0WddmFgmrOm43YWEaj864oGScQ0urkmNyXPT9mQ U9D/eCo0jiZqYUOrmqlrammAm6Dgs2h/UpCiis7lTXD+cpIaL15E26oMFhnMCio1d9I= X-Gm-Gg: AYBFou3f99evv/5joHF4+aYeMh1R+sM76uSpjUX3n3oXXCH8TeBOdVu6mNGHyYsBH+d 9mEkLXOk0MFL6rOleCeMI87iOZ9gs/fWPjhsIVty1TH1czbITj1SmJxfFWN36WKEKFyUZnEp8hu yWNa6gVK7KiJ4aJ6Tikm3sledcgae8+XWzNtrZCJDj7u89agCJtJnqpROqAVgG4Eoj3LZyvUV+Z o6YKibJGv+EkkBLwDT9b1mhhIumOM6iDI6Znxawvd5UuIkzFD9sLCAV1nvDfiLAbzuShm9Mrf74 NihFEv6+peI3lU68ox/shlOPEsMKcm43lUIMnHH0THFX1xJamt8HUOZk037l2kjuhitZbJrFJk6 tbkRMJHdDkYUIFl2jx/y/vsORWKrki5+S9gpL2+W37hYPEkuBediBo5wieLb7ikO8yYOZjA+utS 4gDgc3nw2LmEqGNpo2QMuZ4d4UVAOxEZ4mBT1OAaG7tD8Z4AAVlhMCbq2Igln66m1UMweF9pmde O/TCg2tB2eAzwiCFWM1tjuZLvamITnNm6v6jRNrTTVR1SOpxQoBROvVuTcaI5bi/fMtVnFqmNjw ThTLqnY8lNBg8cMCkdivG3BswHweDjB4tH+0zXYtN8vbqx80B2f02GsGWA== X-Received: by 2002:a67:e112:0:b0:7b0:bd98:68df with SMTP id ada2fe7eead31-7d0543acf6dmr633810137.41.1793280428358; Thu, 29 Oct 2026 06:27:08 -0700 (PDT) Received: from localhost ([144.121.52.163]) by smtp.gmail.com with ESMTPSA id a1e0cc1a2514c-99125931983sm9476046241.2.2026.10.29.06.27.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Oct 2026 06:27:07 -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 v4 4/9] software-isp: Expose the configured image crop Date: Thu, 29 Oct 2026 09:26:26 -0400 Message-ID: <20261029132631.370507-5-halfline@gmail.com> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261029132631.370507-1-halfline@gmail.com> References: <20261016202818.1405645-1-halfline@gmail.com> <20261029132631.370507-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); }