Message ID | 20200401023845.4861-1-ming.qian@nxp.com |
---|---|
State | Accepted |
Headers | show |
Series | [FFmpeg-devel,v4] avcodec/v4l2_m2m: handle the v4l2 eos event | expand |
Context | Check | Description |
---|---|---|
andriy/ffmpeg-patchwork | success | Make fate finished |
On Wed, 01. Apr 10:38, Ming Qian wrote: > when the last frame of capture is dequeueed, > driver may send this V4L2_EVENT_EOS event, > If this event is received, then the capture buffers have been flushed and > avcodec_receive_packet()/avcodec_receive_frame() can return AVERROR_EOF. > Otherwise, the draining continues until all the capture buffers have been dequeued or VIDIOC_DQBUF ioctl returns an EPIPE error. > > Some devices may not support V4L2_EVENT_EOS. > This is logged as a warning message and not treated as a fatal error during initialization. > > 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 | 6 ++++++ > libavcodec/v4l2_m2m_dec.c | 8 ++++++++ > libavcodec/v4l2_m2m_enc.c | 19 +++++++++++++++++++ > 3 files changed, 33 insertions(+) > > diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c > index 8110bbb555..6b1f65fe4c 100644 > --- a/libavcodec/v4l2_context.c > +++ b/libavcodec/v4l2_context.c > @@ -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 0 if reinit was not executed > */ > @@ -171,6 +172,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..9989649784 100644 > --- a/libavcodec/v4l2_m2m_dec.c > +++ b/libavcodec/v4l2_m2m_dec.c > @@ -123,6 +123,14 @@ 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; > } > > diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c > index 84de63ec9d..78cf9ba47a 100644 > --- a/libavcodec/v4l2_m2m_enc.c > +++ b/libavcodec/v4l2_m2m_enc.c > @@ -155,6 +155,23 @@ 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_WARNING, > + "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n"); > + return ret; > + } > + > + return 0; > +} > + > static int v4l2_prepare_encoder(V4L2m2mContext *s) > { > AVCodecContext *avctx = s->avctx; > @@ -164,6 +181,8 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) > /** > * requirements > */ > + v4l2_subscribe_eos_event(s); > + > ret = v4l2_check_b_frame_support(s); > if (ret) > return ret; > -- > 2.26.0 > lgtm Tested on RPi4 and Odroid XU4. Thanks,
On Wed, 08. Apr 20:51, Andriy Gelman wrote: > On Wed, 01. Apr 10:38, Ming Qian wrote: > > when the last frame of capture is dequeueed, > > driver may send this V4L2_EVENT_EOS event, > > If this event is received, then the capture buffers have been flushed and > > avcodec_receive_packet()/avcodec_receive_frame() can return AVERROR_EOF. > > Otherwise, the draining continues until all the capture buffers have been dequeued or VIDIOC_DQBUF ioctl returns an EPIPE error. > > > > Some devices may not support V4L2_EVENT_EOS. > > This is logged as a warning message and not treated as a fatal error during initialization. > > > > 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 | 6 ++++++ > > libavcodec/v4l2_m2m_dec.c | 8 ++++++++ > > libavcodec/v4l2_m2m_enc.c | 19 +++++++++++++++++++ > > 3 files changed, 33 insertions(+) > > > > diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c > > index 8110bbb555..6b1f65fe4c 100644 > > --- a/libavcodec/v4l2_context.c > > +++ b/libavcodec/v4l2_context.c > > @@ -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 0 if reinit was not executed > > */ > > @@ -171,6 +172,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..9989649784 100644 > > --- a/libavcodec/v4l2_m2m_dec.c > > +++ b/libavcodec/v4l2_m2m_dec.c > > @@ -123,6 +123,14 @@ 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; > > } > > > > diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c > > index 84de63ec9d..78cf9ba47a 100644 > > --- a/libavcodec/v4l2_m2m_enc.c > > +++ b/libavcodec/v4l2_m2m_enc.c > > @@ -155,6 +155,23 @@ 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_WARNING, > > + "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > static int v4l2_prepare_encoder(V4L2m2mContext *s) > > { > > AVCodecContext *avctx = s->avctx; > > @@ -164,6 +181,8 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) > > /** > > * requirements > > */ > > + v4l2_subscribe_eos_event(s); > > + > > ret = v4l2_check_b_frame_support(s); > > if (ret) > > return ret; > > -- > > 2.26.0 > > > > lgtm > Tested on RPi4 and Odroid XU4. > Would anyone object if I push this on Tuesday? (I would align the commit message before pushing) Thanks,
On Wed, 08. Apr 20:51, Andriy Gelman wrote: > On Wed, 01. Apr 10:38, Ming Qian wrote: > > when the last frame of capture is dequeueed, > > driver may send this V4L2_EVENT_EOS event, > > If this event is received, then the capture buffers have been flushed and > > avcodec_receive_packet()/avcodec_receive_frame() can return AVERROR_EOF. > > Otherwise, the draining continues until all the capture buffers have been dequeued or VIDIOC_DQBUF ioctl returns an EPIPE error. > > > > Some devices may not support V4L2_EVENT_EOS. > > This is logged as a warning message and not treated as a fatal error during initialization. > > > > 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 | 6 ++++++ > > libavcodec/v4l2_m2m_dec.c | 8 ++++++++ > > libavcodec/v4l2_m2m_enc.c | 19 +++++++++++++++++++ > > 3 files changed, 33 insertions(+) > > > > diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c > > index 8110bbb555..6b1f65fe4c 100644 > > --- a/libavcodec/v4l2_context.c > > +++ b/libavcodec/v4l2_context.c > > @@ -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 0 if reinit was not executed > > */ > > @@ -171,6 +172,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..9989649784 100644 > > --- a/libavcodec/v4l2_m2m_dec.c > > +++ b/libavcodec/v4l2_m2m_dec.c > > @@ -123,6 +123,14 @@ 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; > > } > > > > diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c > > index 84de63ec9d..78cf9ba47a 100644 > > --- a/libavcodec/v4l2_m2m_enc.c > > +++ b/libavcodec/v4l2_m2m_enc.c > > @@ -155,6 +155,23 @@ 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_WARNING, > > + "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n"); > > + return ret; > > + } > > + > > + return 0; > > +} > > + > > static int v4l2_prepare_encoder(V4L2m2mContext *s) > > { > > AVCodecContext *avctx = s->avctx; > > @@ -164,6 +181,8 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) > > /** > > * requirements > > */ > > + v4l2_subscribe_eos_event(s); > > + > > ret = v4l2_check_b_frame_support(s); > > if (ret) > > return ret; > > -- > > 2.26.0 > > > > lgtm > Tested on RPi4 and Odroid XU4. > Applied. Thanks,
diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index 8110bbb555..6b1f65fe4c 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -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 0 if reinit was not executed */ @@ -171,6 +172,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..9989649784 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -123,6 +123,14 @@ 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; } diff --git a/libavcodec/v4l2_m2m_enc.c b/libavcodec/v4l2_m2m_enc.c index 84de63ec9d..78cf9ba47a 100644 --- a/libavcodec/v4l2_m2m_enc.c +++ b/libavcodec/v4l2_m2m_enc.c @@ -155,6 +155,23 @@ 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_WARNING, + "the v4l2 driver does not support end of stream VIDIOC_SUBSCRIBE_EVENT\n"); + return ret; + } + + return 0; +} + static int v4l2_prepare_encoder(V4L2m2mContext *s) { AVCodecContext *avctx = s->avctx; @@ -164,6 +181,8 @@ static int v4l2_prepare_encoder(V4L2m2mContext *s) /** * requirements */ + v4l2_subscribe_eos_event(s); + ret = v4l2_check_b_frame_support(s); if (ret) return ret;
when the last frame of capture is dequeueed, driver may send this V4L2_EVENT_EOS event, If this event is received, then the capture buffers have been flushed and avcodec_receive_packet()/avcodec_receive_frame() can return AVERROR_EOF. Otherwise, the draining continues until all the capture buffers have been dequeued or VIDIOC_DQBUF ioctl returns an EPIPE error. Some devices may not support V4L2_EVENT_EOS. This is logged as a warning message and not treated as a fatal error during initialization. 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 | 6 ++++++ libavcodec/v4l2_m2m_dec.c | 8 ++++++++ libavcodec/v4l2_m2m_enc.c | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+)