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