Stateful encoders need to know if V4L2_BUF_FLAG_ERROR was because the capture buffer was too small or because there was another error. Set this flag (always in combination with FLAG_ERROR) to indicate that the buffer was too small. A corresponding VB2_BUF_STATE_ERROR_TOO_SMALL vb2 state was added. Signed-off-by: Hans Verkuil <hverkuil-cisco@xxxxxxxxx> --- Documentation/media/uapi/v4l/buffer.rst | 9 +++++++++ drivers/media/common/videobuf2/videobuf2-core.c | 12 +++++++++--- drivers/media/common/videobuf2/videobuf2-v4l2.c | 4 ++++ include/media/videobuf2-core.h | 4 ++++ include/uapi/linux/videodev2.h | 2 ++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index 9149b57728e5..64a97677ec20 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -540,6 +540,15 @@ Buffer Flags streaming may continue as normal and the buffer may be reused normally. Drivers set this flag when the ``VIDIOC_DQBUF`` ioctl is called. + * .. _`V4L2-BUF-FLAG-TOO-SMALL`: + + - ``V4L2_BUF_FLAG_TOO_SMALL`` + - 0x00080000 + - When this flag is set, the buffer has been dequeued successfully, + but no data was written since the buffer was too small. If this + flag is set, then ``V4L2_BUF_FLAG_ERROR`` was also set. This can + only happen for capture buffers. Drivers set this flag when + the ``VIDIOC_DQBUF`` ioctl is called. * .. _`V4L2-BUF-FLAG-IN-REQUEST`: - ``V4L2_BUF_FLAG_IN_REQUEST`` diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 4489744fbbd9..187a4589a7bb 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -929,6 +929,7 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) if (WARN_ON(state != VB2_BUF_STATE_DONE && state != VB2_BUF_STATE_ERROR && + state != VB2_BUF_STATE_ERROR_TOO_SMALL && state != VB2_BUF_STATE_QUEUED)) state = VB2_BUF_STATE_ERROR; @@ -1816,6 +1817,9 @@ int vb2_core_dqbuf(struct vb2_queue *q, unsigned int *pindex, void *pb, case VB2_BUF_STATE_ERROR: dprintk(3, "returning done buffer with errors\n"); break; + case VB2_BUF_STATE_ERROR_TOO_SMALL: + dprintk(3, "returning done buffer that's too small\n"); + break; default: dprintk(1, "invalid buffer state\n"); return -EINVAL; @@ -2383,8 +2387,9 @@ __poll_t vb2_core_poll(struct vb2_queue *q, struct file *file, done_entry); spin_unlock_irqrestore(&q->done_lock, flags); - if (vb && (vb->state == VB2_BUF_STATE_DONE - || vb->state == VB2_BUF_STATE_ERROR)) { + if (vb && (vb->state == VB2_BUF_STATE_DONE || + vb->state == VB2_BUF_STATE_ERROR || + vb->state == VB2_BUF_STATE_ERROR_TOO_SMALL)) { return (q->is_output) ? EPOLLOUT | EPOLLWRNORM : EPOLLIN | EPOLLRDNORM; @@ -2812,7 +2817,8 @@ static int vb2_thread(void *data) break; try_to_freeze(); - if (vb->state != VB2_BUF_STATE_ERROR) + if (vb->state != VB2_BUF_STATE_ERROR && + vb->state != VB2_BUF_STATE_ERROR_TOO_SMALL) if (threadio->fnc(vb, threadio->priv)) break; call_void_qop(q, wait_finish, q); diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index e652f4318284..6ac19734e4a2 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -44,6 +44,7 @@ module_param(debug, int, 0644); /* Flags that are set by us */ #define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \ V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \ + V4L2_BUF_FLAG_ERROR_TOO_SMALL | \ V4L2_BUF_FLAG_PREPARED | \ V4L2_BUF_FLAG_IN_REQUEST | \ V4L2_BUF_FLAG_REQUEST_FD | \ @@ -546,6 +547,9 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) case VB2_BUF_STATE_IN_REQUEST: b->flags |= V4L2_BUF_FLAG_IN_REQUEST; break; + case VB2_BUF_STATE_ERROR_TOO_SMALL: + b->flags |= V4L2_BUF_FLAG_TOO_SMALL; + /* fall through */ case VB2_BUF_STATE_ERROR: b->flags |= V4L2_BUF_FLAG_ERROR; /* fall through */ diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index a2b2208b02da..289c3e090257 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -215,6 +215,9 @@ enum vb2_io_modes { * @VB2_BUF_STATE_ERROR: same as above, but the operation on the buffer * has ended with an error, which will be reported * to the userspace when it is dequeued. + * @VB2_BUF_STATE_ERROR_TOO_SMALL: same as above, but the operation on the buffer + * has ended with an error because the receiving buffer + * is too small. */ enum vb2_buffer_state { VB2_BUF_STATE_DEQUEUED, @@ -224,6 +227,7 @@ enum vb2_buffer_state { VB2_BUF_STATE_ACTIVE, VB2_BUF_STATE_DONE, VB2_BUF_STATE_ERROR, + VB2_BUF_STATE_ERROR_TOO_SMALL, }; struct vb2_queue; diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 7aa1293ac7bc..c7c1179eea65 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1064,6 +1064,8 @@ static inline __u64 v4l2_timeval_to_ns(const struct timeval *tv) #define V4L2_BUF_FLAG_TSTAMP_SRC_MASK 0x00070000 #define V4L2_BUF_FLAG_TSTAMP_SRC_EOF 0x00000000 #define V4L2_BUF_FLAG_TSTAMP_SRC_SOE 0x00010000 +/* mem2mem encoder */ +#define V4L2_BUF_FLAG_TOO_SMALL 0x00080000 /* mem2mem encoder/decoder */ #define V4L2_BUF_FLAG_LAST 0x00100000 /* request_fd is valid */ -- 2.23.0