diff options
author | wm4 <wm4@nowhere> | 2015-11-03 14:03:02 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-11-03 14:03:02 +0100 |
commit | 163c6ad862c1bffcec34eb09e03d09c133b15d92 (patch) | |
tree | 254dce347f7f2ebe5cb0cf2671ae2f3d67b5aaf0 /video/decode | |
parent | 4058b418bf3618c5d9b01e08e31774ae115d2365 (diff) |
vd_lavc: make hwdec fallback more tolerant
A hw decoder might fail to decode a frame for multiple reasons, and not
always just because decoding is impossible. We can't generally
distinguish these reasons well. Make it more tolerant by accepting
failures of 3 frames, but not more. The threshold can be adjusted by the
repurposed --vd-lavc-software-fallback option.
(This behavior was suggested much earlier in some PR, but at the time
the "proper" hwdec fallback was indistinguishable from decoding error.
With the current situation, "proper" fallback is still instantious.)
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/lavc.h | 1 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 19 |
2 files changed, 14 insertions, 6 deletions
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); |