[RFC,v1,21/27] gstreamer: Use `FrameBuffer` cookie to associate with `GstBuffer`
diff mbox series

Message ID 20260618123844.656396-22-barnabas.pocze@ideasonboard.com
State Accepted
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 the `FrameBuffer`'s arbitrary "cookie" data to reference the
associated `GstBuffer` while the `FrameBuffer` is attached to a
particular request. Otherwise keep the cookie 0.

This is allowed since the `FrameBuffer`s are allocated with the
`FrameBufferAllocator`. This also removes the need for the explicit
mapping of Stream -> GstBuffer in `RequestWrap`.

Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
---
 src/gstreamer/gstlibcamerasrc.cpp | 37 ++++++++++++++++---------------
 1 file changed, 19 insertions(+), 18 deletions(-)

Comments

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

On Thu, Jun 18, 2026 at 02:38:38PM +0200, Barnabás Pőcze wrote:
> Use the `FrameBuffer`'s arbitrary "cookie" data to reference the
> associated `GstBuffer` while the `FrameBuffer` is attached to a
> particular request. Otherwise keep the cookie 0.
>
> This is allowed since the `FrameBuffer`s are allocated with the
> `FrameBufferAllocator`. This also removes the need for the explicit
> mapping of Stream -> GstBuffer in `RequestWrap`.
>
> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>

Acked-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

> ---
>  src/gstreamer/gstlibcamerasrc.cpp | 37 ++++++++++++++++---------------
>  1 file changed, 19 insertions(+), 18 deletions(-)
>
> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> index 5d3ee3a213..9061f9163c 100644
> --- a/src/gstreamer/gstlibcamerasrc.cpp
> +++ b/src/gstreamer/gstlibcamerasrc.cpp
> @@ -52,7 +52,6 @@ struct RequestWrap {
>  	GstBuffer *detachBuffer(GstPad *srcpad);
>
>  	std::unique_ptr<Request> request_;
> -	std::map<GstPad *, GstBuffer *> buffers_;
>
>  	GstClockTime latency_;
>  	GstClockTime pts_;
> @@ -65,9 +64,15 @@ RequestWrap::RequestWrap(std::unique_ptr<Request> request)
>
>  RequestWrap::~RequestWrap()
>  {
> -	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
> -		if (item.second)
> -			gst_buffer_unref(item.second);
> +	if (!request_)
> +		return;
> +
> +	for (const auto &[stream, fb] : request_->buffers()) {
> +		auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> +		if (buffer)
> +			gst_buffer_unref(buffer);
> +
> +		fb->setCookie(0);
>  	}
>  }
>
> @@ -77,25 +82,21 @@ void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
>  	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
>
>  	request_->addBuffer(stream, fb);
> -
> -	auto item = buffers_.find(srcpad);
> -	if (item != buffers_.end()) {
> -		gst_buffer_unref(item->second);
> -		item->second = buffer;
> -	} else {
> -		buffers_[srcpad] = buffer;
> -	}
> +	fb->setCookie(reinterpret_cast<uint64_t>(buffer));
>  }
>
>  GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
>  {
> -	GstBuffer *buffer = nullptr;
> +	const Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> +	FrameBuffer *fb = request_->findBuffer(stream);
> +	if (!fb)
> +		return nullptr;
>
> -	auto item = buffers_.find(srcpad);
> -	if (item != buffers_.end()) {
> -		buffer = item->second;
> -		item->second = nullptr;
> -	}
> +	auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> +
> +	fb->setCookie(0);
> +
> +	g_assert(!buffer || fb == gst_libcamera_buffer_get_frame_buffer(buffer));
>
>  	return buffer;
>  }
> --
> 2.54.0
>
Nicolas Dufresne June 22, 2026, 2:47 p.m. UTC | #2
Le lundi 22 juin 2026 à 15:49 +0200, Jacopo Mondi a écrit :
> Hi Barnabás
> 
> On Thu, Jun 18, 2026 at 02:38:38PM +0200, Barnabás Pőcze wrote:
> > Use the `FrameBuffer`'s arbitrary "cookie" data to reference the
> > associated `GstBuffer` while the `FrameBuffer` is attached to a
> > particular request. Otherwise keep the cookie 0.
> > 
> > This is allowed since the `FrameBuffer`s are allocated with the
> > `FrameBufferAllocator`. This also removes the need for the explicit
> > mapping of Stream -> GstBuffer in `RequestWrap`.
> > 
> > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> 
> Acked-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

