From d9582ad0a41ed5452ad29bf8511e8c6a3bdbe6f8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 9 May 2013 12:09:23 +0200 Subject: audio/filters: add af_force Its main purpose is for testing in case channel layout stuff breaks, in particular in connection with old audio filters. --- audio/audio.c | 6 ++ audio/audio.h | 1 + audio/filter/af.c | 2 + audio/filter/af_force.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+) create mode 100644 audio/filter/af_force.c (limited to 'audio') diff --git a/audio/audio.c b/audio/audio.c index 248f16790f..8af6a20a1f 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -56,6 +56,12 @@ void mp_audio_copy_config(struct mp_audio *dst, const struct mp_audio *src) dst->rate = src->rate; } +bool mp_audio_config_equals(const struct mp_audio *a, const struct mp_audio *b) +{ + return a->format == b->format && a->rate == b->rate && + mp_chmap_equals(&a->channels, &b->channels); +} + char *mp_audio_fmt_to_str(int srate, const struct mp_chmap *chmap, int format) { char *chstr = mp_chmap_to_str(chmap); diff --git a/audio/audio.h b/audio/audio.h index 6e0a1cb4b1..de35e697c8 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -38,6 +38,7 @@ void mp_audio_set_num_channels(struct mp_audio *mpa, int num_channels); void mp_audio_set_channels_old(struct mp_audio *mpa, int num_channels); void mp_audio_set_channels(struct mp_audio *mpa, const struct mp_chmap *chmap); void mp_audio_copy_config(struct mp_audio *dst, const struct mp_audio *src); +bool mp_audio_config_equals(const struct mp_audio *a, const struct mp_audio *b); char *mp_audio_fmt_to_str(int srate, const struct mp_chmap *chmap, int format); char *mp_audio_config_to_str(struct mp_audio *mpa); diff --git a/audio/filter/af.c b/audio/filter/af.c index 7dacafcc08..77df3e443b 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -29,6 +29,7 @@ extern struct af_info af_info_dummy; extern struct af_info af_info_delay; extern struct af_info af_info_channels; extern struct af_info af_info_format; +extern struct af_info af_info_force; extern struct af_info af_info_volume; extern struct af_info af_info_equalizer; extern struct af_info af_info_pan; @@ -52,6 +53,7 @@ static struct af_info* filter_list[] = { &af_info_dummy, &af_info_delay, &af_info_channels, + &af_info_force, &af_info_volume, &af_info_equalizer, &af_info_pan, diff --git a/audio/filter/af_force.c b/audio/filter/af_force.c new file mode 100644 index 0000000000..51fe83d0f0 --- /dev/null +++ b/audio/filter/af_force.c @@ -0,0 +1,146 @@ +/* + * 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 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. + * + * You should have received a copy of the GNU General Public License along + * with mpv. If not, see . + */ + +#include + +#include + +#include "core/m_config.h" +#include "core/m_option.h" + +#include "audio/format.h" +#include "af.h" + +struct priv { + struct m_config *config; + + int in_format; + int in_srate; + struct mp_chmap in_channels; + int out_format; + int out_srate; + struct mp_chmap out_channels; + + struct mp_audio data; + struct mp_audio temp; +}; + +static const struct priv defaults = { + .in_format = AF_FORMAT_UNKNOWN, + .out_format = AF_FORMAT_UNKNOWN, +}; + +#define OPT_BASE_STRUCT struct priv + +static const struct m_option options[] = { + OPT_AUDIOFORMAT("format", in_format, 0), + OPT_INTRANGE("srate", in_srate, 0, 1000, 8*48000), + OPT_CHMAP("channels", in_channels, CONF_MIN, .min = 0), + OPT_AUDIOFORMAT("out-format", out_format, 0), + OPT_INTRANGE("out-srate", out_srate, 0, 1000, 8*48000), + OPT_CHMAP("out-channels", out_channels, CONF_MIN, .min = 0), + {0} +}; + +static int control(struct af_instance *af, int cmd, void *arg) +{ + struct priv *priv = af->setup; + + switch (cmd) { + case AF_CONTROL_REINIT: { + struct mp_audio *in = arg; + struct mp_audio orig_in = *in; + struct mp_audio *out = af->data; + + if (priv->in_format != AF_FORMAT_UNKNOWN) + mp_audio_set_format(in, priv->in_format); + + if (priv->in_channels.num) + mp_audio_set_channels(in, &priv->in_channels); + + if (priv->in_srate) + in->rate = priv->in_srate; + + mp_audio_copy_config(out, in); + + if (priv->out_format != AF_FORMAT_UNKNOWN) + mp_audio_set_format(out, priv->out_format); + + if (priv->out_channels.num) + mp_audio_set_channels(out, &priv->out_channels); + + if (priv->out_srate) + out->rate = priv->out_srate; + + if (in->nch != out->nch || in->bps != out->bps) { + mp_msg(MSGT_AFILTER, MSGL_ERR, + "[af_force] Forced input/output format are incompatible.\n"); + return AF_ERROR; + } + + return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE; + } + case AF_CONTROL_COMMAND_LINE: { + if (m_config_parse_suboptions(priv->config, "af_force", (char *)arg) < 0) + return AF_ERROR; + return AF_OK; + } + } + return AF_UNKNOWN; +} + +static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) +{ + struct priv *priv = af->setup; + struct mp_audio *r = &priv->temp; + + *r = *af->data; + r->audio = data->audio; + r->len = data->len; + + return r; +} + +static void uninit(struct af_instance *af) +{ + talloc_free(af->setup); +} + +static int af_open(struct af_instance *af) +{ + af->control = control; + af->uninit = uninit; + af->play = play; + af->mul = 1; + struct priv *priv = talloc(NULL, struct priv); + af->setup = priv; + *priv = defaults; + priv->config = m_config_simple(priv); + talloc_steal(priv, priv->config); + m_config_register_options(priv->config, options); + af->data = &priv->data; + return AF_OK; +} + +struct af_info af_info_force = { + "Force audio format", + "force", + "", + "", + 0, + af_open +}; -- cgit v1.2.3