diff options
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/vd_lavc.c | 157 |
1 files changed, 81 insertions, 76 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index a39a37aad3..d8dc3daa73 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -84,7 +84,7 @@ struct vd_lavc_params { int software_fallback; char **avopts; int dr; - char *hwdec_api; + char **hwdec_api; char *hwdec_codecs; int hwdec_image_format; int hwdec_extra_frames; @@ -101,6 +101,8 @@ static const struct m_opt_choice_alternatives discard_names[] = { }; #define OPT_DISCARD(field) OPT_CHOICE_C(field, discard_names) +static char *default_hwdec_api[] = { "no", NULL, }; + const struct m_sub_options vd_lavc_conf = { .opts = (const m_option_t[]){ {"vd-lavc-fast", OPT_BOOL(fast)}, @@ -120,7 +122,7 @@ const struct m_sub_options vd_lavc_conf = { {"vd-lavc-o", OPT_KEYVALUELIST(avopts)}, {"vd-lavc-dr", OPT_CHOICE(dr, {"auto", -1}, {"no", 0}, {"yes", 1})}, - {"hwdec", OPT_STRING(hwdec_api), + {"hwdec", OPT_STRINGLIST(hwdec_api), .help = hwdec_opt_help, .flags = M_OPT_OPTIONAL_PARAM | UPDATE_HWDEC}, {"hwdec-codecs", OPT_STRING(hwdec_codecs)}, @@ -138,7 +140,7 @@ const struct m_sub_options vd_lavc_conf = { .skip_frame = AVDISCARD_DEFAULT, .framedrop = AVDISCARD_NONREF, .dr = -1, - .hwdec_api = "no", + .hwdec_api = default_hwdec_api, .hwdec_codecs = "h264,vc1,hevc,vp8,vp9,av1,prores", // Maximum number of surfaces the player wants to buffer. This number // might require adjustment depending on whatever the player does; @@ -465,94 +467,97 @@ static void select_and_set_hwdec(struct mp_filter *vd) m_config_cache_update(ctx->opts_cache); - bstr opt = bstr0(ctx->opts->hwdec_api); - - bool hwdec_requested = !bstr_equals0(opt, "no"); - bool hwdec_auto_all = bstr_equals0(opt, "auto") || - bstr_equals0(opt, "yes") || - bstr_equals0(opt, ""); - bool hwdec_auto_safe = bstr_equals0(opt, "auto-safe") || - bstr_equals0(opt, "auto-copy-safe"); - bool hwdec_auto_copy = bstr_equals0(opt, "auto-copy") || - bstr_equals0(opt, "auto-copy-safe"); - bool hwdec_auto = hwdec_auto_all || hwdec_auto_copy || hwdec_auto_safe; - - if (!hwdec_requested) { - MP_VERBOSE(vd, "No hardware decoding requested.\n"); - } else if (!hwdec_codec_allowed(vd, codec)) { - MP_VERBOSE(vd, "Not trying to use hardware decoding: codec %s is not " - "on whitelist.\n", codec); - } else { - bool hwdec_name_supported = false; // relevant only if !hwdec_auto - struct hwdec_info *hwdecs = NULL; - int num_hwdecs = 0; - add_all_hwdec_methods(&hwdecs, &num_hwdecs); - - for (int n = 0; n < num_hwdecs; n++) { - struct hwdec_info *hwdec = &hwdecs[n]; + struct hwdec_info *hwdecs = NULL; + int num_hwdecs = 0; + add_all_hwdec_methods(&hwdecs, &num_hwdecs); - if (!hwdec_auto && !(bstr_equals0(opt, hwdec->method_name) || - bstr_equals0(opt, hwdec->name))) - continue; - hwdec_name_supported = true; + char **hwdec_api = ctx->opts->hwdec_api; + for (int i = 0; hwdec_api[i]; i++) { + bstr opt = bstr0(hwdec_api[i]); + + bool hwdec_requested = !bstr_equals0(opt, "no"); + bool hwdec_auto_all = bstr_equals0(opt, "auto") || + bstr_equals0(opt, "yes") || + bstr_equals0(opt, ""); + bool hwdec_auto_safe = bstr_equals0(opt, "auto-safe") || + bstr_equals0(opt, "auto-copy-safe"); + bool hwdec_auto_copy = bstr_equals0(opt, "auto-copy") || + bstr_equals0(opt, "auto-copy-safe"); + bool hwdec_auto = hwdec_auto_all || hwdec_auto_copy || hwdec_auto_safe; + + if (!hwdec_requested) { + MP_VERBOSE(vd, "No hardware decoding requested.\n"); + break; + } else if (!hwdec_codec_allowed(vd, codec)) { + MP_VERBOSE(vd, "Not trying to use hardware decoding: codec %s is not " + "on whitelist.\n", codec); + break; + } else { + bool hwdec_name_supported = false; // relevant only if !hwdec_auto + for (int n = 0; n < num_hwdecs; n++) { + struct hwdec_info *hwdec = &hwdecs[n]; - const char *hw_codec = mp_codec_from_av_codec_id(hwdec->codec->id); - if (!hw_codec || strcmp(hw_codec, codec) != 0) - continue; + if (!hwdec_auto && !(bstr_equals0(opt, hwdec->method_name) || + bstr_equals0(opt, hwdec->name))) + continue; + hwdec_name_supported = true; - if (hwdec_auto_safe && !(hwdec->flags & HWDEC_FLAG_WHITELIST)) - continue; + const char *hw_codec = mp_codec_from_av_codec_id(hwdec->codec->id); + if (!hw_codec || strcmp(hw_codec, codec) != 0) + continue; - MP_VERBOSE(vd, "Looking at hwdec %s...\n", hwdec->name); + if (hwdec_auto_safe && !(hwdec->flags & HWDEC_FLAG_WHITELIST)) + continue; - if (hwdec_auto_copy && !hwdec->copying) { - MP_VERBOSE(vd, "Not using this for auto-copy.\n"); - continue; - } + MP_VERBOSE(vd, "Looking at hwdec %s...\n", hwdec->name); - if (hwdec->lavc_device) { - ctx->hwdec_dev = hwdec_create_dev(vd, hwdec, hwdec_auto); - if (!ctx->hwdec_dev) { - MP_VERBOSE(vd, "Could not create device.\n"); + if (hwdec_auto_copy && !hwdec->copying) { + MP_VERBOSE(vd, "Not using this for auto-copy.\n"); continue; } - const struct hwcontext_fns *fns = - hwdec_get_hwcontext_fns(hwdec->lavc_device); - if (fns && fns->is_emulated && fns->is_emulated(ctx->hwdec_dev)) { - if (hwdec_auto) { - MP_VERBOSE(vd, "Not using emulated API.\n"); - av_buffer_unref(&ctx->hwdec_dev); + if (hwdec->lavc_device) { + ctx->hwdec_dev = hwdec_create_dev(vd, hwdec, hwdec_auto); + if (!ctx->hwdec_dev) { + MP_VERBOSE(vd, "Could not create device.\n"); continue; } - MP_WARN(vd, "Using emulated hardware decoding API.\n"); - } - } else if (!hwdec->copying) { - // Most likely METHOD_INTERNAL, which often use delay-loaded - // VO support as well. - if (ctx->hwdec_devs) { - struct hwdec_imgfmt_request params = { - .imgfmt = pixfmt2imgfmt(hwdec->pix_fmt), - .probing = hwdec_auto, - }; - hwdec_devices_request_for_img_fmt( - ctx->hwdec_devs, ¶ms); - } - } - ctx->use_hwdec = true; - ctx->hwdec = *hwdec; - break; - } - - talloc_free(hwdecs); + const struct hwcontext_fns *fns = + hwdec_get_hwcontext_fns(hwdec->lavc_device); + if (fns && fns->is_emulated && fns->is_emulated(ctx->hwdec_dev)) { + if (hwdec_auto) { + MP_VERBOSE(vd, "Not using emulated API.\n"); + av_buffer_unref(&ctx->hwdec_dev); + continue; + } + MP_WARN(vd, "Using emulated hardware decoding API.\n"); + } + } else if (!hwdec->copying) { + // Most likely METHOD_INTERNAL, which often use delay-loaded + // VO support as well. + if (ctx->hwdec_devs) { + struct hwdec_imgfmt_request params = { + .imgfmt = pixfmt2imgfmt(hwdec->pix_fmt), + .probing = hwdec_auto, + }; + hwdec_devices_request_for_img_fmt( + ctx->hwdec_devs, ¶ms); + } + } - if (!ctx->use_hwdec) { - if (!hwdec_auto && !hwdec_name_supported) - MP_WARN(vd, "Unsupported hwdec: %s\n", ctx->opts->hwdec_api); - MP_VERBOSE(vd, "No hardware decoding available for this codec.\n"); + ctx->use_hwdec = true; + ctx->hwdec = *hwdec; + break; + } + if (ctx->use_hwdec) + break; + else if (!hwdec_auto && !hwdec_name_supported) + MP_WARN(vd, "Unsupported hwdec: %.*s\n", BSTR_P(opt)); } } + talloc_free(hwdecs); + if (ctx->use_hwdec) { MP_VERBOSE(vd, "Trying hardware decoding via %s.\n", ctx->hwdec.name); |