From patchwork Mon Mar 11 12:32:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacopo Mondi X-Patchwork-Id: 19658 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 E1C31C32A3 for ; Mon, 11 Mar 2024 12:32:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0B0CC62C89; Mon, 11 Mar 2024 13:32:48 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ojFxlMA0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 285B76286F for ; Mon, 11 Mar 2024 13:32:45 +0100 (CET) Received: from localhost.localdomain (93-61-96-190.ip145.fastwebnet.it [93.61.96.190]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id DA4DDC85; Mon, 11 Mar 2024 13:32:23 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1710160344; bh=hMSBLGSj2sGGPKdpA0Ln0LMOtcUanFa0GBH/0ec3ZFI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ojFxlMA042u5lcbX+Y6m4otsJwjj7497fifZecJViI/edeacOMtqg7+T01oj/rTH9 iL971FkVveQhWgVF2oua8PBFjZPG6zYLtssJQKws28HtMac88YCC/ln9m9xorfgue9 dOm6Rv10JJEspM1WMPN7PG/yECJEH46EydxTF3pE= From: Jacopo Mondi To: libcamera-devel@lists.libcamera.org Subject: [PATCH v2 2/4] libcamera: rkisp1: Replace usage of RkISP1FrameInfo Date: Mon, 11 Mar 2024 13:32:30 +0100 Message-ID: <20240311123234.32925-3-jacopo.mondi@ideasonboard.com> X-Mailer: git-send-email 2.43.2 In-Reply-To: <20240311123234.32925-1-jacopo.mondi@ideasonboard.com> References: <20240311123234.32925-1-jacopo.mondi@ideasonboard.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: , Cc: Jacopo Mondi Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Now that the pipeline handler can create a private derived class of Request::Private, use it to store the pipeline specific data. In the case of RkISP1 we associate the statistic and paramters buffers with a Request. As the IPA sends notifications for paramters and statistics buffer by identifying them by frame id, associate the frame ids and the Request in the RkISP1CameraData class. This replaces the functionalities of RkISP1FrameInfo which can now be removed. Signed-off-by: Jacopo Mondi Reviewed-by: Stefan Klug Reviewed-by: Daniel Scally Tested-by: Daniel Scally --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 359 +++++++++-------------- 1 file changed, 138 insertions(+), 221 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index 586b46d64630..0479e243d392 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -39,6 +39,7 @@ #include "libcamera/internal/ipa_manager.h" #include "libcamera/internal/media_device.h" #include "libcamera/internal/pipeline_handler.h" +#include "libcamera/internal/request.h" #include "libcamera/internal/v4l2_subdevice.h" #include "libcamera/internal/v4l2_videodevice.h" @@ -48,67 +49,63 @@ namespace libcamera { LOG_DEFINE_CATEGORY(RkISP1) -class PipelineHandlerRkISP1; -class RkISP1CameraData; +class RkISP1Request : public Request::Private +{ +public: + RkISP1Request(Camera *camera) + : Request::Private(camera) + { + } -struct RkISP1FrameInfo { - unsigned int frame; - Request *request; + bool hasPendingBuffers(bool isRaw) const; - FrameBuffer *paramBuffer; FrameBuffer *statBuffer; - FrameBuffer *mainPathBuffer; - FrameBuffer *selfPathBuffer; + FrameBuffer *paramBuffer; + + /* The frame number this request is associated with. */ + unsigned int frame; bool paramDequeued; bool metadataProcessed; }; -class RkISP1Frames +bool RkISP1Request::hasPendingBuffers(bool isRaw) const { -public: - RkISP1Frames(PipelineHandler *pipe); - - RkISP1FrameInfo *create(const RkISP1CameraData *data, Request *request, - bool isRaw); - int destroy(unsigned int frame); - void clear(); - - RkISP1FrameInfo *find(unsigned int frame); - RkISP1FrameInfo *find(FrameBuffer *buffer); - RkISP1FrameInfo *find(Request *request); - -private: - PipelineHandlerRkISP1 *pipe_; - std::map frameInfo_; -}; + return Request::Private::hasPendingBuffers() || + !metadataProcessed || (!isRaw && !paramDequeued); +} +class PipelineHandlerRkISP1; class RkISP1CameraData : public Camera::Private { public: RkISP1CameraData(PipelineHandler *pipe, RkISP1MainPath *mainPath, RkISP1SelfPath *selfPath) - : Camera::Private(pipe), frame_(0), frameInfo_(pipe), - mainPath_(mainPath), selfPath_(selfPath) + : Camera::Private(pipe), frame_(0), mainPath_(mainPath), + selfPath_(selfPath) { } PipelineHandlerRkISP1 *pipe(); int loadIPA(unsigned int hwRevision); + void addRequest(RkISP1Request *request); + Stream mainPathStream_; Stream selfPathStream_; std::unique_ptr sensor_; std::unique_ptr delayedCtrls_; unsigned int frame_; std::vector ipaBuffers_; - RkISP1Frames frameInfo_; RkISP1MainPath *mainPath_; RkISP1SelfPath *selfPath_; std::unique_ptr ipa_; + /* Associate a frame id with a Request. */ + std::map requestMap_; + private: void paramFilled(unsigned int frame); void setSensorControls(unsigned int frame, @@ -157,6 +154,8 @@ public: int start(Camera *camera, const ControlList *controls) override; void stopDevice(Camera *camera) override; + std::unique_ptr createRequestDevice(Camera *camera, + uint64_t cookie) override; int queueRequestDevice(Camera *camera, Request *request) override; bool match(DeviceEnumerator *enumerator) override; @@ -169,13 +168,17 @@ private: return static_cast(camera->_d()); } + RkISP1Request *cameraRequest(Request *request) + { + return static_cast(request->_d()); + } + friend RkISP1CameraData; - friend RkISP1Frames; int initLinks(Camera *camera, const CameraSensor *sensor, const RkISP1CameraConfiguration &config); int createCamera(MediaEntity *sensor); - void tryCompleteRequest(RkISP1FrameInfo *info); + void tryCompleteRequest(RkISP1Request *request); void bufferReady(FrameBuffer *buffer); void paramReady(FrameBuffer *buffer); void statReady(FrameBuffer *buffer); @@ -206,129 +209,6 @@ private: const MediaPad *ispSink_; }; -RkISP1Frames::RkISP1Frames(PipelineHandler *pipe) - : pipe_(static_cast(pipe)) -{ -} - -RkISP1FrameInfo *RkISP1Frames::create(const RkISP1CameraData *data, Request *request, - bool isRaw) -{ - unsigned int frame = data->frame_; - - FrameBuffer *paramBuffer = nullptr; - FrameBuffer *statBuffer = nullptr; - - if (!isRaw) { - if (pipe_->availableParamBuffers_.empty()) { - LOG(RkISP1, Error) << "Parameters buffer underrun"; - return nullptr; - } - - if (pipe_->availableStatBuffers_.empty()) { - LOG(RkISP1, Error) << "Statistic buffer underrun"; - return nullptr; - } - - paramBuffer = pipe_->availableParamBuffers_.front(); - pipe_->availableParamBuffers_.pop(); - - statBuffer = pipe_->availableStatBuffers_.front(); - pipe_->availableStatBuffers_.pop(); - } - - FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_); - FrameBuffer *selfPathBuffer = request->findBuffer(&data->selfPathStream_); - - RkISP1FrameInfo *info = new RkISP1FrameInfo; - - info->frame = frame; - info->request = request; - info->paramBuffer = paramBuffer; - info->mainPathBuffer = mainPathBuffer; - info->selfPathBuffer = selfPathBuffer; - info->statBuffer = statBuffer; - info->paramDequeued = false; - info->metadataProcessed = false; - - frameInfo_[frame] = info; - - return info; -} - -int RkISP1Frames::destroy(unsigned int frame) -{ - RkISP1FrameInfo *info = find(frame); - if (!info) - return -ENOENT; - - pipe_->availableParamBuffers_.push(info->paramBuffer); - pipe_->availableStatBuffers_.push(info->statBuffer); - - frameInfo_.erase(info->frame); - - delete info; - - return 0; -} - -void RkISP1Frames::clear() -{ - for (const auto &entry : frameInfo_) { - RkISP1FrameInfo *info = entry.second; - - pipe_->availableParamBuffers_.push(info->paramBuffer); - pipe_->availableStatBuffers_.push(info->statBuffer); - - delete info; - } - - frameInfo_.clear(); -} - -RkISP1FrameInfo *RkISP1Frames::find(unsigned int frame) -{ - auto itInfo = frameInfo_.find(frame); - - if (itInfo != frameInfo_.end()) - return itInfo->second; - - LOG(RkISP1, Fatal) << "Can't locate info from frame"; - - return nullptr; -} - -RkISP1FrameInfo *RkISP1Frames::find(FrameBuffer *buffer) -{ - for (auto &itInfo : frameInfo_) { - RkISP1FrameInfo *info = itInfo.second; - - if (info->paramBuffer == buffer || - info->statBuffer == buffer || - info->mainPathBuffer == buffer || - info->selfPathBuffer == buffer) - return info; - } - - LOG(RkISP1, Fatal) << "Can't locate info from buffer"; - - return nullptr; -} - -RkISP1FrameInfo *RkISP1Frames::find(Request *request) -{ - for (auto &itInfo : frameInfo_) { - RkISP1FrameInfo *info = itInfo.second; - - if (info->request == request) - return info; - } - - LOG(RkISP1, Fatal) << "Can't locate info from request"; - - return nullptr; -} - PipelineHandlerRkISP1 *RkISP1CameraData::pipe() { return static_cast(Camera::Private::pipe()); @@ -379,23 +259,34 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision) return 0; } +void RkISP1CameraData::addRequest(RkISP1Request *request) +{ + /* Associate the request and the frame number. */ + request->frame = frame_; + requestMap_[frame_] = request; + frame_++; +} + void RkISP1CameraData::paramFilled(unsigned int frame) { PipelineHandlerRkISP1 *pipe = RkISP1CameraData::pipe(); - RkISP1FrameInfo *info = frameInfo_.find(frame); - if (!info) - return; + RkISP1Request *request = requestMap_.at(frame); + ASSERT(request); - info->paramBuffer->_d()->metadata().planes()[0].bytesused = + request->paramBuffer->_d()->metadata().planes()[0].bytesused = sizeof(struct rkisp1_params_cfg); - pipe->param_->queueBuffer(info->paramBuffer); - pipe->stat_->queueBuffer(info->statBuffer); - - if (info->mainPathBuffer) - mainPath_->queueBuffer(info->mainPathBuffer); - - if (selfPath_ && info->selfPathBuffer) - selfPath_->queueBuffer(info->selfPathBuffer); + pipe->param_->queueBuffer(request->paramBuffer); + pipe->stat_->queueBuffer(request->statBuffer); + + FrameBuffer *mainPathBuffer = + request->_o()->findBuffer(&mainPathStream_); + if (mainPathBuffer) + mainPath_->queueBuffer(mainPathBuffer); + + FrameBuffer *selfPathBuffer = + request->_o()->findBuffer(&selfPathStream_); + if (selfPath_ && selfPathBuffer) + selfPath_->queueBuffer(selfPathBuffer); } void RkISP1CameraData::setSensorControls([[maybe_unused]] unsigned int frame, @@ -406,14 +297,13 @@ void RkISP1CameraData::setSensorControls([[maybe_unused]] unsigned int frame, void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &metadata) { - RkISP1FrameInfo *info = frameInfo_.find(frame); - if (!info) - return; + RkISP1Request *request = requestMap_.at(frame); + ASSERT(request); - info->request->metadata().merge(metadata); - info->metadataProcessed = true; + request->_o()->metadata().merge(metadata); + request->metadataProcessed = true; - pipe()->tryCompleteRequest(info); + pipe()->tryCompleteRequest(request); } /* ----------------------------------------------------------------------------- @@ -1013,34 +903,77 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera) } ASSERT(data->queuedRequests_.empty()); - data->frameInfo_.clear(); + data->requestMap_.clear(); freeBuffers(camera); activeCamera_ = nullptr; } +std::unique_ptr PipelineHandlerRkISP1::createRequestDevice(Camera *camera, + uint64_t cookie) +{ + auto request = std::make_unique(camera); + return Request::create(std::move(request), cookie); +} + int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) { RkISP1CameraData *data = cameraData(camera); + RkISP1Request *rkisp1Request = cameraRequest(request); - RkISP1FrameInfo *info = data->frameInfo_.create(data, request, isRaw_); - if (!info) - return -ENOENT; + data->addRequest(rkisp1Request); + data->ipa_->queueRequest(rkisp1Request->frame, request->controls()); - data->ipa_->queueRequest(data->frame_, request->controls()); + /* + * If we're operating in RAW mode (only one RAW stream is captured) + * then we simply queue buffers to the video devices as we don't + * need to run the IPA. + */ if (isRaw_) { - if (info->mainPathBuffer) - data->mainPath_->queueBuffer(info->mainPathBuffer); + FrameBuffer *mainPathBuffer = + request->findBuffer(&data->mainPathStream_); + if (mainPathBuffer) + data->mainPath_->queueBuffer(mainPathBuffer); - if (data->selfPath_ && info->selfPathBuffer) - data->selfPath_->queueBuffer(info->selfPathBuffer); - } else { - data->ipa_->fillParamsBuffer(data->frame_, - info->paramBuffer->cookie()); + FrameBuffer *selfPathBuffer = + request->findBuffer(&data->selfPathStream_); + if (data->selfPath_ && selfPathBuffer) + data->selfPath_->queueBuffer(selfPathBuffer); + + return 0; + } + + /* + * If we run the IPA we need to associate a parameters and a statistics + * buffer with the Request and associate the request with the current + * frame number. + * + * Associate the stat and frame buffers to a Request (if available) + * and then run the IPA. + */ + if (availableParamBuffers_.empty()) { + LOG(RkISP1, Error) << "Parameters buffer underrun"; + return -ENOENT; + } + + if (availableStatBuffers_.empty()) { + LOG(RkISP1, Error) << "Statistic buffer underrun"; + return -ENOENT; } - data->frame_++; + rkisp1Request->paramBuffer = availableParamBuffers_.front(); + rkisp1Request->paramDequeued = false; + rkisp1Request->paramBuffer->_d()->setRequest(request); + availableParamBuffers_.pop(); + + rkisp1Request->statBuffer = availableStatBuffers_.front(); + rkisp1Request->metadataProcessed = false; + rkisp1Request->statBuffer->_d()->setRequest(request); + availableStatBuffers_.pop(); + + data->ipa_->fillParamsBuffer(rkisp1Request->frame, + rkisp1Request->paramBuffer->cookie()); return 0; } @@ -1232,37 +1165,28 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) * Buffer Handling */ -void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1FrameInfo *info) +void PipelineHandlerRkISP1::tryCompleteRequest(RkISP1Request *request) { RkISP1CameraData *data = cameraData(activeCamera_); - Request *request = info->request; - if (request->hasPendingBuffers()) + if (request->hasPendingBuffers(isRaw_)) return; - if (!info->metadataProcessed) - return; + /* Return the stat and param buffers to the pipeline. */ + availableParamBuffers_.push(request->paramBuffer); + availableStatBuffers_.push(request->statBuffer); + data->requestMap_.erase(request->frame); - if (!isRaw_ && !info->paramDequeued) - return; - - data->frameInfo_.destroy(info->frame); - - completeRequest(request); + completeRequest(request->_o()); } void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) { ASSERT(activeCamera_); RkISP1CameraData *data = cameraData(activeCamera_); - - RkISP1FrameInfo *info = data->frameInfo_.find(buffer); - if (!info) - return; + RkISP1Request *request = cameraRequest(buffer->request()); const FrameMetadata &metadata = buffer->metadata(); - Request *request = buffer->request(); - if (metadata.status != FrameMetadata::FrameCancelled) { /* * Record the sensor's timestamp in the request metadata. @@ -1270,55 +1194,48 @@ void PipelineHandlerRkISP1::bufferReady(FrameBuffer *buffer) * \todo The sensor timestamp should be better estimated by connecting * to the V4L2Device::frameStart signal. */ - request->metadata().set(controls::SensorTimestamp, - metadata.timestamp); + request->_o()->metadata().set(controls::SensorTimestamp, + metadata.timestamp); if (isRaw_) { const ControlList &ctrls = data->delayedCtrls_->get(metadata.sequence); - data->ipa_->processStatsBuffer(info->frame, 0, ctrls); + data->ipa_->processStatsBuffer(request->frame, 0, ctrls); } } else { if (isRaw_) - info->metadataProcessed = true; + request->metadataProcessed = true; } - completeBuffer(request, buffer); - tryCompleteRequest(info); + completeBuffer(request->_o(), buffer); + tryCompleteRequest(request); } void PipelineHandlerRkISP1::paramReady(FrameBuffer *buffer) { ASSERT(activeCamera_); - RkISP1CameraData *data = cameraData(activeCamera_); + RkISP1Request *request = cameraRequest(buffer->request()); - RkISP1FrameInfo *info = data->frameInfo_.find(buffer); - if (!info) - return; - - info->paramDequeued = true; - tryCompleteRequest(info); + request->paramDequeued = true; + tryCompleteRequest(request); } void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer) { ASSERT(activeCamera_); RkISP1CameraData *data = cameraData(activeCamera_); - - RkISP1FrameInfo *info = data->frameInfo_.find(buffer); - if (!info) - return; + RkISP1Request *request = cameraRequest(buffer->request()); if (buffer->metadata().status == FrameMetadata::FrameCancelled) { - info->metadataProcessed = true; - tryCompleteRequest(info); + request->metadataProcessed = true; + tryCompleteRequest(request); return; } if (data->frame_ <= buffer->metadata().sequence) data->frame_ = buffer->metadata().sequence + 1; - data->ipa_->processStatsBuffer(info->frame, info->statBuffer->cookie(), + data->ipa_->processStatsBuffer(request->frame, request->statBuffer->cookie(), data->delayedCtrls_->get(buffer->metadata().sequence)); }