2 * Copyright (c) 2013 Paul B Mahol
4 * This file is part of FFmpeg.
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.
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.
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
21 #include "libavutil/avstring.h"
22 #include "libavutil/opt.h"
23 #include "libavutil/samplefmt.h"
28 typedef struct ChanDelay
{
35 typedef struct AudioDelayContext
{
44 void (*delay_channel
)(ChanDelay
*d
, int nb_samples
,
45 const uint8_t *src
, uint8_t *dst
);
48 #define OFFSET(x) offsetof(AudioDelayContext, x)
49 #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
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
},
56 AVFILTER_DEFINE_CLASS(adelay
);
58 static int query_formats(AVFilterContext
*ctx
)
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
,
68 layouts
= ff_all_channel_layouts();
70 return AVERROR(ENOMEM
);
71 ff_set_common_channel_layouts(ctx
, layouts
);
73 formats
= ff_make_format_list(sample_fmts
);
75 return AVERROR(ENOMEM
);
76 ff_set_common_formats(ctx
, formats
);
78 formats
= ff_all_samplerates();
80 return AVERROR(ENOMEM
);
81 ff_set_common_samplerates(ctx
, formats
);
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) \
90 const type *src = (type *)ssrc; \
91 type *dst = (type *)ddst; \
92 type *samples = (type *)d->samples; \
94 while (nb_samples) { \
95 if (d->delay_index < d->delay) { \
96 const int len = FFMIN(nb_samples, d->delay - d->delay_index); \
98 memcpy(&samples[d->delay_index], src, len * sizeof(type)); \
99 memset(dst, fill, len * sizeof(type)); \
100 d->delay_index += len; \
105 *dst = samples[d->index]; \
106 samples[d->index] = *src; \
110 d->index = d->index >= d->delay ? 0 : d->index; \
115 DELAY(u8
, uint8_t, 0x80)
116 DELAY(s16
, int16_t, 0)
117 DELAY(s32
, int32_t, 0)
119 DELAY(dbl
, double, 0)
121 static int config_input(AVFilterLink
*inlink
)
123 AVFilterContext
*ctx
= inlink
->dst
;
124 AudioDelayContext
*s
= ctx
->priv
;
125 char *p
, *arg
, *saveptr
= NULL
;
128 s
->chandelay
= av_calloc(inlink
->channels
, sizeof(*s
->chandelay
));
130 return AVERROR(ENOMEM
);
131 s
->nb_delays
= inlink
->channels
;
132 s
->block_align
= av_get_bytes_per_sample(inlink
->format
);
135 for (i
= 0; i
< s
->nb_delays
; i
++) {
136 ChanDelay
*d
= &s
->chandelay
[i
];
139 if (!(arg
= av_strtok(p
, "|", &saveptr
)))
143 sscanf(arg
, "%f", &delay
);
145 d
->delay
= delay
* inlink
->sample_rate
/ 1000.0;
147 av_log(ctx
, AV_LOG_ERROR
, "Delay must be non negative number.\n");
148 return AVERROR(EINVAL
);
152 for (i
= 0; i
< s
->nb_delays
; i
++) {
153 ChanDelay
*d
= &s
->chandelay
[i
];
158 d
->samples
= av_malloc_array(d
->delay
, s
->block_align
);
160 return AVERROR(ENOMEM
);
162 s
->max_delay
= FFMAX(s
->max_delay
, d
->delay
);
166 av_log(ctx
, AV_LOG_ERROR
, "At least one delay >0 must be specified.\n");
167 return AVERROR(EINVAL
);
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;
181 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*frame
)
183 AVFilterContext
*ctx
= inlink
->dst
;
184 AudioDelayContext
*s
= ctx
->priv
;
188 if (ctx
->is_disabled
|| !s
->delays
)
189 return ff_filter_frame(ctx
->outputs
[0], frame
);
191 out_frame
= ff_get_audio_buffer(inlink
, frame
->nb_samples
);
193 return AVERROR(ENOMEM
);
194 av_frame_copy_props(out_frame
, frame
);
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
];
202 memcpy(dst
, src
, frame
->nb_samples
* s
->block_align
);
204 s
->delay_channel(d
, frame
->nb_samples
, src
, dst
);
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
);
212 static int request_frame(AVFilterLink
*outlink
)
214 AVFilterContext
*ctx
= outlink
->src
;
215 AudioDelayContext
*s
= ctx
->priv
;
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);
223 frame
= ff_get_audio_buffer(outlink
, nb_samples
);
225 return AVERROR(ENOMEM
);
226 s
->max_delay
-= nb_samples
;
228 av_samples_set_silence(frame
->extended_data
, 0,
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
);
237 ret
= filter_frame(ctx
->inputs
[0], frame
);
243 static av_cold
void uninit(AVFilterContext
*ctx
)
245 AudioDelayContext
*s
= ctx
->priv
;
248 for (i
= 0; i
< s
->nb_delays
; i
++)
249 av_free(s
->chandelay
[i
].samples
);
250 av_freep(&s
->chandelay
);
253 static const AVFilterPad adelay_inputs
[] = {
256 .type
= AVMEDIA_TYPE_AUDIO
,
257 .config_props
= config_input
,
258 .filter_frame
= filter_frame
,
263 static const AVFilterPad adelay_outputs
[] = {
266 .request_frame
= request_frame
,
267 .type
= AVMEDIA_TYPE_AUDIO
,
272 AVFilter ff_af_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
,
279 .inputs
= adelay_inputs
,
280 .outputs
= adelay_outputs
,
281 .flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
,