summaryrefslogtreecommitdiffstats
path: root/video/decode/vd_lavc.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-11-03 14:03:02 +0100
committerwm4 <wm4@nowhere>2015-11-03 14:03:02 +0100
commit163c6ad862c1bffcec34eb09e03d09c133b15d92 (patch)
tree254dce347f7f2ebe5cb0cf2671ae2f3d67b5aaf0 /video/decode/vd_lavc.c
parent4058b418bf3618c5d9b01e08e31774ae115d2365 (diff)
downloadmpv-163c6ad862c1bffcec34eb09e03d09c133b15d92.tar.bz2
mpv-163c6ad862c1bffcec34eb09e03d09c133b15d92.tar.xz
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/vd_lavc.c')
-rw-r--r--video/decode/vd_lavc.c19
1 files changed, 13 insertions, 6 deletions
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, &params);
vd->codec_pts = mp_pts_from_av(ctx->pic->pkt_pts, NULL);