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/mathematics.h
"
29
#include "
libavutil/opt.h
"
30
31
#include "
libavresample/avresample.h
"
32
33
#include "
audio.h
"
34
#include "
avfilter.h
"
35
#include "
formats.h
"
36
#include "
internal.h
"
37
38
typedef
struct
ResampleContext
{
39
AVAudioResampleContext
*
avr
;
40
41
int64_t
next_pts
;
42
43
/* set by filter_frame() to signal an output frame to request_frame() */
44
int
got_output
;
45
}
ResampleContext
;
46
47
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
48
{
49
ResampleContext
*s = ctx->
priv
;
50
51
if
(s->
avr
) {
52
avresample_close
(s->
avr
);
53
avresample_free
(&s->
avr
);
54
}
55
}
56
57
static
int
query_formats
(
AVFilterContext
*ctx)
58
{
59
AVFilterLink
*inlink = ctx->
inputs
[0];
60
AVFilterLink
*outlink = ctx->
outputs
[0];
61
62
AVFilterFormats
*in_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
63
AVFilterFormats
*out_formats =
ff_all_formats
(
AVMEDIA_TYPE_AUDIO
);
64
AVFilterFormats
*in_samplerates =
ff_all_samplerates
();
65
AVFilterFormats
*out_samplerates =
ff_all_samplerates
();
66
AVFilterChannelLayouts
*in_layouts =
ff_all_channel_layouts
();
67
AVFilterChannelLayouts
*out_layouts =
ff_all_channel_layouts
();
68
69
ff_formats_ref
(in_formats, &inlink->
out_formats
);
70
ff_formats_ref
(out_formats, &outlink->
in_formats
);
71
72
ff_formats_ref
(in_samplerates, &inlink->
out_samplerates
);
73
ff_formats_ref
(out_samplerates, &outlink->
in_samplerates
);
74
75
ff_channel_layouts_ref
(in_layouts, &inlink->
out_channel_layouts
);
76
ff_channel_layouts_ref
(out_layouts, &outlink->
in_channel_layouts
);
77
78
return
0;
79
}
80
81
static
int
config_output
(
AVFilterLink
*outlink)
82
{
83
AVFilterContext
*ctx = outlink->
src
;
84
AVFilterLink
*inlink = ctx->
inputs
[0];
85
ResampleContext
*s = ctx->
priv
;
86
char
buf1[64], buf2[64];
87
int
ret;
88
89
if
(s->
avr
) {
90
avresample_close
(s->
avr
);
91
avresample_free
(&s->
avr
);
92
}
93
94
if
(inlink->
channel_layout
== outlink->
channel_layout
&&
95
inlink->
sample_rate
== outlink->
sample_rate
&&
96
(inlink->
format
== outlink->
format
||
97
(
av_get_channel_layout_nb_channels
(inlink->
channel_layout
) == 1 &&
98
av_get_channel_layout_nb_channels
(outlink->
channel_layout
) == 1 &&
99
av_get_planar_sample_fmt
(inlink->
format
) ==
100
av_get_planar_sample_fmt
(outlink->
format
))))
101
return
0;
102
103
if
(!(s->
avr
=
avresample_alloc_context
()))
104
return
AVERROR
(ENOMEM);
105
106
av_opt_set_int
(s->
avr
,
"in_channel_layout"
, inlink ->
channel_layout
, 0);
107
av_opt_set_int
(s->
avr
,
"out_channel_layout"
, outlink->
channel_layout
, 0);
108
av_opt_set_int
(s->
avr
,
"in_sample_fmt"
, inlink ->
format
, 0);
109
av_opt_set_int
(s->
avr
,
"out_sample_fmt"
, outlink->
format
, 0);
110
av_opt_set_int
(s->
avr
,
"in_sample_rate"
, inlink ->
sample_rate
, 0);
111
av_opt_set_int
(s->
avr
,
"out_sample_rate"
, outlink->
sample_rate
, 0);
112
113
if
((ret =
avresample_open
(s->
avr
)) < 0)
114
return
ret;
115
116
outlink->
time_base
= (
AVRational
){ 1, outlink->
sample_rate
};
117
s->
next_pts
=
AV_NOPTS_VALUE
;
118
119
av_get_channel_layout_string
(buf1,
sizeof
(buf1),
120
-1, inlink ->channel_layout);
121
av_get_channel_layout_string
(buf2,
sizeof
(buf2),
122
-1, outlink->
channel_layout
);
123
av_log
(ctx,
AV_LOG_VERBOSE
,
124
"fmt:%s srate:%d cl:%s -> fmt:%s srate:%d cl:%s\n"
,
125
av_get_sample_fmt_name
(inlink ->format), inlink ->
sample_rate
, buf1,
126
av_get_sample_fmt_name
(outlink->
format
), outlink->
sample_rate
, buf2);
127
128
return
0;
129
}
130
131
static
int
request_frame
(
AVFilterLink
*outlink)
132
{
133
AVFilterContext
*ctx = outlink->
src
;
134
ResampleContext
*s = ctx->
priv
;
135
int
ret = 0;
136
137
s->
got_output
= 0;
138
while
(ret >= 0 && !s->
got_output
)
139
ret =
ff_request_frame
(ctx->
inputs
[0]);
140
141
/* flush the lavr delay buffer */
142
if
(ret ==
AVERROR_EOF
&& s->
avr
) {
143
AVFilterBufferRef
*buf;
144
int
nb_samples
=
av_rescale_rnd
(
avresample_get_delay
(s->
avr
),
145
outlink->
sample_rate
,
146
ctx->
inputs
[0]->
sample_rate
,
147
AV_ROUND_UP
);
148
149
if
(!nb_samples)
150
return
ret;
151
152
buf =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, nb_samples);
153
if
(!buf)
154
return
AVERROR
(ENOMEM);
155
156
ret =
avresample_convert
(s->
avr
, buf->
extended_data
,
157
buf->
linesize
[0], nb_samples,
158
NULL
, 0, 0);
159
if
(ret <= 0) {
160
avfilter_unref_buffer
(buf);
161
return
(ret == 0) ?
AVERROR_EOF
: ret;
162
}
163
164
buf->
pts
= s->
next_pts
;
165
return
ff_filter_frame
(outlink, buf);
166
}
167
return
ret;
168
}
169
170
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFilterBufferRef
*buf)
171
{
172
AVFilterContext
*ctx = inlink->
dst
;
173
ResampleContext
*s = ctx->
priv
;
174
AVFilterLink
*outlink = ctx->
outputs
[0];
175
int
ret;
176
177
if
(s->
avr
) {
178
AVFilterBufferRef
*buf_out;
179
int
delay,
nb_samples
;
180
181
/* maximum possible samples lavr can output */
182
delay =
avresample_get_delay
(s->
avr
);
183
nb_samples =
av_rescale_rnd
(buf->
audio
->
nb_samples
+ delay,
184
outlink->
sample_rate
, inlink->
sample_rate
,
185
AV_ROUND_UP
);
186
187
buf_out =
ff_get_audio_buffer
(outlink,
AV_PERM_WRITE
, nb_samples);
188
if
(!buf_out) {
189
ret =
AVERROR
(ENOMEM);
190
goto
fail;
191
}
192
193
ret =
avresample_convert
(s->
avr
, buf_out->
extended_data
,
194
buf_out->
linesize
[0], nb_samples,
195
buf->
extended_data
, buf->
linesize
[0],
196
buf->
audio
->
nb_samples
);
197
if
(ret <= 0) {
198
avfilter_unref_buffer
(buf_out);
199
if
(ret < 0)
200
goto
fail;
201
}
202
203
av_assert0
(!
avresample_available
(s->
avr
));
204
205
if
(s->
next_pts
==
AV_NOPTS_VALUE
) {
206
if
(buf->
pts
==
AV_NOPTS_VALUE
) {
207
av_log
(ctx,
AV_LOG_WARNING
,
"First timestamp is missing, "
208
"assuming 0.\n"
);
209
s->
next_pts
= 0;
210
}
else
211
s->
next_pts
=
av_rescale_q
(buf->
pts
, inlink->
time_base
,
212
outlink->
time_base
);
213
}
214
215
if
(ret > 0) {
216
buf_out->
audio
->
nb_samples
= ret;
217
if
(buf->
pts
!=
AV_NOPTS_VALUE
) {
218
buf_out->
pts
=
av_rescale_q
(buf->
pts
, inlink->
time_base
,
219
outlink->
time_base
) -
220
av_rescale
(delay, outlink->
sample_rate
,
221
inlink->
sample_rate
);
222
}
else
223
buf_out->
pts
= s->
next_pts
;
224
225
s->
next_pts
= buf_out->
pts
+ buf_out->
audio
->
nb_samples
;
226
227
ret =
ff_filter_frame
(outlink, buf_out);
228
s->
got_output
= 1;
229
}
230
231
fail:
232
avfilter_unref_buffer
(buf);
233
}
else
{
234
buf->
format
= outlink->
format
;
235
ret =
ff_filter_frame
(outlink, buf);
236
s->
got_output
= 1;
237
}
238
239
return
ret;
240
}
241
242
static
const
AVFilterPad
avfilter_af_resample_inputs
[] = {
243
{
244
.
name
=
"default"
,
245
.type =
AVMEDIA_TYPE_AUDIO
,
246
.filter_frame =
filter_frame
,
247
.min_perms =
AV_PERM_READ
248
},
249
{
NULL
}
250
};
251
252
static
const
AVFilterPad
avfilter_af_resample_outputs
[] = {
253
{
254
.
name
=
"default"
,
255
.type =
AVMEDIA_TYPE_AUDIO
,
256
.config_props =
config_output
,
257
.request_frame =
request_frame
258
},
259
{
NULL
}
260
};
261
262
AVFilter
avfilter_af_resample
= {
263
.
name
=
"resample"
,
264
.description =
NULL_IF_CONFIG_SMALL
(
"Audio resampling and conversion."
),
265
.priv_size =
sizeof
(
ResampleContext
),
266
267
.
uninit
=
uninit
,
268
.
query_formats
=
query_formats
,
269
270
.
inputs
= avfilter_af_resample_inputs,
271
.
outputs
= avfilter_af_resample_outputs,
272
};
Generated on Sat May 25 2013 03:58:44 for FFmpeg by
1.8.2