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_counts
();
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_counts
();
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
if
(!inlink->
channel_layout
)
149
av_opt_set_int
(aresample->
swr
,
"ich"
, inlink->
channels
, 0);
150
if
(!outlink->
channel_layout
)
151
av_opt_set_int
(aresample->
swr
,
"och"
, outlink->
channels
, 0);
152
153
ret =
swr_init
(aresample->
swr
);
154
if
(ret < 0)
155
return
ret;
156
157
out_rate =
av_get_int
(aresample->
swr
,
"osr"
,
NULL
);
158
out_layout =
av_get_int
(aresample->
swr
,
"ocl"
,
NULL
);
159
out_format =
av_get_int
(aresample->
swr
,
"osf"
,
NULL
);
160
outlink->
time_base
= (
AVRational
) {1, out_rate};
161
162
av_assert0
(outlink->
sample_rate
== out_rate);
163
av_assert0
(outlink->
channel_layout
== out_layout || !outlink->
channel_layout
);
164
av_assert0
(outlink->
format
== out_format);
165
166
aresample->
ratio
= (double)outlink->
sample_rate
/ inlink->
sample_rate
;
167
168
av_get_channel_layout_string
(inchl_buf,
sizeof
(inchl_buf), inlink ->
channels
, inlink ->
channel_layout
);
169
av_get_channel_layout_string
(outchl_buf,
sizeof
(outchl_buf), outlink->
channels
, outlink->
channel_layout
);
170
171
av_log
(ctx,
AV_LOG_VERBOSE
,
"ch:%d chl:%s fmt:%s r:%dHz -> ch:%d chl:%s fmt:%s r:%dHz\n"
,
172
inlink ->channels, inchl_buf,
av_get_sample_fmt_name
(inlink->
format
), inlink->
sample_rate
,
173
outlink->
channels
, outchl_buf,
av_get_sample_fmt_name
(outlink->
format
), outlink->
sample_rate
);
174
return
0;
175
}
176
177
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*insamplesref)
178
{
179
AResampleContext
*aresample = inlink->
dst
->
priv
;
180
const
int
n_in = insamplesref->
audio
->
nb_samples
;
181
int
n_out = n_in * aresample->
ratio
* 2 + 256;
182
AVFilterLink
*
const
outlink = inlink->
dst
->
outputs
[0];
183
AVFilterBufferRef
*outsamplesref =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, n_out);
184
int
ret;
185
186
if
(!outsamplesref)
187
return
AVERROR
(ENOMEM);
188
189
avfilter_copy_buffer_ref_props
(outsamplesref, insamplesref);
190
outsamplesref->
format
= outlink->
format
;
191
outsamplesref->
audio
->
channels
= outlink->
channels
;
192
outsamplesref->
audio
->
channel_layout
= outlink->
channel_layout
;
193
outsamplesref->
audio
->
sample_rate
= outlink->
sample_rate
;
194
195
if
(insamplesref->
pts
!=
AV_NOPTS_VALUE
) {
196
int64_t inpts =
av_rescale
(insamplesref->
pts
, inlink->
time_base
.
num
* (int64_t)outlink->
sample_rate
* inlink->
sample_rate
, inlink->
time_base
.
den
);
197
int64_t
outpts
=
swr_next_pts
(aresample->
swr
, inpts);
198
aresample->
next_pts
=
199
outsamplesref->
pts
=
ROUNDED_DIV
(outpts, inlink->
sample_rate
);
200
}
else
{
201
outsamplesref->
pts
=
AV_NOPTS_VALUE
;
202
}
203
n_out =
swr_convert
(aresample->
swr
, outsamplesref->
extended_data
, n_out,
204
(
void
*)insamplesref->
extended_data
, n_in);
205
if
(n_out <= 0) {
206
avfilter_unref_buffer
(outsamplesref);
207
avfilter_unref_buffer
(insamplesref);
208
return
0;
209
}
210
211
outsamplesref->
audio
->
nb_samples
= n_out;
212
213
ret =
ff_filter_frame
(outlink, outsamplesref);
214
aresample->
req_fullfilled
= 1;
215
avfilter_unref_buffer
(insamplesref);
216
return
ret;
217
}
218
219
static
int
request_frame
(
AVFilterLink
*outlink)
220
{
221
AVFilterContext
*ctx = outlink->
src
;
222
AResampleContext
*aresample = ctx->
priv
;
223
AVFilterLink
*
const
inlink = outlink->
src
->
inputs
[0];
224
int
ret;
225
226
aresample->
req_fullfilled
= 0;
227
do
{
228
ret =
ff_request_frame
(ctx->
inputs
[0]);
229
}
while
(!aresample->
req_fullfilled
&& ret>=0);
230
231
if
(ret ==
AVERROR_EOF
) {
232
AVFilterBufferRef
*outsamplesref;
233
int
n_out = 4096;
234
235
outsamplesref =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, n_out);
236
if
(!outsamplesref)
237
return
AVERROR
(ENOMEM);
238
n_out =
swr_convert
(aresample->
swr
, outsamplesref->
extended_data
, n_out, 0, 0);
239
if
(n_out <= 0) {
240
avfilter_unref_buffer
(outsamplesref);
241
return
(n_out == 0) ?
AVERROR_EOF
: n_out;
242
}
243
244
outsamplesref->
audio
->
sample_rate
= outlink->
sample_rate
;
245
outsamplesref->
audio
->
nb_samples
= n_out;
246
#if 0
247
outsamplesref->
pts
= aresample->
next_pts
;
248
if
(aresample->
next_pts
!=
AV_NOPTS_VALUE
)
249
aresample->
next_pts
+=
av_rescale_q
(n_out, (
AVRational
){1 ,outlink->
sample_rate
}, outlink->
time_base
);
250
#else
251
outsamplesref->
pts
=
swr_next_pts
(aresample->
swr
, INT64_MIN);
252
outsamplesref->
pts
=
ROUNDED_DIV
(outsamplesref->
pts
, inlink->
sample_rate
);
253
#endif
254
255
ff_filter_frame
(outlink, outsamplesref);
256
return
0;
257
}
258
return
ret;
259
}
260
261
static
const
AVFilterPad
aresample_inputs
[] = {
262
{
263
.
name
=
"default"
,
264
.type =
AVMEDIA_TYPE_AUDIO
,
265
.filter_frame =
filter_frame
,
266
.min_perms =
AV_PERM_READ
,
267
},
268
{
NULL
},
269
};
270
271
static
const
AVFilterPad
aresample_outputs
[] = {
272
{
273
.
name
=
"default"
,
274
.config_props =
config_output
,
275
.request_frame =
request_frame
,
276
.type =
AVMEDIA_TYPE_AUDIO
,
277
},
278
{
NULL
},
279
};
280
281
AVFilter
avfilter_af_aresample
= {
282
.
name
=
"aresample"
,
283
.description =
NULL_IF_CONFIG_SMALL
(
"Resample audio data."
),
284
.init =
init
,
285
.uninit =
uninit
,
286
.query_formats =
query_formats
,
287
.priv_size =
sizeof
(
AResampleContext
),
288
.
inputs
= aresample_inputs,
289
.
outputs
= aresample_outputs,
290
};
Generated on Sat May 25 2013 04:01:14 for FFmpeg by
1.8.2