This is neat, well no longer type safe, but this is a C/GStreamer wrapper so. I
never noticed this cookie feature (2022). I've also checked the cookie type, it
should work unless you have a CPU with > 64 bit addresses.

Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>

> 
> > ---
> >  src/gstreamer/gstlibcamerasrc.cpp | 37 ++++++++++++++++---------------
> >  1 file changed, 19 insertions(+), 18 deletions(-)
> > 
> > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> > index 5d3ee3a213..9061f9163c 100644
> > --- a/src/gstreamer/gstlibcamerasrc.cpp
> > +++ b/src/gstreamer/gstlibcamerasrc.cpp
> > @@ -52,7 +52,6 @@ struct RequestWrap {
> >  	GstBuffer *detachBuffer(GstPad *srcpad);
> > 
> >  	std::unique_ptr<Request> request_;
> > -	std::map<GstPad *, GstBuffer *> buffers_;
> > 
> >  	GstClockTime latency_;
> >  	GstClockTime pts_;
> > @@ -65,9 +64,15 @@ RequestWrap::RequestWrap(std::unique_ptr<Request> request)
> > 
> >  RequestWrap::~RequestWrap()
> >  {
> > -	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
> > -		if (item.second)
> > -			gst_buffer_unref(item.second);
> > +	if (!request_)
> > +		return;
> > +
> > +	for (const auto &[stream, fb] : request_->buffers()) {
> > +		auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> > +		if (buffer)
> > +			gst_buffer_unref(buffer);
> > +
> > +		fb->setCookie(0);
> >  	}
> >  }
> > 
> > @@ -77,25 +82,21 @@ void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
> >  	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> > 
> >  	request_->addBuffer(stream, fb);
> > -
> > -	auto item = buffers_.find(srcpad);
> > -	if (item != buffers_.end()) {
> > -		gst_buffer_unref(item->second);
> > -		item->second = buffer;
> > -	} else {
> > -		buffers_[srcpad] = buffer;
> > -	}
> > +	fb->setCookie(reinterpret_cast<uint64_t>(buffer));
> >  }
> > 
> >  GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
> >  {
> > -	GstBuffer *buffer = nullptr;
> > +	const Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> > +	FrameBuffer *fb = request_->findBuffer(stream);
> > +	if (!fb)
> > +		return nullptr;
> > 
> > -	auto item = buffers_.find(srcpad);
> > -	if (item != buffers_.end()) {
> > -		buffer = item->second;
> > -		item->second = nullptr;
> > -	}
> > +	auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> > +
> > +	fb->setCookie(0);
> > +
> > +	g_assert(!buffer || fb == gst_libcamera_buffer_get_frame_buffer(buffer));
> > 
> >  	return buffer;
> >  }
> > --
> > 2.54.0
> >
Laurent Pinchart June 23, 2026, 10:13 p.m. UTC | #3
On Mon, Jun 22, 2026 at 10:47:10AM -0400, Nicolas Dufresne wrote:
> Le lundi 22 juin 2026 à 15:49 +0200, Jacopo Mondi a écrit :
> > On Thu, Jun 18, 2026 at 02:38:38PM +0200, Barnabás Pőcze wrote:
> > > Use the `FrameBuffer`'s arbitrary "cookie" data to reference the
> > > associated `GstBuffer` while the `FrameBuffer` is attached to a
> > > particular request. Otherwise keep the cookie 0.
> > > 
> > > This is allowed since the `FrameBuffer`s are allocated with the
> > > `FrameBufferAllocator`. This also removes the need for the explicit
> > > mapping of Stream -> GstBuffer in `RequestWrap`.
> > > 
> > > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> > 
> > Acked-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> 
> This is neat, well no longer type safe, but this is a C/GStreamer wrapper so. I
> never noticed this cookie feature (2022). I've also checked the cookie type, it
> should work unless you have a CPU with > 64 bit addresses.

