[RFC,v1,06/27] libcamera: pipeline: Replace open-coded buffer cancellation
diff mbox series

Message ID 20260618123844.656396-7-barnabas.pocze@ideasonboard.com
State Superseded
Headers show
Series
  • Misc. changes before request-buffer split
Related show

Commit Message

Barnabás Pőcze June 18, 2026, 12:38 p.m. UTC
Use `PipelineHander::cancelRequest()` instead of manually cancelling, completing
each buffer, then completing the request. This has the same behaviour unless
the request has no pending buffers.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 src/libcamera/pipeline/ipu3/ipu3.cpp             | 14 ++------------
 .../pipeline/rpi/common/pipeline_base.cpp        | 16 +---------------
 src/libcamera/pipeline/vimc/vimc.cpp             |  7 +------
 3 files changed, 4 insertions(+), 33 deletions(-)

Comments

Jacopo Mondi June 22, 2026, 12:44 p.m. UTC | #1
Hi Barnabás

On Thu, Jun 18, 2026 at 02:38:23PM +0200, Barnabás Pőcze wrote:
> Use `PipelineHander::cancelRequest()` instead of manually cancelling, completing
> each buffer, then completing the request. This has the same behaviour unless
> the request has no pending buffers.
>
> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> ---
>  src/libcamera/pipeline/ipu3/ipu3.cpp             | 14 ++------------
>  .../pipeline/rpi/common/pipeline_base.cpp        | 16 +---------------
>  src/libcamera/pipeline/vimc/vimc.cpp             |  7 +------
>  3 files changed, 4 insertions(+), 33 deletions(-)
>
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index bf4c2921f2..560fccd8c0 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -790,12 +790,7 @@ void IPU3CameraData::cancelPendingRequests()
>  	while (!pendingRequests_.empty()) {
>  		Request *request = pendingRequests_.front();
>
> -		for (const auto &[stream, buffer] : request->buffers()) {
> -			buffer->_d()->cancel();
> -			pipe()->completeBuffer(request, buffer);
> -		}
> -
> -		pipe()->completeRequest(request);
> +		pipe()->cancelRequest(request);
>  		pendingRequests_.pop();
>  	}
>  }
> @@ -1299,13 +1294,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
>
>  	/* If the buffer is cancelled force a complete of the whole request. */
>  	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
> -		for (const auto &[stream, b] : request->buffers()) {
> -			b->_d()->cancel();
> -			pipe()->completeBuffer(request, b);
> -		}
> -
>  		frameInfos_.remove(info);
> -		pipe()->completeRequest(request);
> +		pipe()->cancelRequest(request);
>  		return;
>  	}
>
> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> index 5a5acf6a16..6a6be5c820 100644
> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> @@ -1401,21 +1401,7 @@ void CameraData::clearIncompleteRequests()
>  	 * back to the application.
>  	 */
>  	while (!requestQueue_.empty()) {
> -		Request *request = requestQueue_.front();
> -
> -		for (auto &b : request->buffers()) {
> -			FrameBuffer *buffer = b.second;
> -			/*
> -			 * Has the buffer already been handed back to the
> -			 * request? If not, do so now.
> -			 */
> -			if (buffer->request()) {

I have an hard time understanding what this check protects against in
this pipeline handler. As far as I understand a similar check is not
there in pipe()->cancelRequest()

> -				buffer->_d()->cancel();
> -				pipe()->completeBuffer(request, buffer);
> -			}
> -		}
> -
> -		pipe()->completeRequest(request);
> +		pipe()->cancelRequest(requestQueue_.front());
>  		requestQueue_.pop();
>  	}
>  }
> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> index 6681c74ee5..3d010d80e5 100644
> --- a/src/libcamera/pipeline/vimc/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> @@ -605,12 +605,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
>
>  	/* If the buffer is cancelled force a complete of the whole request. */
>  	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
> -		for (const auto &[stream, b] : request->buffers()) {
> -			b->_d()->cancel();
> -			pipe->completeBuffer(request, b);
> -		}
> -
> -		pipe->completeRequest(request);
> +		pipe->cancelRequest(request);
>  		return;
>  	}
>
> --
> 2.54.0
>
Barnabás Pőcze June 22, 2026, 12:50 p.m. UTC | #2
2026. 06. 22. 14:44 keltezéssel, Jacopo Mondi írta:
> Hi Barnabás
> 
> On Thu, Jun 18, 2026 at 02:38:23PM +0200, Barnabás Pőcze wrote:
>> Use `PipelineHander::cancelRequest()` instead of manually cancelling, completing
>> each buffer, then completing the request. This has the same behaviour unless
>> the request has no pending buffers.
>>
>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>> ---
>>   src/libcamera/pipeline/ipu3/ipu3.cpp             | 14 ++------------
>>   .../pipeline/rpi/common/pipeline_base.cpp        | 16 +---------------
>>   src/libcamera/pipeline/vimc/vimc.cpp             |  7 +------
>>   3 files changed, 4 insertions(+), 33 deletions(-)
>>
>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> index bf4c2921f2..560fccd8c0 100644
>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> @@ -790,12 +790,7 @@ void IPU3CameraData::cancelPendingRequests()
>>   	while (!pendingRequests_.empty()) {
>>   		Request *request = pendingRequests_.front();
>>
>> -		for (const auto &[stream, buffer] : request->buffers()) {
>> -			buffer->_d()->cancel();
>> -			pipe()->completeBuffer(request, buffer);
>> -		}
>> -
>> -		pipe()->completeRequest(request);
>> +		pipe()->cancelRequest(request);
>>   		pendingRequests_.pop();
>>   	}
>>   }
>> @@ -1299,13 +1294,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
>>
>>   	/* If the buffer is cancelled force a complete of the whole request. */
>>   	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
>> -		for (const auto &[stream, b] : request->buffers()) {
>> -			b->_d()->cancel();
>> -			pipe()->completeBuffer(request, b);
>> -		}
>> -
>>   		frameInfos_.remove(info);
>> -		pipe()->completeRequest(request);
>> +		pipe()->cancelRequest(request);
>>   		return;
>>   	}
>>
>> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>> index 5a5acf6a16..6a6be5c820 100644
>> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>> @@ -1401,21 +1401,7 @@ void CameraData::clearIncompleteRequests()
>>   	 * back to the application.
>>   	 */
>>   	while (!requestQueue_.empty()) {
>> -		Request *request = requestQueue_.front();
>> -
>> -		for (auto &b : request->buffers()) {
>> -			FrameBuffer *buffer = b.second;
>> -			/*
>> -			 * Has the buffer already been handed back to the
>> -			 * request? If not, do so now.
>> -			 */
>> -			if (buffer->request()) {
> 
> I have an hard time understanding what this check protects against in
> this pipeline handler. As far as I understand a similar check is not
> there in pipe()->cancelRequest()

`completeBuffer()` sets the `Request` pointer of `FrameBuffer` to `nullptr`,
so this checks if this buffer of the request has already been completed,
and it will only cancel the not-yet-completed buffers. That is my understanding.
Completion removes the buffer from the `pendingBuffers_` set, and `cancelBuffer()`
will look through those buffers, so it will only consider not-yet-completed buffers,
just like this loop here. So the two are largely equivalent (except when the request
has no pending buffers).


> 
>> -				buffer->_d()->cancel();
>> -				pipe()->completeBuffer(request, buffer);
>> -			}
>> -		}
>> -
>> -		pipe()->completeRequest(request);
>> +		pipe()->cancelRequest(requestQueue_.front());
>>   		requestQueue_.pop();
>>   	}
>>   }
>> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
>> index 6681c74ee5..3d010d80e5 100644
>> --- a/src/libcamera/pipeline/vimc/vimc.cpp
>> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
>> @@ -605,12 +605,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
>>
>>   	/* If the buffer is cancelled force a complete of the whole request. */
>>   	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
>> -		for (const auto &[stream, b] : request->buffers()) {
>> -			b->_d()->cancel();
>> -			pipe->completeBuffer(request, b);
>> -		}
>> -
>> -		pipe->completeRequest(request);
>> +		pipe->cancelRequest(request);
>>   		return;
>>   	}
>>
>> --
>> 2.54.0
>>
Jacopo Mondi June 22, 2026, 2:25 p.m. UTC | #3
On Mon, Jun 22, 2026 at 02:50:16PM +0200, Barnabás Pőcze wrote:
> 2026. 06. 22. 14:44 keltezéssel, Jacopo Mondi írta:
> > Hi Barnabás
> >
> > On Thu, Jun 18, 2026 at 02:38:23PM +0200, Barnabás Pőcze wrote:
> > > Use `PipelineHander::cancelRequest()` instead of manually cancelling, completing
> > > each buffer, then completing the request. This has the same behaviour unless
> > > the request has no pending buffers.
> > >
> > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> > > ---
> > >   src/libcamera/pipeline/ipu3/ipu3.cpp             | 14 ++------------
> > >   .../pipeline/rpi/common/pipeline_base.cpp        | 16 +---------------
> > >   src/libcamera/pipeline/vimc/vimc.cpp             |  7 +------
> > >   3 files changed, 4 insertions(+), 33 deletions(-)
> > >
> > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > > index bf4c2921f2..560fccd8c0 100644
> > > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> > > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> > > @@ -790,12 +790,7 @@ void IPU3CameraData::cancelPendingRequests()
> > >   	while (!pendingRequests_.empty()) {
> > >   		Request *request = pendingRequests_.front();
> > >
> > > -		for (const auto &[stream, buffer] : request->buffers()) {
> > > -			buffer->_d()->cancel();
> > > -			pipe()->completeBuffer(request, buffer);
> > > -		}
> > > -
> > > -		pipe()->completeRequest(request);
> > > +		pipe()->cancelRequest(request);
> > >   		pendingRequests_.pop();
> > >   	}
> > >   }
> > > @@ -1299,13 +1294,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
> > >
> > >   	/* If the buffer is cancelled force a complete of the whole request. */
> > >   	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
> > > -		for (const auto &[stream, b] : request->buffers()) {
> > > -			b->_d()->cancel();
> > > -			pipe()->completeBuffer(request, b);
> > > -		}
> > > -
> > >   		frameInfos_.remove(info);
> > > -		pipe()->completeRequest(request);
> > > +		pipe()->cancelRequest(request);
> > >   		return;
> > >   	}
> > >
> > > diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > > index 5a5acf6a16..6a6be5c820 100644
> > > --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > > +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> > > @@ -1401,21 +1401,7 @@ void CameraData::clearIncompleteRequests()
> > >   	 * back to the application.
> > >   	 */
> > >   	while (!requestQueue_.empty()) {
> > > -		Request *request = requestQueue_.front();
> > > -
> > > -		for (auto &b : request->buffers()) {
> > > -			FrameBuffer *buffer = b.second;
> > > -			/*
> > > -			 * Has the buffer already been handed back to the
> > > -			 * request? If not, do so now.
> > > -			 */
> > > -			if (buffer->request()) {
> >
> > I have an hard time understanding what this check protects against in
> > this pipeline handler. As far as I understand a similar check is not
> > there in pipe()->cancelRequest()
>
> `completeBuffer()` sets the `Request` pointer of `FrameBuffer` to `nullptr`,
> so this checks if this buffer of the request has already been completed,
> and it will only cancel the not-yet-completed buffers. That is my understanding.
> Completion removes the buffer from the `pendingBuffers_` set, and `cancelBuffer()`
> will look through those buffers, so it will only consider not-yet-completed buffers,
> just like this loop here. So the two are largely equivalent (except when the request

Thanks for the explanation

> has no pending buffers).

And what changes in this case ?

>
>
> >
> > > -				buffer->_d()->cancel();
> > > -				pipe()->completeBuffer(request, buffer);
> > > -			}
> > > -		}
> > > -
> > > -		pipe()->completeRequest(request);
> > > +		pipe()->cancelRequest(requestQueue_.front());
> > >   		requestQueue_.pop();
> > >   	}
> > >   }
> > > diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> > > index 6681c74ee5..3d010d80e5 100644
> > > --- a/src/libcamera/pipeline/vimc/vimc.cpp
> > > +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> > > @@ -605,12 +605,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
> > >
> > >   	/* If the buffer is cancelled force a complete of the whole request. */
> > >   	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
> > > -		for (const auto &[stream, b] : request->buffers()) {
> > > -			b->_d()->cancel();
> > > -			pipe->completeBuffer(request, b);
> > > -		}
> > > -
> > > -		pipe->completeRequest(request);
> > > +		pipe->cancelRequest(request);
> > >   		return;
> > >   	}
> > >
> > > --
> > > 2.54.0
> > >
>
Barnabás Pőcze June 22, 2026, 4:22 p.m. UTC | #4
2026. 06. 22. 16:25 keltezéssel, Jacopo Mondi írta:
> On Mon, Jun 22, 2026 at 02:50:16PM +0200, Barnabás Pőcze wrote:
>> 2026. 06. 22. 14:44 keltezéssel, Jacopo Mondi írta:
>>> Hi Barnabás
>>>
>>> On Thu, Jun 18, 2026 at 02:38:23PM +0200, Barnabás Pőcze wrote:
>>>> Use `PipelineHander::cancelRequest()` instead of manually cancelling, completing
>>>> each buffer, then completing the request. This has the same behaviour unless
>>>> the request has no pending buffers.
>>>>
>>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>>>> ---
>>>>    src/libcamera/pipeline/ipu3/ipu3.cpp             | 14 ++------------
>>>>    .../pipeline/rpi/common/pipeline_base.cpp        | 16 +---------------
>>>>    src/libcamera/pipeline/vimc/vimc.cpp             |  7 +------
>>>>    3 files changed, 4 insertions(+), 33 deletions(-)
>>>>
>>>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
>>>> index bf4c2921f2..560fccd8c0 100644
>>>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
>>>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
>>>> @@ -790,12 +790,7 @@ void IPU3CameraData::cancelPendingRequests()
>>>>    	while (!pendingRequests_.empty()) {
>>>>    		Request *request = pendingRequests_.front();
>>>>
>>>> -		for (const auto &[stream, buffer] : request->buffers()) {
>>>> -			buffer->_d()->cancel();
>>>> -			pipe()->completeBuffer(request, buffer);
>>>> -		}
>>>> -
>>>> -		pipe()->completeRequest(request);
>>>> +		pipe()->cancelRequest(request);
>>>>    		pendingRequests_.pop();
>>>>    	}
>>>>    }
>>>> @@ -1299,13 +1294,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
>>>>
>>>>    	/* If the buffer is cancelled force a complete of the whole request. */
>>>>    	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
>>>> -		for (const auto &[stream, b] : request->buffers()) {
>>>> -			b->_d()->cancel();
>>>> -			pipe()->completeBuffer(request, b);
>>>> -		}
>>>> -
>>>>    		frameInfos_.remove(info);
>>>> -		pipe()->completeRequest(request);
>>>> +		pipe()->cancelRequest(request);
>>>>    		return;
>>>>    	}
>>>>
>>>> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>>>> index 5a5acf6a16..6a6be5c820 100644
>>>> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>>>> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>>>> @@ -1401,21 +1401,7 @@ void CameraData::clearIncompleteRequests()
>>>>    	 * back to the application.
>>>>    	 */
>>>>    	while (!requestQueue_.empty()) {
>>>> -		Request *request = requestQueue_.front();
>>>> -
>>>> -		for (auto &b : request->buffers()) {
>>>> -			FrameBuffer *buffer = b.second;
>>>> -			/*
>>>> -			 * Has the buffer already been handed back to the
>>>> -			 * request? If not, do so now.
>>>> -			 */
>>>> -			if (buffer->request()) {
>>>
>>> I have an hard time understanding what this check protects against in
>>> this pipeline handler. As far as I understand a similar check is not
>>> there in pipe()->cancelRequest()
>>
>> `completeBuffer()` sets the `Request` pointer of `FrameBuffer` to `nullptr`,
>> so this checks if this buffer of the request has already been completed,
>> and it will only cancel the not-yet-completed buffers. That is my understanding.
>> Completion removes the buffer from the `pendingBuffers_` set, and `cancelBuffer()`
>> will look through those buffers, so it will only consider not-yet-completed buffers,
>> just like this loop here. So the two are largely equivalent (except when the request
> 
> Thanks for the explanation
> 
>> has no pending buffers).
> 
> And what changes in this case ?

`cancelRequest()` always marks the request as cancelled, the above loop will only
mark it cancelled if there is at least one pending buffer. I don't think the difference
is really noticable since `clearIncompleteRequests()` is only called in the stop/timeout case.


> 
>>
>>
>>>
>>>> -				buffer->_d()->cancel();
>>>> -				pipe()->completeBuffer(request, buffer);
>>>> -			}
>>>> -		}
>>>> -
>>>> -		pipe()->completeRequest(request);
>>>> +		pipe()->cancelRequest(requestQueue_.front());
>>>>    		requestQueue_.pop();
>>>>    	}
>>>>    }
>>>> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
>>>> index 6681c74ee5..3d010d80e5 100644
>>>> --- a/src/libcamera/pipeline/vimc/vimc.cpp
>>>> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
>>>> @@ -605,12 +605,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
>>>>
>>>>    	/* If the buffer is cancelled force a complete of the whole request. */
>>>>    	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
>>>> -		for (const auto &[stream, b] : request->buffers()) {
>>>> -			b->_d()->cancel();
>>>> -			pipe->completeBuffer(request, b);
>>>> -		}
>>>> -
>>>> -		pipe->completeRequest(request);
>>>> +		pipe->cancelRequest(request);
>>>>    		return;
>>>>    	}
>>>>
>>>> --
>>>> 2.54.0
>>>>
>>
Laurent Pinchart June 23, 2026, 1:04 p.m. UTC | #5
On Mon, Jun 22, 2026 at 06:22:11PM +0200, Barnabás Pőcze wrote:
> 2026. 06. 22. 16:25 keltezéssel, Jacopo Mondi írta:
> > On Mon, Jun 22, 2026 at 02:50:16PM +0200, Barnabás Pőcze wrote:
> >> 2026. 06. 22. 14:44 keltezéssel, Jacopo Mondi írta:
> >>> On Thu, Jun 18, 2026 at 02:38:23PM +0200, Barnabás Pőcze wrote:
> >>>> Use `PipelineHander::cancelRequest()` instead of manually cancelling, completing
> >>>> each buffer, then completing the request. This has the same behaviour unless
> >>>> the request has no pending buffers.
> >>>>
> >>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> >>>> ---
> >>>>    src/libcamera/pipeline/ipu3/ipu3.cpp             | 14 ++------------
> >>>>    .../pipeline/rpi/common/pipeline_base.cpp        | 16 +---------------
> >>>>    src/libcamera/pipeline/vimc/vimc.cpp             |  7 +------
> >>>>    3 files changed, 4 insertions(+), 33 deletions(-)
> >>>>
> >>>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> >>>> index bf4c2921f2..560fccd8c0 100644
> >>>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> >>>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> >>>> @@ -790,12 +790,7 @@ void IPU3CameraData::cancelPendingRequests()
> >>>>    	while (!pendingRequests_.empty()) {
> >>>>    		Request *request = pendingRequests_.front();
> >>>>
> >>>> -		for (const auto &[stream, buffer] : request->buffers()) {
> >>>> -			buffer->_d()->cancel();
> >>>> -			pipe()->completeBuffer(request, buffer);
> >>>> -		}
> >>>> -
> >>>> -		pipe()->completeRequest(request);
> >>>> +		pipe()->cancelRequest(request);
> >>>>    		pendingRequests_.pop();
> >>>>    	}
> >>>>    }
> >>>> @@ -1299,13 +1294,8 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
> >>>>
> >>>>    	/* If the buffer is cancelled force a complete of the whole request. */
> >>>>    	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
> >>>> -		for (const auto &[stream, b] : request->buffers()) {
> >>>> -			b->_d()->cancel();
> >>>> -			pipe()->completeBuffer(request, b);
> >>>> -		}
> >>>> -
> >>>>    		frameInfos_.remove(info);
> >>>> -		pipe()->completeRequest(request);
> >>>> +		pipe()->cancelRequest(request);
> >>>>    		return;
> >>>>    	}
> >>>>
> >>>> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> >>>> index 5a5acf6a16..6a6be5c820 100644
> >>>> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> >>>> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> >>>> @@ -1401,21 +1401,7 @@ void CameraData::clearIncompleteRequests()
> >>>>    	 * back to the application.
> >>>>    	 */
> >>>>    	while (!requestQueue_.empty()) {
> >>>> -		Request *request = requestQueue_.front();
> >>>> -
> >>>> -		for (auto &b : request->buffers()) {
> >>>> -			FrameBuffer *buffer = b.second;
> >>>> -			/*
> >>>> -			 * Has the buffer already been handed back to the
> >>>> -			 * request? If not, do so now.
> >>>> -			 */
> >>>> -			if (buffer->request()) {
> >>>
> >>> I have an hard time understanding what this check protects against in
> >>> this pipeline handler. As far as I understand a similar check is not
> >>> there in pipe()->cancelRequest()
> >>
> >> `completeBuffer()` sets the `Request` pointer of `FrameBuffer` to `nullptr`,
> >> so this checks if this buffer of the request has already been completed,
> >> and it will only cancel the not-yet-completed buffers. That is my understanding.
> >> Completion removes the buffer from the `pendingBuffers_` set, and `cancelBuffer()`
> >> will look through those buffers, so it will only consider not-yet-completed buffers,
> >> just like this loop here. So the two are largely equivalent (except when the request
> > 
> > Thanks for the explanation
> > 
> >> has no pending buffers).
> > 
> > And what changes in this case ?
> 
> `cancelRequest()` always marks the request as cancelled, the above loop will only
> mark it cancelled if there is at least one pending buffer. I don't think the difference
> is really noticable since `clearIncompleteRequests()` is only called in the stop/timeout case.

The new behaviour seems better to me. The only case I can see where a
request would still be pending without having any pending buffer is when
we're waiting for metadata. Those requests should be marked as
cancelled, not complete successfully.

Could you capture this in the commit message ? And while at it reflow
the commit message text. With that,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> >>>> -				buffer->_d()->cancel();
> >>>> -				pipe()->completeBuffer(request, buffer);
> >>>> -			}
> >>>> -		}
> >>>> -
> >>>> -		pipe()->completeRequest(request);
> >>>> +		pipe()->cancelRequest(requestQueue_.front());
> >>>>    		requestQueue_.pop();
> >>>>    	}
> >>>>    }
> >>>> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> >>>> index 6681c74ee5..3d010d80e5 100644
> >>>> --- a/src/libcamera/pipeline/vimc/vimc.cpp
> >>>> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> >>>> @@ -605,12 +605,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
> >>>>
> >>>>    	/* If the buffer is cancelled force a complete of the whole request. */
> >>>>    	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
> >>>> -		for (const auto &[stream, b] : request->buffers()) {
> >>>> -			b->_d()->cancel();
> >>>> -			pipe->completeBuffer(request, b);
> >>>> -		}
> >>>> -
> >>>> -		pipe->completeRequest(request);
> >>>> +		pipe->cancelRequest(request);
> >>>>    		return;
> >>>>    	}
> >>>>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index bf4c2921f2..560fccd8c0 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -790,12 +790,7 @@  void IPU3CameraData::cancelPendingRequests()
 	while (!pendingRequests_.empty()) {
 		Request *request = pendingRequests_.front();
 
-		for (const auto &[stream, buffer] : request->buffers()) {
-			buffer->_d()->cancel();
-			pipe()->completeBuffer(request, buffer);
-		}
-
-		pipe()->completeRequest(request);
+		pipe()->cancelRequest(request);
 		pendingRequests_.pop();
 	}
 }
