GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavfilter/af_adelay.c Lines: 104 146 71.2 %
Date: 2020-10-23 17:01:47 Branches: 58 124 46.8 %

Line Branch Exec Source
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/eval.h"
23
#include "libavutil/opt.h"
24
#include "libavutil/samplefmt.h"
25
#include "avfilter.h"
26
#include "audio.h"
27
#include "filters.h"
28
#include "internal.h"
29
30
typedef struct ChanDelay {
31
    int delay;
32
    unsigned delay_index;
33
    unsigned index;
34
    uint8_t *samples;
35
} ChanDelay;
36
37
typedef struct AudioDelayContext {
38
    const AVClass *class;
39
    int all;
40
    char *delays;
41
    ChanDelay *chandelay;
42
    int nb_delays;
43
    int block_align;
44
    int64_t padding;
45
    int64_t max_delay;
46
    int64_t next_pts;
47
    int eof;
48
49
    void (*delay_channel)(ChanDelay *d, int nb_samples,
50
                          const uint8_t *src, uint8_t *dst);
51
} AudioDelayContext;
52
53
#define OFFSET(x) offsetof(AudioDelayContext, x)
54
#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
55
56
static const AVOption adelay_options[] = {
57
    { "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A },
58
    { "all",    "use last available delay for remained channels", OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A },
59
    { NULL }
60
};
61
62
AVFILTER_DEFINE_CLASS(adelay);
63
64
1
static int query_formats(AVFilterContext *ctx)
65
{
66
    AVFilterChannelLayouts *layouts;
67
    AVFilterFormats *formats;
68
    static const enum AVSampleFormat sample_fmts[] = {
69
        AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
70
        AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
71
        AV_SAMPLE_FMT_NONE
72
    };
73
    int ret;
74
75
1
    layouts = ff_all_channel_counts();
76
1
    if (!layouts)
77
        return AVERROR(ENOMEM);
78
1
    ret = ff_set_common_channel_layouts(ctx, layouts);
79
1
    if (ret < 0)
80
        return ret;
81
82
1
    formats = ff_make_format_list(sample_fmts);
83
1
    if (!formats)
84
        return AVERROR(ENOMEM);
85
1
    ret = ff_set_common_formats(ctx, formats);
86
1
    if (ret < 0)
87
        return ret;
88
89
1
    formats = ff_all_samplerates();
90
1
    if (!formats)
91
        return AVERROR(ENOMEM);
92
1
    return ff_set_common_samplerates(ctx, formats);
93
}
94
95
#define DELAY(name, type, fill)                                           \
96
static void delay_channel_## name ##p(ChanDelay *d, int nb_samples,       \
97
                                      const uint8_t *ssrc, uint8_t *ddst) \
98
{                                                                         \
99
    const type *src = (type *)ssrc;                                       \
100
    type *dst = (type *)ddst;                                             \
101
    type *samples = (type *)d->samples;                                   \
102
                                                                          \
103
    while (nb_samples) {                                                  \
104
        if (d->delay_index < d->delay) {                                  \
105
            const int len = FFMIN(nb_samples, d->delay - d->delay_index); \
106
                                                                          \
107
            memcpy(&samples[d->delay_index], src, len * sizeof(type));    \
108
            memset(dst, fill, len * sizeof(type));                        \
109
            d->delay_index += len;                                        \
110
            src += len;                                                   \
111
            dst += len;                                                   \
112
            nb_samples -= len;                                            \
113
        } else {                                                          \
114
            *dst = samples[d->index];                                     \
115
            samples[d->index] = *src;                                     \
116
            nb_samples--;                                                 \
117
            d->index++;                                                   \
118
            src++, dst++;                                                 \
119
            d->index = d->index >= d->delay ? 0 : d->index;               \
120
        }                                                                 \
121
    }                                                                     \
122
}
123
124
DELAY(u8,  uint8_t, 0x80)
125

