summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-04-04 14:57:00 +0200
committerwm4 <wm4@nowhere>2017-04-04 14:57:00 +0200
commit98f8c4f36de0f08fec649aab16358190bf8d41b8 (patch)
tree81fcca695155a0e508a4f73a9a949cda651d20f8 /audio
parentd018028fdb4710f18b7babf5f68ea0e89e0f7bd9 (diff)
downloadmpv-98f8c4f36de0f08fec649aab16358190bf8d41b8.tar.bz2
mpv-98f8c4f36de0f08fec649aab16358190bf8d41b8.tar.xz
af: implement generic lavfi option bridge too
Literally copy-pasted from the same commit for video filters. (Once new code for filters is implemented, this will all go away or at least get unified anyway.)
Diffstat (limited to 'audio')
-rw-r--r--audio/filter/af.c27
-rw-r--r--audio/filter/af_lavfi.c82
2 files changed, 99 insertions, 10 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c
index 84ee377136..189c12b875 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -41,6 +41,7 @@ extern const struct af_info af_info_lavrresample;
extern const struct af_info af_info_scaletempo;
extern const struct af_info af_info_bs2b;
extern const struct af_info af_info_lavfi;
+extern const struct af_info af_info_lavfi_bridge;
extern const struct af_info af_info_rubberband;
static const struct af_info *const filter_list[] = {
@@ -56,6 +57,7 @@ static const struct af_info *const filter_list[] = {
#endif
&af_info_scaletempo,
&af_info_lavfi,
+ &af_info_lavfi_bridge,
NULL
};
@@ -79,6 +81,7 @@ const struct m_obj_list af_obj_list = {
.get_desc = get_desc,
.description = "audio filters",
.allow_disable_entries = true,
+ .allow_unknown_entries = true,
.aliases = {
{"force", "format"},
{0}
@@ -149,10 +152,17 @@ contain the commandline parameters for the filter */
static struct af_instance *af_create(struct af_stream *s, char *name,
char **args)
{
+ const char *lavfi_name = NULL;
+ char **lavfi_args = NULL;
struct m_obj_desc desc;
if (!m_obj_list_find(&desc, &af_obj_list, bstr0(name))) {
- MP_ERR(s, "Couldn't find audio filter '%s'.\n", name);
- return NULL;
+ if (!m_obj_list_find(&desc, &af_obj_list, bstr0("lavfi-bridge"))) {
+ MP_ERR(s, "Couldn't find audio filter '%s'.\n", name);
+ return NULL;
+ }
+ lavfi_name = name;
+ lavfi_args = args;
+ args = NULL;
}
MP_VERBOSE(s, "Adding filter %s \n", name);
@@ -170,6 +180,19 @@ static struct af_instance *af_create(struct af_stream *s, char *name,
name, s->opts->af_defs, args);
if (!config)
goto error;
+ if (lavfi_name) {
+ // Pass the filter arguments as proper sub-options to the bridge filter.
+ struct m_config_option *name_opt = m_config_get_co(config, bstr0("name"));
+ assert(name_opt);
+ assert(name_opt->opt->type == &m_option_type_string);
+ if (m_config_set_option_raw(config, name_opt, &lavfi_name, 0) < 0)
+ goto error;
+ struct m_config_option *opts = m_config_get_co(config, bstr0("opts"));
+ assert(opts);
+ assert(opts->opt->type == &m_option_type_keyvalue_list);
+ if (m_config_set_option_raw(config, opts, &lavfi_args, 0) < 0)
+ goto error;
+ }
af->priv = config->optstruct;
// Initialize the new filter
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index 6c371b7315..4c914a9fde 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -57,6 +57,9 @@
#endif
struct priv {
+ // Single filter bridge, instead of a graph.
+ bool is_bridge;
+
AVFilterGraph *graph;
AVFilterContext *in;
AVFilterContext *out;
@@ -72,6 +75,8 @@ struct priv {
// options
char *cfg_graph;
char **cfg_avopts;
+ char *cfg_filter_name;
+ char **cfg_filter_opts;
};
static void destroy_graph(struct af_instance *af)
@@ -89,13 +94,12 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
struct priv *p = af->priv;
AVFilterContext *in = NULL, *out = NULL;
- if (bstr0(p->cfg_graph).len == 0) {
+ if (!p->is_bridge && bstr0(p->cfg_graph).len == 0) {
MP_FATAL(af, "lavfi: no filter graph set\n");
return false;
}
destroy_graph(af);
- MP_VERBOSE(af, "lavfi: create graph: '%s'\n", p->cfg_graph);
AVFilterGraph *graph = avfilter_graph_alloc();
if (!graph)
@@ -123,14 +127,46 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
"out", NULL, NULL, graph) < 0)
goto error;
- outputs->name = av_strdup("in");
- outputs->filter_ctx = in;
+ if (p->is_bridge) {
+ AVFilterContext *filter = avfilter_graph_alloc_filter(graph,
+ avfilter_get_by_name(p->cfg_filter_name), "filter");
+ if (!filter)
+ goto error;
- inputs->name = av_strdup("out");
- inputs->filter_ctx = out;
+ if (mp_set_avopts(af->log, filter->priv, p->cfg_filter_opts) < 0)
+ goto error;
- if (graph_parse(graph, p->cfg_graph, inputs, outputs, NULL) < 0)
- goto error;
+ if (avfilter_init_str(filter, NULL) < 0)
+ goto error;
+
+ // Yep, we have to manually link those filters.
+ if (filter->nb_inputs != 1 ||
+ avfilter_pad_get_type(filter->input_pads, 0) != AVMEDIA_TYPE_AUDIO ||
+ filter->nb_outputs != 1 ||
+ avfilter_pad_get_type(filter->output_pads, 0) != AVMEDIA_TYPE_AUDIO)
+ {
+ MP_ERR(af, "The filter is required to have 1 audio input pad and "
+ "1 audio output pad.\n");
+ goto error;
+ }
+ if (avfilter_link(in, 0, filter, 0) < 0 ||
+ avfilter_link(filter, 0, out, 0) < 0)
+ {
+ MP_ERR(af, "Failed to link filter.\n");
+ goto error;
+ }
+ } else {
+ MP_VERBOSE(af, "lavfi: create graph: '%s'\n", p->cfg_graph);
+
+ outputs->name = av_strdup("in");
+ outputs->filter_ctx = in;
+
+ inputs->name = av_strdup("out");
+ inputs->filter_ctx = out;
+
+ if (graph_parse(graph, p->cfg_graph, inputs, outputs, NULL) < 0)
+ goto error;
+ }
if (avfilter_graph_config(graph, NULL) < 0)
goto error;
@@ -322,10 +358,23 @@ static void uninit(struct af_instance *af)
static int af_open(struct af_instance *af)
{
+ struct priv *p = af->priv;
+
af->control = control;
af->uninit = uninit;
af->filter_frame = filter_frame;
af->filter_out = filter_out;
+
+ if (p->is_bridge) {
+ if (!p->cfg_filter_name) {
+ MP_ERR(af, "Filter name not set!\n");
+ return 0;
+ }
+ if (!avfilter_get_by_name(p->cfg_filter_name)) {
+ MP_ERR(af, "libavfilter filter '%s' not found!\n", p->cfg_filter_name);
+ return 0;
+ }
+ }
return AF_OK;
}
@@ -342,3 +391,20 @@ const struct af_info af_info_lavfi = {
{0}
},
};
+
+const struct af_info af_info_lavfi_bridge = {
+ .info = "libavfilter bridge (explicit options)",
+ .name = "lavfi-bridge",
+ .open = af_open,
+ .priv_size = sizeof(struct priv),
+ .priv_defaults = &(const struct priv){
+ .is_bridge = true,
+ },
+ .options = (const struct m_option[]) {
+ OPT_STRING("name", cfg_filter_name, M_OPT_MIN, .min = 1),
+ OPT_KEYVALUELIST("opts", cfg_filter_opts, 0),
+ OPT_STRING("graph", cfg_graph, 0),
+ OPT_KEYVALUELIST("o", cfg_avopts, 0),
+ {0}
+ },
+};