Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavfilter
af_channelsplit.c
Go to the documentation of this file.
1
/*
2
* This file is part of Libav.
3
*
4
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
*/
18
26
#include "
libavutil/channel_layout.h
"
27
#include "
libavutil/internal.h
"
28
#include "
libavutil/opt.h
"
29
30
#include "
audio.h
"
31
#include "
avfilter.h
"
32
#include "
formats.h
"
33
#include "
internal.h
"
34
35
typedef
struct
ChannelSplitContext
{
36
const
AVClass
*
class
;
37
38
uint64_t
channel_layout
;
39
char
*
channel_layout_str
;
40
}
ChannelSplitContext
;
41
42
#define OFFSET(x) offsetof(ChannelSplitContext, x)
43
#define A AV_OPT_FLAG_AUDIO_PARAM
44
static
const
AVOption
options
[] = {
45
{
"channel_layout"
,
"Input channel layout."
,
OFFSET
(channel_layout_str),
AV_OPT_TYPE_STRING
, { .str =
"stereo"
}, .flags =
A
},
46
{
NULL
},
47
};
48
49
static
const
AVClass
channelsplit_class
= {
50
.
class_name
=
"channelsplit filter"
,
51
.item_name =
av_default_item_name
,
52
.option =
options
,
53
.version =
LIBAVUTIL_VERSION_INT
,
54
};
55
56
static
int
init
(
AVFilterContext
*ctx,
const
char
*arg)
57
{
58
ChannelSplitContext
*s = ctx->
priv
;
59
int
nb_channels
;
60
int
ret = 0, i;
61
62
s->
class
= &
channelsplit_class
;
63
av_opt_set_defaults
(s);
64
if
((ret =
av_set_options_string
(s, arg,
"="
,
":"
)) < 0) {
65
av_log
(ctx,
AV_LOG_ERROR
,
"Error parsing options string '%s'.\n"
, arg);
66
return
ret;
67
}
68
if
(!(s->
channel_layout
=
av_get_channel_layout
(s->
channel_layout_str
))) {
69
av_log
(ctx,
AV_LOG_ERROR
,
"Error parsing channel layout '%s'.\n"
,
70
s->
channel_layout_str
);
71
ret =
AVERROR
(EINVAL);
72
goto
fail;
73
}
74
75
nb_channels =
av_get_channel_layout_nb_channels
(s->
channel_layout
);
76
for
(i = 0; i <
nb_channels
; i++) {
77
uint64_t channel =
av_channel_layout_extract_channel
(s->
channel_layout
, i);
78
AVFilterPad
pad = { 0 };
79
80
pad.
type
=
AVMEDIA_TYPE_AUDIO
;
81
pad.
name
=
av_get_channel_name
(channel);
82
83
ff_insert_outpad
(ctx, i, &pad);
84
}
85
86
fail:
87
av_opt_free
(s);
88
return
ret;
89
}
90
91
static
int
query_formats
(
AVFilterContext
*ctx)
92
{
93
ChannelSplitContext
*s = ctx->
priv
;
94
AVFilterChannelLayouts
*in_layouts =
NULL
;
95
int
i;
96
97
ff_set_common_formats
(ctx,
ff_planar_sample_fmts
());
98
ff_set_common_samplerates
(ctx,
ff_all_samplerates
());
99
100
ff_add_channel_layout
(&in_layouts, s->
channel_layout
);
101
ff_channel_layouts_ref
(in_layouts, &ctx->
inputs
[0]->
out_channel_layouts
);
102
103
for
(i = 0; i < ctx->
nb_outputs
; i++) {
104
AVFilterChannelLayouts
*out_layouts =
NULL
;
105
uint64_t channel =
av_channel_layout_extract_channel
(s->
channel_layout
, i);
106
107
ff_add_channel_layout
(&out_layouts, channel);
108
ff_channel_layouts_ref
(out_layouts, &ctx->
outputs
[i]->
in_channel_layouts
);
109
}
110
111
return
0;
112
}
113
114
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*buf)
115
{
116
AVFilterContext
*ctx = inlink->
dst
;
117
int
i, ret = 0;
118
119
for
(i = 0; i < ctx->
nb_outputs
; i++) {
120
AVFilterBufferRef
*buf_out =
avfilter_ref_buffer
(buf, ~
AV_PERM_WRITE
);
121
122
if
(!buf_out) {
123
ret =
AVERROR
(ENOMEM);
124
break
;
125
}
126
127
buf_out->
data
[0] = buf_out->
extended_data
[0] = buf_out->
extended_data
[i];
128
buf_out->
audio
->
channel_layout
=
129
av_channel_layout_extract_channel
(buf->
audio
->
channel_layout
, i);
130
131
ret =
ff_filter_frame
(ctx->
outputs
[i], buf_out);
132
if
(ret < 0)
133
break
;
134
}
135
avfilter_unref_buffer
(buf);
136
return
ret;
137
}
138
139
static
const
AVFilterPad
avfilter_af_channelsplit_inputs
[] = {
140
{
141
.
name
=
"default"
,
142
.type =
AVMEDIA_TYPE_AUDIO
,
143
.filter_frame =
filter_frame
,
144
},
145
{
NULL
}
146
};
147
148
AVFilter
avfilter_af_channelsplit
= {
149
.
name
=
"channelsplit"
,
150
.description =
NULL_IF_CONFIG_SMALL
(
"Split audio into per-channel streams"
),
151
.priv_size =
sizeof
(
ChannelSplitContext
),
152
153
.
init
=
init
,
154
.
query_formats
=
query_formats
,
155
156
.
inputs
= avfilter_af_channelsplit_inputs,
157
.
outputs
=
NULL
,
158
};