Stateless codecs have to find buffers based on a timestamp (vb2_find_timestamp).
The timestamp is set to 0 initially, so prohibit finding timestamp 0 since it
could find unused buffers without associated memory (userptr or dmabuf).

The memory associated with a buffer will also disappear if the same buffer was
requeued with a different userptr address or dmabuf fd. Detect this and set the
timestamp of that buffer to 0 if this happens.

Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>
---
Note: I think it is still necessary to lock a buffer when it is in use as
a reference frame, otherwise a userspace application can queue it again with
a different dmabuf fd, which could free the memory of the old dmabuf.

vb2_find_buffer should probably do that.
---
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index e07b6bdb6982..b664d9790330 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1043,6 +1043,8 @@ static int __prepare_userptr(struct vb2_buffer *vb)
                                reacquired = true;
                                call_void_vb_qop(vb, buf_cleanup, vb);
                        }
+                       if (!q->is_output)
+                               vb->timestamp = 0;
                        call_void_memop(vb, put_userptr, 
vb->planes[plane].mem_priv);
                }

@@ -1157,6 +1159,8 @@ static int __prepare_dmabuf(struct vb2_buffer *vb)
                /* Skip the plane if already verified */
                if (dbuf == vb->planes[plane].dbuf &&
                        vb->planes[plane].length == planes[plane].length) {
+                       if (!q->is_output)
+                               vb->timestamp = 0;
                        dma_buf_put(dbuf);
                        continue;
                }
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 3aeaea3af42a..8e966fa81b7e 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -603,6 +603,9 @@ int vb2_find_timestamp(const struct vb2_queue *q, u64 
timestamp,
 {
        unsigned int i;

+       if (!timestamp)
+               return -1;
+
        for (i = start_idx; i < q->num_buffers; i++)
                if (q->bufs[i]->timestamp == timestamp)
                        return i;
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 8a10889dc2fd..01bf4b2199c7 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -59,14 +59,14 @@ struct vb2_v4l2_buffer {
  * vb2_find_timestamp() - Find buffer with given timestamp in the queue
  *
  * @q:         pointer to &struct vb2_queue with videobuf2 queue.
- * @timestamp: the timestamp to find.
+ * @timestamp: the timestamp to find. Must be > 0.
  * @start_idx: the start index (usually 0) in the buffer array to start
  *             searching from. Note that there may be multiple buffers
  *             with the same timestamp value, so you can restart the search
  *             by setting @start_idx to the previously found index + 1.
  *
  * Returns the buffer index of the buffer with the given @timestamp, or
- * -1 if no buffer with @timestamp was found.
+ * -1 if no buffer with @timestamp was found or if @timestamp was 0.
  */
 int vb2_find_timestamp(const struct vb2_queue *q, u64 timestamp,
                       unsigned int start_idx);

Reply via email to