summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-03-13 00:29:17 +0100
committerwm4 <wm4@nowhere>2014-03-13 00:29:17 +0100
commit3bc78a84cd776387fbbfe120cdfaa5b56d329c61 (patch)
treeda28a0812d81442532ba76fcd66adddded19456b
parent1a86322dcaed46cdae89c8a53ae3fbe8dbc85968 (diff)
downloadmpv-3bc78a84cd776387fbbfe120cdfaa5b56d329c61.tar.bz2
mpv-3bc78a84cd776387fbbfe120cdfaa5b56d329c61.tar.xz
af_lavfi: beat it into working with Libav
The main incompatibility was that Libav didn't have av_opt_set_int_list. But since that function is excessively ugly and idiotic (look how it handles types), I'm not missing it much. Use an aformat filter instead to handle the functionality that was indirectly provided by it. This is similar to how vf_lavfi works. The other incompatibility was channel handling. Libav consistently uses channel layouts only, why ffmpeg still requires messing with channel counts to some degree. Get rid of most channel count uses (and hope channel layouts are "exact" enough). Only in one case FFmpeg fails with a runtime check if we feed it AVFrames with channel count unset. Another issue were AVFrame accessor functions. FFmpeg introduced these for ABI compatibility with Libav. I refuse to use them, and it's not my problem if FFmpeg doesn't manage to provide a stable ABI for fields provided both by FFmpeg and Libav.
-rw-r--r--audio/filter/af_lavfi.c62
-rwxr-xr-xold-configure12
-rw-r--r--wscript8
3 files changed, 41 insertions, 41 deletions
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index eaec556dc7..4049e54021 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -53,6 +53,14 @@
avfilter_graph_parse(graph, filters, &(inputs), &(outputs), log_ctx)
#endif
+// ":" is deprecated, but "|" doesn't work in earlier versions.
+#if (IS_LIBAV_FORK && LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(3, 7, 0)) || \
+ (!IS_LIBAV_FORK && LIBAVFILTER_VERSION_INT >= AV_VERSION_INT(3, 50, 100))
+#define FMTSEP "|"
+#else
+#define FMTSEP ":"
+#endif
+
struct priv {
AVFilterGraph *graph;
AVFilterContext *in;
@@ -78,8 +86,7 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
{
void *tmp = talloc_new(NULL);
struct priv *p = af->priv;
- AVFilterContext *in = NULL, *out = NULL;
- int r;
+ AVFilterContext *in = NULL, *out = NULL, *f_format = NULL;
if (bstr0(p->cfg_graph).len == 0) {
MP_FATAL(af, "lavfi: no filter graph set\n");
@@ -104,12 +111,29 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
if (!outputs || !inputs)
goto error;
+ // Build list of acceptable output sample formats. libavfilter will insert
+ // conversion filters if needed.
+ static const enum AVSampleFormat sample_fmts[] = {
+ AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
+ AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL,
+ AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
+ AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
+ AV_SAMPLE_FMT_NONE
+ };
+ char *fmtstr = talloc_strdup(tmp, "");
+ for (int n = 0; sample_fmts[n] != AV_SAMPLE_FMT_NONE; n++) {
+ const char *name = av_get_sample_fmt_name(sample_fmts[n]);
+ if (name) {
+ const char *s = fmtstr[0] ? FMTSEP : "";
+ fmtstr = talloc_asprintf_append_buffer(fmtstr, "%s%s", s, name);
+ }
+ }
+
char *src_args = talloc_asprintf(tmp,
- "sample_rate=%d:sample_fmt=%s:channels=%d:time_base=%d/%d:"
+ "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:"
"channel_layout=0x%"PRIx64, config->rate,
av_get_sample_fmt_name(af_to_avformat(config->format)),
- config->channels.num, 1, config->rate,
- mp_chmap_to_lavc(&config->channels));
+ 1, config->rate, mp_chmap_to_lavc(&config->channels));
if (avfilter_graph_create_filter(&in, avfilter_get_by_name("abuffer"),
"src", src_args, NULL, graph) < 0)
@@ -119,27 +143,18 @@ static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
"out", NULL, NULL, graph) < 0)
goto error;
- static const enum AVSampleFormat sample_fmts[] = {
- AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
- AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL,
- AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
- AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
- AV_SAMPLE_FMT_NONE
- };
- r = av_opt_set_int_list(out, "sample_fmts", sample_fmts,
- AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
- if (r < 0)
+ if (avfilter_graph_create_filter(&f_format, avfilter_get_by_name("aformat"),
+ "format", fmtstr, NULL, graph) < 0)
goto error;
- r = av_opt_set_int(out, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN);
- if (r < 0)
+ if (avfilter_link(f_format, 0, out, 0) < 0)
goto error;
outputs->name = av_strdup("in");
outputs->filter_ctx = in;
inputs->name = av_strdup("out");
- inputs->filter_ctx = out;
+ inputs->filter_ctx = f_format;
if (graph_parse(graph, p->cfg_graph, inputs, outputs, NULL) < 0)
goto error;
@@ -191,8 +206,6 @@ static int control(struct af_instance *af, int cmd, void *arg)
struct mp_chmap out_cm;
mp_chmap_from_lavc(&out_cm, l_out->channel_layout);
- if (!out_cm.num || out_cm.num != l_out->channels)
- mp_chmap_from_channels(&out_cm, l_out->channels);
mp_audio_set_channels(out, &out_cm);
if (!mp_audio_config_valid(out))
@@ -223,9 +236,12 @@ static int filter(struct af_instance *af, struct mp_audio *data, int flags)
// Timebase is 1/sample_rate
frame->pts = p->samples_in;
- av_frame_set_channels(frame, l_in->channels);
- av_frame_set_channel_layout(frame, l_in->channel_layout);
- av_frame_set_sample_rate(frame, l_in->sample_rate);
+ frame->channel_layout = l_in->channel_layout;
+ frame->sample_rate = l_in->sample_rate;
+#if !IS_LIBAV_FORK
+ // FFmpeg being a stupid POS
+ frame->channels = l_in->channels;
+#endif
frame->extended_data = frame->data;
for (int n = 0; n < data->num_planes; n++)
diff --git a/old-configure b/old-configure
index 42897f3c15..06f9ee16e1 100755
--- a/old-configure
+++ b/old-configure
@@ -2831,21 +2831,11 @@ fi
echores "$vf_lavfi"
-echocheck "libavutil av_opt_set_int_list() API"
-_avutil_has_opt_set_int_list=no
-statement_check libavutil/opt.h 'av_opt_set_int_list(0,0,(int*)0,0,0)' && _avutil_has_opt_set_int_list=yes
-echores "$_avutil_has_opt_set_int_list"
-
-
echocheck "using libavfilter through af_lavfi"
if test "$af_lavfi" = auto ; then
af_lavfi=no
if test "$libavfilter" = yes ; then
- if test "$_avutil_has_opt_set_int_list" = no ; then
- res_comment="libavutil too old"
- else
- af_lavfi=yes
- fi
+ af_lavfi=yes
fi
fi
if test "$af_lavfi" = yes ; then
diff --git a/wscript b/wscript
index 3bfa395005..00bba48629 100644
--- a/wscript
+++ b/wscript
@@ -385,12 +385,6 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
'desc': 'libavutil ref-counting API',
'func': check_statement('libavutil/frame.h', 'av_frame_unref(NULL)',
use='libav'),
- } , {
- 'name': 'av-opt-set-int-list',
- 'desc': 'libavutil av_opt_set_int_list() API',
- 'func': check_statement('libavutil/opt.h',
- 'av_opt_set_int_list(0,0,(int*)0,0,0)',
- use='libav')
}, {
'name': '--libavfilter',
'desc': 'libavfilter',
@@ -406,7 +400,7 @@ Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
}, {
'name': '--af-lavfi',
'desc': 'using libavfilter through af_lavfi',
- 'deps': [ 'libavfilter', 'av-opt-set-int-list' ],
+ 'deps': [ 'libavfilter', 'avutil-refcounting' ],
'func': check_true
}, {
'name': '--libavdevice',