#include "internal.h"
typedef struct ChanDelay {
- int delay;
- unsigned delay_index;
- unsigned index;
+ int64_t delay;
+ size_t delay_index;
+ size_t index;
uint8_t *samples;
} ChanDelay;
typedef struct AudioDelayContext {
const AVClass *class;
+ int all;
char *delays;
ChanDelay *chandelay;
int nb_delays;
static const AVOption adelay_options[] = {
{ "delays", "set list of delays for each channel", OFFSET(delays), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A },
+ { "all", "use last available delay for remained channels", OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A },
{ NULL }
};
p = s->delays;
for (i = 0; i < s->nb_delays; i++) {
ChanDelay *d = &s->chandelay[i];
- float delay;
+ float delay, div;
char type = 0;
int ret;
p = NULL;
- ret = av_sscanf(arg, "%d%c", &d->delay, &type);
+ ret = av_sscanf(arg, "%"SCNd64"%c", &d->delay, &type);
if (ret != 2 || type != 'S') {
- av_sscanf(arg, "%f", &delay);
- d->delay = delay * inlink->sample_rate / 1000.0;
+ div = type == 's' ? 1.0 : 1000.0;
+ if (av_sscanf(arg, "%f", &delay) != 1) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid syntax for delay.\n");
+ return AVERROR(EINVAL);
+ }
+ d->delay = delay * inlink->sample_rate / div;
}
if (d->delay < 0) {
}
}
+ if (s->all && i) {
+ for (int j = i; j < s->nb_delays; j++)
+ s->chandelay[j].delay = s->chandelay[i-1].delay;
+ }
+
s->padding = s->chandelay[0].delay;
for (i = 1; i < s->nb_delays; i++) {
ChanDelay *d = &s->chandelay[i];
if (!d->delay)
continue;
+ if (d->delay > SIZE_MAX) {
+ av_log(ctx, AV_LOG_ERROR, "Requested delay is too big.\n");
+ return AVERROR(EINVAL);
+ }
+
d->samples = av_malloc_array(d->delay, s->block_align);
if (!d->samples)
return AVERROR(ENOMEM);
{ NULL }
};
-AVFilter ff_af_adelay = {
+const AVFilter ff_af_adelay = {
.name = "adelay",
.description = NULL_IF_CONFIG_SMALL("Delay one or more audio channels."),
.query_formats = query_formats,