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_resample.c
Go to the documentation of this file.
1
/*
2
*
3
* This file is part of Libav.
4
*
5
* Libav is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* Libav is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with Libav; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
/**
21
* @file
22
* sample format and channel layout conversion audio filter
23
*/
24
25
#include "
libavutil/avassert.h
"
26
#include "
libavutil/avstring.h
"
27
#include "
libavutil/common.h
"
28
#include "
libavutil/dict.h
"
29
#include "
libavutil/mathematics.h
"
30
#include "
libavutil/opt.h
"
31
32
#include "
libavresample/avresample.h
"
33
34
#include "
audio.h
"
35
#include "
avfilter.h
"
36
#include "
formats.h
"
37
#include "
internal.h
"
38
39
typedef
struct
ResampleContext
{
40
AVAudioResampleContext
*
avr
;
41
AVDictionary
*
options
;
42
43
int64_t
next_pts
;
44
45
/* set by filter_frame() to signal an output frame to request_frame() */
46
int
got_output
;
47
}
ResampleContext
;
48
49
static
av_cold
int
init
(
AVFilterContext
*ctx,
const
char
*args)
50
{
51
ResampleContext
*s = ctx->
priv
;
52
53
if
(args) {
54
int
ret =
av_dict_parse_string
(&s->
options
, args,
"="
,
":"
, 0);
55
if
(ret < 0) {
56
av_log
(ctx,
AV_LOG_ERROR
,
"error setting option string: %s\n"
, args);
57
return
ret;
58
}
59
60
/* do not allow the user to override basic format options */
61
av_dict_set
(&s->
options
,
"in_channel_layout"
,
NULL
, 0);
62
av_dict_set
(&s->
options
,
"out_channel_layout"
,
NULL
, 0);
63
av_dict_set
(&s->
options
,
"in_sample_fmt"
,
NULL
, 0);
64
av_dict_set
(&s->
options
,
"out_sample_fmt"
,
NULL
, 0);
65
av_dict_set
(&s->
options
,
"in_sample_rate"
,
NULL
, 0);
66
av_dict_set
(&s->
options
,
"out_sample_rate"
,
NULL
, 0);
67
}
68
69
return
0;
70
}
71
72
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
73
{
74
ResampleContext
*s = ctx->
priv
;
75
76
if
(s->
avr
) {
77
avresample_close
(s->
avr
);
78
avresample_free
(&s->
avr
);
79
}
80
av_dict_free
(&s->
options
);
81
}
82
83
static
int
query_formats
(
AVFilterContext
*ctx)
84
{
85
AVFilterLink
*inlink = ctx->
inputs
[0];
86
AVFilterLink
*outlink = ctx->
outputs
[0];
87
88
AVFilterFormats
*in_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
89
AVFilterFormats
*out_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
90
AVFilterFormats
*in_samplerates =
ff_all_samplerates
();
91
AVFilterFormats
*out_samplerates =
ff_all_samplerates
();
92
AVFilterChannelLayouts
*in_layouts =
ff_all_channel_layouts
();
93
AVFilterChannelLayouts
*out_layouts =
ff_all_channel_layouts
();
94
95
ff_formats_ref
(in_formats, &inlink->
out_formats
);
96
ff_formats_ref
(out_formats, &outlink->
in_formats
);
97
98
ff_formats_ref
(in_samplerates, &inlink->
out_samplerates
);
99
ff_formats_ref
(out_samplerates, &outlink->
in_samplerates
);
100
101
ff_channel_layouts_ref
(in_layouts, &inlink->
out_channel_layouts
);
102
ff_channel_layouts_ref
(out_layouts, &outlink->
in_channel_layouts
);
103
104
return
0;
105
}
106
107
static
int
config_output
(
AVFilterLink
*outlink)
108
{
109
AVFilterContext
*ctx = outlink->
src
;
110
AVFilterLink
*inlink = ctx->
inputs
[0];
111
ResampleContext
*s = ctx->
priv
;
112
char
buf1[64], buf2[64];
113
int
ret;
114
115
if
(s->
avr
) {
116
avresample_close
(s->
avr
);
117
avresample_free
(&s->
avr
);
118
}
119
120
if
(inlink->
channel_layout
== outlink->
channel_layout
&&
121
inlink->
sample_rate
== outlink->
sample_rate
&&
122
(inlink->
format
== outlink->
format
||
123
(
av_get_channel_layout_nb_channels
(inlink->
channel_layout
) == 1 &&
124
av_get_channel_layout_nb_channels
(outlink->
channel_layout
) == 1 &&
125
av_get_planar_sample_fmt
(inlink->
format
) ==
126
av_get_planar_sample_fmt
(outlink->
format
))))
127
return
0;
128
129
if
(!(s->
avr
=
avresample_alloc_context
()))
130
return
AVERROR
(ENOMEM);
131
132
if
(s->
options
) {
133
AVDictionaryEntry
*e =
NULL
;
134
while
((e =
av_dict_get
(s->
options
,
""
, e,
AV_DICT_IGNORE_SUFFIX
)))
135
av_log
(ctx,
AV_LOG_VERBOSE
,
"lavr option: %s=%s\n"
, e->
key
, e->
value
);
136
137
av_opt_set_dict
(s->
avr
, &s->
options
);
138
}
139
140
av_opt_set_int
(s->
avr
,
"in_channel_layout"
, inlink ->
channel_layout
, 0);
141
av_opt_set_int
(s->
avr
,
"out_channel_layout"
, outlink->
channel_layout
, 0);
142
av_opt_set_int
(s->
avr
,
"in_sample_fmt"
, inlink ->
format
, 0);
143
av_opt_set_int
(s->
avr
,
"out_sample_fmt"
, outlink->
format
, 0);
144
av_opt_set_int
(s->
avr
,
"in_sample_rate"
, inlink ->
sample_rate
, 0);
145
av_opt_set_int
(s->
avr
,
"out_sample_rate"
, outlink->
sample_rate
, 0);
146
147
if
((ret =
avresample_open
(s->
avr
)) < 0)
148
return
ret;
149
150
outlink->
time_base
= (
AVRational
){ 1, outlink->
sample_rate
};
151
s->
next_pts
=
AV_NOPTS_VALUE
;
152
153
av_get_channel_layout_string
(buf1,
sizeof
(buf1),
154
-1, inlink ->channel_layout);
155
av_get_channel_layout_string
(buf2,
sizeof
(buf2),
156
-1, outlink->
channel_layout
);
157
av_log
(ctx,
AV_LOG_VERBOSE
,
158
"fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n"
,
159
av_get_sample_fmt_name
(inlink ->format), inlink ->
sample_rate
, buf1,
160
av_get_sample_fmt_name
(outlink->
format
), outlink->
sample_rate
, buf2);
161
162
return
0;
163
}
164
165
static
int
request_frame
(
AVFilterLink
*outlink)
166
{
167
AVFilterContext
*ctx = outlink->
src
;
168
ResampleContext
*s = ctx->
priv
;
169
int
ret = 0;
170
171
s->
got_output
= 0;
172
while
(ret >= 0 && !s->
got_output
)
173
ret =
ff_request_frame
(ctx->
inputs
[0]);
174
175
/* flush the lavr delay buffer */
176
if
(ret ==
AVERROR_EOF
&& s->
avr
) {
177
AVFilterBufferRef
*buf;
178
int
nb_samples
=
av_rescale_rnd
(
avresample_get_delay
(s->
avr
),
179
outlink->
sample_rate
,
180
ctx->
inputs
[0]->
sample_rate
,
181
AV_ROUND_UP
);
182
183
if
(!nb_samples)
184
return
ret;
185
186
buf =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, nb_samples);
187
if
(!buf)
188
return
AVERROR
(ENOMEM);
189
190
ret =
avresample_convert
(s->
avr
, buf->
extended_data
,
191
buf->
linesize
[0], nb_samples,
192
NULL
, 0, 0);
193
if
(ret <= 0) {
194
avfilter_unref_buffer
(buf);
195
return
(ret == 0) ?
AVERROR_EOF
: ret;
196
}
197
198
buf->
pts
= s->
next_pts
;
199
return
ff_filter_frame
(outlink, buf);
200
}
201
return
ret;
202
}
203
204
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*buf)
205
{
206
AVFilterContext
*ctx = inlink->
dst
;
207
ResampleContext
*s = ctx->
priv
;
208
AVFilterLink
*outlink = ctx->
outputs
[0];
209
int
ret;
210
211
if
(s->
avr
) {
212
AVFilterBufferRef
*buf_out;
213
int
delay,
nb_samples
;
214
215
/* maximum possible samples lavr can output */
216
delay =
avresample_get_delay
(s->
avr
);
217
nb_samples =
av_rescale_rnd
(buf->
audio
->
nb_samples
+ delay,
218
outlink->
sample_rate
, inlink->
sample_rate
,
219
AV_ROUND_UP
);
220
221
buf_out =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, nb_samples);
222
if
(!buf_out) {
223
ret =
AVERROR
(ENOMEM);
224
goto
fail;
225
}
226
227
ret =
avresample_convert
(s->
avr
, buf_out->
extended_data
,
228
buf_out->
linesize
[0], nb_samples,
229
buf->
extended_data
, buf->
linesize
[0],
230
buf->
audio
->
nb_samples
);
231
if
(ret <= 0) {
232
avfilter_unref_buffer
(buf_out);
233
if
(ret < 0)
234
goto
fail;
235
}
236
237
av_assert0
(!
avresample_available
(s->
avr
));
238
239
if
(s->
next_pts
==
AV_NOPTS_VALUE
) {
240
if
(buf->
pts
==
AV_NOPTS_VALUE
) {
241
av_log
(ctx,
AV_LOG_WARNING
,
"First timestamp is missing, "
242
"assuming 0.\n"
);
243
s->
next_pts
= 0;
244
}
else
245
s->
next_pts
=
av_rescale_q
(buf->
pts
, inlink->
time_base
,
246
outlink->
time_base
);
247
}
248
249
if
(ret > 0) {
250
buf_out->
audio
->
nb_samples
= ret;
251
if
(buf->
pts
!=
AV_NOPTS_VALUE
) {
252
buf_out->
pts
=
av_rescale_q
(buf->
pts
, inlink->
time_base
,
253
outlink->
time_base
) -
254
av_rescale
(delay, outlink->
sample_rate
,
255
inlink->
sample_rate
);
256
}
else
257
buf_out->
pts
= s->
next_pts
;
258
259
s->
next_pts
= buf_out->
pts
+ buf_out->
audio
->
nb_samples
;
260
261
ret =
ff_filter_frame
(outlink, buf_out);
262
s->
got_output
= 1;
263
}
264
265
fail:
266
avfilter_unref_buffer
(buf);
267
}
else
{
268
buf->
format
= outlink->
format
;
269
ret =
ff_filter_frame
(outlink, buf);
270
s->
got_output
= 1;
271
}
272
273
return
ret;
274
}
275
276
static
const
AVFilterPad
avfilter_af_resample_inputs
[] = {
277
{
278
.
name
=
"default"
,
279
.type =
AVMEDIA_TYPE_AUDIO
,
280
.filter_frame =
filter_frame
,
281
.min_perms =
AV_PERM_READ
282
},
283
{
NULL
}
284
};
285
286
static
const
AVFilterPad
avfilter_af_resample_outputs
[] = {
287
{
288
.
name
=
"default"
,
289
.type =
AVMEDIA_TYPE_AUDIO
,
290
.config_props =
config_output
,
291
.request_frame =
request_frame
292
},
293
{
NULL
}
294
};
295
296
AVFilter
avfilter_af_resample
= {
297
.
name
=
"resample"
,
298
.description =
NULL_IF_CONFIG_SMALL
(
"Audio resampling and conversion."
),
299
.priv_size =
sizeof
(
ResampleContext
),
300
301
.
init
=
init
,
302
.
uninit
=
uninit
,
303
.
query_formats
=
query_formats
,
304
305
.
inputs
= avfilter_af_resample_inputs,
306
.
outputs
= avfilter_af_resample_outputs,
307
};
Generated on Sat May 25 2013 04:01:14 for FFmpeg by
1.8.2