vd_lavc: separate opts to two structs and reorganize

The options in vd_lavc are all related, but they don't all require the
same thing for runtime changes. To avoid having to manually add UPDATE_*
to every single option flag, the options can be split into two separate
structs. The vd_lavc_conf becomes a catch all for all the --vd-lavc
options that require the full UPDATE_VD flag. The rest of the options
are split off into the new hwdec_conf instead. Additionally,
--vd-lavc-software-fallback is renamed to --hwdec-software-fallback and
moved to the hwdec_conf as well. The new name better reflects what it
does and it logically fits with those more. UPDATE_* flags are added on
everything now so these should all now be changeable on runtime.
This commit is contained in:
Dudemanguy committed 2025-01-29 15:07:42 +00:00
1 parent 838df2c252
commit 8c4ca44e24
5 files changed
+65 -34

No files matched your search

@@ -0,0 +1 @@
rename `--vd-lavc-software-fallback` to `--hwdec-software-fallback`
+8 -8
View File
@@ -1826,14 +1826,7 @@ Video
``mpv --hwdec=vdpau --hwdec-codecs=h264,mpeg2video``
Enable vdpau decoding for h264 and mpeg2 only.
``--vd-lavc-check-hw-profile=<yes|no>``
Check hardware decoder profile (default: yes). If ``no`` is set, the
highest profile of the hardware decoder is unconditionally selected, and
decoding is forced even if the profile of the video is higher than that.
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|N>``
``--hwdec-software-fallback=<yes|no|N>``
Fallback to software decoding if the hardware-accelerated decoder fails
(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``.
@@ -1843,6 +1836,13 @@ Video
the number of packets that could not be decoded. Values below an unspecified
count will not have this problem, because mpv retains the packets.
``--vd-lavc-check-hw-profile=<yes|no>``
Check hardware decoder profile (default: yes). If ``no`` is set, the
highest profile of the hardware decoder is unconditionally selected, and
decoding is forced even if the profile of the video is higher than that.
The result is most likely broken decoding, but may also help if the
detected or reported profiles are somehow incorrect.
``--vd-lavc-film-grain=<auto|cpu|gpu>``
Enables film grain application on the GPU. If video decoding is done on
the CPU, doing film grain application on the GPU can speed up decoding.
+3
View File
@@ -72,6 +72,7 @@ extern const struct m_sub_options demux_lavf_conf;
extern const struct m_sub_options demux_mkv_conf;
extern const struct m_sub_options vd_lavc_conf;
extern const struct m_sub_options ad_lavc_conf;
extern const struct m_sub_options hwdec_conf;
extern const struct m_sub_options input_config;
extern const struct m_sub_options encode_config;
extern const struct m_sub_options ra_ctx_conf;
@@ -671,6 +672,8 @@ static const m_option_t mp_opts[] = {
{"", OPT_SUBSTRUCT(vd_lavc_params, vd_lavc_conf)},
{"ad-lavc", OPT_SUBSTRUCT(ad_lavc_params, ad_lavc_conf)},
{"", OPT_SUBSTRUCT(hwdec_opts, hwdec_conf)},
{"", OPT_SUBSTRUCT(demux_lavf, demux_lavf_conf)},
{"demuxer-rawaudio", OPT_SUBSTRUCT(demux_rawaudio, demux_rawaudio_conf)},
{"demuxer-rawvideo", OPT_SUBSTRUCT(demux_rawvideo, demux_rawvideo_conf)},
+2
View File
@@ -363,6 +363,8 @@ typedef struct MPOpts {
struct vd_lavc_params *vd_lavc_params;
struct ad_lavc_params *ad_lavc_params;
struct hwdec_opts *hwdec_opts;
struct input_opts *input_opts;
struct clipboard_opts *clipboard_opts;
+51 -26
View File
@@ -81,13 +81,8 @@ struct vd_lavc_params {
bool old_x264;
bool apply_cropping;
bool check_hw_profile;
int software_fallback;
char **avopts;
int dr;
char **hwdec_api;
char *hwdec_codecs;
int hwdec_image_format;
int hwdec_extra_frames;
};
static const struct m_opt_choice_alternatives discard_names[] = {
@@ -111,34 +106,61 @@ const struct m_sub_options vd_lavc_conf = {
{"vd-lavc-skipidct", OPT_DISCARD(skip_idct)},
{"vd-lavc-skipframe", OPT_DISCARD(skip_frame)},
{"vd-lavc-framedrop", OPT_DISCARD(framedrop)},
{"vd-lavc-threads", OPT_INT(threads), M_RANGE(0, DBL_MAX), .flags = UPDATE_VD},
{"vd-lavc-threads", OPT_INT(threads), M_RANGE(0, DBL_MAX)},
{"vd-lavc-bitexact", OPT_BOOL(bitexact)},
{"vd-lavc-assume-old-x264", OPT_BOOL(old_x264)},
{"vd-lavc-check-hw-profile", OPT_BOOL(check_hw_profile)},
{"vd-lavc-software-fallback", OPT_CHOICE(software_fallback,
{"no", INT_MAX}, {"yes", 1}), M_RANGE(1, INT_MAX)},
{"vd-lavc-o", OPT_KEYVALUELIST(avopts)},
{"vd-lavc-dr", OPT_CHOICE(dr,
{"auto", -1}, {"no", 0}, {"yes", 1})},
{"vd-apply-cropping", OPT_BOOL(apply_cropping)},
{"hwdec", OPT_STRINGLIST(hwdec_api),
.help = hwdec_opt_help,
.flags = M_OPT_OPTIONAL_PARAM | M_OPT_ALLOW_NO | UPDATE_HWDEC},
{"hwdec-codecs", OPT_STRING(hwdec_codecs)},
{"hwdec-image-format", OPT_IMAGEFORMAT(hwdec_image_format)},
{"hwdec-extra-frames", OPT_INT(hwdec_extra_frames), M_RANGE(0, 256)},
{0}
},
.change_flags = UPDATE_VD,
.size = sizeof(struct vd_lavc_params),
.defaults = &(const struct vd_lavc_params){
.film_grain = -1 /*auto*/,
.check_hw_profile = true,
.software_fallback = 3,
.skip_loop_filter = AVDISCARD_DEFAULT,
.skip_idct = AVDISCARD_DEFAULT,
.skip_frame = AVDISCARD_DEFAULT,
.framedrop = AVDISCARD_NONREF,
.dr = -1,
.apply_cropping = true,
},
};
#undef OPT_BASE_STRUCT
#define OPT_BASE_STRUCT struct hwdec_opts
struct hwdec_opts {
int software_fallback;
char **hwdec_api;
char *hwdec_codecs;
int hwdec_image_format;
int hwdec_extra_frames;
};
const struct m_sub_options hwdec_conf = {
.opts = (const m_option_t[]){
{"hwdec", OPT_STRINGLIST(hwdec_api),
.help = hwdec_opt_help,
.flags = M_OPT_OPTIONAL_PARAM | M_OPT_ALLOW_NO | UPDATE_HWDEC},
{"hwdec-codecs", OPT_STRING(hwdec_codecs),
.flags = UPDATE_HWDEC},
{"hwdec-extra-frames", OPT_INT(hwdec_extra_frames), M_RANGE(0, 256),
.flags = UPDATE_VD},
{"hwdec-image-format", OPT_IMAGEFORMAT(hwdec_image_format),
.flags = UPDATE_VO},
{"hwdec-software-fallback", OPT_CHOICE(software_fallback,
{"no", INT_MAX}, {"yes", 1}), M_RANGE(1, INT_MAX),
.flags = UPDATE_HWDEC},
{"vd-lavc-software-fallback", OPT_REPLACED("hwdec-software-fallback")},
{0}
},
.size = sizeof(struct hwdec_opts),
.defaults = &(const struct hwdec_opts){
.software_fallback = 3,
.hwdec_api = (char *[]){"no", NULL,},
.hwdec_codecs = "h264,vc1,hevc,vp8,vp9,av1,prores",
// Maximum number of surfaces the player wants to buffer. This number
@@ -146,7 +168,6 @@ const struct m_sub_options vd_lavc_conf = {
// for example, if vo_gpu increases the number of reference surfaces for
// interpolation, this value has to be increased too.
.hwdec_extra_frames = 6,
.apply_cropping = true,
},
};
@@ -170,6 +191,8 @@ typedef struct lavc_ctx {
struct mp_log *log;
struct m_config_cache *opts_cache;
struct vd_lavc_params *opts;
struct m_config_cache *hwdec_opts_cache;
struct hwdec_opts *hwdec_opts;
struct mp_codec_params *codec;
AVCodecContext *avctx;
AVFrame *pic;
@@ -418,7 +441,7 @@ static void add_all_hwdec_methods(struct hwdec_info **infos, int *num_infos)
static bool hwdec_codec_allowed(struct mp_filter *vd, const char *codec)
{
vd_ffmpeg_ctx *ctx = vd->priv;
bstr s = bstr0(ctx->opts->hwdec_codecs);
bstr s = bstr0(ctx->hwdec_opts->hwdec_codecs);
while (s.len) {
bstr item;
bstr_split_tok(s, ",", &item, &s);
@@ -473,13 +496,13 @@ static void select_and_set_hwdec(struct mp_filter *vd)
vd_ffmpeg_ctx *ctx = vd->priv;
const char *codec = ctx->codec->codec;
m_config_cache_update(ctx->opts_cache);
m_config_cache_update(ctx->hwdec_opts_cache);
struct hwdec_info *hwdecs = NULL;
int num_hwdecs = 0;
add_all_hwdec_methods(&hwdecs, &num_hwdecs);
char **hwdec_api = ctx->opts->hwdec_api;
char **hwdec_api = ctx->hwdec_opts->hwdec_api;
for (int i = 0; hwdec_api && hwdec_api[i]; i++) {
bstr opt = bstr0(hwdec_api[i]);
@@ -597,7 +620,7 @@ static void select_and_set_hwdec(struct mp_filter *vd)
} else {
// If software fallback is disabled and we get here, all hwdec must
// have failed. Tell the ctx to always force an eof.
if (ctx->opts->software_fallback == INT_MAX) {
if (ctx->hwdec_opts->software_fallback == INT_MAX) {
MP_WARN(ctx, "Software decoding fallback is disabled.\n");
ctx->force_eof = true;
} else {
@@ -905,13 +928,13 @@ static int init_generic_hwaccel(struct mp_filter *vd, enum AVPixelFormat hw_fmt)
AVHWFramesContext *new_fctx = (void *)new_frames_ctx->data;
if (ctx->opts->hwdec_image_format)
new_fctx->sw_format = imgfmt2pixfmt(ctx->opts->hwdec_image_format);
if (ctx->hwdec_opts->hwdec_image_format)
new_fctx->sw_format = imgfmt2pixfmt(ctx->hwdec_opts->hwdec_image_format);
// 1 surface is already included by libavcodec. The field is 0 if the
// hwaccel supports dynamic surface allocation.
if (new_fctx->initial_pool_size)
new_fctx->initial_pool_size += ctx->opts->hwdec_extra_frames - 1;
new_fctx->initial_pool_size += ctx->hwdec_opts->hwdec_extra_frames - 1;
const struct hwcontext_fns *fns =
hwdec_get_hwcontext_fns(new_fctx->device_ctx->type);
@@ -1112,14 +1135,14 @@ static void prepare_decoding(struct mp_filter *vd)
static void handle_err(struct mp_filter *vd)
{
vd_ffmpeg_ctx *ctx = vd->priv;
struct vd_lavc_params *opts = ctx->opts;
struct hwdec_opts *hwdec_opts = ctx->hwdec_opts;
MP_WARN(vd, "Error while decoding frame%s!\n",
ctx->use_hwdec ? " (hardware decoding)" : "");
if (ctx->use_hwdec) {
ctx->hwdec_fail_count += 1;
if (ctx->hwdec_fail_count >= opts->software_fallback)
if (ctx->hwdec_fail_count >= hwdec_opts->software_fallback)
ctx->hwdec_failed = true;
}
}
@@ -1150,7 +1173,7 @@ static int send_packet(struct mp_filter *vd, struct demux_packet *pkt)
return ret;
if (ctx->hw_probing && ctx->num_sent_packets < 32 &&
ctx->opts->software_fallback <= 32)
ctx->hwdec_opts->software_fallback <= 32)
{
pkt = pkt ? demux_copy_packet(pkt) : NULL;
MP_TARRAY_APPEND(ctx, ctx->sent_packets, ctx->num_sent_packets, pkt);
@@ -1406,6 +1429,8 @@ static struct mp_decoder *create(struct mp_filter *parent,
ctx->log = vd->log;
ctx->opts_cache = m_config_cache_alloc(ctx, vd->global, &vd_lavc_conf);
ctx->opts = ctx->opts_cache->opts;
ctx->hwdec_opts_cache = m_config_cache_alloc(ctx, vd->global, &hwdec_conf);
ctx->hwdec_opts = ctx->hwdec_opts_cache->opts;
ctx->codec = codec;
ctx->decoder = talloc_strdup(ctx, decoder);
ctx->hwdec_swpool = mp_image_pool_new(ctx);