FFmpeg
Loading...
Searching...
No Matches
af_channelsplit.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
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.
8 *
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.
13 *
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
17 */
18
19/**
20 * @file
21 * Channel split filter
22 *
23 * Split an audio stream into per-channel streams.
24 */
25#include "libavutil/avassert.h"
28#include "libavutil/internal.h"
29#include "libavutil/mem.h"
30#include "libavutil/opt.h"
31
32#include "audio.h"
33#include "avfilter.h"
34#include "filters.h"
35#include "formats.h"
36
45
46#define OFFSET(x) offsetof(ChannelSplitContext, x)
47#define A AV_OPT_FLAG_AUDIO_PARAM
48#define F AV_OPT_FLAG_FILTERING_PARAM
50 { "channel_layout", "Input channel layout.", OFFSET(channel_layout), AV_OPT_TYPE_CHLAYOUT, { .str = "stereo" }, .flags = A|F },
51 { "channels", "Channels to extract.", OFFSET(channels_str), AV_OPT_TYPE_STRING, { .str = "all" }, .flags = A|F },
52 { NULL }
53};
54
56
58{
59 ChannelSplitContext *s = ctx->priv;
60 AVChannelLayout channel_layout = { 0 };
61 int all = 0, ret = 0, i;
62
63 if (!strcmp(s->channels_str, "all")) {
64 if ((ret = av_channel_layout_copy(&channel_layout, &s->channel_layout)) < 0)
65 goto fail;
66 all = 1;
67 } else {
68 if ((ret = av_channel_layout_from_string(&channel_layout, s->channels_str)) < 0)
69 goto fail;
70 }
71
72 s->map = av_calloc(channel_layout.nb_channels, sizeof(*s->map));
73 if (!s->map)
74 return AVERROR(ENOMEM);
75
76 for (i = 0; i < channel_layout.nb_channels; i++) {
78 char buf[64];
79 AVFilterPad pad = { .flags = AVFILTERPAD_FLAG_FREE_NAME };
80
81 av_channel_name(buf, sizeof(buf), channel);
83 pad.name = av_strdup(buf);
84 if (!pad.name) {
85 ret = AVERROR(ENOMEM);
86 goto fail;
87 }
88
89 if (all) {
90 s->map[i] = i;
91 } else {
92 char buf[128];
93 av_channel_layout_describe(&s->channel_layout, buf, sizeof(buf));
94 if ((ret = av_channel_layout_index_from_channel(&s->channel_layout, channel)) < 0) {
95 av_log(ctx, AV_LOG_ERROR, "Channel name '%s' not present in channel layout '%s'.\n",
96 pad.name, buf);
97 av_freep(&pad.name);
98 goto fail;
99 }
100
101 s->map[i] = ret;
102 }
103
104 if ((ret = ff_append_outpad(ctx, &pad)) < 0)
105 goto fail;
106 }
107
108fail:
109 av_channel_layout_uninit(&channel_layout);
110 return ret;
111}
112
114{
115 ChannelSplitContext *s = ctx->priv;
116
117 av_channel_layout_uninit(&s->channel_layout);
118 av_freep(&s->map);
119}
120
122 AVFilterFormatsConfig **cfg_in,
123 AVFilterFormatsConfig **cfg_out)
124{
125 ChannelSplitContext *s = ctx->priv;
126 AVFilterChannelLayouts *in_layouts = NULL;
127 int i, ret;
128
129 ret = ff_set_common_formats2(ctx, cfg_in, cfg_out, ff_planar_sample_fmts());
130 if (ret < 0)
131 return ret;
132
133 if ((ret = ff_add_channel_layout(&in_layouts, &s->channel_layout)) < 0 ||
134 (ret = ff_channel_layouts_ref(in_layouts, &cfg_in[0]->channel_layouts)) < 0)
135 return ret;
136
137 for (i = 0; i < ctx->nb_outputs; i++) {
138 AVChannelLayout channel_layout = { 0 };
139 AVFilterChannelLayouts *out_layouts = NULL;
140 enum AVChannel channel = av_channel_layout_channel_from_index(&s->channel_layout, s->map[i]);
141
142 channel_layout.u.map = av_mallocz(sizeof(*channel_layout.u.map));
143 if (!channel_layout.u.map)
144 return AVERROR(ENOMEM);
145
146 channel_layout.u.map[0].id = channel;
147 channel_layout.nb_channels = 1;
148 channel_layout.order = AV_CHANNEL_ORDER_CUSTOM;
149
151 if (ret < 0) {
152 av_channel_layout_uninit(&channel_layout);
153 return ret;
154 }
155
156 ret = ff_add_channel_layout(&out_layouts, &channel_layout);
157 av_channel_layout_uninit(&channel_layout);
158 if (ret < 0)
159 return ret;
160
161 ret = ff_channel_layouts_ref(out_layouts, &cfg_out[i]->channel_layouts);
162 if (ret < 0)
163 return ret;
164 }
165
166 return 0;
167}
168
169static int filter_frame(AVFilterLink *outlink, AVFrame *buf)
170{
171 AVFrame *buf_out;
172 AVFilterContext *ctx = outlink->src;
173 ChannelSplitContext *s = ctx->priv;
174 const int i = FF_OUTLINK_IDX(outlink);
175 int ret;
176
177 buf_out = av_frame_clone(buf);
178 if (!buf_out)
179 return AVERROR(ENOMEM);
180
181 buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[s->map[i]];
182
184 ret = av_channel_layout_copy(&buf_out->ch_layout, &outlink->ch_layout);
185 if (ret < 0) {
186 av_frame_free(&buf_out);
187 return ret;
188 }
189
190 return ff_filter_frame(ctx->outputs[i], buf_out);
191}
192
194{
195 AVFilterLink *inlink = ctx->inputs[0];
196 int status, ret;
197 AVFrame *in;
198 int64_t pts;
199
200 for (int i = 0; i < ctx->nb_outputs; i++) {
202 }
203
204 ret = ff_inlink_consume_frame(inlink, &in);
205 if (ret < 0)
206 return ret;
207 if (ret > 0) {
208 for (int i = 0; i < ctx->nb_outputs; i++) {
209 if (ff_outlink_get_status(ctx->outputs[i]))
210 continue;
211
212 ret = filter_frame(ctx->outputs[i], in);
213 if (ret < 0)
214 break;
215 }
216
217 av_frame_free(&in);
218 if (ret < 0)
219 return ret;
220 }
221
222 if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
223 for (int i = 0; i < ctx->nb_outputs; i++) {
224 if (ff_outlink_get_status(ctx->outputs[i]))
225 continue;
226 ff_outlink_set_status(ctx->outputs[i], status, pts);
227 }
228 return 0;
229 }
230
232
233 return FFERROR_NOT_READY;
234}
235
237 .p.name = "channelsplit",
238 .p.description = NULL_IF_CONFIG_SMALL("Split audio into per-channel streams."),
239 .p.priv_class = &channelsplit_class,
241 .priv_size = sizeof(ChannelSplitContext),
242 .init = init,
244 .uninit = uninit,
247};
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
const FFFilter ff_af_channelsplit
static int filter_frame(AVFilterLink *outlink, AVFrame *buf)
static const AVOption channelsplit_options[]
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
#define OFFSET(x)
static AVFormatContext * ctx
#define A(x)
Definition vpx_arith.h:28
const AVFilterPad ff_audio_default_filterpad[1]
An AVFilterPad array whose only entry has name "default" and is of type AVMEDIA_TYPE_AUDIO.
Definition audio.c:34
simple assert() macros that are a bit more flexible than ISO C assert().
int ff_append_outpad(AVFilterContext *f, AVFilterPad *p)
Definition avfilter.c:138
int ff_outlink_get_status(AVFilterLink *link)
Get the status on an output link.
Definition avfilter.c:1648
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition avfilter.c:1467
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition avfilter.c:1520
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
Public libavutil channel layout APIs header.
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static const uint16_t channel_layouts[7]
Definition dca_lbr.c:112
#define F(x)
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
channel
Use these values when setting the channel map with ebur128_set_channel().
Definition ebur128.h:39
int ff_set_common_formats2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *formats)
Definition formats.c:1137
AVFilterFormats * ff_planar_sample_fmts(void)
Construct a formats list containing all planar sample formats.
Definition formats.c:660
int ff_add_channel_layout(AVFilterChannelLayouts **l, const AVChannelLayout *channel_layout)
Definition formats.c:588
int ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
Add *ref as a new reference to f.
Definition formats.c:751
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CHLAYOUT
Underlying C type is AVChannelLayout.
Definition opt.h:330
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
Definition avfilter.h:161
int av_channel_layout_from_string(AVChannelLayout *channel_layout, const char *str)
Initialize a channel layout from a given string description.
int av_channel_layout_index_from_channel(const AVChannelLayout *channel_layout, enum AVChannel channel)
Get the index of a given channel in a channel layout.
int av_channel_layout_retype(AVChannelLayout *channel_layout, enum AVChannelOrder order, int flags)
Change the AVChannelOrder of a channel layout.
#define AV_CHANNEL_LAYOUT_RETYPE_FLAG_CANONICAL
The specified retype target order is ignored and the simplest possible (canonical) order is used for ...
int av_channel_name(char *buf, size_t buf_size, enum AVChannel channel_id)
Get a human readable string in an abbreviated form describing a given channel.
enum AVChannel av_channel_layout_channel_from_index(const AVChannelLayout *channel_layout, unsigned int idx)
Get the channel with the given index in a channel layout.
void av_channel_layout_uninit(AVChannelLayout *channel_layout)
Free any allocated data in the channel layout and reset the channel count to 0.
AVChannel
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
int av_channel_layout_copy(AVChannelLayout *dst, const AVChannelLayout *src)
Make a copy of a channel layout.
@ AV_CHANNEL_ORDER_CUSTOM
The channel order does not correspond to any other predefined order and is stored as an explicit map.
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FF_FILTER_FORWARD_WANTED_ANY(filter, inlink)
Forward the frame_wanted_out flag from any of the output links to an input link.
Definition filters.h:705
#define AVFILTERPAD_FLAG_FREE_NAME
The pad's name is allocated and should be freed generically.
Definition filters.h:64
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition filters.h:629
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
Definition filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition filters.h:652
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FF_OUTLINK_IDX(link)
Definition filters.h:216
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
Macro definitions for various function/variable attributes.
#define av_cold
Definition attributes.h:117
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
enum AVChannel id
An AVChannelLayout holds information about the channel layout of audio data.
enum AVChannelOrder order
Channel order used in this layout.
union AVChannelLayout::@162063043056170047076125117143030261346263330336 u
Details about which channels are present in this layout.
int nb_channels
Number of channels in this layout.
AVChannelCustom * map
This member must be used when the channel order is AV_CHANNEL_ORDER_CUSTOM.
Describe the class of an AVClass context structure.
Definition log.h:76
A list of supported channel layouts.
Definition formats.h:85
An instance of a filter.
Definition avfilter.h:273
Lists of formats / etc.
Definition avfilter.h:120
A filter pad used for either input or output.
Definition filters.h:40
enum AVMediaType type
AVFilterPad type.
Definition filters.h:51
const char * name
Pad name.
Definition filters.h:46
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
AVChannelLayout ch_layout
Channel layout of the audio data.
Definition frame.h:815
uint8_t ** extended_data
pointers to the data planes/channels.
Definition frame.h:533
AVOption.
Definition opt.h:428
AVChannelLayout channel_layout
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
static int64_t pts