diff options
Diffstat (limited to 'audio/filter')
-rw-r--r-- | audio/filter/af.c | 14 | ||||
-rw-r--r-- | audio/filter/af.h | 3 | ||||
-rw-r--r-- | audio/filter/af_lavfi.c | 46 | ||||
-rw-r--r-- | audio/filter/af_lavrresample.c | 45 | ||||
-rw-r--r-- | audio/filter/af_rubberband.c | 14 |
5 files changed, 82 insertions, 40 deletions
diff --git a/audio/filter/af.c b/audio/filter/af.c index 7ff3b49ae8..ac1b4926d8 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -59,9 +59,7 @@ static const struct af_info *const filter_list[] = { &af_info_rubberband, #endif &af_info_scaletempo, -#if HAVE_LIBAVFILTER &af_info_lavfi, -#endif NULL }; @@ -166,6 +164,7 @@ static struct af_instance *af_create(struct af_stream *s, char *name, .info = desc.p, .data = talloc_zero(af, struct mp_audio), .log = mp_log_new(af, s->log, name), + .opts = s->opts, .replaygain_data = s->replaygain_data, .out_pool = mp_audio_pool_create(af), }; @@ -695,6 +694,17 @@ int af_control_by_label(struct af_stream *s, int cmd, void *arg, bstr label) } } +int af_send_command(struct af_stream *s, char *label, char *cmd, char *arg) +{ + char *args[2] = {cmd, arg}; + if (strcmp(label, "all") == 0) { + af_control_all(s, AF_CONTROL_COMMAND, args); + return 0; + } else { + return af_control_by_label(s, AF_CONTROL_COMMAND, args, bstr0(label)); + } +} + // Used by filters to add a filtered frame to the output queue. // Ownership of frame is transferred from caller to the filter chain. void af_add_output_frame(struct af_instance *af, struct mp_audio *frame) diff --git a/audio/filter/af.h b/audio/filter/af.h index ba64379661..9c49081f66 100644 --- a/audio/filter/af.h +++ b/audio/filter/af.h @@ -53,6 +53,7 @@ struct af_info { struct af_instance { const struct af_info *info; struct mp_log *log; + struct MPOpts *opts; struct replaygain_data *replaygain_data; int (*control)(struct af_instance *af, int cmd, void *arg); void (*uninit)(struct af_instance *af); @@ -123,6 +124,7 @@ enum af_control { AF_CONTROL_SET_PLAYBACK_SPEED, AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE, AF_CONTROL_GET_METADATA, + AF_CONTROL_COMMAND, }; // Argument for AF_CONTROL_SET_PAN_LEVEL @@ -143,6 +145,7 @@ struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg); void af_control_all(struct af_stream *s, int cmd, void *arg); int af_control_by_label(struct af_stream *s, int cmd, void *arg, bstr label); void af_seek_reset(struct af_stream *s); +int af_send_command(struct af_stream *s, char *label, char *cmd, char *arg); void af_add_output_frame(struct af_instance *af, struct mp_audio *frame); int af_filter_frame(struct af_stream *s, struct mp_audio *frame); diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c index af521abd9c..bc4a687487 100644 --- a/audio/filter/af_lavfi.c +++ b/audio/filter/af_lavfi.c @@ -3,18 +3,18 @@ * * Filter graph creation code taken from FFmpeg ffplay.c (LGPL 2.1 or later) * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> @@ -50,6 +50,7 @@ #if LIBAVFILTER_VERSION_MICRO < 100 #define graph_parse(graph, filters, inputs, outputs, log_ctx) \ avfilter_graph_parse(graph, filters, inputs, outputs, log_ctx) +#define avfilter_graph_send_command(a, b, c, d, e, f, g) -1 #else #define graph_parse(graph, filters, inputs, outputs, log_ctx) \ avfilter_graph_parse_ptr(graph, filters, &(inputs), &(outputs), log_ctx) @@ -222,6 +223,14 @@ static int control(struct af_instance *af, int cmd, void *arg) return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE; } + case AF_CONTROL_COMMAND: { + if (!p->graph) + break; + char **args = arg; + return avfilter_graph_send_command(p->graph, "all", + args[0], args[1], &(char){0}, 0, 0) + >= 0 ? CONTROL_OK : CONTROL_ERROR; + } case AF_CONTROL_GET_METADATA: if (p->metadata) { *(struct mp_tags *)arg = *p->metadata; @@ -257,32 +266,15 @@ static int filter_frame(struct af_instance *af, struct mp_audio *data) if (!p->graph) goto error; - AVFilterLink *l_in = p->in->outputs[0]; - if (data) { - frame = av_frame_alloc(); + frame = mp_audio_to_avframe_and_unref(data); + data = NULL; if (!frame) goto error; - frame->nb_samples = data->samples; - frame->format = l_in->format; - // Timebase is 1/sample_rate frame->pts = p->samples_in; - - frame->channel_layout = l_in->channel_layout; - frame->sample_rate = l_in->sample_rate; -#if LIBAVFILTER_VERSION_MICRO >= 100 - // 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++) - frame->data[n] = data->planes[n]; - frame->linesize[0] = frame->nb_samples * data->sstride; - - p->samples_in += data->samples; + p->samples_in += frame->nb_samples; } if (av_buffersrc_add_frame(p->in, frame) < 0) diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c index f7f448cad0..6fbb445563 100644 --- a/audio/filter/af_lavrresample.c +++ b/audio/filter/af_lavrresample.c @@ -179,6 +179,37 @@ bool af_lavrresample_test_conversion(int src_format, int dst_format) check_output_conversion(dst_format) != AV_SAMPLE_FMT_NONE; } +static struct mp_chmap fudge_pairs[][2] = { + {MP_CHMAP2(BL, BR), MP_CHMAP2(SL, SR)}, + {MP_CHMAP2(SL, SR), MP_CHMAP2(BL, BR)}, + {MP_CHMAP2(SDL, SDR), MP_CHMAP2(SL, SR)}, + {MP_CHMAP2(SL, SR), MP_CHMAP2(SDL, SDR)}, +}; + +// Modify out_layout and return the new value. The intention is reducing the +// loss libswresample's rematrixing will cause by exchanging similar, but +// strictly speaking incompatible channel pairs. For example, 7.1 should be +// changed to 7.1(wide) without dropping the SL/SR channels. (We still leave +// it to libswresample to create the remix matrix.) +static uint64_t fudge_layout_conversion(struct af_instance *af, + uint64_t in, uint64_t out) +{ + for (int n = 0; n < MP_ARRAY_SIZE(fudge_pairs); n++) { + uint64_t a = mp_chmap_to_lavc(&fudge_pairs[n][0]); + uint64_t b = mp_chmap_to_lavc(&fudge_pairs[n][1]); + if ((in & a) == a && (in & b) == 0 && + (out & a) == 0 && (out & b) == b) + { + out = (out & ~b) | a; + + MP_VERBOSE(af, "Fudge: %s -> %s\n", + mp_chmap_to_str(&fudge_pairs[n][0]), + mp_chmap_to_str(&fudge_pairs[n][1])); + } + } + return out; +} + // mp_chmap_get_reorder() performs: // to->speaker[n] = from->speaker[src[n]] // but libavresample does: @@ -230,10 +261,13 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in, av_opt_set_double(s->avrctx, "cutoff", s->opts.cutoff, 0); + int normalize = s->opts.normalize; + if (normalize < 0) + normalize = af->opts->audio_normalize; #if HAVE_LIBSWRESAMPLE - av_opt_set_double(s->avrctx, "rematrix_maxval", s->opts.normalize ? 1 : 1000, 0); + av_opt_set_double(s->avrctx, "rematrix_maxval", normalize ? 1 : 1000, 0); #else - av_opt_set_int(s->avrctx, "normalize_mix_level", s->opts.normalize, 0); + av_opt_set_int(s->avrctx, "normalize_mix_level", !!normalize, 0); #endif if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0) @@ -297,6 +331,8 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in, if (map_out.num > out_lavc.num) mp_audio_set_channels(&s->pool_fmt, &map_out); + out_ch_layout = fudge_layout_conversion(af, in_ch_layout, out_ch_layout); + // Real conversion; output is input to avrctx_out. av_opt_set_int(s->avrctx, "in_channel_layout", in_ch_layout, 0); av_opt_set_int(s->avrctx, "out_channel_layout", out_ch_layout, 0); @@ -583,7 +619,7 @@ const struct af_info af_info_lavrresample = { .filter_size = 16, .cutoff = 0.0, .phase_shift = 10, - .normalize = 1, + .normalize = -1, }, .playback_speed = 1.0, .allow_detach = 1, @@ -594,7 +630,8 @@ const struct af_info af_info_lavrresample = { OPT_FLAG("linear", opts.linear, 0), OPT_DOUBLE("cutoff", opts.cutoff, M_OPT_RANGE, .min = 0, .max = 1), OPT_FLAG("detach", allow_detach, 0), - OPT_FLAG("normalize", opts.normalize, 0), + OPT_CHOICE("normalize", opts.normalize, 0, + ({"no", 0}, {"yes", 1}, {"auto", -1})), OPT_KEYVALUELIST("o", avopts, 0), {0} }, diff --git a/audio/filter/af_rubberband.c b/audio/filter/af_rubberband.c index 2619e4b210..48bb510679 100644 --- a/audio/filter/af_rubberband.c +++ b/audio/filter/af_rubberband.c @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> |