[libcamera-devel] [PATCH v2 06/12] gstreamer: Handle completed requests in the libcamerasrc task
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Thu Jun 30 11:45:45 CEST 2022
On Thu, Jun 30, 2022 at 01:21:34PM +0530, Umang Jain wrote:
> Hi Laurent,
>
> Thank you for the patch.
>
> On 6/30/22 05:32, Laurent Pinchart via libcamera-devel wrote:
> > Move the request wrap to a completed queue in the request completion
> > handler to move more of the request completion processing to the
> > libcamerasrc task. This lowers the amount of time spent in the
> > completion handler, and prepares for reworking the usage of locks.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> > ---
> > Changes since v1:
> >
> > - Use GST_CLOCK_TIME_NONE and GST_CLOCK_TIME_IS_VALID()
> > ---
> > src/gstreamer/gstlibcamerasrc.cpp | 82 ++++++++++++++++++-------------
> > 1 file changed, 48 insertions(+), 34 deletions(-)
> >
> > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> > index f2f48d53991a..2cb915637874 100644
> > --- a/src/gstreamer/gstlibcamerasrc.cpp
> > +++ b/src/gstreamer/gstlibcamerasrc.cpp
> > @@ -57,10 +57,13 @@ struct RequestWrap {
> >
> > std::unique_ptr<Request> request_;
> > std::map<Stream *, GstBuffer *> buffers_;
> > +
> > + GstClockTime latency_;
> > + GstClockTime pts_;
> > };
> >
> > RequestWrap::RequestWrap(std::unique_ptr<Request> request)
> > - : request_(std::move(request))
> > + : request_(std::move(request)), latency_(0), pts_(GST_CLOCK_TIME_NONE)
> > {
> > }
> >
> > @@ -109,6 +112,7 @@ struct GstLibcameraSrcState {
> > std::unique_ptr<CameraConfiguration> config_;
> > std::vector<GstPad *> srcpads_;
> > std::queue<std::unique_ptr<RequestWrap>> queuedRequests_;
> > + std::queue<std::unique_ptr<RequestWrap>> completedRequests_;
> > guint group_id_;
> >
> > void requestCompleted(Request *request);
> > @@ -165,9 +169,6 @@ GstLibcameraSrcState::requestCompleted(Request *request)
> > return;
> > }
> >
> > - GstClockTime latency;
> > - GstClockTime pts;
> > -
> > if (GST_ELEMENT_CLOCK(src_)) {
> > int64_t timestamp = request->metadata().get(controls::SensorTimestamp);
> >
> > @@ -178,31 +179,11 @@ GstLibcameraSrcState::requestCompleted(Request *request)
> >
> > /* Deduced from: sys_now - sys_base_time == gst_now - gst_base_time */
> > GstClockTime sys_base_time = sys_now - (gst_now - gst_base_time);
> > - pts = timestamp - sys_base_time;
> > - latency = sys_now - timestamp;
> > - } else {
> > - latency = 0;
> > - pts = GST_CLOCK_TIME_NONE;
> > + wrap->pts_ = timestamp - sys_base_time;
> > + wrap->latency_ = sys_now - timestamp;
> > }
> >
> > - for (GstPad *srcpad : srcpads_) {
> > - Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> > - GstBuffer *buffer = wrap->detachBuffer(stream);
> > -
> > - FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer);
> > -
> > - if (GST_CLOCK_TIME_IS_VALID(pts)) {
> > - GST_BUFFER_PTS(buffer) = pts;
> > - gst_libcamera_pad_set_latency(srcpad, latency);
> > - } else {
> > - GST_BUFFER_PTS(buffer) = 0;
> > - }
> > -
> > - GST_BUFFER_OFFSET(buffer) = fb->metadata().sequence;
> > - GST_BUFFER_OFFSET_END(buffer) = fb->metadata().sequence;
> > -
> > - gst_libcamera_pad_queue_buffer(srcpad, buffer);
> > - }
> > + completedRequests_.push(std::move(wrap));
> >
> > gst_task_resume(src_->task);
> > }
> > @@ -316,6 +297,39 @@ gst_libcamera_src_task_run(gpointer user_data)
> > /* The RequestWrap will be deleted in the completion handler. */
> > }
> >
> > + {
> > + GLibLocker lock(GST_OBJECT(self));
> > +
> > + if (!state->completedRequests_.empty()) {
> > + wrap = std::move(state->completedRequests_.front());
> > + state->completedRequests_.pop();
> > + }
> > + }
> > +
> > + if (!wrap) {
> > + gst_task_pause(self->task);
> > + return;
> > + }
> > +
> > + for (GstPad *srcpad : state->srcpads_) {
> > + Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> > + GstBuffer *buffer = wrap->detachBuffer(stream);
> > +
> > + FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer);
> > +
> > + if (GST_CLOCK_TIME_IS_VALID(wrap->pts_)) {
> > + GST_BUFFER_PTS(buffer) = wrap->pts_;
> > + gst_libcamera_pad_set_latency(srcpad, wrap->latency_);
> > + } else {
> > + GST_BUFFER_PTS(buffer) = 0;
> > + }
> > +
> > + GST_BUFFER_OFFSET(buffer) = fb->metadata().sequence;
> > + GST_BUFFER_OFFSET_END(buffer) = fb->metadata().sequence;
> > +
> > + gst_libcamera_pad_queue_buffer(srcpad, buffer);
> > + }
> > +
> > GstFlowReturn ret = GST_FLOW_OK;
> > gst_flow_combiner_reset(self->flow_combiner);
> > for (GstPad *srcpad : state->srcpads_) {
> > @@ -344,13 +358,11 @@ gst_libcamera_src_task_run(gpointer user_data)
> > * happen in lock step with the callback thread which may want
> > * to resume the task and might push pending buffers.
> > */
> > - GLibLocker lock(GST_OBJECT(self));
> > - bool do_pause = true;
> > - for (GstPad *srcpad : state->srcpads_) {
> > - if (gst_libcamera_pad_has_pending(srcpad)) {
> > - do_pause = false;
> > - break;
> > - }
> > + bool do_pause;
> > +
> > + {
> > + GLibLocker lock(GST_OBJECT(self));
> > + do_pause = state->completedRequests_.empty();
> > }
> >
> > if (do_pause)
> > @@ -504,6 +516,8 @@ gst_libcamera_src_task_leave([[maybe_unused]] GstTask *task,
> >
> > state->cam_->stop();
> >
> > + state->completedRequests_ = {};
> > +
>
>
> Ah so when we stop we might have some RequestWrap(s) being added to
> completedRequests_ but won't be processed by the libcamera_src_task_run
> - since we have are already in libcamera_src_task_leave.
>
> I wonder if need to do any 'processing' for them before clearing them
> out here. Maybe not, those are just "cancelled" ones right?
Mostly, there could also occasionally be some completed requests.
> So, the 'processing' part for completedRequests_ is just, detaching the
> buffer, setting up latency and presentation time(pts I believe) and
> re-queuing the buffer the pad. So that's minimal, so I guess it's safe
> to clear them out.
Given that the task is stopped due to the element being stopped, I don't
see how we could meaningful process the completed requests anyway.
> Reviewed-by: Umang Jain <umang.jain at ideasonboard.com>
>
> > for (GstPad *srcpad : state->srcpads_)
> > gst_libcamera_pad_set_pool(srcpad, nullptr);
> >
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list