264862
DELAY(s16, int16_t, 0)
126
DELAY(s32, int32_t, 0)
127
DELAY(flt, float,   0)
128
DELAY(dbl, double,  0)
129
130
1
static int config_input(AVFilterLink *inlink)
131
{
132
1
    AVFilterContext *ctx = inlink->dst;
133
1
    AudioDelayContext *s = ctx->priv;
134
1
    char *p, *arg, *saveptr = NULL;
135
    int i;
136
137
1
    s->chandelay = av_calloc(inlink->channels, sizeof(*s->chandelay));
138
1
    if (!s->chandelay)
139
        return AVERROR(ENOMEM);
140
1
    s->nb_delays = inlink->channels;
141
1
    s->block_align = av_get_bytes_per_sample(inlink->format);
142
143
1
    p = s->delays;
144
2
    for (i = 0; i < s->nb_delays; i++) {
145
2
        ChanDelay *d = &s->chandelay[i];
146
        float delay, div;
147
2
        char type = 0;
148
        int ret;
149
150
2
        if (!(arg = av_strtok(p, "|", &saveptr)))
151
1
            break;
152
153
1
        p = NULL;
154
155
1
        ret = av_sscanf(arg, "%d%c", &d->delay, &type);
156

1
        if (ret != 2 || type != 'S') {
157
1
            div = type == 's' ? 1.0 : 1000.0;
158
1
            if (av_sscanf(arg, "%f", &delay) != 1) {
159
                av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n");
160
                return AVERROR(EINVAL);
161
            }
162
1
            d->delay = delay * inlink->sample_rate / div;
163
        }
164
165
1
        if (d->delay < 0) {
166
            av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n");
167
            return AVERROR(EINVAL);
168
        }
169
    }
170
171

1
    if (s->all && i) {
172
        for (int j = i; j < s->nb_delays; j++)
173
            s->chandelay[j].delay = s->chandelay[i-1].delay;
174
    }
175
176
1
    s->padding = s->chandelay[0].delay;
177
2
    for (i = 1; i < s->nb_delays; i++) {
178
1
        ChanDelay *d = &s->chandelay[i];
179
180
1
        s->padding = FFMIN(s->padding, d->delay);
181
    }
182
183
1
    if (s->padding) {
184
        for (i = 0; i < s->nb_delays; i++) {
185
            ChanDelay *d = &s->chandelay[i];
186
187
            d->delay -= s->padding;
188
        }
189
    }
190
191
3
    for (i = 0; i < s->nb_delays; i++) {
192
2
        ChanDelay *d = &s->chandelay[i];
193
194
2
        if (!d->delay)
195
1
            continue;
196
197
1
        d->samples = av_malloc_array(d->delay, s->block_align);
198
1
        if (!d->samples)
199
            return AVERROR(ENOMEM);
200
201
1
        s->max_delay = FFMAX(s->max_delay, d->delay);
202
    }
203
204

1
    switch (inlink->format) {
205
    case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; break;
206
1
    case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; break;
207
    case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; break;
208
    case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; break;
209
    case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; break;
210
    }
211
212
1
    return 0;
213
}
214
215
260
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
216
{
217
260
    AVFilterContext *ctx = inlink->dst;
218
260
    AudioDelayContext *s = ctx->priv;
219
    AVFrame *out_frame;
220
    int i;
221
222

260
    if (ctx->is_disabled || !s->delays)
223
        return ff_filter_frame(ctx->outputs[0], frame);
224
225
260
    out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples);
226
260
    if (!out_frame) {
227
        av_frame_free(&frame);
228
        return AVERROR(ENOMEM);
229
    }
230
260
    av_frame_copy_props(out_frame, frame);
231
232
780
    for (i = 0; i < s->nb_delays; i++) {
233
520
        ChanDelay *d = &s->chandelay[i];
234
520
        const uint8_t *src = frame->extended_data[i];
235
520
        uint8_t *dst = out_frame->extended_data[i];
236
237
520
        if (!d->delay)
238
260
            memcpy(dst, src, frame->nb_samples * s->block_align);
239
        else
240
260
            s->delay_channel(d, frame->nb_samples, src, dst);
241
    }
242
243
260
    out_frame->pts = s->next_pts;
