summaryrefslogtreecommitdiffstats
path: root/audio/filter/af_format.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/filter/af_format.c')
-rw-r--r--audio/filter/af_format.c173
1 files changed, 90 insertions, 83 deletions
diff --git a/audio/filter/af_format.c b/audio/filter/af_format.c
index c4af9b768b..3e1eef664c 100644
--- a/audio/filter/af_format.c
+++ b/audio/filter/af_format.c
@@ -15,18 +15,14 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-
-#include <libavutil/common.h>
-
-#include "options/m_option.h"
-
+#include "audio/aframe.h"
#include "audio/format.h"
-#include "af.h"
-
-struct priv {
- struct m_config *config;
+#include "filters/f_autoconvert.h"
+#include "filters/filter_internal.h"
+#include "filters/user_filters.h"
+#include "options/m_option.h"
+struct f_opts {
int in_format;
int in_srate;
struct m_channels in_channels;
@@ -37,98 +33,109 @@ struct priv {
int fail;
};
-static void force_in_params(struct af_instance *af, struct mp_audio *in)
-{
- struct priv *priv = af->priv;
-
- if (priv->in_format != AF_FORMAT_UNKNOWN)
- mp_audio_set_format(in, priv->in_format);
-
- if (priv->in_channels.num_chmaps > 0)
- mp_audio_set_channels(in, &priv->in_channels.chmaps[0]);
-
- if (priv->in_srate)
- in->rate = priv->in_srate;
-}
+struct priv {
+ struct f_opts *opts;
+ struct mp_pin *in_pin;
+};
-static void force_out_params(struct af_instance *af, struct mp_audio *out)
+static void process(struct mp_filter *f)
{
- struct priv *priv = af->priv;
+ struct priv *p = f->priv;
- if (priv->out_format != AF_FORMAT_UNKNOWN)
- mp_audio_set_format(out, priv->out_format);
+ if (!mp_pin_can_transfer_data(f->ppins[1], p->in_pin))
+ return;
- if (priv->out_channels.num_chmaps > 0)
- mp_audio_set_channels(out, &priv->out_channels.chmaps[0]);
+ struct mp_frame frame = mp_pin_out_read(p->in_pin);
- if (priv->out_srate)
- out->rate = priv->out_srate;
-}
+ if (p->opts->fail) {
+ MP_ERR(f, "Failing on purpose.\n");
+ goto error;
+ }
-static int control(struct af_instance *af, int cmd, void *arg)
-{
- struct priv *priv = af->priv;
+ if (frame.type == MP_FRAME_EOF) {
+ mp_pin_in_write(f->ppins[1], frame);
+ return;
+ }
- switch (cmd) {
- case AF_CONTROL_REINIT: {
- struct mp_audio *in = arg;
- struct mp_audio orig_in = *in;
- struct mp_audio *out = af->data;
+ if (frame.type != MP_FRAME_AUDIO) {
+ MP_ERR(f, "audio frame expected\n");
+ goto error;
+ }
- force_in_params(af, in);
- mp_audio_copy_config(out, in);
- force_out_params(af, out);
+ struct mp_aframe *in = frame.data;
- if (in->nch != out->nch || in->bps != out->bps) {
- MP_ERR(af, "Forced input/output formats are incompatible.\n");
- return AF_ERROR;
+ if (p->opts->out_channels.num_chmaps > 0) {
+ if (!mp_aframe_set_chmap(in, &p->opts->out_channels.chmaps[0])) {
+ MP_ERR(f, "could not force output channels\n");
+ goto error;
}
+ }
- if (priv->fail) {
- MP_ERR(af, "Failing on purpose.\n");
- return AF_ERROR;
- }
+ if (p->opts->out_srate)
+ mp_aframe_set_rate(in, p->opts->out_srate);
- return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE;
- }
- }
- return AF_UNKNOWN;
-}
+ mp_pin_in_write(f->ppins[1], frame);
+ return;
-static int filter(struct af_instance *af, struct mp_audio *data)
-{
- if (data)
- mp_audio_copy_config(data, af->data);
- af_add_output_frame(af, data);
- return 0;
+error:
+ mp_frame_unref(&frame);
+ mp_filter_internal_mark_failed(f);
}
-static int af_open(struct af_instance *af)
+static const struct mp_filter_info af_format_filter = {
+ .name = "format",
+ .priv_size = sizeof(struct priv),
+ .process = process,
+};
+
+static struct mp_filter *af_format_create(struct mp_filter *parent,
+ void *options)
{
- af->control = control;
- af->filter_frame = filter;
+ struct mp_filter *f = mp_filter_create(parent, &af_format_filter);
+ if (!f) {
+ talloc_free(options);
+ return NULL;
+ }
- force_in_params(af, af->data);
- force_out_params(af, af->data);
+ struct priv *p = f->priv;
+ p->opts = talloc_steal(p, options);
- return AF_OK;
-}
+ mp_filter_add_pin(f, MP_PIN_IN, "in");
+ mp_filter_add_pin(f, MP_PIN_OUT, "out");
-#define OPT_BASE_STRUCT struct priv
+ struct mp_autoconvert *conv = mp_autoconvert_create(f);
+ if (!conv)
+ abort();
-const struct af_info af_info_format = {
- .info = "Force audio format",
- .name = "format",
- .open = af_open,
- .priv_size = sizeof(struct priv),
- .options = (const struct m_option[]) {
- OPT_AUDIOFORMAT("format", in_format, 0),
- OPT_INTRANGE("srate", in_srate, 0, 1000, 8*48000),
- OPT_CHANNELS("channels", in_channels, 0, .min = 1),
- OPT_AUDIOFORMAT("out-format", out_format, 0),
- OPT_INTRANGE("out-srate", out_srate, 0, 1000, 8*48000),
- OPT_CHANNELS("out-channels", out_channels, 0, .min = 1),
- OPT_FLAG("fail", fail, 0),
- {0}
+ if (p->opts->in_format)
+ mp_autoconvert_add_afmt(conv, p->opts->in_format);
+ if (p->opts->in_srate)
+ mp_autoconvert_add_srate(conv, p->opts->in_srate);
+ if (p->opts->in_channels.num_chmaps > 0)
+ mp_autoconvert_add_chmap(conv, &p->opts->in_channels.chmaps[0]);
+
+ mp_pin_connect(conv->f->pins[0], f->ppins[0]);
+ p->in_pin = conv->f->pins[1];
+
+ return f;
+}
+
+#define OPT_BASE_STRUCT struct f_opts
+
+const struct mp_user_filter_entry af_format = {
+ .desc = {
+ .name = "format",
+ .description = "Force audio format",
+ .priv_size = sizeof(struct f_opts),
+ .options = (const struct m_option[]) {
+ OPT_AUDIOFORMAT("format", in_format, 0),
+ OPT_INTRANGE("srate", in_srate, 0, 1000, 8*48000),
+ OPT_CHANNELS("channels", in_channels, 0, .min = 1),
+ OPT_INTRANGE("out-srate", out_srate, 0, 1000, 8*48000),
+ OPT_CHANNELS("out-channels", out_channels, 0, .min = 1),
+ OPT_FLAG("fail", fail, 0),
+ {0}
+ },
},
+ .create = af_format_create,
};