From patchwork Mon Mar 16 02:41:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Niklas_S=C3=B6derlund?= X-Patchwork-Id: 3114 Return-Path: Received: from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net [195.74.38.228]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D604260417 for ; Mon, 16 Mar 2020 03:42:33 +0100 (CET) X-Halon-ID: b76e5d8f-672f-11ea-9f40-0050569116f7 Authorized-sender: niklas@soderlund.pp.se Received: from bismarck.berto.se (p4fca2392.dip0.t-ipconnect.de [79.202.35.146]) by bin-vsp-out-03.atm.binero.net (Halon) with ESMTPA id b76e5d8f-672f-11ea-9f40-0050569116f7; Mon, 16 Mar 2020 03:42:02 +0100 (CET) From: =?utf-8?q?Niklas_S=C3=B6derlund?= To: libcamera-devel@lists.libcamera.org Date: Mon, 16 Mar 2020 03:41:45 +0100 Message-Id: <20200316024146.2474424-6-niklas.soderlund@ragnatech.se> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200316024146.2474424-1-niklas.soderlund@ragnatech.se> References: <20200316024146.2474424-1-niklas.soderlund@ragnatech.se> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC 5/6] libcamera: ipu3: Do not unconditionally queue buffers to CIO2 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Mar 2020 02:42:34 -0000 Instead of unconditionally cycling buffers between the CIO2 and IMGU pick a buffer when a request is queued to the pipeline. This is needed if operations are the be applied to the buffer coming from CIO2 with parameters coming from a Request. The approach to pick a CIO2 buffer when a request is queued is similar to other pipelines, where parameters and statistic buffers are picked this way. Signed-off-by: Niklas Söderlund --- src/libcamera/pipeline/ipu3/ipu3.cpp | 69 +++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 0c2a217c9ea8f6ba..dbb0c4328aa0efe5 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -119,6 +120,10 @@ public: int allocateBuffers(); void freeBuffers(); + FrameBuffer *getBuffer(); + void putBuffer(FrameBuffer *buffer); + int queueBuffer(FrameBuffer *buffer); + int start(); int stop(); @@ -130,6 +135,7 @@ public: private: std::vector> buffers_; + std::queue availableBuffers_; }; class IPU3Stream : public Stream @@ -157,6 +163,8 @@ public: void imguInputBufferReady(FrameBuffer *buffer); void cio2BufferReady(FrameBuffer *buffer); + std::map cio2ToRequest_; + CIO2Device cio2_; ImgUDevice *imgu_; @@ -717,11 +725,20 @@ void PipelineHandlerIPU3::stop(Camera *camera) int PipelineHandlerIPU3::queueRequestDevice(Camera *camera, Request *request) { + IPU3CameraData *data = cameraData(camera); + FrameBuffer *buffer; int error = 0; + /* Get a CIO2 buffer and track it it's used for this request. */ + buffer = data->cio2_.getBuffer(); + if (!buffer) + return -EINVAL; + data->cio2ToRequest_[buffer] = request; + data->cio2_.queueBuffer(buffer); + for (auto it : request->buffers()) { IPU3Stream *stream = static_cast(it.first); - FrameBuffer *buffer = it.second; + buffer = it.second; int ret = stream->device_->dev->queueBuffer(buffer); if (ret < 0) @@ -893,7 +910,9 @@ void IPU3CameraData::imguInputBufferReady(FrameBuffer *buffer) if (buffer->metadata().status == FrameMetadata::FrameCancelled) return; - cio2_.output_->queueBuffer(buffer); + /* Remove association between CIO2 buffer an Request. */ + cio2ToRequest_.erase(buffer); + cio2_.putBuffer(buffer); } /** @@ -1416,30 +1435,58 @@ int CIO2Device::configure(const Size &size, int CIO2Device::allocateBuffers() { int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_); - if (ret < 0) + if (ret < 0) { LOG(IPU3, Error) << "Failed to allocate CIO2 buffers"; + return ret; + } + + for (std::unique_ptr &buffer : buffers_) + availableBuffers_.push(buffer.get()); return ret; } void CIO2Device::freeBuffers() { + while (!availableBuffers_.empty()) + availableBuffers_.pop(); + buffers_.clear(); if (output_->releaseBuffers()) LOG(IPU3, Error) << "Failed to release CIO2 buffers"; } +FrameBuffer *CIO2Device::getBuffer() +{ + if (availableBuffers_.empty()) { + LOG(IPU3, Error) << "CIO2 buffer underrun"; + return nullptr; + } + + FrameBuffer *buffer = availableBuffers_.front(); + + availableBuffers_.pop(); + + return buffer; +} + +void CIO2Device::putBuffer(FrameBuffer *buffer) +{ + availableBuffers_.push(buffer); +} + +int CIO2Device::queueBuffer(FrameBuffer *buffer) +{ + int ret = output_->queueBuffer(buffer); + if (ret) + LOG(IPU3, Error) << "Failed to queue CIO2 buffer"; + + return ret; +} + int CIO2Device::start() { - for (const std::unique_ptr &buffer : buffers_) { - int ret = output_->queueBuffer(buffer.get()); - if (ret) { - LOG(IPU3, Error) << "Failed to queue CIO2 buffer"; - return ret; - } - } - return output_->streamOn(); }