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_adelay.c
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2013 Paul B Mahol
3
*
4
* This file is part of FFmpeg.
5
*
6
* FFmpeg is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* FFmpeg is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with FFmpeg; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include "
libavutil/avstring.h
"
22
#include "
libavutil/opt.h
"
23
#include "
libavutil/samplefmt.h
"
24
#include "
avfilter.h
"
25
#include "
audio.h
"
26
#include "
internal.h
"
27
28
typedef
struct
ChanDelay
{
29
int
delay
;
30
unsigned
delay_index
;
31
unsigned
index
;
32
uint8_t
*
samples
;
33
}
ChanDelay
;
34
35
typedef
struct
AudioDelayContext
{
36
const
AVClass
*
class
;
37
char
*
delays
;
38
ChanDelay
*
chandelay
;
39
int
nb_delays
;
40
int
block_align
;
41
unsigned
max_delay
;
42
int64_t
next_pts
;
43
44
void
(*
delay_channel
)(
ChanDelay
*d,
int
nb_samples,
45
const
uint8_t
*
src
,
uint8_t
*dst);
46
}
AudioDelayContext
;
47
48
#define OFFSET(x) offsetof(AudioDelayContext, x)
49
#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
50
51
static
const
AVOption
adelay_options
[] = {
52
{
"delays"
,
"set list of delays for each channel"
,
OFFSET
(delays),
AV_OPT_TYPE_STRING
, {.str=NULL}, 0, 0,
A
},
53
{ NULL }
54
};
55
56
AVFILTER_DEFINE_CLASS
(adelay);
57
58
static
int
query_formats
(
AVFilterContext
*ctx)
59
{
60
AVFilterChannelLayouts
*
layouts
;
61
AVFilterFormats
*
formats
;
62
static
const
enum
AVSampleFormat
sample_fmts
[] = {
63
AV_SAMPLE_FMT_U8P
,
AV_SAMPLE_FMT_S16P
,
AV_SAMPLE_FMT_S32P
,
64
AV_SAMPLE_FMT_FLTP
,
AV_SAMPLE_FMT_DBLP
,
65
AV_SAMPLE_FMT_NONE
66
};
67
68
layouts =
ff_all_channel_layouts
();
69
if
(!layouts)
70
return
AVERROR
(ENOMEM);
71
ff_set_common_channel_layouts
(ctx, layouts);
72
73
formats =
ff_make_format_list
(sample_fmts);
74
if
(!formats)
75
return
AVERROR
(ENOMEM);
76
ff_set_common_formats
(ctx, formats);
77
78
formats =
ff_all_samplerates
();
79
if
(!formats)
80
return
AVERROR
(ENOMEM);
81
ff_set_common_samplerates
(ctx, formats);
82
83
return
0;
84
}
85
86
#define DELAY(name, type, fill) \
87
static void delay_channel_## name ##p(ChanDelay *d, int nb_samples, \
88
const uint8_t *ssrc, uint8_t *ddst) \
89
{ \
90
const type *src = (type *)ssrc; \
91
type *dst = (type *)ddst; \
92
type *samples = (type *)d->samples; \
93
\
94
while (nb_samples) { \
95
if (d->delay_index < d->delay) { \
96
const int len = FFMIN(nb_samples, d->delay - d->delay_index); \
97
\
98
memcpy(&samples[d->delay_index], src, len * sizeof(type)); \
99
memset(dst, fill, len * sizeof(type)); \
100
d->delay_index += len; \
101
src += len; \
102
dst += len; \
103
nb_samples -= len; \
104
} else { \
105
*dst = samples[d->index]; \
106
samples[d->index] = *src; \
107
nb_samples--; \
108
d->index++; \
109
src++, dst++; \
110
d->index = d->index >= d->delay ? 0 : d->index; \
111
} \
112
} \
113
}
114
115
DELAY
(u8,
uint8_t
, 0x80)
116
DELAY
(s16, int16_t, 0)
117
DELAY
(s32,
int32_t
, 0)
118
DELAY
(flt,
float
, 0)
119
DELAY
(dbl,
double
, 0)
120
121
static
int
config_input
(
AVFilterLink
*inlink)
122
{
123
AVFilterContext
*ctx = inlink->dst;
124
AudioDelayContext
*
s
= ctx->
priv
;
125
char
*p, *
arg
, *saveptr = NULL;
126
int
i;
127
128
s->
chandelay
=
av_calloc
(inlink->channels,
sizeof
(*s->
chandelay
));
129
if
(!s->
chandelay
)
130
return
AVERROR
(ENOMEM);
131
s->
nb_delays
= inlink->channels;
132
s->
block_align
=
av_get_bytes_per_sample
(inlink->format);
133
134
p = s->
delays
;
135
for
(i = 0; i < s->
nb_delays
; i++) {
136
ChanDelay
*d = &s->
chandelay
[i];
137
float
delay;
138
139
if
(!(arg =
av_strtok
(p,
"|"
, &saveptr)))
140
break
;
141
142
p = NULL;
143
sscanf(arg,
"%f"
, &delay);
144
145
d->
delay
= delay * inlink->sample_rate / 1000.0;
146
if
(d->
delay
< 0) {
147
av_log
(ctx,
AV_LOG_ERROR
,
"Delay must be non negative number.\n"
);
148
return
AVERROR
(EINVAL);
149
}
150
}
151
152
for
(i = 0; i < s->
nb_delays
; i++) {
153
ChanDelay
*d = &s->
chandelay
[i];
154
155
if
(!d->
delay
)
156
continue
;
157
158
d->
samples
= av_malloc_array(d->
delay
, s->
block_align
);
159
if
(!d->
samples
)
160
return
AVERROR
(ENOMEM);
161
162
s->
max_delay
=
FFMAX
(s->
max_delay
, d->
delay
);
163
}
164
165
if
(!s->
max_delay
) {
166
av_log
(ctx,
AV_LOG_ERROR
,
"At least one delay >0 must be specified.\n"
);
167
return
AVERROR
(EINVAL);
168
}
169
170
switch
(inlink->format) {
171
case
AV_SAMPLE_FMT_U8P
: s->
delay_channel
= delay_channel_u8p ;
break
;
172
case
AV_SAMPLE_FMT_S16P
: s->
delay_channel
= delay_channel_s16p;
break
;
173
case
AV_SAMPLE_FMT_S32P
: s->
delay_channel
= delay_channel_s32p;
break
;
174
case
AV_SAMPLE_FMT_FLTP
: s->
delay_channel
= delay_channel_fltp;
break
;
175
case
AV_SAMPLE_FMT_DBLP
: s->
delay_channel
= delay_channel_dblp;
break
;
176
}
177
178
return
0;
179
}
180
181
static
int
filter_frame
(
AVFilterLink
*inlink,
AVFrame
*
frame
)
182
{
183
AVFilterContext
*ctx = inlink->
dst
;
184
AudioDelayContext
*
s
= ctx->
priv
;
185
AVFrame
*out_frame;
186
int
i;
187
188
if
(ctx->
is_disabled
|| !s->
delays
)
189
return
ff_filter_frame
(ctx->
outputs
[0], frame);
190
191
out_frame =
ff_get_audio_buffer
(inlink, frame->
nb_samples
);
192
if
(!out_frame)
193
return
AVERROR
(ENOMEM);
194
av_frame_copy_props
(out_frame, frame);
195
196
for
(i = 0; i < s->
nb_delays
; i++) {
197
ChanDelay
*d = &s->
chandelay
[i];
198
const
uint8_t
*
src
= frame->
extended_data
[i];
199
uint8_t
*dst = out_frame->
extended_data
[i];
200
201
if
(!d->
delay
)
202
memcpy(dst, src, frame->
nb_samples
* s->
block_align
);
203
else
204
s->
delay_channel
(d, frame->
nb_samples
, src, dst);
205
}
206
207
s->
next_pts
= frame->
pts
+
av_rescale_q
(frame->
nb_samples
, (
AVRational
){1, inlink->
sample_rate
}, inlink->time_base);
208
av_frame_free
(&
frame
);
209
return
ff_filter_frame
(ctx->outputs[0], out_frame);
210
}
211
212
static
int
request_frame
(
AVFilterLink
*outlink)
213
{
214
AVFilterContext
*ctx = outlink->
src
;
215
AudioDelayContext
*
s
= ctx->
priv
;
216
int
ret
;
217
218
ret =
ff_request_frame
(ctx->
inputs
[0]);
219
if
(ret ==
AVERROR_EOF
&& !ctx->
is_disabled
&& s->
max_delay
) {
220
int
nb_samples =
FFMIN
(s->
max_delay
, 2048);
221
AVFrame
*
frame
;
222
223
frame =
ff_get_audio_buffer
(outlink, nb_samples);
224
if
(!frame)
225
return
AVERROR
(ENOMEM);
226
s->
max_delay
-= nb_samples;
227
228
av_samples_set_silence
(frame->
extended_data
, 0,
229
frame->
nb_samples
,
230
outlink->
channels
,
231
frame->
format
);
232
233
frame->
pts
= s->
next_pts
;
234
if
(s->
next_pts
!=
AV_NOPTS_VALUE
)
235
s->
next_pts
+=
av_rescale_q
(nb_samples, (
AVRational
){1, outlink->
sample_rate
}, outlink->
time_base
);
236
237
ret =
filter_frame
(ctx->
inputs
[0], frame);
238
}
239
240
return
ret
;
241
}
242
243
static
av_cold
void
uninit
(
AVFilterContext
*ctx)
244
{
245
AudioDelayContext
*
s
= ctx->
priv
;
246
int
i;
247
248
for
(i = 0; i < s->
nb_delays
; i++)
249
av_free
(s->
chandelay
[i].
samples
);
250
av_freep
(&s->
chandelay
);
251
}
252
253
static
const
AVFilterPad
adelay_inputs
[] = {
254
{
255
.
name
=
"default"
,
256
.type =
AVMEDIA_TYPE_AUDIO
,
257
.config_props =
config_input
,
258
.filter_frame =
filter_frame
,
259
},
260
{ NULL }
261
};
262
263
static
const
AVFilterPad
adelay_outputs
[] = {
264
{
265
.
name
=
"default"
,
266
.request_frame =
request_frame
,
267
.type =
AVMEDIA_TYPE_AUDIO
,
268
},
269
{ NULL }
270
};
271
272
AVFilter
ff_af_adelay
= {
273
.
name
=
"adelay"
,
274
.description =
NULL_IF_CONFIG_SMALL
(
"Delay one or more audio channels."
),
275
.query_formats =
query_formats
,
276
.priv_size =
sizeof
(
AudioDelayContext
),
277
.priv_class = &adelay_class,
278
.
uninit
=
uninit
,
279
.
inputs
= adelay_inputs,
280
.
outputs
= adelay_outputs,
281
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
,
282
};
Generated on Sun Mar 23 2014 23:50:07 for FFmpeg by
1.8.2