libcamera will need work to be ported to CHERI.

> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> 
> > > ---
> > >  src/gstreamer/gstlibcamerasrc.cpp | 37 ++++++++++++++++---------------
> > >  1 file changed, 19 insertions(+), 18 deletions(-)
> > > 
> > > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> > > index 5d3ee3a213..9061f9163c 100644
> > > --- a/src/gstreamer/gstlibcamerasrc.cpp
> > > +++ b/src/gstreamer/gstlibcamerasrc.cpp
> > > @@ -52,7 +52,6 @@ struct RequestWrap {
> > >  	GstBuffer *detachBuffer(GstPad *srcpad);
> > > 
> > >  	std::unique_ptr<Request> request_;
> > > -	std::map<GstPad *, GstBuffer *> buffers_;
> > > 
> > >  	GstClockTime latency_;
> > >  	GstClockTime pts_;
> > > @@ -65,9 +64,15 @@ RequestWrap::RequestWrap(std::unique_ptr<Request> request)
> > > 
> > >  RequestWrap::~RequestWrap()
> > >  {
> > > -	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
> > > -		if (item.second)
> > > -			gst_buffer_unref(item.second);
> > > +	if (!request_)
> > > +		return;
> > > +
> > > +	for (const auto &[stream, fb] : request_->buffers()) {
> > > +		auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> > > +		if (buffer)
> > > +			gst_buffer_unref(buffer);
> > > +
> > > +		fb->setCookie(0);
> > >  	}
> > >  }
> > > 
> > > @@ -77,25 +82,21 @@ void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
> > >  	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> > > 
> > >  	request_->addBuffer(stream, fb);
> > > -
> > > -	auto item = buffers_.find(srcpad);
> > > -	if (item != buffers_.end()) {
> > > -		gst_buffer_unref(item->second);
> > > -		item->second = buffer;
> > > -	} else {
> > > -		buffers_[srcpad] = buffer;
> > > -	}
> > > +	fb->setCookie(reinterpret_cast<uint64_t>(buffer));
> > >  }
> > > 
> > >  GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
> > >  {
> > > -	GstBuffer *buffer = nullptr;
> > > +	const Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> > > +	FrameBuffer *fb = request_->findBuffer(stream);
> > > +	if (!fb)
> > > +		return nullptr;
> > > 
> > > -	auto item = buffers_.find(srcpad);
> > > -	if (item != buffers_.end()) {
> > > -		buffer = item->second;
> > > -		item->second = nullptr;
> > > -	}
> > > +	auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());

	GstBuffer *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());

I'm toying with the idea of dropping the cookie in the C API though, but
we can figure that out later, if needed.

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

> > > +
> > > +	fb->setCookie(0);
> > > +
> > > +	g_assert(!buffer || fb == gst_libcamera_buffer_get_frame_buffer(buffer));
> > > 
> > >  	return buffer;
> > >  }
Barnabás Pőcze June 24, 2026, 8:17 a.m. UTC | #4
2026. 06. 24. 0:13 keltezéssel, Laurent Pinchart írta:
> On Mon, Jun 22, 2026 at 10:47:10AM -0400, Nicolas Dufresne wrote:
>> Le lundi 22 juin 2026 à 15:49 +0200, Jacopo Mondi a écrit :
>>> On Thu, Jun 18, 2026 at 02:38:38PM +0200, Barnabás Pőcze wrote:
>>>> Use the `FrameBuffer`'s arbitrary "cookie" data to reference the
>>>> associated `GstBuffer` while the `FrameBuffer` is attached to a
>>>> particular request. Otherwise keep the cookie 0.
>>>>
>>>> This is allowed since the `FrameBuffer`s are allocated with the
>>>> `FrameBufferAllocator`. This also removes the need for the explicit
>>>> mapping of Stream -> GstBuffer in `RequestWrap`.
>>>>
>>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>>>
>>> Acked-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>
>> This is neat, well no longer type safe, but this is a C/GStreamer wrapper so. I
>> never noticed this cookie feature (2022). I've also checked the cookie type, it
>> should work unless you have a CPU with > 64 bit addresses.
> 
> libcamera will need work to be ported to CHERI.

