summaryrefslogtreecommitdiffstats
path: root/filters/f_lavfi.c
diff options
context:
space:
mode:
Diffstat (limited to 'filters/f_lavfi.c')
-rw-r--r--filters/f_lavfi.c128
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(&params->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){