[libcamera-devel] [PATCH v4 7/8] libcamera: pipeline: rkisp1: Use SOF event to warn about late parameters
Jacopo Mondi
jacopo at jmondi.org
Thu Dec 17 15:18:38 CET 2020
Hi Niklas,
On Tue, Dec 15, 2020 at 01:48:10AM +0100, Niklas Söderlund wrote:
> In the Timeline approach the idea was to delay queuing buffers to the
> device until the IPA had a chance to prepare the parameters buffer. A
> check was still added to warn if the IPA queued buffers before the
> parameters buffer was filled in.
>
> This check happened much sooner then needed as the parameter buffers
> does not have to be ready when the buffer is queued but just before it's
> consumed. As the pipeline now has true knowledge of each SOF we can move
> the check there and remove the delaying of queuing of buffers.
>
> This change really speeds up the IPA reactions as the delays used in the
> Timeline where approximated while with this change they are driven by
> events reported by the device.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
Thanks
j
> ---
> src/libcamera/pipeline/rkisp1/rkisp1.cpp | 78 ++++++++----------------
> 1 file changed, 24 insertions(+), 54 deletions(-)
>
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index 513a60b04e5f2e21..3851d94e7b133356 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -41,7 +41,6 @@ namespace libcamera {
> LOG_DEFINE_CATEGORY(RkISP1)
>
> class PipelineHandlerRkISP1;
> -class RkISP1ActionQueueBuffers;
> class RkISP1CameraData;
>
> enum RkISP1ActionType {
> @@ -202,7 +201,6 @@ private:
> PipelineHandler::cameraData(camera));
> }
>
> - friend RkISP1ActionQueueBuffers;
> friend RkISP1CameraData;
> friend RkISP1Frames;
>
> @@ -213,6 +211,7 @@ private:
> void bufferReady(FrameBuffer *buffer);
> void paramReady(FrameBuffer *buffer);
> void statReady(FrameBuffer *buffer);
> + void frameStart(uint32_t sequence);
>
> int allocateBuffers(Camera *camera);
> int freeBuffers(Camera *camera);
> @@ -347,53 +346,6 @@ RkISP1FrameInfo *RkISP1Frames::find(Request *request)
> return nullptr;
> }
>
> -class RkISP1ActionQueueBuffers : public FrameAction
> -{
> -public:
> - RkISP1ActionQueueBuffers(unsigned int frame, RkISP1CameraData *data,
> - PipelineHandlerRkISP1 *pipe)
> - : FrameAction(frame, QueueBuffers), data_(data), pipe_(pipe)
> - {
> - }
> -
> -protected:
> - void run() override
> - {
> - RkISP1FrameInfo *info = data_->frameInfo_.find(frame());
> - if (!info)
> - LOG(RkISP1, Fatal) << "Frame not known";
> -
> - /*
> - * \todo: If parameters are not filled a better method to handle
> - * the situation than queuing a buffer with unknown content
> - * should be used.
> - *
> - * It seems excessive to keep an internal zeroed scratch
> - * parameters buffer around as this should not happen unless the
> - * devices is under too much load. Perhaps failing the request
> - * and returning it to the application with an error code is
> - * better than queue it to hardware?
> - */
> - if (!info->paramFilled)
> - LOG(RkISP1, Error)
> - << "Parameters not ready on time for frame "
> - << frame();
> -
> - pipe_->param_->queueBuffer(info->paramBuffer);
> - pipe_->stat_->queueBuffer(info->statBuffer);
> -
> - if (info->mainPathBuffer)
> - pipe_->mainPath_.queueBuffer(info->mainPathBuffer);
> -
> - if (info->selfPathBuffer)
> - pipe_->selfPath_.queueBuffer(info->selfPathBuffer);
> - }
> -
> -private:
> - RkISP1CameraData *data_;
> - PipelineHandlerRkISP1 *pipe_;
> -};
> -
> int RkISP1CameraData::loadIPA()
> {
> ipa_ = IPAManager::createIPA(pipe_, 1, 1);
> @@ -950,9 +902,14 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request)
> op.controls = { request->controls() };
> data->ipa_->processEvent(op);
>
> - data->timeline_.scheduleAction(std::make_unique<RkISP1ActionQueueBuffers>(data->frame_,
> - data,
> - this));
> + param_->queueBuffer(info->paramBuffer);
> + stat_->queueBuffer(info->statBuffer);
> +
> + if (info->mainPathBuffer)
> + mainPath_.queueBuffer(info->mainPathBuffer);
> +
> + if (info->selfPathBuffer)
> + selfPath_.queueBuffer(info->selfPathBuffer);
>
> data->frame_++;
>
> @@ -1102,6 +1059,7 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
> mainPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady);
> selfPath_.bufferReady().connect(this, &PipelineHandlerRkISP1::bufferReady);
> stat_->bufferReady.connect(this, &PipelineHandlerRkISP1::statReady);
> + isp_->frameStart.connect(this, &PipelineHandlerRkISP1::frameStart);
> param_->bufferReady.connect(this, &PipelineHandlerRkISP1::paramReady);
>
> /*
> @@ -1181,8 +1139,6 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer)
> if (!info)
> return;
>
> - data->timeline_.bufferReady(buffer);
> -
> if (data->frame_ <= buffer->metadata().sequence)
> data->frame_ = buffer->metadata().sequence + 1;
>
> @@ -1192,6 +1148,20 @@ void PipelineHandlerRkISP1::statReady(FrameBuffer *buffer)
> data->ipa_->processEvent(op);
> }
>
> +void PipelineHandlerRkISP1::frameStart(uint32_t sequence)
> +{
> + if (!activeCamera_)
> + return;
> +
> + RkISP1CameraData *data = cameraData(activeCamera_);
> +
> + RkISP1FrameInfo *info = data->frameInfo_.find(sequence);
> + if (!info || !info->paramFilled)
> + LOG(RkISP1, Info)
> + << "Parameters not ready on time for frame "
> + << sequence;
> +}
> +
> REGISTER_PIPELINE_HANDLER(PipelineHandlerRkISP1)
>
> } /* namespace libcamera */
> --
> 2.29.2
>
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel at lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel
More information about the libcamera-devel
mailing list