@@ -1299,13 +1294,8 @@  void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
 
 	/* If the buffer is cancelled force a complete of the whole request. */
 	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
-		for (const auto &[stream, b] : request->buffers()) {
-			b->_d()->cancel();
-			pipe()->completeBuffer(request, b);
-		}
-
 		frameInfos_.remove(info);
-		pipe()->completeRequest(request);
+		pipe()->cancelRequest(request);
 		return;
 	}
 
diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
index 5a5acf6a16..6a6be5c820 100644
--- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
@@ -1401,21 +1401,7 @@  void CameraData::clearIncompleteRequests()
 	 * back to the application.
 	 */
 	while (!requestQueue_.empty()) {
-		Request *request = requestQueue_.front();
-
-		for (auto &b : request->buffers()) {
-			FrameBuffer *buffer = b.second;
-			/*
-			 * Has the buffer already been handed back to the
-			 * request? If not, do so now.
-			 */
-			if (buffer->request()) {
-				buffer->_d()->cancel();
-				pipe()->completeBuffer(request, buffer);
-			}
-		}
-
-		pipe()->completeRequest(request);
+		pipe()->cancelRequest(requestQueue_.front());
 		requestQueue_.pop();
 	}
 }
diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
index 6681c74ee5..3d010d80e5 100644
--- a/src/libcamera/pipeline/vimc/vimc.cpp
+++ b/src/libcamera/pipeline/vimc/vimc.cpp
@@ -605,12 +605,7 @@  void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
 
 	/* If the buffer is cancelled force a complete of the whole request. */
 	if (buffer->metadata().status == FrameMetadata::FrameCancelled) {
-		for (const auto &[stream, b] : request->buffers()) {
-			b->_d()->cancel();
-			pipe->completeBuffer(request, b);
-		}
-
-		pipe->completeRequest(request);
+		pipe->cancelRequest(request);
 		return;
 	}