FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
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
const
AVClass
*
class
;
41
AVAudioResampleContext
*
avr
;
42
AVDictionary
*
options
;
43
44
int64_t
next_pts
;
45
46
/* set by filter_frame() to signal an output frame to request_frame() */
47
int
got_output
;
48
}
ResampleContext
;
49
50
static
av_cold
int
init
(
AVFilterContext
*ctx,
AVDictionary
**opts)
51
{
52
ResampleContext
*
s
= ctx->
priv
;
53
const
AVClass
*avr_class =
avresample_get_class
();
54
AVDictionaryEntry
*e =
NULL
;
55
56
while
((e =
av_dict_get
(*opts,
""
, e,
AV_DICT_IGNORE_SUFFIX
))) {
57
if
(
av_opt_find
(&avr_class, e->
key
,
NULL
, 0,
58
AV_OPT_SEARCH_FAKE_OBJ
|
AV_OPT_SEARCH_CHILDREN
))
59
av_dict_set
(&s->
options
, e->
key
, e->
value
, 0);
60
}
61
62
e =
NULL
;
63
while
((e =
av_dict_get
(s->
options
,
""
, e,
AV_DICT_IGNORE_SUFFIX
)))
64
av_dict_set
(opts, e->
key
,
NULL
, 0);
65
66
/* do not allow the user to override basic format options */
67
av_dict_set
(&s->
options
,
"in_channel_layout"
,
NULL
, 0);
68
av_dict_set
(&s->
options
,
"out_channel_layout"
,
NULL
, 0);
69
av_dict_set
(&s->
options
,
"in_sample_fmt"
,
NULL
, 0);
70
av_dict_set
(&s->
options
,
"out_sample_fmt"
,
NULL
, 0);
71
av_dict_set
(&s->
options
,
"in_sample_rate"
,
NULL
, 0);
72
av_dict_set
(&s->
options
,
"out_sample_rate"
,
NULL
, 0);
73
74
return
0;
75
}
76
77
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
78
{
79
ResampleContext
*
s
= ctx->
priv
;
80
81
if
(s->
avr
) {
82
avresample_close
(s->
avr
);
83
avresample_free
(&s->
avr
);
84
}
85
av_dict_free
(&s->
options
);
86
}
87
88
static
int
query_formats
(
AVFilterContext
*ctx)
89
{
90
AVFilterLink
*inlink = ctx->
inputs
[0];
91
AVFilterLink
*outlink = ctx->
outputs
[0];
92
93
AVFilterFormats
*in_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
94
AVFilterFormats
*out_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
95
AVFilterFormats
*in_samplerates =
ff_all_samplerates
();
96
AVFilterFormats
*out_samplerates =
ff_all_samplerates
();
97
AVFilterChannelLayouts
*in_layouts =
ff_all_channel_layouts
();
98
AVFilterChannelLayouts
*out_layouts =
ff_all_channel_layouts
();
99
100
ff_formats_ref
(in_formats, &inlink->
out_formats
);
101
ff_formats_ref
(out_formats, &outlink->
in_formats
);
102
103
ff_formats_ref
(in_samplerates, &inlink->
out_samplerates
);
104
ff_formats_ref
(out_samplerates, &outlink->
in_samplerates
);
105
106
ff_channel_layouts_ref
(in_layouts, &inlink->
out_channel_layouts
);
107
ff_channel_layouts_ref
(out_layouts, &outlink->
in_channel_layouts
);
108
109
return
0;
110
}
111
112
static
int
config_output
(
AVFilterLink
*outlink)
113
{
114
AVFilterContext
*ctx = outlink->
src
;
115
AVFilterLink
*inlink = ctx->
inputs
[0];
116
ResampleContext
*
s
= ctx->
priv
;
117
char
buf1[64], buf2[64];
118
int
ret
;
119
120
if
(s->
avr
) {
121
avresample_close
(s->
avr
);
122
avresample_free
(&s->
avr
);
123
}
124
125
if
(inlink->
channel_layout
== outlink->
channel_layout
&&
126
inlink->
sample_rate
== outlink->
sample_rate
&&
127
(inlink->
format
== outlink->
format
||
128
(
av_get_channel_layout_nb_channels
(inlink->
channel_layout
) == 1 &&
129
av_get_channel_layout_nb_channels
(outlink->
channel_layout
) == 1 &&
130
av_get_planar_sample_fmt
(inlink->
format
) ==
131
av_get_planar_sample_fmt
(outlink->
format
))))
132
return
0;
133
134
if
(!(s->
avr
=
avresample_alloc_context
()))
135
return
AVERROR
(ENOMEM);
136
137
if
(s->
options
) {
138
AVDictionaryEntry
*e =
NULL
;
139
while
((e =
av_dict_get
(s->
options
,
""
, e,
AV_DICT_IGNORE_SUFFIX
)))
140
av_log
(ctx,
AV_LOG_VERBOSE
,
"lavr option: %s=%s\n"
, e->
key
, e->
value
);
141
142
av_opt_set_dict
(s->
avr
, &s->
options
);
143
}
144
145
av_opt_set_int
(s->
avr
,
"in_channel_layout"
, inlink ->
channel_layout
, 0);
146
av_opt_set_int
(s->
avr
,
"out_channel_layout"
, outlink->
channel_layout
, 0);
147
av_opt_set_int
(s->
avr
,
"in_sample_fmt"
, inlink ->
format
, 0);
148
av_opt_set_int
(s->
avr
,
"out_sample_fmt"
, outlink->
format
, 0);
149
av_opt_set_int
(s->
avr
,
"in_sample_rate"
, inlink ->
sample_rate
, 0);
150
av_opt_set_int
(s->
avr
,
"out_sample_rate"
, outlink->
sample_rate
, 0);
151
152
if
((ret =
avresample_open
(s->
avr
)) < 0)
153
return
ret
;
154
155
outlink->
time_base
= (
AVRational
){ 1, outlink->
sample_rate
};
156
s->
next_pts
=
AV_NOPTS_VALUE
;
157
158
av_get_channel_layout_string
(buf1,
sizeof
(buf1),
159
-1, inlink ->channel_layout);
160
av_get_channel_layout_string
(buf2,
sizeof
(buf2),
161
-1, outlink->
channel_layout
);
162
av_log
(ctx,
AV_LOG_VERBOSE
,
163
"fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n"
,
164
av_get_sample_fmt_name
(inlink ->format), inlink ->
sample_rate
, buf1,
165
av_get_sample_fmt_name
(outlink->
format
), outlink->
sample_rate
, buf2);
166
167
return
0;
168
}
169
170
static
int
request_frame
(
AVFilterLink
*outlink)
171
{
172
AVFilterContext
*ctx = outlink->
src
;
173
ResampleContext
*
s
= ctx->
priv
;
174
int
ret
= 0;
175
176
s->
got_output
= 0;
177
while
(ret >= 0 && !s->
got_output
)
178
ret =
ff_request_frame
(ctx->
inputs
[0]);
179
180
/* flush the lavr delay buffer */
181
if
(ret ==
AVERROR_EOF
&& s->
avr
) {
182
AVFrame
*
frame
;
183
int
nb_samples
=
av_rescale_rnd
(
avresample_get_delay
(s->
avr
),
184
outlink->
sample_rate
,
185
ctx->
inputs
[0]->
sample_rate
,
186
AV_ROUND_UP
);
187
188
if
(!nb_samples)
189
return
ret
;
190
191
frame =
ff_get_audio_buffer
(outlink, nb_samples);
192
if
(!frame)
193
return
AVERROR
(ENOMEM);
194
195
ret =
avresample_convert
(s->
avr
, frame->
extended_data
,
196
frame->
linesize
[0], nb_samples,
197
NULL
, 0, 0);
198
if
(ret <= 0) {
199
av_frame_free
(&frame);
200
return
(ret == 0) ?
AVERROR_EOF
:
ret
;
201
}
202
203
frame->
pts
= s->
next_pts
;
204
return
ff_filter_frame
(outlink, frame);
205
}
206
return
ret
;
207
}
208
209
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*
in
)
210
{
211
AVFilterContext
*ctx = inlink->
dst
;
212
ResampleContext
*
s
= ctx->
priv
;
213
AVFilterLink
*outlink = ctx->
outputs
[0];
214
int
ret
;
215
216
if
(s->
avr
) {
217
AVFrame
*
out
;
218
int
delay,
nb_samples
;
219
220
/* maximum possible samples lavr can output */
221
delay =
avresample_get_delay
(s->
avr
);
222
nb_samples =
av_rescale_rnd
(in->
nb_samples
+ delay,
223
outlink->
sample_rate
, inlink->
sample_rate
,
224
AV_ROUND_UP
);
225
226
out =
ff_get_audio_buffer
(outlink, nb_samples);
227
if
(!out) {
228
ret =
AVERROR
(ENOMEM);
229
goto
fail;
230
}
231
232
ret =
avresample_convert
(s->
avr
, out->
extended_data
, out->
linesize
[0],
233
nb_samples, in->
extended_data
, in->
linesize
[0],
234
in->
nb_samples
);
235
if
(ret <= 0) {
236
av_frame_free
(&out);
237
if
(ret < 0)
238
goto
fail;
239
}
240
241
av_assert0
(!
avresample_available
(s->
avr
));
242
243
if
(s->
next_pts
==
AV_NOPTS_VALUE
) {
244
if
(in->
pts
==
AV_NOPTS_VALUE
) {
245
av_log
(ctx,
AV_LOG_WARNING
,
"First timestamp is missing, "
246
"assuming 0.\n"
);
247
s->
next_pts
= 0;
248
}
else
249
s->
next_pts
=
av_rescale_q
(in->
pts
, inlink->
time_base
,
250
outlink->
time_base
);
251
}
252
253
if
(ret > 0) {
254
out->
nb_samples
=
ret
;
255
if
(in->
pts
!=
AV_NOPTS_VALUE
) {
256
out->
pts
=
av_rescale_q
(in->
pts
, inlink->
time_base
,
257
outlink->
time_base
) -
258
av_rescale
(delay, outlink->
sample_rate
,
259
inlink->
sample_rate
);
260
}
else
261
out->
pts
= s->
next_pts
;
262
263
s->
next_pts
= out->
pts
+ out->
nb_samples
;
264
265
ret =
ff_filter_frame
(outlink, out);
266
s->
got_output
= 1;
267
}
268
269
fail:
270
av_frame_free
(&in);
271
}
else
{
272
in->
format
= outlink->
format
;
273
ret =
ff_filter_frame
(outlink, in);
274
s->
got_output
= 1;
275
}
276
277
return
ret
;
278
}
279
280
static
const
AVClass
*
resample_child_class_next
(
const
AVClass
*prev)
281
{
282
return
prev ?
NULL
:
avresample_get_class
();
283
}
284
285
static
void
*
resample_child_next
(
void
*obj,
void
*prev)
286
{
287
ResampleContext
*
s
= obj;
288
return
prev ?
NULL
: s->
avr
;
289
}
290
291
static
const
AVClass
resample_class
= {
292
.
class_name
=
"resample"
,
293
.item_name =
av_default_item_name
,
294
.version =
LIBAVUTIL_VERSION_INT
,
295
.child_class_next =
resample_child_class_next
,
296
.
child_next
=
resample_child_next
,
297
};
298
299
static
const
AVFilterPad
avfilter_af_resample_inputs
[] = {
300
{
301
.
name
=
"default"
,
302
.type =
AVMEDIA_TYPE_AUDIO
,
303
.filter_frame =
filter_frame
,
304
},
305
{
NULL
}
306
};
307
308
static
const
AVFilterPad
avfilter_af_resample_outputs
[] = {
309
{
310
.
name
=
"default"
,
311
.type =
AVMEDIA_TYPE_AUDIO
,
312
.config_props =
config_output
,
313
.request_frame =
request_frame
314
},
315
{
NULL
}
316
};
317
318
AVFilter
avfilter_af_resample
= {
319
.
name
=
"resample"
,
320
.description =
NULL_IF_CONFIG_SMALL
(
"Audio resampling and conversion."
),
321
.priv_size =
sizeof
(
ResampleContext
),
322
.priv_class = &resample_class,
323
324
.
init_dict
=
init
,
325
.
uninit
=
uninit
,
326
.
query_formats
=
query_formats
,
327
328
.
inputs
= avfilter_af_resample_inputs,
329
.
outputs
= avfilter_af_resample_outputs,
330
};
Generated on Fri May 24 2013 19:21:01 for FFmpeg by
1.8.2