Maybe `uintmax_t`, or arguably something like `union epoll_data`. I would just remove
`setCookie()` and have `cookie()` return a reference to an `epoll_data` like thing.


> 
>> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
>>
>>>> ---
>>>>   src/gstreamer/gstlibcamerasrc.cpp | 37 ++++++++++++++++---------------
>>>>   1 file changed, 19 insertions(+), 18 deletions(-)
>>>>
>>>> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
>>>> index 5d3ee3a213..9061f9163c 100644
>>>> --- a/src/gstreamer/gstlibcamerasrc.cpp
>>>> +++ b/src/gstreamer/gstlibcamerasrc.cpp
>>>> @@ -52,7 +52,6 @@ struct RequestWrap {
>>>>   	GstBuffer *detachBuffer(GstPad *srcpad);
>>>>
>>>>   	std::unique_ptr<Request> request_;
>>>> -	std::map<GstPad *, GstBuffer *> buffers_;
>>>>
>>>>   	GstClockTime latency_;
>>>>   	GstClockTime pts_;
>>>> @@ -65,9 +64,15 @@ RequestWrap::RequestWrap(std::unique_ptr<Request> request)
>>>>
>>>>   RequestWrap::~RequestWrap()
>>>>   {
>>>> -	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
>>>> -		if (item.second)
>>>> -			gst_buffer_unref(item.second);
>>>> +	if (!request_)
>>>> +		return;
>>>> +
>>>> +	for (const auto &[stream, fb] : request_->buffers()) {
>>>> +		auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
>>>> +		if (buffer)
>>>> +			gst_buffer_unref(buffer);
>>>> +
>>>> +		fb->setCookie(0);
>>>>   	}
>>>>   }
>>>>
>>>> @@ -77,25 +82,21 @@ void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
>>>>   	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
>>>>
>>>>   	request_->addBuffer(stream, fb);
>>>> -
>>>> -	auto item = buffers_.find(srcpad);
>>>> -	if (item != buffers_.end()) {
>>>> -		gst_buffer_unref(item->second);
>>>> -		item->second = buffer;
>>>> -	} else {
>>>> -		buffers_[srcpad] = buffer;
>>>> -	}
>>>> +	fb->setCookie(reinterpret_cast<uint64_t>(buffer));
>>>>   }
>>>>
>>>>   GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
>>>>   {
>>>> -	GstBuffer *buffer = nullptr;
>>>> +	const Stream *stream = gst_libcamera_pad_get_stream(srcpad);
>>>> +	FrameBuffer *fb = request_->findBuffer(stream);
>>>> +	if (!fb)
>>>> +		return nullptr;
>>>>
>>>> -	auto item = buffers_.find(srcpad);
>>>> -	if (item != buffers_.end()) {
>>>> -		buffer = item->second;
>>>> -		item->second = nullptr;
>>>> -	}
>>>> +	auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> 
> 	GstBuffer *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> 
> I'm toying with the idea of dropping the cookie in the C API though, but
> we can figure that out later, if needed.

Well, a map is always an option, but this direct approach is very convenient.
It would also be reasonably simple to implement a reasonably type-safe
`GData`-like thing and add those to `Request` and `FrameBuffer` (and possibly
others).


> 
> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
>>>> +
>>>> +	fb->setCookie(0);
>>>> +
>>>> +	g_assert(!buffer || fb == gst_libcamera_buffer_get_frame_buffer(buffer));
>>>>
>>>>   	return buffer;
>>>>   }
> 
> --
> Regards,
> 
> Laurent Pinchart
Laurent Pinchart June 24, 2026, 9:20 a.m. UTC | #5
On Wed, Jun 24, 2026 at 10:17:48AM +0200, Barnabás Pőcze wrote:
> 2026. 06. 24. 0:13 keltezéssel, Laurent Pinchart írta:
> > On Mon, Jun 22, 2026 at 10:47:10AM -0400, Nicolas Dufresne wrote:
> >> Le lundi 22 juin 2026 à 15:49 +0200, Jacopo Mondi a écrit :
> >>> On Thu, Jun 18, 2026 at 02:38:38PM +0200, Barnabás Pőcze wrote:
> >>>> Use the `FrameBuffer`'s arbitrary "cookie" data to reference the
> >>>> associated `GstBuffer` while the `FrameBuffer` is attached to a
> >>>> particular request. Otherwise keep the cookie 0.
> >>>>
> >>>> This is allowed since the `FrameBuffer`s are allocated with the
> >>>> `FrameBufferAllocator`. This also removes the need for the explicit
> >>>> mapping of Stream -> GstBuffer in `RequestWrap`.
> >>>>
> >>>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> >>>
> >>> Acked-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> >>
> >> This is neat, well no longer type safe, but this is a C/GStreamer wrapper so. I
> >> never noticed this cookie feature (2022). I've also checked the cookie type, it
> >> should work unless you have a CPU with > 64 bit addresses.
> > 
> > libcamera will need work to be ported to CHERI.
> 
> Maybe `uintmax_t`, or arguably something like `union epoll_data`. I would just remove
> `setCookie()` and have `cookie()` return a reference to an `epoll_data` like thing.
> 
> >> Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
> >>
> >>>> ---
> >>>>   src/gstreamer/gstlibcamerasrc.cpp | 37 ++++++++++++++++---------------
> >>>>   1 file changed, 19 insertions(+), 18 deletions(-)
> >>>>
> >>>> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
> >>>> index 5d3ee3a213..9061f9163c 100644
> >>>> --- a/src/gstreamer/gstlibcamerasrc.cpp
> >>>> +++ b/src/gstreamer/gstlibcamerasrc.cpp
> >>>> @@ -52,7 +52,6 @@ struct RequestWrap {
> >>>>   	GstBuffer *detachBuffer(GstPad *srcpad);
> >>>>
> >>>>   	std::unique_ptr<Request> request_;
> >>>> -	std::map<GstPad *, GstBuffer *> buffers_;
> >>>>
> >>>>   	GstClockTime latency_;
> >>>>   	GstClockTime pts_;
> >>>> @@ -65,9 +64,15 @@ RequestWrap::RequestWrap(std::unique_ptr<Request> request)
> >>>>
> >>>>   RequestWrap::~RequestWrap()
> >>>>   {
> >>>> -	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
> >>>> -		if (item.second)
> >>>> -			gst_buffer_unref(item.second);
> >>>> +	if (!request_)
> >>>> +		return;
> >>>> +
> >>>> +	for (const auto &[stream, fb] : request_->buffers()) {
> >>>> +		auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> >>>> +		if (buffer)
> >>>> +			gst_buffer_unref(buffer);
> >>>> +
> >>>> +		fb->setCookie(0);
> >>>>   	}
> >>>>   }
> >>>>
> >>>> @@ -77,25 +82,21 @@ void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
> >>>>   	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> >>>>
> >>>>   	request_->addBuffer(stream, fb);
> >>>> -
> >>>> -	auto item = buffers_.find(srcpad);
> >>>> -	if (item != buffers_.end()) {
> >>>> -		gst_buffer_unref(item->second);
> >>>> -		item->second = buffer;
> >>>> -	} else {
> >>>> -		buffers_[srcpad] = buffer;
> >>>> -	}
> >>>> +	fb->setCookie(reinterpret_cast<uint64_t>(buffer));
> >>>>   }
> >>>>
> >>>>   GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
> >>>>   {
> >>>> -	GstBuffer *buffer = nullptr;
> >>>> +	const Stream *stream = gst_libcamera_pad_get_stream(srcpad);
> >>>> +	FrameBuffer *fb = request_->findBuffer(stream);
> >>>> +	if (!fb)
> >>>> +		return nullptr;
> >>>>
> >>>> -	auto item = buffers_.find(srcpad);
> >>>> -	if (item != buffers_.end()) {
> >>>> -		buffer = item->second;
> >>>> -		item->second = nullptr;
> >>>> -	}
> >>>> +	auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> > 
> > 	GstBuffer *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
> > 
> > I'm toying with the idea of dropping the cookie in the C API though, but
> > we can figure that out later, if needed.
> 
> Well, a map is always an option, but this direct approach is very convenient.
> It would also be reasonably simple to implement a reasonably type-safe
> `GData`-like thing and add those to `Request` and `FrameBuffer` (and possibly
> others).

It's certainly doable, but I'm not sure we should. It's one of those
convenience vs. complexity question. We haven't fully answered where to
draw the line, if we should keep the API footprint as small as possible,
or include some convenience features (and if so, which ones). Nothing
that needs to be answered right now.

> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > 
> >>>> +
> >>>> +	fb->setCookie(0);
> >>>> +
> >>>> +	g_assert(!buffer || fb == gst_libcamera_buffer_get_frame_buffer(buffer));
> >>>>
> >>>>   	return buffer;
> >>>>   }

