X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fv4l2_m2m_dec.c;h=ab07c0a24a2b8ca554d1d3459f3855cb88bc559e;hb=e5bcda6473a2d6984216004506374669501fcf3b;hp=686e13038757e14b3a29b0c57de09b0abab697a8;hpb=fac834b2ae0b2802f1eca9fd804fbdf6cd34ac33;p=ffmpeg diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 686e1303875..ab07c0a24a2 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "libavcodec/avcodec.h" #include "libavcodec/decode.h" +#include "libavcodec/internal.h" #include "v4l2_context.h" #include "v4l2_m2m.h" @@ -38,7 +39,7 @@ static int v4l2_try_start(AVCodecContext *avctx) V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; - struct v4l2_selection selection; + struct v4l2_selection selection = { 0 }; int ret; /* 1. start the output process */ @@ -122,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; } @@ -130,39 +138,40 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) V4L2m2mContext *s = ((V4L2m2mPriv*)avctx->priv_data)->context; V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; - AVPacket avpkt = {0}; int ret; - ret = ff_decode_get_packet(avctx, &avpkt); - if (ret < 0 && ret != AVERROR_EOF) - return ret; + if (!s->buf_pkt.size) { + ret = ff_decode_get_packet(avctx, &s->buf_pkt); + if (ret < 0 && ret != AVERROR_EOF) + return ret; + } if (s->draining) goto dequeue; - ret = ff_v4l2_context_enqueue_packet(output, &avpkt); - if (ret < 0) { - if (ret != AVERROR(EAGAIN)) - return ret; - /* no input buffers available, continue dequeing */ - } + ret = ff_v4l2_context_enqueue_packet(output, &s->buf_pkt); + if (ret < 0 && ret != AVERROR(EAGAIN)) + goto fail; - if (avpkt.size) { + /* if EAGAIN don't unref packet and try to enqueue in the next iteration */ + if (ret != AVERROR(EAGAIN)) + av_packet_unref(&s->buf_pkt); + + if (!s->draining) { ret = v4l2_try_start(avctx); if (ret) { - av_packet_unref(&avpkt); - /* cant recover */ - if (ret == AVERROR(ENOMEM)) - return ret; - - return 0; + if (ret != AVERROR(ENOMEM)) + ret = 0; + goto fail; } } dequeue: - av_packet_unref(&avpkt); return ff_v4l2_context_dequeue_frame(capture, frame, -1); +fail: + av_packet_unref(&s->buf_pkt); + return ret; } static av_cold int v4l2_decode_init(AVCodecContext *avctx) @@ -192,15 +201,12 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) capture->av_codec_id = AV_CODEC_ID_RAWVIDEO; capture->av_pix_fmt = avctx->pix_fmt; + s->avctx = avctx; ret = ff_v4l2_m2m_codec_init(priv); if (ret) { av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); - s->self_ref = NULL; - av_buffer_unref(&priv->context_ref); - return ret; } - s->avctx = avctx; return v4l2_prepare_decoder(s); } @@ -242,9 +248,9 @@ static const AVOption options[] = { .close = v4l2_decode_close, \ .bsfs = bsf_name, \ .capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \ - .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS, \ + .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_CLEANUP, \ .wrapper_name = "v4l2m2m", \ - }; + } M2MDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb"); M2MDEC(hevc, "HEVC", AV_CODEC_ID_HEVC, "hevc_mp4toannexb");