Commit 8ac8e905 authored by Ming Qian's avatar Ming Qian Committed by Andriy Gelman

avcodec/v4l2_m2m: handle v4l2 end of stream event

When flushing the capture buffers, the driver may send a V4L2_EVENT_EOS
to notify that draining is completed. Currently, v4l2_m2m does not
subscribe to this event, which can cause some devices (i.e. imx8qm) to
hang at the end of encoding/decoding. Support for handling the event is
added in this commit.

Some devices may not signal V4L2_EVENT_EOS. This is logged as a warning
message during initialization and not treated as a fatal error.
Signed-off-by: 's avatarMing Qian <ming.qian@nxp.com>
Signed-off-by: 's avatarAndriy Gelman <andriy.gelman@gmail.com>
parent 0607f1bc
...@@ -154,6 +154,7 @@ static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_upd ...@@ -154,6 +154,7 @@ static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_upd
} }
/** /**
* handle resolution change event and end of stream event
* returns 1 if reinit was successful, negative if it failed * returns 1 if reinit was successful, negative if it failed
* returns 0 if reinit was not executed * returns 0 if reinit was not executed
*/ */
...@@ -171,6 +172,11 @@ static int v4l2_handle_event(V4L2Context *ctx) ...@@ -171,6 +172,11 @@ static int v4l2_handle_event(V4L2Context *ctx)
return 0; return 0;
} }
if (evt.type == V4L2_EVENT_EOS) {
ctx->done = 1;
return 0;
}
if (evt.type != V4L2_EVENT_SOURCE_CHANGE) if (evt.type != V4L2_EVENT_SOURCE_CHANGE)
return 0; return 0;
......
...@@ -123,6 +123,13 @@ static int v4l2_prepare_decoder(V4L2m2mContext *s) ...@@ -123,6 +123,13 @@ 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_WARNING,
"the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n");
return 0; return 0;
} }
......
...@@ -155,6 +155,17 @@ static int v4l2_check_b_frame_support(V4L2m2mContext *s) ...@@ -155,6 +155,17 @@ static int v4l2_check_b_frame_support(V4L2m2mContext *s)
return AVERROR_PATCHWELCOME; return AVERROR_PATCHWELCOME;
} }
static inline void v4l2_subscribe_eos_event(V4L2m2mContext *s)
{
struct v4l2_event_subscription sub;
memset(&sub, 0, sizeof(sub));
sub.type = V4L2_EVENT_EOS;
if (ioctl(s->fd, VIDIOC_SUBSCRIBE_EVENT, &sub) < 0)
av_log(s->avctx, AV_LOG_WARNING,
"the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n");
}
static int v4l2_prepare_encoder(V4L2m2mContext *s) static int v4l2_prepare_encoder(V4L2m2mContext *s)
{ {
AVCodecContext *avctx = s->avctx; AVCodecContext *avctx = s->avctx;
...@@ -164,6 +175,8 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) ...@@ -164,6 +175,8 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s)
/** /**
* requirements * requirements
*/ */
v4l2_subscribe_eos_event(s);
ret = v4l2_check_b_frame_support(s); ret = v4l2_check_b_frame_support(s);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment