diff mbox series

[FFmpeg-devel,2/2] avcodec/v4l2_context: Log warning when all capture buffers are in userspace

Message ID 20200406042203.10681-2-andriy.gelman@gmail.com
State Accepted
Commit 2a9d62356152d4ef079416101664f26d2562c681
Headers show
Series [FFmpeg-devel,1/2] avcodec/v4l2_context: Use av_freep | expand

Checks

Context Check Description
andriy/ffmpeg-patchwork success Make fate finished

Commit Message

Andriy Gelman April 6, 2020, 4:22 a.m. UTC
From: Andriy Gelman <andriy.gelman@gmail.com>

v4l2_m2m uses device memory mapped buffers to store dequeued
frames/packets (reference counted by AVBufferRef). When the
reference count drops to zero, the buffer ownership is returned back to
the device, so that they can re-filled with frames/packets.

There are some cases when all the buffers are in userspace (i.e. due to
internal buffering in ffmpeg). On the s5p-mfc this causes an infinite
wait when polling to dequeue the buffers, which can be prevented by
increasing the total number of capture buffers. This commit adds a
warning when this occurs.

Signed-off-by: Andriy Gelman <andriy.gelman@gmail.com>
---
 libavcodec/v4l2_context.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

Comments

Ming Qian April 9, 2020, 7:13 a.m. UTC | #1
Lgtm,

But if don't prevent enqueue frame buffer of capture port, unlikely to happen this case.
And I think we can get a proper num_frame_buffers by g_ctrl V4L2_CID_MIN_BUFFERS_FOR_CAPTURE and V4L2_CID_MIN_BUFFERS_FOR_OUTPUT.



Best regards,
Ming Qian
Tel#:86-512-6805-6630


-----Original Message-----
From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Andriy Gelman
Sent: Monday, April 6, 2020 12:22 PM
To: ffmpeg-devel@ffmpeg.org
Cc: Andriy Gelman <andriy.gelman@gmail.com>
Subject: [EXT] [FFmpeg-devel] [PATCH 2/2] avcodec/v4l2_context: Log warning when all capture buffers are in userspace

Caution: EXT Email

From: Andriy Gelman <andriy.gelman@gmail.com>

v4l2_m2m uses device memory mapped buffers to store dequeued frames/packets (reference counted by AVBufferRef). When the reference count drops to zero, the buffer ownership is returned back to the device, so that they can re-filled with frames/packets.

There are some cases when all the buffers are in userspace (i.e. due to internal buffering in ffmpeg). On the s5p-mfc this causes an infinite wait when polling to dequeue the buffers, which can be prevented by increasing the total number of capture buffers. This commit adds a warning when this occurs.

Signed-off-by: Andriy Gelman <andriy.gelman@gmail.com>
---
 libavcodec/v4l2_context.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 31af10d28e..5145772c45 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -285,6 +285,18 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
     };
     int i, ret;