Patch
diff mbox series

diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp
index 5d3ee3a213..9061f9163c 100644
--- a/src/gstreamer/gstlibcamerasrc.cpp
+++ b/src/gstreamer/gstlibcamerasrc.cpp
@@ -52,7 +52,6 @@  struct RequestWrap {
 	GstBuffer *detachBuffer(GstPad *srcpad);
 
 	std::unique_ptr<Request> request_;
-	std::map<GstPad *, GstBuffer *> buffers_;
 
 	GstClockTime latency_;
 	GstClockTime pts_;
@@ -65,9 +64,15 @@  RequestWrap::RequestWrap(std::unique_ptr<Request> request)
 
 RequestWrap::~RequestWrap()
 {
-	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
-		if (item.second)
-			gst_buffer_unref(item.second);
+	if (!request_)
+		return;
+
+	for (const auto &[stream, fb] : request_->buffers()) {
+		auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
+		if (buffer)
+			gst_buffer_unref(buffer);
+
+		fb->setCookie(0);
 	}
 }
 
@@ -77,25 +82,21 @@  void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
 	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
 
 	request_->addBuffer(stream, fb);
-
-	auto item = buffers_.find(srcpad);
-	if (item != buffers_.end()) {
-		gst_buffer_unref(item->second);
-		item->second = buffer;
-	} else {
-		buffers_[srcpad] = buffer;
-	}
+	fb->setCookie(reinterpret_cast<uint64_t>(buffer));
 }
 
 GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
 {
-	GstBuffer *buffer = nullptr;
+	const Stream *stream = gst_libcamera_pad_get_stream(srcpad);
+	FrameBuffer *fb = request_->findBuffer(stream);
+	if (!fb)
+		return nullptr;
 
-	auto item = buffers_.find(srcpad);
-	if (item != buffers_.end()) {
-		buffer = item->second;
-		item->second = nullptr;
-	}
+	auto *buffer = reinterpret_cast<GstBuffer *>(fb->cookie());
+
+	fb->setCookie(0);
+
+	g_assert(!buffer || fb == gst_libcamera_buffer_get_frame_buffer(buffer));
 
 	return buffer;
 }