From patchwork Mon Apr 15 23:18:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 994 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 25D9D60B2E for ; Tue, 16 Apr 2019 01:18:19 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id B51ED1BF203; Mon, 15 Apr 2019 23:18:18 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:53 +0200 Message-Id: <20190415231859.9747-2-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 1/7] libcamera: stream: Make Stream inheritable X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:19 -0000 In preparation for multiple streams support prepare to allow sub-classing the Stream class by removing the 'final' specifier from the class definition and make its private members protected. Signed-off-by: Jacopo Mondi Reviewed-by: Niklas Söderlund Reviewed-by: Laurent Pinchart --- include/libcamera/stream.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h index d0f7b0e12485..8a47930f8614 100644 --- a/include/libcamera/stream.h +++ b/include/libcamera/stream.h @@ -43,7 +43,7 @@ private: Size size_; }; -class Stream final +class Stream { public: class StillCapture : public StreamUsage @@ -68,7 +68,7 @@ public: BufferPool &bufferPool() { return bufferPool_; } const StreamConfiguration &configuration() const { return configuration_; } -private: +protected: friend class Camera; BufferPool bufferPool_; From patchwork Mon Apr 15 23:18:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 995 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id BFB5160B2E for ; Tue, 16 Apr 2019 01:18:19 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 4F3811BF203; Mon, 15 Apr 2019 23:18:19 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:54 +0200 Message-Id: <20190415231859.9747-3-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 2/7] libcamera: camera: Propagate freeBuffers() error X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:19 -0000 The error return code of PipelineHandler::freeBuffers() was not propagate up to applications by the Camera class. Fix this by returning the incremental error accumulated by multiple calls (one per Stream) to freeBuffers(). Do not return the error code of the call to freeBuffers() in the allocateBuffers() method error path not to overwrite the original error code returned from the allocation method. Signed-off-by: Jacopo Mondi --- src/libcamera/camera.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index bdf14b31d8ee..7f2dc904df16 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -671,6 +671,8 @@ int Camera::allocateBuffers() */ int Camera::freeBuffers() { + int ret = 0; + if (!stateIs(CameraPrepared)) return -EACCES; @@ -683,12 +685,12 @@ int Camera::freeBuffers() * by the V4L2 device that has allocated them. */ stream->bufferPool().destroyBuffers(); - pipe_->freeBuffers(this, stream); + ret |= pipe_->freeBuffers(this, stream); } state_ = CameraConfigured; - return 0; + return ret; } /** From patchwork Mon Apr 15 23:18:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 996 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9CF7A60DC4 for ; Tue, 16 Apr 2019 01:18:20 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id E743A1BF203; Mon, 15 Apr 2019 23:18:19 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:55 +0200 Message-Id: <20190415231859.9747-4-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 3/7] libcamera: camera: Pass the stream set to allocate/freeBuffers() X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:20 -0000 Pipeline handlers might need to perform allocation of internal buffers, setup operations, or simple sanity check before going into the per-stream buffer allocation. As of now, PipelineHandler::allocateBuffers() is called once for each active stream, leaving no space for stream-independent configuration. Change this by providing to the pipeline handlers the full set of active streams, and ask them to loop over them to perform per-streams memory allocations and freeing. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- src/libcamera/camera.cpp | 17 ++++++----------- src/libcamera/include/pipeline_handler.h | 6 ++++-- src/libcamera/pipeline/ipu3/ipu3.cpp | 13 +++++++++---- src/libcamera/pipeline/uvcvideo.cpp | 13 +++++++++---- src/libcamera/pipeline/vimc.cpp | 13 +++++++++---- src/libcamera/pipeline_handler.cpp | 11 ++++++----- 6 files changed, 43 insertions(+), 30 deletions(-) diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 7f2dc904df16..21caa24b90b5 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -647,13 +647,11 @@ int Camera::allocateBuffers() return -EINVAL; } - for (Stream *stream : activeStreams_) { - int ret = pipe_->allocateBuffers(this, stream); - if (ret) { - LOG(Camera, Error) << "Failed to allocate buffers"; - freeBuffers(); - return ret; - } + int ret = pipe_->allocateBuffers(this, activeStreams_); + if (ret) { + LOG(Camera, Error) << "Failed to allocate buffers"; + freeBuffers(); + return ret; } state_ = CameraPrepared; @@ -671,8 +669,6 @@ int Camera::allocateBuffers() */ int Camera::freeBuffers() { - int ret = 0; - if (!stateIs(CameraPrepared)) return -EACCES; @@ -685,12 +681,11 @@ int Camera::freeBuffers() * by the V4L2 device that has allocated them. */ stream->bufferPool().destroyBuffers(); - ret |= pipe_->freeBuffers(this, stream); } state_ = CameraConfigured; - return ret; + return pipe_->freeBuffers(this, activeStreams_); } /** diff --git a/src/libcamera/include/pipeline_handler.h b/src/libcamera/include/pipeline_handler.h index 33b820e706cc..a0862ebf35df 100644 --- a/src/libcamera/include/pipeline_handler.h +++ b/src/libcamera/include/pipeline_handler.h @@ -58,8 +58,10 @@ public: streamConfiguration(Camera *camera, const std::vector &usages) = 0; virtual int configureStreams(Camera *camera, const CameraConfiguration &config) = 0; - virtual int allocateBuffers(Camera *camera, Stream *stream) = 0; - virtual int freeBuffers(Camera *camera, Stream *stream) = 0; + virtual int allocateBuffers(Camera *camera, + const std::set &streams) = 0; + virtual int freeBuffers(Camera *camera, + const std::set &streams) = 0; virtual int start(Camera *camera) = 0; virtual void stop(Camera *camera); diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index ca09da753b90..f96e8763bce9 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -145,8 +145,10 @@ public: int configureStreams(Camera *camera, const CameraConfiguration &config) override; - int allocateBuffers(Camera *camera, Stream *stream) override; - int freeBuffers(Camera *camera, Stream *stream) override; + int allocateBuffers(Camera *camera, + const std::set &streams) override; + int freeBuffers(Camera *camera, + const std::set &streams) override; int start(Camera *camera) override; void stop(Camera *camera) override; @@ -305,9 +307,11 @@ int PipelineHandlerIPU3::configureStreams(Camera *camera, return 0; } -int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream) +int PipelineHandlerIPU3::allocateBuffers(Camera *camera, + const std::set &streams) { IPU3CameraData *data = cameraData(camera); + Stream *stream = *streams.begin(); CIO2Device *cio2 = &data->cio2_; ImgUDevice *imgu = data->imgu_; int ret; @@ -346,7 +350,8 @@ int PipelineHandlerIPU3::allocateBuffers(Camera *camera, Stream *stream) return 0; } -int PipelineHandlerIPU3::freeBuffers(Camera *camera, Stream *stream) +int PipelineHandlerIPU3::freeBuffers(Camera *camera, + const std::set &streams) { IPU3CameraData *data = cameraData(camera); diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp index cd472cfadd86..b8f634d88b46 100644 --- a/src/libcamera/pipeline/uvcvideo.cpp +++ b/src/libcamera/pipeline/uvcvideo.cpp @@ -32,8 +32,10 @@ public: int configureStreams(Camera *camera, const CameraConfiguration &config) override; - int allocateBuffers(Camera *camera, Stream *stream) override; - int freeBuffers(Camera *camera, Stream *stream) override; + int allocateBuffers(Camera *camera, + const std::set &streams) override; + int freeBuffers(Camera *camera, + const std::set &streams) override; int start(Camera *camera) override; void stop(Camera *camera) override; @@ -127,9 +129,11 @@ int PipelineHandlerUVC::configureStreams(Camera *camera, return 0; } -int PipelineHandlerUVC::allocateBuffers(Camera *camera, Stream *stream) +int PipelineHandlerUVC::allocateBuffers(Camera *camera, + const std::set &streams) { UVCCameraData *data = cameraData(camera); + Stream *stream = *streams.begin(); const StreamConfiguration &cfg = stream->configuration(); LOG(UVC, Debug) << "Requesting " << cfg.bufferCount << " buffers"; @@ -137,7 +141,8 @@ int PipelineHandlerUVC::allocateBuffers(Camera *camera, Stream *stream) return data->video_->exportBuffers(&stream->bufferPool()); } -int PipelineHandlerUVC::freeBuffers(Camera *camera, Stream *stream) +int PipelineHandlerUVC::freeBuffers(Camera *camera, + const std::set &streams) { UVCCameraData *data = cameraData(camera); return data->video_->releaseBuffers(); diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp index c8bbe2a19847..22449e47bc2d 100644 --- a/src/libcamera/pipeline/vimc.cpp +++ b/src/libcamera/pipeline/vimc.cpp @@ -32,8 +32,10 @@ public: int configureStreams(Camera *camera, const CameraConfiguration &config) override; - int allocateBuffers(Camera *camera, Stream *stream) override; - int freeBuffers(Camera *camera, Stream *stream) override; + int allocateBuffers(Camera *camera, + const std::set &streams) override; + int freeBuffers(Camera *camera, + const std::set &streams) override; int start(Camera *camera) override; void stop(Camera *camera) override; @@ -127,9 +129,11 @@ int PipelineHandlerVimc::configureStreams(Camera *camera, return 0; } -int PipelineHandlerVimc::allocateBuffers(Camera *camera, Stream *stream) +int PipelineHandlerVimc::allocateBuffers(Camera *camera, + const std::set &streams) { VimcCameraData *data = cameraData(camera); + Stream *stream = *streams.begin(); const StreamConfiguration &cfg = stream->configuration(); LOG(VIMC, Debug) << "Requesting " << cfg.bufferCount << " buffers"; @@ -137,7 +141,8 @@ int PipelineHandlerVimc::allocateBuffers(Camera *camera, Stream *stream) return data->video_->exportBuffers(&stream->bufferPool()); } -int PipelineHandlerVimc::freeBuffers(Camera *camera, Stream *stream) +int PipelineHandlerVimc::freeBuffers(Camera *camera, + const std::set &streams) { VimcCameraData *data = cameraData(camera); return data->video_->releaseBuffers(); diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp index 43550c0e0210..911d08448e69 100644 --- a/src/libcamera/pipeline_handler.cpp +++ b/src/libcamera/pipeline_handler.cpp @@ -193,10 +193,11 @@ PipelineHandler::~PipelineHandler() * \fn PipelineHandler::allocateBuffers() * \brief Allocate buffers for a stream * \param[in] camera The camera the \a stream belongs to - * \param[in] stream The stream to allocate buffers for + * \param[in] streams The set of streams to allocate buffers for * - * This method allocates buffers internally in the pipeline handler and - * associates them with the stream's buffer pool. + * This method allocates buffers internally in the pipeline handler for each + * stream in the \a streams buffer set, and associates them with the stream's + * buffer pool. * * The intended caller of this method is the Camera class. * @@ -207,9 +208,9 @@ PipelineHandler::~PipelineHandler() * \fn PipelineHandler::freeBuffers() * \brief Free all buffers associated with a stream * \param[in] camera The camera the \a stream belongs to - * \param[in] stream The stream to free buffers from + * \param[in] streams The set of streams to free buffers from * - * After a capture session has been stopped all buffers associated with the + * After a capture session has been stopped all buffers associated with each * stream shall be freed. * * The intended caller of this method is the Camera class. From patchwork Mon Apr 15 23:18:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 997 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 65D3660DC3 for ; Tue, 16 Apr 2019 01:18:21 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id BF5701BF205; Mon, 15 Apr 2019 23:18:20 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:56 +0200 Message-Id: <20190415231859.9747-5-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 4/7] libcamera: request: Add empty() method X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:22 -0000 Add method to verify if a request has pending buffers yet to be completed or it is empty and ready from completion. Reviewed-by: Niklas Söderlund Signed-off-by: Jacopo Mondi --- include/libcamera/request.h | 2 ++ src/libcamera/request.cpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/libcamera/request.h b/include/libcamera/request.h index 0dbd425115e8..6f97aa177ae0 100644 --- a/include/libcamera/request.h +++ b/include/libcamera/request.h @@ -37,6 +37,8 @@ public: Status status() const { return status_; } + bool empty() const { return pending_.empty(); } + private: friend class Camera; friend class PipelineHandler; diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index e0e77e972411..33055c5ac533 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -106,6 +106,13 @@ Buffer *Request::findBuffer(Stream *stream) const * \return The request completion status */ +/** + * \fn Request::empty() + * \brief Retrieve if a request has buffers yet to be completed + * + * \return True if no buffer is pending for completion, false otherwise + */ + /** * \brief Prepare the resources for the completion handler */ @@ -127,7 +134,7 @@ int Request::prepare() */ void Request::complete(Status status) { - ASSERT(pending_.empty()); + ASSERT(empty()); status_ = status; } @@ -149,7 +156,7 @@ bool Request::completeBuffer(Buffer *buffer) int ret = pending_.erase(buffer); ASSERT(ret == 1); - return pending_.empty(); + return empty(); } } /* namespace libcamera */ From patchwork Mon Apr 15 23:18:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 998 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 039DC60DC8 for ; Tue, 16 Apr 2019 01:18:22 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 8A9161BF203; Mon, 15 Apr 2019 23:18:21 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:57 +0200 Message-Id: <20190415231859.9747-6-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 5/7] libcamera: camera: Validate Request befor queueing it X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:22 -0000 Validate the Request before proceeding to prepare it at Camera::queueRequest() time. For now limit the validation to making sure the Request contains at least one Stream to capture from. Signed-off-by: Jacopo Mondi --- src/libcamera/camera.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/libcamera/camera.cpp b/src/libcamera/camera.cpp index 21caa24b90b5..e93e7b3b8477 100644 --- a/src/libcamera/camera.cpp +++ b/src/libcamera/camera.cpp @@ -715,8 +715,9 @@ Request *Camera::createRequest() * \param[in] request The request to queue to the camera * * This method queues a \a request allocated with createRequest() to the camera - * for capture. Once the request has been queued, the camera will notify its - * completion through the \ref requestCompleted signal. + * for capture and validates it by making sure it contains at least one stream + * where to capture from. Once the request has been queued, the camera will + * notify its completion through the \ref requestCompleted signal. * * Ownership of the request is transferred to the camera. It will be deleted * automatically after it completes. @@ -724,6 +725,7 @@ Request *Camera::createRequest() * \return 0 on success or a negative error code otherwise * \retval -ENODEV The camera has been disconnected from the system * \retval -EACCES The camera is not running so requests can't be queued + * \retval -EINVAL The request is not valid */ int Camera::queueRequest(Request *request) { @@ -733,6 +735,15 @@ int Camera::queueRequest(Request *request) if (!stateIs(CameraRunning)) return -EACCES; + /* + * \todo: Centralize validation if it gets more complex and update + * the documentation. + */ + if (request->empty()) { + LOG(Camera, Error) << "Invalid request"; + return -EINVAL; + } + int ret = request->prepare(); if (ret) { LOG(Camera, Error) << "Failed to prepare request"; From patchwork Mon Apr 15 23:18:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 999 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EF6FB60DC1 for ; Tue, 16 Apr 2019 01:18:22 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 2A7941BF203; Mon, 15 Apr 2019 23:18:21 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:58 +0200 Message-Id: <20190415231859.9747-7-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 6/7] libcamera: request: Expose the Stream to Buffers map X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:23 -0000 Add to the Request class a method to access the map to Stream to Buffer. Prepare the IPU3 pipeline handler to support multiple streams by retrieving the buffers to queue from the map exposed by this change, to better show the purpose of the patch. Reviewed-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Jacopo Mondi --- include/libcamera/request.h | 1 + src/libcamera/pipeline/ipu3/ipu3.cpp | 19 ++++++++----------- src/libcamera/request.cpp | 10 ++++++++++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/include/libcamera/request.h b/include/libcamera/request.h index 6f97aa177ae0..e9687f7e14d3 100644 --- a/include/libcamera/request.h +++ b/include/libcamera/request.h @@ -32,6 +32,7 @@ public: Request(const Request &) = delete; Request &operator=(const Request &) = delete; + const std::map &buffers() const { return bufferMap_; } int setBuffers(const std::map &streamMap); Buffer *findBuffer(Stream *stream) const; diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index f96e8763bce9..7d865fa329ea 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -409,19 +409,16 @@ int PipelineHandlerIPU3::queueRequest(Camera *camera, Request *request) { IPU3CameraData *data = cameraData(camera); V4L2Device *output = data->imgu_->output_.dev; - Stream *stream = &data->stream_; - /* Queue a buffer to the ImgU output for capture. */ - Buffer *buffer = request->findBuffer(stream); - if (!buffer) { - LOG(IPU3, Error) - << "Attempt to queue request with invalid stream"; - return -ENOENT; - } + /* Queue buffers to the ImgU output for capture. */ + for (auto &it : request->buffers()) { + Buffer *buffer = it.second; - int ret = output->queueBuffer(buffer); - if (ret < 0) - return ret; + int ret = output->queueBuffer(buffer); + if (ret < 0) + return ret; + + } PipelineHandler::queueRequest(camera, request); diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index 33055c5ac533..7fa034e6c747 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -51,6 +51,16 @@ Request::Request(Camera *camera) { } +/** + * \fn Request::buffers() + * \brief Retrieve the request's streams to buffer map + * + * Return a reference to the map that associates each Stream part of the + * request to the Buffer the Stream output should be directed to. + * + * \return The map of Stream to Buffer + */ + /** * \brief Set the streams to capture with associated buffers * \param[in] streamMap The map of streams to buffers From patchwork Mon Apr 15 23:18:59 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 1000 Return-Path: Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 89FC660DC1 for ; Tue, 16 Apr 2019 01:18:23 +0200 (CEST) X-Originating-IP: 2.224.242.101 Received: from uno.lan (2-224-242-101.ip172.fastwebnet.it [2.224.242.101]) (Authenticated sender: jacopo@jmondi.org) by relay8-d.mail.gandi.net (Postfix) with ESMTPSA id 204781BF205; Mon, 15 Apr 2019 23:18:22 +0000 (UTC) From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Apr 2019 01:18:59 +0200 Message-Id: <20190415231859.9747-8-jacopo@jmondi.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190415231859.9747-1-jacopo@jmondi.org> References: <20190415231859.9747-1-jacopo@jmondi.org> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v5 7/7] libcamera: buffer: Store Request reference in Buffer X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Apr 2019 23:18:24 -0000 Add to the Buffer class methods to set and retrieve a reference to the Request instance this buffer is part of. As Buffers might outlive the Request they are associated with, the reference is only temporary valid during the buffer completion interval (since when the buffer gets queued to Camera for processing, until it gets marked as completed). To show this change purpose, use the new Buffer::request() method in IPU3 pipeline handler, as it will soon be moved to support multiple streams where buffers might complete in an order different from the request queuing one. Signed-off-by: Jacopo Mondi --- include/libcamera/buffer.h | 6 ++++ src/libcamera/buffer.cpp | 45 +++++++++++++++++++++++++++- src/libcamera/pipeline/ipu3/ipu3.cpp | 2 +- src/libcamera/request.cpp | 4 +++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h index 0c844d126a27..a2daaaf346dc 100644 --- a/include/libcamera/buffer.h +++ b/include/libcamera/buffer.h @@ -13,6 +13,7 @@ namespace libcamera { class BufferPool; +class Request; class Plane final { @@ -52,14 +53,18 @@ public: unsigned int sequence() const { return sequence_; } Status status() const { return status_; } std::vector &planes() { return planes_; } + Request *request() const { return request_; } private: friend class BufferPool; friend class PipelineHandler; + friend class Request; friend class V4L2Device; void cancel(); + void setRequest(Request *req) { request_ = req; } + unsigned int index_; unsigned int bytesused_; uint64_t timestamp_; @@ -67,6 +72,7 @@ private: Status status_; std::vector planes_; + Request *request_; }; class BufferPool final diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp index e2d1cf04411e..790c6dcffe3a 100644 --- a/src/libcamera/buffer.cpp +++ b/src/libcamera/buffer.cpp @@ -196,7 +196,7 @@ void *Plane::mem() */ Buffer::Buffer() - : index_(-1) + : index_(-1), request_(nullptr) { } @@ -248,6 +248,26 @@ Buffer::Buffer() * \return The buffer status */ +/** + * \fn Buffer::request() + * \brief Retrieve the request this buffer belongs to + * + * The intended callers of this method are buffer completion slots + * implemented in CameraData sub-classes which needs to associated a request + * to the just completed buffer, before calling Request::completeBuffer(). + * + * It is up to the caller of this function to deal with the case the buffer has + * been already marked as complete, and the reference to the Request has been + * invalidated and set to nullptr. + * + * See also Buffer::setRequest() for a more detailed explanation of the + * validity interval of the Request reference contained in a Buffer. + * + * \return The Request this Buffer belongs to or nullptr if the Buffer has + * not been queued to the Camera for processing yet or it has completed already. + * \sa Buffer::setRequest() + */ + /** * \brief Mark a buffer as cancel by setting its status to BufferCancelled */ @@ -259,6 +279,29 @@ void Buffer::cancel() status_ = BufferCancelled; } +/** + * \fn Buffer::setRequest() + * \brief Set the request this buffer belongs to + * + * Buffers are associated to Streams in a Request, which is then sent to the + * Camera for processing. This method stores in the Buffer a pointer to the + * Request this Buffer is part of, for later retrieval through the + * Buffer::request() method. + * + * Buffers are associated to requests at Request::prepare() time and said + * association is valid until the buffer does not complete at + * Request::completeBuffer() time. Before and after the buffer completion + * interval (the time between when the request is queued to the Camera, and + * the buffer is marked as 'complete' by pipeline handlers) the reference to + * Request is set to nullptr. + * + * The intended caller of this methods is the Request class at + * Request::prepare() time, when it stores a reference to itself through a + * call to this method, and at Request::completeBuffer() time, where it + * invalidates the request_ reference by calling this method with a nullptr as + * argument. + */ + /** * \class BufferPool * \brief A pool of buffers diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 7d865fa329ea..ce680835cec2 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -630,7 +630,7 @@ void PipelineHandlerIPU3::IPU3CameraData::imguInputBufferReady(Buffer *buffer) */ void PipelineHandlerIPU3::IPU3CameraData::imguOutputBufferReady(Buffer *buffer) { - Request *request = queuedRequests_.front(); + Request *request = buffer->request(); pipe_->completeBuffer(camera_, request, buffer); pipe_->completeRequest(camera_, request); diff --git a/src/libcamera/request.cpp b/src/libcamera/request.cpp index 7fa034e6c747..6b175e125596 100644 --- a/src/libcamera/request.cpp +++ b/src/libcamera/request.cpp @@ -130,6 +130,8 @@ int Request::prepare() { for (auto const &pair : bufferMap_) { Buffer *buffer = pair.second; + + buffer->setRequest(this); pending_.insert(buffer); } @@ -166,6 +168,8 @@ bool Request::completeBuffer(Buffer *buffer) int ret = pending_.erase(buffer); ASSERT(ret == 1); + buffer->setRequest(nullptr); + return empty(); }