Custom "buffer pool" or "allocator" with avdec_mjpeg
Thomas Oldbury
t.oldbury at thermoteknix.com
Mon Sep 5 11:49:18 UTC 2022
Hi all,
I am trying to get a GStreamer application working where the upstream element (an appsink) will be able to pass a custom buffer pool into an avdec_mjpeg decoder. The reason for doing this is to avoid a memcpy() operation between the avdec_mjpeg decode and the display. This implementation is an embedded system with limited resources (it is an FPGA SoC, Xilinx Zynq) and so avoiding a memcpy is essential to maintaining performance.
In the ideal world, I would implement a custom allocator that when presented with a request for a new buffer would choose one of the N buffers available in FPGA space. (N ~14 at present, could be extended later.) Or I could set up a bufferpool with all these buffers available. The buffer addresses are fixed: they are mmap'd representations of physical addresses, so unfortunately I can't do this any other way (unless I write my own JPEG decoder, which I'm trying to avoid doing.)
In the ideal world, the JPEG decode would directly decompress the pixel data into the passed framebuffer, achieving zero-copy performance.
The problem I'm having is I've tried setting up an ALLOCATION query like so:
gst_element_foreach_sink_pad(GST_ELEMENT(gAppSink), cb_padForeach, NULL);
then my cb_padForeach implementation is like this:
gboolean cb_padForeach(GstElement *element, GstPad *pad, gpointer user_data)
{
printf("pad %08x %08x %08x\n", element, pad, user_data);
GstCaps *resultCaps = gst_caps_new_empty_simple("result");
GstCaps *caps = gst_caps_new_empty_simple("mycaps");
gboolean need_pool = FALSE;
GstQuery *query = gst_query_new_allocation(caps, TRUE);
gst_pad_query(pad, query);
gst_query_parse_allocation(query, &resultCaps, &need_pool);
GstBufferPool *pool = gst_buffer_pool_new();
gst_buffer_pool_config_set_params(GST_STRUCTURE(pool), NULL, 460800, 36, 36);
gst_query_add_allocation_pool(query, pool, 460800, 36, 36);
gst_caps_unref(caps);
gst_caps_unref(resultCaps);
return TRUE;
}
It may be obvious, but I don't *really* know what I'm doing here; I'm trying to set the bufferpool up for now to have 36 qty of buffers each 460800 bytes long, but avdec_mjpeg is still using its two buffers (I can see if I print the buffer addresses going into appsink.) I know this block is entered, but it doesn't appear to influence any behaviour in GStreamer. N.B. I use 36 in this example as I saw some code in the avdec_X plugin that suggested it wanted to see at least 32 buffers in its ALLOCATION query, but I'm unclear as to whether that is encountered here. I just set it high for now so I could ensure I wasn't trapping on this. And I'm aware that this is not using my FPGA buffer addresses, but one step at a time!
I'd appreciate pointers (no pun intended) to any examples of setting up custom bufferpools or allocators in the upstream.
This is my pipeline (in gstreamer syntax, the implementation is in C):
udpsrc port=5555 ! 'application/x-rtp,payload=26' ! rtpjpegdepay ! queue ! jpegparse ! avdec_mjpeg ! videoconvert ! appsink
I know this pipeline works ok as I can replace appsink with a display sink and I see video from my test pattern generator, also running with GStreamer.
[P.S. I had posted this on IRC, but as I was using a web-client I lost any chat history, and I've just moved house so I've been offline for a week, so apologies if I'm repeating myself.]
Thanks in advance for any advice,
Tom
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/gstreamer-devel/attachments/20220905/7360d4c8/attachment.htm>
More information about the gstreamer-devel
mailing list