diff mbox series

[FFmpeg-devel,v2] avcodec/v4l2_m2m: handle the v4l2 eos event

Message ID 20200317112259.29898-1-ming.qian@nxp.com
State Superseded
Headers show
Series [FFmpeg-devel,v2] avcodec/v4l2_m2m: handle the v4l2 eos event
Related show

Checks

Context Check Description
andriy/ffmpeg-patchwork pending
andriy/ffmpeg-patchwork success Applied patch
andriy/ffmpeg-patchwork success Configure finished
andriy/ffmpeg-patchwork success Make finished
andriy/ffmpeg-patchwork success Make fate finished

Commit Message

Ming Qian March 17, 2020, 11:22 a.m. UTC
when the last frame of capture is dequeueed,
driver may send this V4L2_EVENT_EOS event,
if this event is received, then we can set the capture port done

if the v4l2 m2m driver don't support V4L2_EVENT_EOS,
just output some error message, not make it error.

Without this patch imx8qm often hangs at the end of encoding/decoding when
flushing the capture buffers

Signed-off-by: Ming Qian <ming.qian@nxp.com>
---
 libavcodec/v4l2_context.c |  5 +++++
 libavcodec/v4l2_m2m_dec.c |  9 +++++++++
 libavcodec/v4l2_m2m_enc.c | 22 +++++++++++++++++++++-
 3 files changed, 35 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c
index 8110bbb555..c10862aa12 100644
--- a/libavcodec/v4l2_context.c
+++ b/libavcodec/v4l2_context.c
@@ -171,6 +171,11 @@  static int v4l2_handle_event(V4L2Context *ctx)
         return 0;
     }
 
+    if (evt.type == V4L2_EVENT_EOS) {
+        ctx->done = 1;
+        return 0;
+    }
+
     if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
         return 0;
 
diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c
index d666edffe4..7a4d2a43cb 100644
--- a/libavcodec/v4l2_m2m_dec.c
+++ b/libavcodec/v4l2_m2m_dec.c
@@ -123,6 +123,15 @@  static int v4l2_prepare_decoder(V4L2m2mContext *s)
         }
     }
 
+    memset(&sub, 0, sizeof(sub));
+    sub.type = V4L2_EVENT_EOS;
+    ret = ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
+    if (ret < 0) {
+        av_log(s->avctx, AV_LOG_ERROR,
+                "the v4l2 driver does not support VIDIOC_SUBSCRIBE_EVENT\n"
+                "you must provide an eos event to finish encode\n");
+    }
+
     return 0;
 }
 
diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c
index 5b954f4435..849d28e9a8 100644
--- a/libavcodec/v4l2_m2m_enc.c
+++ b/libavcodec/v4l2_m2m_enc.c
@@ -155,6 +155,24 @@  static int v4l2_check_b_frame_support(V4L2m2mContext *s)
     return AVERROR_PATCHWELCOME;
 }
 
+static int v4l2_subscribe_eos_event(V4L2m2mContext *s)
+{
+    struct v4l2_event_subscription sub;
+    int ret;
+
+    memset(&sub, 0, sizeof(sub));
+    sub.type = V4L2_EVENT_EOS;
+    ret = ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
+    if (ret < 0) {
+        av_log(s->avctx, AV_LOG_ERROR,
+                "the v4l2 driver does not support VIDIOC_SUBSCRIBE_EVENT\n"
+                "you must provide an eos event to finish encode\n");
+        return ret;
+    }
+
+    return 0;
+}
+
 static int v4l2_prepare_encoder(V4L2m2mContext *s)
 {
     AVCodecContext *avctx = s->avctx;
@@ -164,10 +182,12 @@  static int v4l2_prepare_encoder(V4L2m2mContext *s)
     /**
      * requirements
      */
-    ret = v4l2_check_b_frame_support(s);
+    ret = v4l2_subscribe_eos_event(s);
     if (ret)
         return ret;
 
+    v4l2_check_b_frame_support(s);
+
     /**
      * settingss
      */