diff options
author | wm4 <wm4@nowhere> | 2014-03-13 00:29:17 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-03-13 00:29:17 +0100 |
commit | 3bc78a84cd776387fbbfe120cdfaa5b56d329c61 (patch) | |
tree | da28a0812d81442532ba76fcd66adddded19456b | |
parent | 1a86322dcaed46cdae89c8a53ae3fbe8dbc85968 (diff) | |
download | mpv-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.c | 62 | ||||
-rwxr-xr-x | old-configure | 12 | ||||
-rw-r--r-- | wscript | 8 |
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 @@ -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', |