Hi Hans, Since this function only return DEQUEUED and DONE buffers, it cannot be used to find a capture buffer that is both used for frame output and is part of the frame reference list. E.g. a bottom field referencing a top field that is already part of the capture buffer being used for frame output. (top and bottom field is output in same buffer) Jernej Škrabec and me have worked around this issue in cedrus driver by first checking the tag/timestamp of the current buffer being used for output frame. // field pictures may reference current capture buffer and is not returned by vb2_find_tag if (v4l2_buf->tag == dpb->tag) buf_idx = v4l2_buf->vb2_buf.index; else buf_idx = vb2_find_tag(cap_q, dpb->tag, 0); What is the recommended way to handle such case? Could vb2_find_timestamp be extended to allow QUEUED buffers to be returned? In our sample code we only keep at most one output, one capture buffer in queue and use buffer indices as tag/timestamp to simplify buffer handling. FFmpeg keeps track of buffers/frames referenced and a buffer will not be reused until the codec and display pipeline have released all references to it. Sample code having interlaced and multi-slice support using previous tag version of this patchset can be found at: https://github.com/jernejsk/LibreELEC.tv/blob/hw_dec_ffmpeg/projects/Allwinner/patches/linux/0025-H264-fixes.patch#L120-L124 https://github.com/Kwiboo/FFmpeg/compare/4.0.3-Leia-Beta5...v4l2-request-hwaccel Regards, Jonas On 2018-12-12 13:38, hverkuil-cisco@xxxxxxxxx wrote: > From: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> > > Use v4l2_timeval_to_ns instead of timeval_to_ns to ensure that > both kernelspace and userspace will use the same conversion > function. > > Next add a new vb2_find_timestamp() function to find buffers > with a specific timestamp. > > This function will only look at DEQUEUED and DONE buffers, i.e. > buffers that are already processed. > > Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> > --- > .../media/common/videobuf2/videobuf2-v4l2.c | 22 +++++++++++++++++-- > include/media/videobuf2-v4l2.h | 19 +++++++++++++++- > 2 files changed, 38 insertions(+), 3 deletions(-) > > diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c > index 1244c246d0c4..8d1231c2da65 100644 > --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c > +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c > @@ -143,7 +143,7 @@ static void __copy_timestamp(struct vb2_buffer *vb, const void *pb) > * and the timecode field and flag if needed. > */ > if (q->copy_timestamp) > - vb->timestamp = timeval_to_ns(&b->timestamp); > + vb->timestamp = v4l2_timeval_to_ns(&b->timestamp); > vbuf->flags |= b->flags & V4L2_BUF_FLAG_TIMECODE; > if (b->flags & V4L2_BUF_FLAG_TIMECODE) > vbuf->timecode = b->timecode; > @@ -460,7 +460,8 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) > b->flags = vbuf->flags; > b->field = vbuf->field; > b->timestamp = ns_to_timeval(vb->timestamp); > - b->timecode = vbuf->timecode; > + if (b->flags & V4L2_BUF_FLAG_TIMECODE) > + b->timecode = vbuf->timecode; > b->sequence = vbuf->sequence; > b->reserved2 = 0; > b->request_fd = 0; > @@ -586,6 +587,23 @@ static const struct vb2_buf_ops v4l2_buf_ops = { > .copy_timestamp = __copy_timestamp, > }; > > +int vb2_find_timestamp(const struct vb2_queue *q, u64 timestamp, > + unsigned int start_idx) > +{ > + unsigned int i; > + > + for (i = start_idx; i < q->num_buffers; i++) { > + struct vb2_buffer *vb = q->bufs[i]; > + > + if ((vb->state == VB2_BUF_STATE_DEQUEUED || > + vb->state == VB2_BUF_STATE_DONE) && > + vb->timestamp == timestamp) > + return i; > + } > + return -1; > +} > +EXPORT_SYMBOL_GPL(vb2_find_timestamp); > + > /* > * vb2_querybuf() - query video buffer information > * @q: videobuf queue > diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h > index 727855463838..80f1afa0edad 100644 > --- a/include/media/videobuf2-v4l2.h > +++ b/include/media/videobuf2-v4l2.h > @@ -32,7 +32,7 @@ > * &enum v4l2_field. > * @timecode: frame timecode. > * @sequence: sequence count of this frame. > - * @request_fd: the request_fd associated with this buffer > + * @request_fd: the request_fd associated with this buffer. > * @planes: plane information (userptr/fd, length, bytesused, data_offset). > * > * Should contain enough information to be able to cover all the fields > @@ -55,6 +55,23 @@ struct vb2_v4l2_buffer { > #define to_vb2_v4l2_buffer(vb) \ > container_of(vb, struct vb2_v4l2_buffer, vb2_buf) > > +/** > + * 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. Only buffers in state DEQUEUED or DONE > + * are considered. > + * @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. > + */ > +int vb2_find_timestamp(const struct vb2_queue *q, u64 timestamp, > + unsigned int start_idx); > + > int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b); > > /**