[libcamera-devel] [PATCH 2/2] libcamera: pipeline-handler: Consider max in-flight requests constraint
Umang Jain
umang.jain at ideasonboard.com
Wed Dec 14 06:37:25 CET 2022
Hi Jacopo,
On 12/13/22 9:25 PM, Jacopo Mondi wrote:
> Hi Umang,
>
> On Mon, Dec 12, 2022 at 08:32:56PM +0530, Umang Jain via libcamera-devel wrote:
>> This patch introduces a new constraint in the pipeline handler base
>> class which allows various derived pipeline handlers to set and
>> restrict the number of maximum in-flight requests that can be queued to
>> the underlying components (for e.g. the IPA).
> It's my understanding that the max number of in-flight requests is
> what the properties::PipelineDepth property expresses.
Indeed, that's why understanding as well. The properties::PipelineDepth
should be set by the pipeline-handlers.
We need to identify and atleast agree upon the correct PipelineDepth for
the two platforms that uses the FCQueue (IPU3 and RkISP1) as well. Some
grey areas there as well
>
> Can't we access that property at queue request time, or maybe better we
> could cache it at camera registration time, since it's constant ?
If we intent to use the properties::PipelineDepth, as the size of the
FCQueue - it needs to exist / set before IPA is constructed.
(See IPAIPU3::IPAIPU3() for context)
So I think queue request time is quite late there. Camera registeration
time might be possible with some changes (looking at
PipelineHandlerIPU3::registerCameras())
>
> Also, can this feature be tested in test/ ? Probably not, as it
> requires a compliant pipeline handler ? Maybe vimc can be instrumented
I have been thinking about that as well. It's shouldn't be too difficult.
> ?
>
>> The pipeline handler is now equipped with the responsibility of not to
>> over queue the requests to the underlying layers. The derived
>> pipeline handler (or even IPA) can also have various kind of requests
>> queue(arrays, queues or ring-buffer) hence, it might be an issue where
>> the application queues the requests at a rate where these kind of
>> queues can over-flow. The patch ensures that the base PipelineHandler
>> will never let the requests overflow to underlying layers, once the
>> derived pipeline handler sets its maximum capacity of handling
>> in-flight requests using PipelineHandler::setMaxQueueRequests().
>>
>> The queue request management introduced in the pipeline handler base
>> class is now used by the IPU3 and RkISP1 pipeline handlers. This will
>> prevent over-writing of frame contexts (i.e. FCQueue) in these two
>> pipeline handlers.
>>
>> Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
>> ---
>> include/libcamera/internal/pipeline_handler.h | 4 ++
>> src/libcamera/pipeline/ipu3/ipu3.cpp | 1 +
>> src/libcamera/pipeline/rkisp1/rkisp1.cpp | 1 +
>> src/libcamera/pipeline_handler.cpp | 51 ++++++++++++++++++-
>> 4 files changed, 56 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/libcamera/internal/pipeline_handler.h b/include/libcamera/internal/pipeline_handler.h
>> index ec4f662d..83f8bd9f 100644
>> --- a/include/libcamera/internal/pipeline_handler.h
>> +++ b/include/libcamera/internal/pipeline_handler.h
>> @@ -70,6 +70,7 @@ public:
>> protected:
>> void registerCamera(std::shared_ptr<Camera> camera);
>> void hotplugMediaDevice(MediaDevice *media);
>> + void setMaxQueueRequests(uint32_t maxRequests);
>>
>> virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
>> virtual void stopDevice(Camera *camera) = 0;
>> @@ -97,6 +98,9 @@ private:
>> Mutex lock_;
>> unsigned int useCount_ LIBCAMERA_TSA_GUARDED_BY(lock_);
>>
>> + uint32_t maxQueueRequests_;
>> + uint32_t requestsQueueCounter_;
>> +
>> friend class PipelineHandlerFactoryBase;
>> };
>>
>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> index e4d79ea4..d1d42f78 100644
>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> @@ -422,6 +422,7 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate()
>> PipelineHandlerIPU3::PipelineHandlerIPU3(CameraManager *manager)
>> : PipelineHandler(manager), cio2MediaDev_(nullptr), imguMediaDev_(nullptr)
>> {
>> + setMaxQueueRequests(ipa::ipu3::kMaxFrameContexts);
>> }
>>
>> std::unique_ptr<CameraConfiguration>
>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> index eb9ad65c..a48adba9 100644
>> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> @@ -599,6 +599,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
>> PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager)
>> : PipelineHandler(manager), hasSelfPath_(true)
>> {
>> + setMaxQueueRequests(ipa::rkisp1::kMaxFrameContexts);
>> }
>>
>> std::unique_ptr<CameraConfiguration>
>> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
>> index cfade490..103f9db0 100644
>> --- a/src/libcamera/pipeline_handler.cpp
>> +++ b/src/libcamera/pipeline_handler.cpp
>> @@ -67,7 +67,8 @@ LOG_DEFINE_CATEGORY(Pipeline)
>> * through the PipelineHandlerFactoryBase::create() function.
>> */
>> PipelineHandler::PipelineHandler(CameraManager *manager)
>> - : manager_(manager), useCount_(0)
>> + : manager_(manager), useCount_(0), maxQueueRequests_(0),
>> + requestsQueueCounter_(0)
>> {
>> }
>>
>> @@ -428,6 +429,9 @@ void PipelineHandler::doQueueRequest(Request *request)
>> Camera::Private *data = camera->_d();
>> data->queuedRequests_.push_back(request);
>>
>> + if (maxQueueRequests_)
>> + requestsQueueCounter_++;
>> +
>> request->_d()->sequence_ = data->requestSequence_++;
>>
>> if (request->_d()->cancelled_) {
>> @@ -455,6 +459,10 @@ void PipelineHandler::doQueueRequests()
>> if (!request->_d()->prepared_)
>> break;
>>
>> + if (maxQueueRequests_ &&
>> + requestsQueueCounter_ >= maxQueueRequests_)
>> + break;
>> +
>> doQueueRequest(request);
>> waitingRequests_.pop();
>> }
>> @@ -531,6 +539,9 @@ void PipelineHandler::completeRequest(Request *request)
>> ASSERT(!req->hasPendingBuffers());
>> data->queuedRequests_.pop_front();
>> camera->requestComplete(req);
>> +
>> + if (maxQueueRequests_)
>> + requestsQueueCounter_--;
>> }
>> }
>>
>> @@ -647,6 +658,44 @@ void PipelineHandler::disconnect()
>> * constant for the whole lifetime of the pipeline handler.
>> */
>>
>> +/**
>> + * \var PipelineHandler::maxQueueRequests_
>> + * \brief Maximum number of in-flight requests that can be queued
>> + *
>> + * A hardware can handle a certain number of maximum requests at a given
>> + * point. If such a constraint exists, set maxQueueRequests_ via
>> + * \a setMaxQueueRequests() in the derived pipeline handler.
>> + *
>> + * The derived pipeline handler can choose not to define such constraint as
>> + * well. In that case, the derived pipeline handler can avoid setting
>> + * \a setMaxQueueReqeuests(), hence \a maxQueueRequests_ and
>> + * \a requestsQueueCounter_ will be 0.
>> + */
>> +
>> +/**
>> + * \var PipelineHandler::requestsQueueCounter_
>> + * \brief Number of requests queued to the underlying hardware
>> + *
>> + * If \a setMaxQueueRequests() is set by the derived pipeline handler,
>> + * requestsQueueCounter_ reflects the number of requests queued
>> + * to the underlying hardware by the pipeline handler.
>> + */
>> +
>> +/**
>> + * \brief Sets the maximum number of requests that can be queued
>> + * \param[in] maxRequests Maximum number of in-flight requests
>> + *
>> + * A hardware can handle a certain number of requests at a given point.
>> + * This function sets the maximum number of in-flight requests that can
>> + * be queued to the hardware by the pipeline handler. Each derived pipeline
>> + * handler should set the maximum number of in-flight requests it can handle
>> + * at a given point using this function, if at all such a constraint exists.
>> + */
>> +void PipelineHandler::setMaxQueueRequests(uint32_t maxRequests)
>> +{
>> + maxQueueRequests_ = maxRequests;
>> +}
>> +
>> /**
>> * \fn PipelineHandler::name()
>> * \brief Retrieve the pipeline handler name
>> --
>> 2.38.1
>>
More information about the libcamera-devel
mailing list