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]

Reply via email to