+    if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) {
+        for (i = 0; i < ctx->num_buffers; i++) {
+            if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
+                break;
+        }
+        if (i == ctx->num_buffers)
+            av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to "
+                                                "userspace. Increase num_capture_buffers "
+                                                "to prevent device deadlock or dropped "
+                                                "packets/frames.\n");
+    }
+
     /* if we are draining and there are no more capture buffers queued in the driver we are done */
     if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
         for (i = 0; i < ctx->num_buffers; i++) {
--
2.25.1
Andriy Gelman April 27, 2020, 8:28 p.m. UTC | #2
Hi Ming,

Thanks for looking over the patch.

On Thu, 09. Apr 07:13, Ming Qian wrote:
> Lgtm,
> 
> But if don't prevent enqueue frame buffer of capture port, unlikely to happen this case.

The problem happens when all the capture packets/frames are buffered internally
by ffmpeg (i.e. the buffer state is V4L2BUF_RET_USER). 

I see it on the s5p-mfc even with your patch: 
https://patchwork.ffmpeg.org/project/ffmpeg/patch/20200316020208.27547-1-ming.qian@nxp.com/

> And I think we can get a proper num_frame_buffers by g_ctrl V4L2_CID_MIN_BUFFERS_FOR_CAPTURE and V4L2_CID_MIN_BUFFERS_FOR_OUTPUT.
> 

The values for V4L2_CID_MIN_BUFFERS_FOR_CAPTURE and
V4L2_CID_MIN_BUFFERS_FOR_OUTPUT are the minimum values for the hardware device
and are lower than our defaults. I don't think we should use the minimum values
because the frames/packets may be buffered.

There is another option to request additional buffers via 
CREATE_BUFS ioctl, but it's not supported by all hardware (thanks to ndufresne
on #v4l for suggesting). I feel adding this ioctl should be a separate patch and we
still need a warning if it's not supported.

I'll apply this patch on Wednesday if no one objects. 

Thanks,
Andriy

> 
> 
> 
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Andriy Gelman
> Sent: Monday, April 6, 2020 12:22 PM
> To: ffmpeg-devel@ffmpeg.org
> Cc: Andriy Gelman <andriy.gelman@gmail.com>
> Subject: [EXT] [FFmpeg-devel] [PATCH 2/2] avcodec/v4l2_context: Log warning when all capture buffers are in userspace
> 
> Caution: EXT Email
> 
> From: Andriy Gelman <andriy.gelman@gmail.com>
> 
> v4l2_m2m uses device memory mapped buffers to store dequeued frames/packets (reference counted by AVBufferRef). When the reference count drops to zero, the buffer ownership is returned back to the device, so that they can re-filled with frames/packets.
> 
> There are some cases when all the buffers are in userspace (i.e. due to internal buffering in ffmpeg). On the s5p-mfc this causes an infinite wait when polling to dequeue the buffers, which can be prevented by increasing the total number of capture buffers. This commit adds a warning when this occurs.
> 
> Signed-off-by: Andriy Gelman <andriy.gelman@gmail.com>
> ---
>  libavcodec/v4l2_context.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 31af10d28e..5145772c45 100644
> --- a/libavcodec/v4l2_context.c
> +++ b/libavcodec/v4l2_context.c
> @@ -285,6 +285,18 @@ static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
>      };
>      int i, ret;
> 
> +    if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) {
> +        for (i = 0; i < ctx->num_buffers; i++) {
> +            if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
> +                break;
> +        }
> +        if (i == ctx->num_buffers)
> +            av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to "
> +                                                "userspace. Increase num_capture_buffers "
> +                                                "to prevent device deadlock or dropped "
> +                                                "packets/frames.\n");
> +    }
> +
>      /* if we are draining and there are no more capture buffers queued in the driver we are done */
>      if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
>          for (i = 0; i < ctx->num_buffers; i++) {
> --
> 2.25.1
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fffmpeg.org%2Fmailman%2Flistinfo%2Fffmpeg-devel&amp;data=02%7C01%7Cming.qian%40nxp.com%7C38355e6d2f7b41f639f708d7d9e2f2e9%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637217441076225890&amp;sdata=KmGkJyH%2FxR3jBkrTLI89EWTYhrpNchkJM7ldqjHKUSw%3D&amp;reserved=0
> 
> To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Andriy Gelman April 30, 2020, 3:43 p.m. UTC | #3
On Mon, 27. Apr 16:28, Andriy Gelman wrote:
> Hi Ming,
> 
> Thanks for looking over the patch.
> 
> On Thu, 09. Apr 07:13, Ming Qian wrote:
> > Lgtm,
> > 
> > But if don't prevent enqueue frame buffer of capture port, unlikely to happen this case.
> 
> The problem happens when all the capture packets/frames are buffered internally
> by ffmpeg (i.e. the buffer state is V4L2BUF_RET_USER). 
> 
> I see it on the s5p-mfc even with your patch: 
> https://patchwork.ffmpeg.org/project/ffmpeg/patch/20200316020208.27547-1-ming.qian@nxp.com/
> 
> > And I think we can get a proper num_frame_buffers by g_ctrl V4L2_CID_MIN_BUFFERS_FOR_CAPTURE and V4L2_CID_MIN_BUFFERS_FOR_OUTPUT.
> > 
> 
> The values for V4L2_CID_MIN_BUFFERS_FOR_CAPTURE and
> V4L2_CID_MIN_BUFFERS_FOR_OUTPUT are the minimum values for the hardware device
> and are lower than our defaults. I don't think we should use the minimum values
> because the frames/packets may be buffered.
> 
> There is another option to request additional buffers via 
> CREATE_BUFS ioctl, but it's not supported by all hardware (thanks to ndufresne
> on #v4l for suggesting). I feel adding this ioctl should be a separate patch and we
> still need a warning if it's not supported.
> 
> I'll apply this patch on Wednesday if no one objects. 
> 

Applied.

Thanks,
diff mbox series

Patch

diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index 31af10d28e..5145772c45 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -285,6 +285,18 @@  static V4L2Buffer* v4l2_dequeue_v4l2buf(V4L2Context *ctx, int timeout)
     };
     int i, ret;
 
+    if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx->buffers) {
+        for (i = 0; i < ctx->num_buffers; i++) {
+            if (ctx->buffers[i].status == V4L2BUF_IN_DRIVER)
+                break;
+        }
+        if (i == ctx->num_buffers)
+            av_log(logger(ctx), AV_LOG_WARNING, "All capture buffers returned to "
+                                                "userspace. Increase num_capture_buffers "
+                                                "to prevent device deadlock or dropped "
+                                                "packets/frames.\n");
+    }
+
     /* if we are draining and there are no more capture buffers queued in the driver we are done */
     if (!V4L2_TYPE_IS_OUTPUT(ctx->type) && ctx_to_m2mctx(ctx)->draining) {
         for (i = 0; i < ctx->num_buffers; i++) {