2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Channel split filter
23 * Split an audio stream into per-channel streams.
26 #include "libavutil/attributes.h"
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/internal.h"
29 #include "libavutil/opt.h"
36 typedef struct ChannelSplitContext
{
39 uint64_t channel_layout
;
40 char *channel_layout_str
;
41 } ChannelSplitContext
;
43 #define OFFSET(x) offsetof(ChannelSplitContext, x)
44 #define A AV_OPT_FLAG_AUDIO_PARAM
45 #define F AV_OPT_FLAG_FILTERING_PARAM
46 static const AVOption channelsplit_options
[] = {
47 { "channel_layout", "Input channel layout.", OFFSET(channel_layout_str
), AV_OPT_TYPE_STRING
, { .str
= "stereo" }, .flags
= A
|F
},
51 AVFILTER_DEFINE_CLASS(channelsplit
);
53 static av_cold
int init(AVFilterContext
*ctx
)
55 ChannelSplitContext
*s
= ctx
->priv
;
59 if (!(s
->channel_layout
= av_get_channel_layout(s
->channel_layout_str
))) {
60 av_log(ctx
, AV_LOG_ERROR
, "Error parsing channel layout '%s'.\n",
61 s
->channel_layout_str
);
62 ret
= AVERROR(EINVAL
);
66 nb_channels
= av_get_channel_layout_nb_channels(s
->channel_layout
);
67 for (i
= 0; i
< nb_channels
; i
++) {
68 uint64_t channel
= av_channel_layout_extract_channel(s
->channel_layout
, i
);
69 AVFilterPad pad
= { 0 };
71 pad
.type
= AVMEDIA_TYPE_AUDIO
;
72 pad
.name
= av_get_channel_name(channel
);
74 ff_insert_outpad(ctx
, i
, &pad
);
81 static int query_formats(AVFilterContext
*ctx
)
83 ChannelSplitContext
*s
= ctx
->priv
;
84 AVFilterChannelLayouts
*in_layouts
= NULL
;
87 ff_set_common_formats (ctx
, ff_planar_sample_fmts());
88 ff_set_common_samplerates(ctx
, ff_all_samplerates());
90 ff_add_channel_layout(&in_layouts
, s
->channel_layout
);
91 ff_channel_layouts_ref(in_layouts
, &ctx
->inputs
[0]->out_channel_layouts
);
93 for (i
= 0; i
< ctx
->nb_outputs
; i
++) {
94 AVFilterChannelLayouts
*out_layouts
= NULL
;
95 uint64_t channel
= av_channel_layout_extract_channel(s
->channel_layout
, i
);
97 ff_add_channel_layout(&out_layouts
, channel
);
98 ff_channel_layouts_ref(out_layouts
, &ctx
->outputs
[i
]->in_channel_layouts
);
104 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*buf
)
106 AVFilterContext
*ctx
= inlink
->dst
;
109 for (i
= 0; i
< ctx
->nb_outputs
; i
++) {
110 AVFrame
*buf_out
= av_frame_clone(buf
);
113 ret
= AVERROR(ENOMEM
);
117 buf_out
->data
[0] = buf_out
->extended_data
[0] = buf_out
->extended_data
[i
];
118 buf_out
->channel_layout
=
119 av_channel_layout_extract_channel(buf
->channel_layout
, i
);
120 av_frame_set_channels(buf_out
, 1);
122 ret
= ff_filter_frame(ctx
->outputs
[i
], buf_out
);
130 static const AVFilterPad avfilter_af_channelsplit_inputs
[] = {
133 .type
= AVMEDIA_TYPE_AUDIO
,
134 .filter_frame
= filter_frame
,
139 AVFilter ff_af_channelsplit
= {
140 .name
= "channelsplit",
141 .description
= NULL_IF_CONFIG_SMALL("Split audio into per-channel streams."),
142 .priv_size
= sizeof(ChannelSplitContext
),
143 .priv_class
= &channelsplit_class
,
145 .query_formats
= query_formats
,
146 .inputs
= avfilter_af_channelsplit_inputs
,
148 .flags
= AVFILTER_FLAG_DYNAMIC_OUTPUTS
,