2 * Copyright (c) 2010 S.N. Hemanth Meenakshisundaram <smeenaks@ucsd.edu>
3 * Copyright (c) 2011 Stefano Sabatini
4 * Copyright (c) 2011 Mina Nagy Zaki
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * sample format and channel layout conversion audio filter
28 #include "libavutil/channel_layout.h"
29 #include "libavutil/opt.h"
30 #include "libswresample/swresample.h"
37 enum AVSampleFormat out_sample_fmt
;
39 struct SwrContext
*swr
;
41 char *channel_layout_str
;
44 #define OFFSET(x) offsetof(AConvertContext, x)
45 #define A AV_OPT_FLAG_AUDIO_PARAM
46 #define F AV_OPT_FLAG_FILTERING_PARAM
47 static const AVOption aconvert_options
[] = {
48 { "sample_fmt", "", OFFSET(format_str
), AV_OPT_TYPE_STRING
, .flags
= A
|F
},
49 { "channel_layout", "", OFFSET(channel_layout_str
), AV_OPT_TYPE_STRING
, .flags
= A
|F
},
53 AVFILTER_DEFINE_CLASS(aconvert
);
55 static av_cold
int init(AVFilterContext
*ctx
)
57 AConvertContext
*aconvert
= ctx
->priv
;
60 av_log(ctx
, AV_LOG_WARNING
, "This filter is deprecated, use aformat instead\n");
62 aconvert
->out_sample_fmt
= AV_SAMPLE_FMT_NONE
;
63 aconvert
->out_chlayout
= 0;
65 if (aconvert
->format_str
&& strcmp(aconvert
->format_str
, "auto") &&
66 (ret
= ff_parse_sample_format(&aconvert
->out_sample_fmt
, aconvert
->format_str
, ctx
)) < 0)
68 if (aconvert
->channel_layout_str
&& strcmp(aconvert
->channel_layout_str
, "auto"))
69 return ff_parse_channel_layout(&aconvert
->out_chlayout
, NULL
, aconvert
->channel_layout_str
, ctx
);
73 static av_cold
void uninit(AVFilterContext
*ctx
)
75 AConvertContext
*aconvert
= ctx
->priv
;
76 swr_free(&aconvert
->swr
);
79 static int query_formats(AVFilterContext
*ctx
)
81 AVFilterFormats
*formats
= NULL
;
82 AConvertContext
*aconvert
= ctx
->priv
;
83 AVFilterLink
*inlink
= ctx
->inputs
[0];
84 AVFilterLink
*outlink
= ctx
->outputs
[0];
85 AVFilterChannelLayouts
*layouts
;
87 ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_AUDIO
),
88 &inlink
->out_formats
);
89 if (aconvert
->out_sample_fmt
!= AV_SAMPLE_FMT_NONE
) {
91 ff_add_format(&formats
, aconvert
->out_sample_fmt
);
92 ff_formats_ref(formats
, &outlink
->in_formats
);
94 ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_AUDIO
),
95 &outlink
->in_formats
);
97 ff_channel_layouts_ref(ff_all_channel_layouts(),
98 &inlink
->out_channel_layouts
);
99 if (aconvert
->out_chlayout
!= 0) {
101 ff_add_channel_layout(&layouts
, aconvert
->out_chlayout
);
102 ff_channel_layouts_ref(layouts
, &outlink
->in_channel_layouts
);
104 ff_channel_layouts_ref(ff_all_channel_layouts(),
105 &outlink
->in_channel_layouts
);
110 static int config_output(AVFilterLink
*outlink
)
113 AVFilterContext
*ctx
= outlink
->src
;
114 AVFilterLink
*inlink
= ctx
->inputs
[0];
115 AConvertContext
*aconvert
= ctx
->priv
;
116 char buf1
[64], buf2
[64];
118 /* if not specified in args, use the format and layout of the output */
119 if (aconvert
->out_sample_fmt
== AV_SAMPLE_FMT_NONE
)
120 aconvert
->out_sample_fmt
= outlink
->format
;
121 if (aconvert
->out_chlayout
== 0)
122 aconvert
->out_chlayout
= outlink
->channel_layout
;
124 aconvert
->swr
= swr_alloc_set_opts(aconvert
->swr
,
125 aconvert
->out_chlayout
, aconvert
->out_sample_fmt
, inlink
->sample_rate
,
126 inlink
->channel_layout
, inlink
->format
, inlink
->sample_rate
,
129 return AVERROR(ENOMEM
);
130 ret
= swr_init(aconvert
->swr
);
134 av_get_channel_layout_string(buf1
, sizeof(buf1
),
135 -1, inlink
->channel_layout
);
136 av_get_channel_layout_string(buf2
, sizeof(buf2
),
137 -1, outlink
->channel_layout
);
138 av_log(ctx
, AV_LOG_VERBOSE
,
139 "fmt:%s cl:%s -> fmt:%s cl:%s\n",
140 av_get_sample_fmt_name(inlink
->format
), buf1
,
141 av_get_sample_fmt_name(outlink
->format
), buf2
);
146 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*insamplesref
)
148 AConvertContext
*aconvert
= inlink
->dst
->priv
;
149 const int n
= insamplesref
->nb_samples
;
150 AVFilterLink
*const outlink
= inlink
->dst
->outputs
[0];
151 AVFrame
*outsamplesref
= ff_get_audio_buffer(outlink
, n
);
155 return AVERROR(ENOMEM
);
156 swr_convert(aconvert
->swr
, outsamplesref
->extended_data
, n
,
157 (void *)insamplesref
->extended_data
, n
);
159 av_frame_copy_props(outsamplesref
, insamplesref
);
160 av_frame_set_channels(outsamplesref
, outlink
->channels
);
161 outsamplesref
->channel_layout
= outlink
->channel_layout
;
163 ret
= ff_filter_frame(outlink
, outsamplesref
);
164 av_frame_free(&insamplesref
);
168 static const AVFilterPad aconvert_inputs
[] = {
171 .type
= AVMEDIA_TYPE_AUDIO
,
172 .filter_frame
= filter_frame
,
177 static const AVFilterPad aconvert_outputs
[] = {
180 .type
= AVMEDIA_TYPE_AUDIO
,
181 .config_props
= config_output
,
186 AVFilter ff_af_aconvert
= {
188 .description
= NULL_IF_CONFIG_SMALL("Convert the input audio to sample_fmt:channel_layout."),
189 .priv_size
= sizeof(AConvertContext
),
190 .priv_class
= &aconvert_class
,
193 .query_formats
= query_formats
,
194 .inputs
= aconvert_inputs
,
195 .outputs
= aconvert_outputs
,