From a9b191971ca0c7106fc290d41014e38eb5d30fbd Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 19 Mar 2020 13:15:49 +0100 Subject: [PATCH] v4l2: fix buffer recycle Only set the OUTSTANDING flag when we placed the buffer in an io area and need to recycle it later. When we captured a frame, put it in the queue. Then dequeue it into the io area after recycling buffers. Fixes #217 --- spa/plugins/v4l2/v4l2-source.c | 1 + spa/plugins/v4l2/v4l2-utils.c | 37 ++++++++++++++++++++-------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 4f429e00d..9f2454d16 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -859,6 +859,7 @@ static int impl_node_process(void *object) b = spa_list_first(&port->queue, struct buffer, link); spa_list_remove(&b->link); + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUTSTANDING); spa_log_trace(this->log, NAME " %p: dequeue buffer %d", this, b->id); diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index a8b5ee87f..4bbc27259 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -1165,7 +1165,6 @@ static int mmap_read(struct impl *this) { struct port *port = &this->out_ports[0]; struct spa_v4l2_device *dev = &port->dev; - struct spa_io_buffers *io; struct v4l2_buffer buf; struct buffer *b; struct spa_data *d; @@ -1210,26 +1209,16 @@ static int mmap_read(struct impl *this) if (buf.flags & V4L2_BUF_FLAG_ERROR) d[0].flags |= SPA_CHUNK_FLAG_CORRUPTED; - SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUTSTANDING); - - io = port->io; - if (io != NULL && io->status != SPA_STATUS_HAVE_DATA) { - io->buffer_id = b->id; - io->status = SPA_STATUS_HAVE_DATA; - } - else { - spa_list_append(&port->queue, &b->link); - } - - spa_log_trace(this->log, "v4l2 %p: now queued %d", this, b->id); - spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA); - + spa_list_append(&port->queue, &b->link); return 0; } static void v4l2_on_fd_events(struct spa_source *source) { struct impl *this = source->data; + struct spa_io_buffers *io; + struct port *port = &this->out_ports[0]; + struct buffer *b; if (source->rmask & SPA_IO_ERR) { struct port *port = &this->out_ports[0]; @@ -1246,6 +1235,24 @@ static void v4l2_on_fd_events(struct spa_source *source) if (mmap_read(this) < 0) return; + + if (spa_list_is_empty(&port->queue)) + return; + + io = port->io; + if (io != NULL && io->status != SPA_STATUS_HAVE_DATA) { + if (io->buffer_id < port->n_buffers) + spa_v4l2_buffer_recycle(this, io->buffer_id); + + b = spa_list_first(&port->queue, struct buffer, link); + spa_list_remove(&b->link); + SPA_FLAG_SET(b->flags, BUFFER_FLAG_OUTSTANDING); + + io->buffer_id = b->id; + io->status = SPA_STATUS_HAVE_DATA; + spa_log_trace(this->log, "v4l2 %p: now queued %d", this, b->id); + } + spa_node_call_ready(&this->callbacks, SPA_STATUS_HAVE_DATA); } static int spa_v4l2_use_buffers(struct impl *this, struct spa_buffer **buffers, uint32_t n_buffers)