diff options
Diffstat (limited to 'filters/f_lavfi.c')
-rw-r--r-- | filters/f_lavfi.c | 128 |
1 files changed, 91 insertions, 37 deletions
diff --git a/filters/f_lavfi.c b/filters/f_lavfi.c index 71624a449b..afc9f2d445 100644 --- a/filters/f_lavfi.c +++ b/filters/f_lavfi.c @@ -32,6 +32,9 @@ #include <libavfilter/avfilter.h> #include <libavfilter/buffersink.h> #include <libavfilter/buffersrc.h> +#include <libplacebo/utils/libav.h> + +#include "config.h" #include "common/common.h" #include "common/av_common.h" @@ -40,10 +43,12 @@ #include "audio/format.h" #include "audio/aframe.h" +#include "audio/chmap_avchannel.h" #include "video/mp_image.h" #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" @@ -95,6 +100,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 { @@ -253,8 +261,7 @@ static void precreate_graph(struct lavfi *c, bool first_init) c->failed = false; c->graph = avfilter_graph_alloc(); - if (!c->graph) - abort(); + MP_HANDLE_OOM(c->graph); if (mp_set_avopts(c->log, c->graph, c->graph_opts) < 0) goto error; @@ -394,7 +401,7 @@ static bool init_pads(struct lavfi *c) } else if (pad->type == MP_FRAME_VIDEO) { dst_filter = avfilter_get_by_name("buffersink"); } else { - assert(0); + MP_ASSERT_UNREACHABLE(); } if (!dst_filter) @@ -470,7 +477,11 @@ static bool init_pads(struct lavfi *c) params->sample_rate = mp_aframe_get_rate(fmt); struct mp_chmap chmap = {0}; mp_aframe_get_chmap(fmt, &chmap); +#if !HAVE_AV_CHANNEL_LAYOUT params->channel_layout = mp_chmap_to_lavc(&chmap); +#else + mp_chmap_to_av_layout(¶ms->ch_layout, &chmap); +#endif pad->timebase = (AVRational){1, mp_aframe_get_rate(fmt)}; filter_name = "abuffer"; } else if (pad->type == MP_FRAME_VIDEO) { @@ -482,9 +493,13 @@ static bool init_pads(struct lavfi *c) params->sample_aspect_ratio.den = fmt->params.p_h; params->hw_frames_ctx = fmt->hwctx; params->frame_rate = av_d2q(fmt->nominal_fps, 1000000); +#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(9, 16, 100) + params->color_space = pl_system_to_av(fmt->params.repr.sys); + params->color_range = pl_levels_to_av(fmt->params.repr.levels); +#endif filter_name = "buffer"; } else { - assert(0); + MP_ASSERT_UNREACHABLE(); } params->time_base = pad->timebase; @@ -541,11 +556,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 filter graph: %s\n", + hwdec_ctx->driver_name, c->graph_string); + 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); + } } } @@ -793,7 +819,8 @@ static bool lavfi_command(struct mp_filter *f, struct mp_filter_command *cmd) switch (cmd->type) { case MP_FILTER_COMMAND_TEXT: { - return avfilter_graph_send_command(c->graph, "all", cmd->cmd, cmd->arg, + return avfilter_graph_send_command(c->graph, cmd->target, + cmd->cmd, cmd->arg, &(char){0}, 0, 0) >= 0; } case MP_FILTER_COMMAND_GET_META: { @@ -830,8 +857,7 @@ static struct lavfi *lavfi_alloc(struct mp_filter *parent) c->log = f->log; c->public.f = f; c->tmp_frame = av_frame_alloc(); - if (!c->tmp_frame) - abort(); + MP_HANDLE_OOM(c->tmp_frame); return c; } @@ -879,6 +905,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); @@ -889,12 +916,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) { @@ -904,6 +933,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); @@ -922,7 +952,9 @@ struct lavfi_user_opts { char *filter_name; char **filter_opts; - int fix_pts; + bool fix_pts; + + char *hwdec_interop; }; static struct mp_filter *lavfi_create(struct mp_filter *parent, void *options) @@ -930,10 +962,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) { @@ -944,19 +977,23 @@ static struct mp_filter *lavfi_create(struct mp_filter *parent, void *options) return l ? l->f : NULL; } -static bool is_single_media_only(const AVFilterPad *pads, int media_type) -{ - int count = avfilter_pad_count(pads); - if (count != 1) - return false; - return avfilter_pad_get_type(pads, 0) == media_type; -} - // Does it have exactly one video input and one video output? static bool is_usable(const AVFilter *filter, int media_type) { - return is_single_media_only(filter->inputs, media_type) && - is_single_media_only(filter->outputs, media_type); +#if LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(8, 3, 0) + int nb_inputs = avfilter_filter_pad_count(filter, 0), + nb_outputs = avfilter_filter_pad_count(filter, 1); +#else + int nb_inputs = avfilter_pad_count(filter->inputs), + nb_outputs = avfilter_pad_count(filter->outputs); +#endif + bool input_ok = filter->flags & AVFILTER_FLAG_DYNAMIC_INPUTS; + bool output_ok = filter->flags & AVFILTER_FLAG_DYNAMIC_OUTPUTS; + if (nb_inputs == 1) + input_ok = avfilter_pad_get_type(filter->inputs, 0) == media_type; + if (nb_outputs == 1) + output_ok = avfilter_pad_get_type(filter->outputs, 0) == media_type; + return input_ok && output_ok; } bool mp_lavfi_is_usable(const char *name, int media_type) @@ -997,7 +1034,11 @@ static const char *get_avopt_type_name(enum AVOptionType type) case AV_OPT_TYPE_VIDEO_RATE: return "fps"; case AV_OPT_TYPE_DURATION: return "duration"; case AV_OPT_TYPE_COLOR: return "color"; - case AV_OPT_TYPE_CHANNEL_LAYOUT: return "channellayout"; +#if LIBAVUTIL_VERSION_MAJOR < 59 + case AV_OPT_TYPE_CHANNEL_LAYOUT: return "ch_layout"; +#else + case AV_OPT_TYPE_CHLAYOUT: return "ch_layout"; +#endif case AV_OPT_TYPE_BOOL: return "bool"; case AV_OPT_TYPE_CONST: // fallthrough default: @@ -1091,9 +1132,12 @@ const struct mp_user_filter_entry af_lavfi = { .name = "lavfi", .priv_size = sizeof(OPT_BASE_STRUCT), .options = (const m_option_t[]){ - OPT_STRING("graph", graph, M_OPT_MIN, .min = 1), - OPT_FLAG("fix-pts", fix_pts, 0), - OPT_KEYVALUELIST("o", avopts, 0), + {"graph", OPT_STRING(graph)}, + {"fix-pts", OPT_BOOL(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){ @@ -1110,9 +1154,12 @@ const struct mp_user_filter_entry af_lavfi_bridge = { .name = "lavfi-bridge", .priv_size = sizeof(OPT_BASE_STRUCT), .options = (const m_option_t[]){ - OPT_STRING("name", filter_name, M_OPT_MIN, .min = 1), - OPT_KEYVALUELIST("opts", filter_opts, 0), - OPT_KEYVALUELIST("o", avopts, 0), + {"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){ @@ -1130,8 +1177,11 @@ const struct mp_user_filter_entry vf_lavfi = { .name = "lavfi", .priv_size = sizeof(OPT_BASE_STRUCT), .options = (const m_option_t[]){ - OPT_STRING("graph", graph, M_OPT_MIN, .min = 1), - OPT_KEYVALUELIST("o", avopts, 0), + {"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){ @@ -1148,9 +1198,13 @@ const struct mp_user_filter_entry vf_lavfi_bridge = { .name = "lavfi-bridge", .priv_size = sizeof(OPT_BASE_STRUCT), .options = (const m_option_t[]){ - OPT_STRING("name", filter_name, M_OPT_MIN, .min = 1), - OPT_KEYVALUELIST("opts", filter_opts, 0), - OPT_KEYVALUELIST("o", avopts, 0), + {"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){ |