[libcamera-devel] [PATCH v1 3/4] ipa: ipu3: Prevent over queuing of requests
Umang Jain
umang.jain at ideasonboard.com
Fri Jun 10 10:32:03 CEST 2022
Hi Jacopo,
On 6/10/22 09:49, Jacopo Mondi wrote:
> Hi Umang,
>
> On Fri, Jun 03, 2022 at 03:22:58PM +0200, Umang Jain via libcamera-devel wrote:
>> The IPAIPU3 processes each IPAFrameContext present in the FCQueue
>> ring buffer. If the application queues the requests at a pace where
>> IPAFrameContext(s) can get potentially over-written without getting
>> processed by the IPA, it would lead to un-desirable effects.
>>
>> Hence, inspect the FCQueue if it is full and reject any further
>> queuing of requests. This requires changes to the IPAIPU3 mojom
>> interface. The IPAIPU3::queueRequest() cannot be [async] anymore
>> since we need to return a success/failure value.
>>
>> The rejection by the IPA doesn't mean it cannot be queued
>> later. The request is still preserved in
>> IPU3CameraData::pendingRequests_. It shall be queued sequentially
>> on subsequent calls to IPU3CameraData::queuePendingRequests().
>>
>> Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
>> ---
>> I am not super-happy with changing the interface and dropping [async]
>> but this is what I've for now. Would appreciate any other ideas...
> I feel like this change handles the issue at the very bottom of the
> call stack, once a request has been queued from the ph to the IPA.
>
> I wonder if we shouldn't try to tackle the problem from the top
> instead, which means at the time a request is queued to the camera by
> the application.
>
> The lenght of the FCQueue represents the maximum number of requests
> in-flight at a time, iow the number of requests queued to the camera
> and not yet completed.
>
> Would it make sense to make this a global camera property and have the
> base pipeline handler class defer queueing requests when too many are
> in-flight ?
In the last call, I brought up this issue. However, it was geared
towards a solution to avoid dropping [async] from the mojom interface.
The design I have in mind and shared in the call as well is basically
that, the PH should be responsible to queue up requests to the IPA - in
a way that it doesn't do over-queuing.
The way it should be done is - communicating the size of the FCQueue to
the PH during init/configure phase (or make a global in mojom interface
where it's shared to both parts - not sure yet, I haven't decided). The
PH will queue requests to the IPA, increment a counter. We already have
a callback from IPA to PH when a frame processing completes - so
decrement the counter. The max the counter can reach is FCQueue.size() -
beyond that it should just stop queuing and let the request sit in
PipelineHandler::pendingRequests_ queue. The queuePendingRequests() is a
recurring call on every request queue by the application - so as long as
the counter < FCQueue.size() - it will keep queuing and stop when it's >
FCQueue.size(). As frames get completed, counter will decrement and
queuing shall start again.
> Thanks
> j
>
>> ---
>> include/libcamera/ipa/ipu3.mojom | 2 +-
>> src/ipa/ipu3/ipu3.cpp | 11 +++++++++--
>> src/libcamera/pipeline/ipu3/ipu3.cpp | 10 +++++++++-
>> 3 files changed, 19 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/libcamera/ipa/ipu3.mojom b/include/libcamera/ipa/ipu3.mojom
>> index d1b1c6b8..3faffd9c 100644
>> --- a/include/libcamera/ipa/ipu3.mojom
>> +++ b/include/libcamera/ipa/ipu3.mojom
>> @@ -30,7 +30,7 @@ interface IPAIPU3Interface {
>> mapBuffers(array<libcamera.IPABuffer> buffers);
>> unmapBuffers(array<uint32> ids);
>>
>> - [async] queueRequest(uint32 frame, libcamera.ControlList controls);
>> + queueRequest(uint32 frame, libcamera.ControlList controls) => (int32 ret);
>> [async] fillParamsBuffer(uint32 frame, uint32 bufferId);
>> [async] processStatsBuffer(uint32 frame, int64 frameTimestamp,
>> uint32 bufferId, libcamera.ControlList sensorControls);
>> diff --git a/src/ipa/ipu3/ipu3.cpp b/src/ipa/ipu3/ipu3.cpp
>> index 1d6ee515..63aa9b56 100644
>> --- a/src/ipa/ipu3/ipu3.cpp
>> +++ b/src/ipa/ipu3/ipu3.cpp
>> @@ -145,7 +145,7 @@ public:
>> void mapBuffers(const std::vector<IPABuffer> &buffers) override;
>> void unmapBuffers(const std::vector<unsigned int> &ids) override;
>>
>> - void queueRequest(const uint32_t frame, const ControlList &controls) override;
>> + int queueRequest(const uint32_t frame, const ControlList &controls) override;
>> void fillParamsBuffer(const uint32_t frame, const uint32_t bufferId) override;
>> void processStatsBuffer(const uint32_t frame, const int64_t frameTimestamp,
>> const uint32_t bufferId,
>> @@ -616,11 +616,18 @@ void IPAIPU3::processStatsBuffer(const uint32_t frame,
>> *
>> * Parse the request to handle any IPA-managed controls that were set from the
>> * application such as manual sensor settings.
>> + *
>> + * \return 0 if successful, -EPERM otherwise.
>> */
>> -void IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls)
>> +int IPAIPU3::queueRequest(const uint32_t frame, const ControlList &controls)
>> {
>> + if (context_.frameContexts.isFull())
>> + return -EPERM;
>> +
>> /* \todo Start processing for 'frame' based on 'controls'. */
>> *context_.frameContexts.get(frame) = { frame, controls };
>> +
>> + return 0;
>> }
>>
>> /**
>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> index fd989e61..d69e28d4 100644
>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> @@ -874,7 +874,15 @@ void IPU3CameraData::queuePendingRequests()
>>
>> info->rawBuffer = rawBuffer;
>>
>> - ipa_->queueRequest(info->id, request->controls());
>> + /*
>> + * Queueing request to the IPA can fail in cases like over-flowing
>> + * its queue. Hence, keep the request preserved in pendingRequests_
>> + * if a failure occurs.
>> + */
>> + if (ipa_->queueRequest(info->id, request->controls()) != 0) {
>> + frameInfos_.remove(info);
>> + break;
>> + }
>>
>> pendingRequests_.pop();
>> processingRequests_.push(request);
>> --
>> 2.31.1
>>
More information about the libcamera-devel
mailing list