diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 94beae933a..4eb29eb4f7 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -823,9 +823,10 @@ Video The result is most likely broken decoding, but may also help if the detected or reported profiles are somehow incorrect. -``--vd-lavc-software-fallback=`` +``--vd-lavc-software-fallback=`` Fallback to software decoding if the hardware-accelerated decoder fails - (default: yes). + (default: 3). If this is a number, then fallback will be triggered if + N frames fail to decode in a row. 1 is equivalent to ``yes``. ``--vd-lavc-bitexact`` Only use bit-exact algorithms in all decoding steps (for codec testing). diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 90b2d6a886..b655b8480b 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -34,6 +34,7 @@ typedef struct lavc_ctx { int hwdec_profile; bool hwdec_request_reinit; + int hwdec_fail_count; } vd_ffmpeg_ctx; struct vd_lavc_hwdec { diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 9ce657bb5c..c80ec26deb 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -102,7 +102,8 @@ const struct m_sub_options vd_lavc_conf = { OPT_INT("threads", threads, M_OPT_MIN, .min = 0), OPT_FLAG("bitexact", bitexact, 0), OPT_FLAG("check-hw-profile", check_hw_profile, 0), - OPT_FLAG("software-fallback", software_fallback, 0), + OPT_CHOICE_OR_INT("software-fallback", software_fallback, 0, 1, INT_MAX, + ({"no", INT_MAX}, {"yes", 1})), OPT_KEYVALUELIST("o", avopts, 0), {0} }, @@ -110,7 +111,7 @@ const struct m_sub_options vd_lavc_conf = { .defaults = &(const struct vd_lavc_params){ .show_all = 0, .check_hw_profile = 1, - .software_fallback = 1, + .software_fallback = 3, .skip_loop_filter = AVDISCARD_DEFAULT, .skip_idct = AVDISCARD_DEFAULT, .skip_frame = AVDISCARD_DEFAULT, @@ -463,6 +464,7 @@ static void uninit_avctx(struct dec_video *vd) av_frame_free(&ctx->pic); ctx->hwdec_failed = false; + ctx->hwdec_fail_count = 0; } static void update_image_params(struct dec_video *vd, AVFrame *frame, @@ -609,7 +611,7 @@ static void decode(struct dec_video *vd, struct demux_packet *packet, int ret; vd_ffmpeg_ctx *ctx = vd->priv; AVCodecContext *avctx = ctx->avctx; - struct vd_lavc_params *lavc_param = ctx->opts->vd_lavc_params; + struct vd_lavc_params *opts = ctx->opts->vd_lavc_params; AVPacket pkt; if (ctx->hwdec_request_reinit) @@ -617,7 +619,7 @@ static void decode(struct dec_video *vd, struct demux_packet *packet, if (flags) { // hr-seek framedrop vs. normal framedrop - avctx->skip_frame = flags == 2 ? AVDISCARD_NONREF : lavc_param->framedrop; + avctx->skip_frame = flags == 2 ? AVDISCARD_NONREF : opts->framedrop; } else { // normal playback avctx->skip_frame = ctx->skip_frame; @@ -631,8 +633,11 @@ static void decode(struct dec_video *vd, struct demux_packet *packet, if (ret < 0) { MP_WARN(vd, "Error while decoding frame!\n"); - if (lavc_param->software_fallback) - ctx->hwdec_failed = true; + if (ctx->hwdec) { + ctx->hwdec_fail_count += 1; + if (ctx->hwdec_fail_count >= opts->software_fallback) + ctx->hwdec_failed = true; + } return; } @@ -645,6 +650,8 @@ static void decode(struct dec_video *vd, struct demux_packet *packet, if (!got_picture) return; + ctx->hwdec_fail_count = 0; + struct mp_image_params params; update_image_params(vd, ctx->pic, ¶ms); vd->codec_pts = mp_pts_from_av(ctx->pic->pkt_pts, NULL);