FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
libavfilter
af_aresample.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Stefano Sabatini
3
* Copyright (c) 2011 Mina Nagy Zaki
4
*
5
* This file is part of FFmpeg.
6
*
7
* FFmpeg is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* FFmpeg is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with FFmpeg; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
/**
23
* @file
24
* resampling audio filter
25
*/
26
27
#include "
libavutil/avstring.h
"
28
#include "
libavutil/channel_layout.h
"
29
#include "
libavutil/opt.h
"
30
#include "
libavutil/samplefmt.h
"
31
#include "
libavutil/avassert.h
"
32
#include "
libswresample/swresample.h
"
33
#include "
avfilter.h
"
34
#include "
audio.h
"
35
#include "
internal.h
"
36
37
typedef
struct
{
38
double
ratio
;
39
struct
SwrContext
*
swr
;
40
int64_t
next_pts
;
41
int
req_fullfilled
;
42
}
AResampleContext
;
43
44
static
av_cold
int
init
(
AVFilterContext
*ctx,
const
char
*args)
45
{
46
AResampleContext
*aresample = ctx->
priv
;
47
int
ret = 0;
48
char
*argd =
av_strdup
(args);
49
50
aresample->
next_pts
=
AV_NOPTS_VALUE
;
51
aresample->
swr
=
swr_alloc
();
52
if
(!aresample->
swr
) {
53
ret =
AVERROR
(ENOMEM);
54
goto
end
;
55
}
56
57
if
(args) {
58
char
*ptr = argd, *token;
59
60
while
(token =
av_strtok
(ptr,
":"
, &ptr)) {
61
char
*
value
;
62
av_strtok
(token,
"="
, &value);
63
64
if
(value) {
65
if
((ret =
av_opt_set
(aresample->
swr
, token, value, 0)) < 0)
66
goto
end
;
67
}
else
{
68
int
out_rate;
69
if
((ret =
ff_parse_sample_rate
(&out_rate, token, ctx)) < 0)
70
goto
end
;
71
if
((ret =
av_opt_set_int
(aresample->
swr
,
"osr"
, out_rate, 0)) < 0)
72
goto
end
;
73
}
74
}
75
}
76
end
:
77
av_free
(argd);
78
return
ret;
79
}
80
81
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
82
{
83
AResampleContext
*aresample = ctx->
priv
;
84
swr_free
(&aresample->
swr
);
85
}
86
87
static
int
query_formats
(
AVFilterContext
*ctx)
88
{
89
AResampleContext
*aresample = ctx->
priv
;
90
int
out_rate =
av_get_int
(aresample->
swr
,
"osr"
,
NULL
);
91
uint64_t out_layout =
av_get_int
(aresample->
swr
,
"ocl"
,
NULL
);
92
enum
AVSampleFormat
out_format =
av_get_int
(aresample->
swr
,
"osf"
,
NULL
);
93
94
AVFilterLink
*inlink = ctx->
inputs
[0];
95
AVFilterLink
*outlink = ctx->
outputs
[0];
96
97
AVFilterFormats
*in_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
98
AVFilterFormats
*out_formats;
99
AVFilterFormats
*in_samplerates =
ff_all_samplerates
();
100
AVFilterFormats
*out_samplerates;
101
AVFilterChannelLayouts
*in_layouts =
ff_all_channel_layouts
();
102
AVFilterChannelLayouts
*out_layouts;
103
104
ff_formats_ref
(in_formats, &inlink->
out_formats
);
105
ff_formats_ref
(in_samplerates, &inlink->
out_samplerates
);
106
ff_channel_layouts_ref
(in_layouts, &inlink->
out_channel_layouts
);
107
108
if
(out_rate > 0) {
109
out_samplerates =
ff_make_format_list
((
int
[]){ out_rate, -1 });
110
}
else
{
111
out_samplerates =
ff_all_samplerates
();
112
}
113
ff_formats_ref
(out_samplerates, &outlink->
in_samplerates
);
114
115
if
(out_format !=
AV_SAMPLE_FMT_NONE
) {
116
out_formats =
ff_make_format_list
((
int
[]){ out_format, -1 });
117
}
else
118
out_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
119
ff_formats_ref
(out_formats, &outlink->
in_formats
);
120
121
if
(out_layout) {
122
out_layouts =
avfilter_make_format64_list
((int64_t[]){ out_layout, -1 });
123
}
else
124
out_layouts =
ff_all_channel_layouts
();
125
ff_channel_layouts_ref
(out_layouts, &outlink->
in_channel_layouts
);
126
127
return
0;
128
}
129
130
131
static
int
config_output
(
AVFilterLink
*outlink)
132
{
133
int
ret;
134
AVFilterContext
*ctx = outlink->
src
;
135
AVFilterLink
*inlink = ctx->
inputs
[0];
136
AResampleContext
*aresample = ctx->
priv
;
137
int
out_rate;
138
uint64_t out_layout;
139
enum
AVSampleFormat
out_format;
140
char
inchl_buf[128], outchl_buf[128];
141
142
aresample->
swr
=
swr_alloc_set_opts
(aresample->
swr
,
143
outlink->
channel_layout
, outlink->
format
, outlink->
sample_rate
,
144
inlink->
channel_layout
, inlink->
format
, inlink->
sample_rate
,
145
0, ctx);
146
if
(!aresample->
swr
)
147
return
AVERROR
(ENOMEM);
148
149
ret =
swr_init
(aresample->
swr
);
150
if
(ret < 0)
151
return
ret;
152
153
out_rate =
av_get_int
(aresample->
swr
,
"osr"
,
NULL
);
154
out_layout =
av_get_int
(aresample->
swr
,
"ocl"
,
NULL
);
155
out_format =
av_get_int
(aresample->
swr
,
"osf"
,
NULL
);
156
outlink->
time_base
= (
AVRational
) {1, out_rate};
157
158
av_assert0
(outlink->
sample_rate
== out_rate);
159
av_assert0
(outlink->
channel_layout
== out_layout);
160
av_assert0
(outlink->
format
== out_format);
161
162
aresample->
ratio
= (double)outlink->
sample_rate
/ inlink->
sample_rate
;
163
164
av_get_channel_layout_string
(inchl_buf,
sizeof
(inchl_buf), -1, inlink ->
channel_layout
);
165
av_get_channel_layout_string
(outchl_buf,
sizeof
(outchl_buf), -1, outlink->
channel_layout
);
166
167
av_log
(ctx,
AV_LOG_VERBOSE
,
"chl:%s fmt:%s r:%dHz -> chl:%s fmt:%s r:%dHz\n"
,
168
inchl_buf,
av_get_sample_fmt_name
(inlink->
format
), inlink->
sample_rate
,
169
outchl_buf,
av_get_sample_fmt_name
(outlink->
format
), outlink->
sample_rate
);
170
return
0;
171
}
172
173
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*insamplesref)
174
{
175
AResampleContext
*aresample = inlink->
dst
->
priv
;
176
const
int
n_in = insamplesref->
audio
->
nb_samples
;
177
int
n_out = n_in * aresample->
ratio
* 2 + 256;
178
AVFilterLink
*
const
outlink = inlink->
dst
->
outputs
[0];
179
AVFilterBufferRef
*outsamplesref =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, n_out);
180
int
ret;
181
182
if
(!outsamplesref)
183
return
AVERROR
(ENOMEM);
184
185
avfilter_copy_buffer_ref_props
(outsamplesref, insamplesref);
186
outsamplesref->
format
= outlink->
format
;
187
outsamplesref->
audio
->
channels
= outlink->
channels
;
188
outsamplesref->
audio
->
channel_layout
= outlink->
channel_layout
;
189
outsamplesref->
audio
->
sample_rate
= outlink->
sample_rate
;
190
191
if
(insamplesref->
pts
!=
AV_NOPTS_VALUE
) {
192
int64_t inpts =
av_rescale
(insamplesref->
pts
, inlink->
time_base
.
num
* (int64_t)outlink->
sample_rate
* inlink->
sample_rate
, inlink->
time_base
.
den
);
193
int64_t
outpts
=
swr_next_pts
(aresample->
swr
, inpts);
194
aresample->
next_pts
=
195
outsamplesref->
pts
=
ROUNDED_DIV
(outpts, inlink->
sample_rate
);
196
}
else
{
197
outsamplesref->
pts
=
AV_NOPTS_VALUE
;
198
}
199
n_out =
swr_convert
(aresample->
swr
, outsamplesref->
extended_data
, n_out,
200
(
void
*)insamplesref->
extended_data
, n_in);
201
if
(n_out <= 0) {
202
avfilter_unref_buffer
(outsamplesref);
203
avfilter_unref_buffer
(insamplesref);
204
return
0;
205
}
206
207
outsamplesref->
audio
->
nb_samples
= n_out;
208
209
ret =
ff_filter_frame
(outlink, outsamplesref);
210
aresample->
req_fullfilled
= 1;
211
avfilter_unref_buffer
(insamplesref);
212
return
ret;
213
}
214
215
static
int
request_frame
(
AVFilterLink
*outlink)
216
{
217
AVFilterContext
*ctx = outlink->
src
;
218
AResampleContext
*aresample = ctx->
priv
;
219
AVFilterLink
*
const
inlink = outlink->
src
->
inputs
[0];
220
int
ret;
221
222
aresample->
req_fullfilled
= 0;
223
do
{
224
ret =
ff_request_frame
(ctx->
inputs
[0]);
225
}
while
(!aresample->
req_fullfilled
&& ret>=0);
226
227
if
(ret ==
AVERROR_EOF
) {
228
AVFilterBufferRef
*outsamplesref;
229
int
n_out = 4096;
230
231
outsamplesref =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, n_out);
232
if
(!outsamplesref)
233
return
AVERROR
(ENOMEM);
234
n_out =
swr_convert
(aresample->
swr
, outsamplesref->
extended_data
, n_out, 0, 0);
235
if
(n_out <= 0) {
236
avfilter_unref_buffer
(outsamplesref);
237
return
(n_out == 0) ?
AVERROR_EOF
: n_out;
238
}
239
240
outsamplesref->
audio
->
sample_rate
= outlink->
sample_rate
;
241
outsamplesref->
audio
->
nb_samples
= n_out;
242
#if 0
243
outsamplesref->
pts
= aresample->
next_pts
;
244
if
(aresample->
next_pts
!=
AV_NOPTS_VALUE
)
245
aresample->
next_pts
+=
av_rescale_q
(n_out, (
AVRational
){1 ,outlink->
sample_rate
}, outlink->
time_base
);
246
#else
247
outsamplesref->
pts
=
swr_next_pts
(aresample->
swr
, INT64_MIN);
248
outsamplesref->
pts
=
ROUNDED_DIV
(outsamplesref->
pts
, inlink->
sample_rate
);
249
#endif
250
251
ff_filter_frame
(outlink, outsamplesref);
252
return
0;
253
}
254
return
ret;
255
}
256
257
static
const
AVFilterPad
aresample_inputs
[] = {
258
{
259
.
name
=
"default"
,
260
.type =
AVMEDIA_TYPE_AUDIO
,
261
.filter_frame =
filter_frame
,
262
.min_perms =
AV_PERM_READ
,
263
},
264
{
NULL
},
265
};
266
267
static
const
AVFilterPad
aresample_outputs
[] = {
268
{
269
.
name
=
"default"
,
270
.config_props =
config_output
,
271
.request_frame =
request_frame
,
272
.type =
AVMEDIA_TYPE_AUDIO
,
273
},
274
{
NULL
},
275
};
276
277
AVFilter
avfilter_af_aresample
= {
278
.
name
=
"aresample"
,
279
.description =
NULL_IF_CONFIG_SMALL
(
"Resample audio data."
),
280
.init =
init
,
281
.uninit =
uninit
,
282
.query_formats =
query_formats
,
283
.priv_size =
sizeof
(
AResampleContext
),
284
.
inputs
= aresample_inputs,
285
.
outputs
= aresample_outputs,
286
};
Generated on Sat May 25 2013 03:58:44 for FFmpeg by
1.8.2