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 <aardelean@deviqon.com>
This commit is contained in:
Alexandru Ardelean
2026-03-27 13:42:13 +02:00
committed by Ramiro Polla
parent 24adcf3a72
commit 1011e4d647
+22 -25
View File
@@ -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;
@@ -359,10 +363,9 @@ static void list_standards(AVFormatContext *ctx)
static void mmap_free(struct video_data *s, int n)
{
while (--n > 0) {
v4l2_munmap(s->buf_start[n], s->buf_len[n]);
v4l2_munmap(s->buf_data[n].start, s->buf_data[n].len);
}
av_freep(&s->buf_start);
av_freep(&s->buf_len);
av_freep(&s->buf_data);
}
static int mmap_init(AVFormatContext *ctx)
@@ -386,15 +389,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);
}
@@ -427,19 +424,19 @@ 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) {
s->buf_data[i].len = buf_length;
if (s->frame_size > 0 && s->buf_data[i].len < 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);
"buf_data[%d].len = %d < expected frame size %d\n",
i, buf_length, s->frame_size);
res = AVERROR(ENOMEM);
goto fail;
}
s->buf_start[i] = v4l2_mmap(NULL, buf_length,
PROT_READ | PROT_WRITE, MAP_SHARED,
s->fd, buf_offset);
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));
goto fail;
@@ -607,7 +604,7 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt)
}
}
/* Image is at s->buff_start[buf.index] */
/* Image is at s->buf_data[buf.index].start */
if (atomic_load(&s->buffers_queued) == FFMAX(s->buffers / 8, 1)) {
/* when we start getting low on queued buffers, fall back on copying data */
res = av_new_packet(pkt, bytesused);
@@ -616,7 +613,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) {
@@ -626,7 +623,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));