summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst5
-rw-r--r--video/decode/lavc.h1
-rw-r--r--video/decode/vd_lavc.c19
3 files changed, 17 insertions, 8 deletions
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=<yes|no>``
+``--vd-lavc-software-fallback=<yes|no|N>``
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, &params);
vd->codec_pts = mp_pts_from_av(ctx->pic->pkt_pts, NULL);