244
260
    s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base);
245
260
    av_frame_free(&frame);
246
260
    return ff_filter_frame(ctx->outputs[0], out_frame);
247
}
248
249
521
static int activate(AVFilterContext *ctx)
250
{
251
521
    AVFilterLink *inlink = ctx->inputs[0];
252
521
    AVFilterLink *outlink = ctx->outputs[0];
253
521
    AudioDelayContext *s = ctx->priv;
254
521
    AVFrame *frame = NULL;
255
    int ret, status;
256
    int64_t pts;
257
258
521
    FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
259
260
520
    if (s->padding) {
261
        int nb_samples = FFMIN(s->padding, 2048);
262
263
        frame = ff_get_audio_buffer(outlink, nb_samples);
264
        if (!frame)
265
            return AVERROR(ENOMEM);
266
        s->padding -= nb_samples;
267
268
        av_samples_set_silence(frame->extended_data, 0,
269
                               frame->nb_samples,
270
                               outlink->channels,
271
                               frame->format);
272
273
        frame->pts = s->next_pts;
274
        if (s->next_pts != AV_NOPTS_VALUE)
275
            s->next_pts += av_rescale_q(nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
276
277
        return ff_filter_frame(outlink, frame);
278
    }
279
280
520
    ret = ff_inlink_consume_frame(inlink, &frame);
281
520
    if (ret < 0)
282
        return ret;
283
284
520
    if (ret > 0)
285
259
        return filter_frame(inlink, frame);
286
287
261
    if (ff_inlink_acknowledge_status(inlink, &status, &pts)) {
288
2
        if (status == AVERROR_EOF)
289
2
            s->eof = 1;
290
    }
291
292

261
    if (s->eof && s->max_delay) {
293
1
        int nb_samples = FFMIN(s->max_delay, 2048);
294
295
1
        frame = ff_get_audio_buffer(outlink, nb_samples);
296
1
        if (!frame)
297
            return AVERROR(ENOMEM);
298
1
        s->max_delay -= nb_samples;
299
300
1
        av_samples_set_silence(frame->extended_data, 0,
301
1
                               frame->nb_samples,
302
                               outlink->channels,
303
1
                               frame->format);
304
305
1
        frame->pts = s->next_pts;
306
1
        return filter_frame(inlink, frame);
307
    }
308
309

260
    if (s->eof && s->max_delay == 0) {
310
1
        ff_outlink_set_status(outlink, AVERROR_EOF, s->next_pts);
311
1
        return 0;
312
    }
313
314
259
    if (!s->eof)
315
259
        FF_FILTER_FORWARD_WANTED(outlink, inlink);
316
317
    return FFERROR_NOT_READY;
318
}
319
320
1
static av_cold void uninit(AVFilterContext *ctx)
321
{
322
1
    AudioDelayContext *s = ctx->priv;
323
324
1
    if (s->chandelay) {
325
3
        for (int i = 0; i < s->nb_delays; i++)
326
2
            av_freep(&s->chandelay[i].samples);
327
    }
328
1
    av_freep(&s->chandelay);
329
1
}
330
331
static const AVFilterPad adelay_inputs[] = {
332
    {
333
        .name         = "default",
334
        .type         = AVMEDIA_TYPE_AUDIO,
335
        .config_props = config_input,
336
    },
337
    { NULL }
338
};
339
340
static const AVFilterPad adelay_outputs[] = {
341
    {
342
        .name = "default",
343
        .type = AVMEDIA_TYPE_AUDIO,
344
    },
345
    { NULL }
346
};
347
348
AVFilter ff_af_adelay = {
349
    .name          = "adelay",
350
    .description   = NULL_IF_CONFIG_SMALL("Delay one or more audio channels."),
351
    .query_formats = query_formats,
352
    .priv_size     = sizeof(AudioDelayContext),
353
    .priv_class    = &adelay_class,
354
    .activate      = activate,
355
    .uninit        = uninit,
356
    .inputs        = adelay_inputs,
357
    .outputs       = adelay_outputs,
358
    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL,
359
};