summaryrefslogtreecommitdiffstats
path: root/filters/f_lavfi.c
diff options
context:
space:
mode:
authorPhilip Langdale <philipl@overt.org>2022-03-12 11:24:51 -0800
committerPhilip Langdale <github.philipl@overt.org>2022-09-21 09:39:34 -0700
commit989d873d6ec57171a55f432d6f87a9e5a61a706c (patch)
tree0077fcefc7be591eea5d6ad2e4e2373c8d59b49d /filters/f_lavfi.c
parent5629ed81eed90f95a04bb3d8ff64f135bd186651 (diff)
downloadmpv-989d873d6ec57171a55f432d6f87a9e5a61a706c.tar.bz2
mpv-989d873d6ec57171a55f432d6f87a9e5a61a706c.tar.xz
filters: lavfi: allow hwdec_interop selection for filters
Today, lavfi filters are provided a hw_device from the first hwdec_interop that was loaded, regardless of whether it's the right one or not. In most situations where a hardware based filter is used, we need more control over the device. In this change, a `hwdec_interop` option is added to the lavfi wrapper filter configuration and this is used to pick the correct hw_device to inject into the filter or graph (in the case of a graph, all filters get the same device). Note that this requires the use of the explicit lavfi syntax to allow for the extra configuration. eg: ``` mpv --vf=hwupload ``` becomes ``` mpv --vf=lavfi=[hwupload]:hwdec_interop=cuda-nvdec ``` or ``` mpv --vf=lavfi-bridge=[hwupload]:hwdec_interop=cuda-nvdec ```
Diffstat (limited to 'filters/f_lavfi.c')
-rw-r--r--filters/f_lavfi.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/filters/f_lavfi.c b/filters/f_lavfi.c
index ec6fb9f095..cbb3066430 100644
--- a/filters/f_lavfi.c
+++ b/filters/f_lavfi.c
@@ -47,6 +47,7 @@
#include "audio/fmt-conversion.h"
#include "video/fmt-conversion.h"
#include "video/hwdec.h"
+#include "video/out/gpu/hwdec.h"
#include "f_lavfi.h"
#include "filter.h"
@@ -98,6 +99,9 @@ struct lavfi {
double delay; // seconds of audio apparently buffered by filter
struct mp_lavfi public;
+
+ // Identify a specific hwdec_interop to use
+ char *hwdec_interop;
};
struct lavfi_pad {
@@ -548,11 +552,22 @@ static void init_graph(struct lavfi *c)
if (init_pads(c)) {
struct mp_stream_info *info = mp_filter_find_stream_info(c->f);
if (info && info->hwdec_devs) {
- struct mp_hwdec_ctx *hwdec = hwdec_devices_get_first(info->hwdec_devs);
- for (int n = 0; n < c->graph->nb_filters; n++) {
- AVFilterContext *filter = c->graph->filters[n];
- if (hwdec && hwdec->av_device_ref)
- filter->hw_device_ctx = av_buffer_ref(hwdec->av_device_ref);
+ struct mp_hwdec_ctx *hwdec_ctx = NULL;
+ if (c->hwdec_interop) {
+ int imgfmt =
+ ra_hwdec_driver_get_imgfmt_for_name(c->hwdec_interop);
+ hwdec_ctx = mp_filter_load_hwdec_device(c->f, imgfmt);
+ } else {
+ hwdec_ctx = hwdec_devices_get_first(info->hwdec_devs);
+ }
+ if (hwdec_ctx && hwdec_ctx->av_device_ref) {
+ MP_VERBOSE(c, "Configuring hwdec_interop=%s for filters\n",
+ hwdec_ctx->driver_name);
+ for (int n = 0; n < c->graph->nb_filters; n++) {
+ AVFilterContext *filter = c->graph->filters[n];
+ filter->hw_device_ctx =
+ av_buffer_ref(hwdec_ctx->av_device_ref);
+ }
}
}
@@ -886,6 +901,7 @@ error:
struct mp_lavfi *mp_lavfi_create_graph(struct mp_filter *parent,
enum mp_frame_type type, bool bidir,
+ char *hwdec_interop,
char **graph_opts, const char *graph)
{
struct lavfi *c = lavfi_alloc(parent);
@@ -896,12 +912,14 @@ struct mp_lavfi *mp_lavfi_create_graph(struct mp_filter *parent,
c->force_bidir = bidir;
c->graph_opts = mp_dup_str_array(c, graph_opts);
c->graph_string = talloc_strdup(c, graph);
+ c->hwdec_interop = talloc_strdup(c, hwdec_interop);
return do_init(c);
}
struct mp_lavfi *mp_lavfi_create_filter(struct mp_filter *parent,
enum mp_frame_type type, bool bidir,
+ char *hwdec_interop,
char **graph_opts,
const char *filter, char **filter_opts)
{
@@ -911,6 +929,7 @@ struct mp_lavfi *mp_lavfi_create_filter(struct mp_filter *parent,
c->force_type = type;
c->force_bidir = bidir;
+ c->hwdec_interop = talloc_strdup(c, hwdec_interop);
c->graph_opts = mp_dup_str_array(c, graph_opts);
c->graph_string = talloc_strdup(c, filter);
c->direct_filter_opts = mp_dup_str_array(c, filter_opts);
@@ -930,6 +949,8 @@ struct lavfi_user_opts {
char **filter_opts;
int fix_pts;
+
+ char *hwdec_interop;
};
static struct mp_filter *lavfi_create(struct mp_filter *parent, void *options)
@@ -937,10 +958,11 @@ static struct mp_filter *lavfi_create(struct mp_filter *parent, void *options)
struct lavfi_user_opts *opts = options;
struct mp_lavfi *l;
if (opts->is_bridge) {
- l = mp_lavfi_create_filter(parent, opts->type, true, opts->avopts,
+ l = mp_lavfi_create_filter(parent, opts->type, true,
+ opts->hwdec_interop, opts->avopts,
opts->filter_name, opts->filter_opts);
} else {
- l = mp_lavfi_create_graph(parent, opts->type, true,
+ l = mp_lavfi_create_graph(parent, opts->type, true, opts->hwdec_interop,
opts->avopts, opts->graph);
}
if (l) {
@@ -1101,6 +1123,9 @@ const struct mp_user_filter_entry af_lavfi = {
{"graph", OPT_STRING(graph)},
{"fix-pts", OPT_FLAG(fix_pts)},
{"o", OPT_KEYVALUELIST(avopts)},
+ {"hwdec_interop",
+ OPT_STRING_VALIDATE(hwdec_interop,
+ ra_hwdec_validate_drivers_only_opt)},
{0}
},
.priv_defaults = &(const OPT_BASE_STRUCT){
@@ -1120,6 +1145,9 @@ const struct mp_user_filter_entry af_lavfi_bridge = {
{"name", OPT_STRING(filter_name)},
{"opts", OPT_KEYVALUELIST(filter_opts)},
{"o", OPT_KEYVALUELIST(avopts)},
+ {"hwdec_interop",
+ OPT_STRING_VALIDATE(hwdec_interop,
+ ra_hwdec_validate_drivers_only_opt)},
{0}
},
.priv_defaults = &(const OPT_BASE_STRUCT){
@@ -1139,6 +1167,9 @@ const struct mp_user_filter_entry vf_lavfi = {
.options = (const m_option_t[]){
{"graph", OPT_STRING(graph)},
{"o", OPT_KEYVALUELIST(avopts)},
+ {"hwdec_interop",
+ OPT_STRING_VALIDATE(hwdec_interop,
+ ra_hwdec_validate_drivers_only_opt)},
{0}
},
.priv_defaults = &(const OPT_BASE_STRUCT){
@@ -1158,6 +1189,10 @@ const struct mp_user_filter_entry vf_lavfi_bridge = {
{"name", OPT_STRING(filter_name)},
{"opts", OPT_KEYVALUELIST(filter_opts)},
{"o", OPT_KEYVALUELIST(avopts)},
+ {"hwdec_interop",
+ OPT_STRING_VALIDATE(hwdec_interop,
+ ra_hwdec_validate_drivers_only_opt)},
+
{0}
},
.priv_defaults = &(const OPT_BASE_STRUCT){