PR #22763 opened by commodo URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22763 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22763.patch
For a PoC with trying out Zero-Copy for V4L2 M2M, a few minor cleanups were done. The PoC is still under discussion, but in the meantime, these 2 patches seem reasonable to propose for going in master. Reference to PoC:: https://code.ffmpeg.org/commodo/FFmpeg/src/branch/v4l2-m2m-dmabuf >From 333b52988edabb3a4135750e7bec121f87933900 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean <[email protected]> Date: Fri, 27 Mar 2026 13:42:13 +0200 Subject: [PATCH 1/2] avdevice/v4l2: wrap buf_start and buf_len into a struct This reduces the number of malloc() & free() calls, and structures the data for the buffers a bit neatly. In case more per-buffer data needs to be added, having a separate struct is useful. Signed-off-by: Alexandru Ardelean <[email protected]> --- libavdevice/v4l2.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index c38ecbb378..56e176a439 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -80,6 +80,11 @@ static const int desired_video_buffers = 256; */ #define V4L_TS_CONVERT_READY V4L_TS_DEFAULT +struct buf_data { + void *start; + unsigned int len; +}; + struct video_data { AVClass *class; int fd; @@ -97,8 +102,7 @@ struct video_data { int buffers; atomic_int buffers_queued; - void **buf_start; - unsigned int *buf_len; + struct buf_data *buf_data; char *standard; v4l2_std_id std_id; int channel; @@ -377,15 +381,9 @@ static int mmap_init(AVFormatContext *ctx) return AVERROR(ENOMEM); } s->buffers = req.count; - s->buf_start = av_malloc_array(s->buffers, sizeof(void *)); - if (!s->buf_start) { - av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer pointers\n"); - return AVERROR(ENOMEM); - } - s->buf_len = av_malloc_array(s->buffers, sizeof(unsigned int)); - if (!s->buf_len) { - av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer sizes\n"); - av_freep(&s->buf_start); + s->buf_data = av_malloc_array(s->buffers, sizeof(struct buf_data)); + if (!s->buf_data) { + av_log(ctx, AV_LOG_ERROR, "Cannot allocate buffer data\n"); return AVERROR(ENOMEM); } @@ -417,18 +415,18 @@ static int mmap_init(AVFormatContext *ctx) buf_offset = buf.m.offset; } - s->buf_len[i] = buf_length; - if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) { + if (s->frame_size > 0 && buf_length < s->frame_size) { av_log(ctx, AV_LOG_ERROR, "buf_len[%d] = %d < expected frame size %d\n", - i, s->buf_len[i], s->frame_size); + i, buf_length, s->frame_size); return AVERROR(ENOMEM); } - s->buf_start[i] = v4l2_mmap(NULL, buf_length, + s->buf_data[i].len = buf_length; + s->buf_data[i].start = v4l2_mmap(NULL, buf_length, PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf_offset); - if (s->buf_start[i] == MAP_FAILED) { + if (s->buf_data[i].start == MAP_FAILED) { res = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", av_err2str(res)); return res; @@ -601,7 +599,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) enqueue_buffer(s, &buf); return res; } - memcpy(pkt->data, s->buf_start[buf.index], bytesused); + memcpy(pkt->data, s->buf_data[buf.index].start, bytesused); res = enqueue_buffer(s, &buf); if (res) { @@ -611,7 +609,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) } else { struct buff_data *buf_descriptor; - pkt->data = s->buf_start[buf.index]; + pkt->data = s->buf_data[buf.index].start; pkt->size = bytesused; buf_descriptor = av_malloc(sizeof(struct buff_data)); @@ -689,10 +687,9 @@ static void mmap_close(struct video_data *s) */ v4l2_ioctl(s->fd, VIDIOC_STREAMOFF, &type); for (i = 0; i < s->buffers; i++) { - v4l2_munmap(s->buf_start[i], s->buf_len[i]); + v4l2_munmap(s->buf_data[i].start, s->buf_data[i].len); } - av_freep(&s->buf_start); - av_freep(&s->buf_len); + av_freep(&s->buf_data); } static int v4l2_set_parameters(AVFormatContext *ctx) -- 2.52.0 >From f05b587034b03d6eeaba40d02e2416ac59007100 Mon Sep 17 00:00:00 2001 From: Alexandru Ardelean <[email protected]> Date: Sat, 28 Mar 2026 11:03:18 +0200 Subject: [PATCH 2/2] avdevice/v4l2: rename 'buff_data' -> 'buf_desc' Since we've added a 'buf_data' struct, rename this to avoid any confusion about this one. Signed-off-by: Alexandru Ardelean <[email protected]> --- libavdevice/v4l2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index 56e176a439..a35f53ec46 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -125,7 +125,7 @@ struct video_data { int (*munmap_f)(void *_start, size_t length); }; -struct buff_data { +struct buf_desc { struct video_data *s; int index; }; @@ -454,7 +454,7 @@ static void mmap_release_buffer(void *opaque, uint8_t *data) { struct v4l2_plane planes[VIDEO_MAX_PLANES]; struct v4l2_buffer buf = { 0 }; - struct buff_data *buf_descriptor = opaque; + struct buf_desc *buf_descriptor = opaque; struct video_data *s = buf_descriptor->s; buf.type = s->buf_type; @@ -607,12 +607,12 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) return res; } } else { - struct buff_data *buf_descriptor; + struct buf_desc *buf_descriptor; pkt->data = s->buf_data[buf.index].start; pkt->size = bytesused; - buf_descriptor = av_malloc(sizeof(struct buff_data)); + buf_descriptor = av_malloc(sizeof(struct buf_desc)); if (!buf_descriptor) { /* Something went wrong... Since av_malloc() failed, we cannot even * allocate a buffer for memcpying into it -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
