* Split an audio stream into per-channel streams.
*/
-#include "libavutil/audioconvert.h"
+#include "libavutil/attributes.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/internal.h"
#include "libavutil/opt.h"
#include "audio.h"
.version = LIBAVUTIL_VERSION_INT,
};
-static int init(AVFilterContext *ctx, const char *arg)
+static av_cold int init(AVFilterContext *ctx)
{
ChannelSplitContext *s = ctx->priv;
int nb_channels;
int ret = 0, i;
- s->class = &channelsplit_class;
- av_opt_set_defaults(s);
- if ((ret = av_set_options_string(s, arg, "=", ":")) < 0) {
- av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", arg);
- return ret;
- }
if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) {
av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n",
s->channel_layout_str);
}
fail:
- av_opt_free(s);
return ret;
}
return 0;
}
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
{
AVFilterContext *ctx = inlink->dst;
- int i;
+ int i, ret = 0;
for (i = 0; i < ctx->nb_outputs; i++) {
- AVFilterBufferRef *buf_out = avfilter_ref_buffer(buf, ~AV_PERM_WRITE);
+ AVFrame *buf_out = av_frame_clone(buf);
- if (!buf_out)
- return;
+ if (!buf_out) {
+ ret = AVERROR(ENOMEM);
+ break;
+ }
buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i];
- buf_out->audio->channel_layout =
- av_channel_layout_extract_channel(buf->audio->channel_layout, i);
+ buf_out->channel_layout =
+ av_channel_layout_extract_channel(buf->channel_layout, i);
- ff_filter_samples(ctx->outputs[i], buf_out);
+ ret = ff_filter_frame(ctx->outputs[i], buf_out);
+ if (ret < 0)
+ break;
}
- avfilter_unref_buffer(buf);
+ av_frame_free(&buf);
+ return ret;
}
-AVFilter avfilter_af_channelsplit = {
+static const AVFilterPad avfilter_af_channelsplit_inputs[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .filter_frame = filter_frame,
+ },
+ { NULL }
+};
+
+AVFilter ff_af_channelsplit = {
.name = "channelsplit",
.description = NULL_IF_CONFIG_SMALL("Split audio into per-channel streams"),
.priv_size = sizeof(ChannelSplitContext),
+ .priv_class = &channelsplit_class,
.init = init,
.query_formats = query_formats,
- .inputs = (const AVFilterPad[]){{ .name = "default",
- .type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = filter_samples, },
- { NULL }},
- .outputs = (const AVFilterPad[]){{ NULL }},
+ .inputs = avfilter_af_channelsplit_inputs,
+ .outputs = NULL,
+
+ .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
};