Is this being reviewed? št 20. 1. 2022 o 12:38 David Lacko <deiwo...@gmail.com> napísal(a):
> Adds command 'delays' to the adelay filter. > This command accepts same values as the option with one difference, to > apply > delay to all channels prefix 'all:' to the argument is accepted. > > Signed-off-by: David Lacko <deiwo...@gmail.com> > --- > libavfilter/af_adelay.c | 182 ++++++++++++++++++++++++++++++++++------ > 1 file changed, 156 insertions(+), 26 deletions(-) > > diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c > index ed8a8ae739..382be3dca2 100644 > --- a/libavfilter/af_adelay.c > +++ b/libavfilter/af_adelay.c > @@ -31,6 +31,7 @@ typedef struct ChanDelay { > int64_t delay; > size_t delay_index; > size_t index; > + unsigned int samples_size; > uint8_t *samples; > } ChanDelay; > > @@ -48,13 +49,14 @@ typedef struct AudioDelayContext { > > void (*delay_channel)(ChanDelay *d, int nb_samples, > const uint8_t *src, uint8_t *dst); > + int (*resize_channel_samples)(ChanDelay *d, int64_t new_delay); > } AudioDelayContext; > > #define OFFSET(x) offsetof(AudioDelayContext, x) > #define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM > > static const AVOption adelay_options[] = { > - { "delays", "set list of delays for each channel", OFFSET(delays), > AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A }, > + { "delays", "set list of delays for each channel", OFFSET(delays), > AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, A | AV_OPT_FLAG_RUNTIME_PARAM }, > { "all", "use last available delay for remained channels", > OFFSET(all), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, A }, > { NULL } > }; > @@ -96,11 +98,93 @@ DELAY(s32, int32_t, 0) > DELAY(flt, float, 0) > DELAY(dbl, double, 0) > > +#define CHANGE_DELAY(name, type, fill) > \ > +static int resize_samples_## name ##p(ChanDelay *d, int64_t new_delay) > \ > +{ > \ > + type *samples; > \ > + > \ > + if (new_delay == d->delay) { > \ > + return 0; > \ > + } > \ > + > \ > + if (new_delay == 0) { > \ > + av_freep(&d->samples); > \ > + d->samples_size = 0; > \ > + d->delay = 0; > \ > + d->index = 0; > \ > + d->delay_index = 0; > \ > + return 0; > \ > + } > \ > + > \ > + samples = (type *) av_fast_realloc(d->samples, &d->samples_size, > new_delay * sizeof(type)); \ > + if (!samples) { > \ > + return AVERROR(ENOMEM); > \ > + } > \ > + > \ > + if (new_delay < d->delay) { > \ > + if (d->index > new_delay) { > \ > + d->index -= new_delay; > \ > + memmove(samples, &samples[new_delay], d->index * > sizeof(type)); \ > + d->delay_index = new_delay; > \ > + } else if (d->delay_index > d->index) { > \ > + memmove(&samples[d->index], > &samples[d->index+(d->delay-new_delay)], \ > + (new_delay - d->index) * sizeof(type)); > \ > + d->delay_index -= d->delay - new_delay; > \ > + } > \ > + } else { > \ > + size_t block_size; > \ > + if (d->delay_index >= d->delay) { > \ > + block_size = (d->delay - d->index) * sizeof(type); > \ > + memmove(&samples[d->index+(new_delay - d->delay)], > &samples[d->index], block_size); \ > + d->delay_index = new_delay; > \ > + } else { > \ > + d->delay_index += new_delay - d->delay; > \ > + } > \ > + block_size = (new_delay - d->delay) * sizeof(type); > \ > + memset(&samples[d->index], fill, block_size); > \ > + } > \ > + d->delay = new_delay; > \ > + d->samples = (void *) samples; > \ > + return 0; > \ > +} > + > +CHANGE_DELAY(u8, uint8_t, 0x80) > +CHANGE_DELAY(s16, int16_t, 0) > +CHANGE_DELAY(s32, int32_t, 0) > +CHANGE_DELAY(flt, float, 0) > +CHANGE_DELAY(dbl, double, 0) > + > +static int parse_delays(char *p, char **saveptr, int64_t *result, > AVFilterContext *ctx, int sample_rate) { > + float delay, div; > + int ret; > + char *arg; > + char type = 0; > + > + if (!(arg = av_strtok(p, "|", saveptr))) > + return 1; > + > + ret = av_sscanf(arg, "%"SCNd64"%c", result, &type); > + if (ret != 2 || type != 'S') { > + 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); > + } > + *result = delay * sample_rate / div; > + } > + > + if (*result < 0) { > + av_log(ctx, AV_LOG_ERROR, "Delay must be non negative number.\n"); > + return AVERROR(EINVAL); > + } > + return 0; > +} > + > static int config_input(AVFilterLink *inlink) > { > AVFilterContext *ctx = inlink->dst; > AudioDelayContext *s = ctx->priv; > - char *p, *arg, *saveptr = NULL; > + char *p, *saveptr = NULL; > int i; > > s->chandelay = av_calloc(inlink->channels, sizeof(*s->chandelay)); > @@ -112,29 +196,14 @@ static int config_input(AVFilterLink *inlink) > p = s->delays; > for (i = 0; i < s->nb_delays; i++) { > ChanDelay *d = &s->chandelay[i]; > - float delay, div; > - char type = 0; > int ret; > > - if (!(arg = av_strtok(p, "|", &saveptr))) > + ret = parse_delays(p, &saveptr, &d->delay, ctx, > inlink->sample_rate); > + if (ret == 1) > break; > - > + else if (ret < 0) > + return ret; > p = NULL; > - > - ret = av_sscanf(arg, "%"SCNd64"%c", &d->delay, &type); > - if (ret != 2 || type != 'S') { > - 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) { > - av_log(ctx, AV_LOG_ERROR, "Delay must be non negative > number.\n"); > - return AVERROR(EINVAL); > - } > } > > if (s->all && i) { > @@ -171,21 +240,81 @@ static int config_input(AVFilterLink *inlink) > d->samples = av_malloc_array(d->delay, s->block_align); > if (!d->samples) > return AVERROR(ENOMEM); > + d->samples_size = d->delay * s->block_align; > > s->max_delay = FFMAX(s->max_delay, d->delay); > } > > switch (inlink->format) { > - case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; break; > - case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; break; > - case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; break; > - case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; break; > - case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; break; > + case AV_SAMPLE_FMT_U8P : s->delay_channel = delay_channel_u8p ; > + s->resize_channel_samples = > resize_samples_u8p; break; > + case AV_SAMPLE_FMT_S16P: s->delay_channel = delay_channel_s16p; > + s->resize_channel_samples = > resize_samples_s16p; break; > + case AV_SAMPLE_FMT_S32P: s->delay_channel = delay_channel_s32p; > + s->resize_channel_samples = > resize_samples_s32p; break; > + case AV_SAMPLE_FMT_FLTP: s->delay_channel = delay_channel_fltp; > + s->resize_channel_samples = > resize_samples_fltp; break; > + case AV_SAMPLE_FMT_DBLP: s->delay_channel = delay_channel_dblp; > + s->resize_channel_samples = > resize_samples_dblp; break; > } > > return 0; > } > > +static int process_command(AVFilterContext *ctx, const char *cmd, const > char *args, > + char *res, int res_len, int flags) > +{ > + int ret = AVERROR(ENOSYS); > + AVFilterLink *inlink = ctx->inputs[0]; > + AudioDelayContext *s = ctx->priv; > + > + if (!strcmp(cmd, "delays")) { > + int64_t delay; > + char *p, *saveptr = NULL; > + int64_t all_delay = -1; > + int64_t max_delay = 0; > + char *args_cpy = av_strdup(args); > + if (args_cpy == NULL) { > + return AVERROR(ENOMEM); > + } > + > + ret = 0; > + p = args_cpy; > + > + if (!strncmp(args, "all:", 4)) { > + p = &args_cpy[4]; > + ret = parse_delays(p, &saveptr, &all_delay, ctx, > inlink->sample_rate); > + if (ret == 1) > + ret = AVERROR(EINVAL); > + else if (ret == 0) > + delay = all_delay; > + } > + > + if (!ret) { > + for (int i = 0; i < s->nb_delays; i++) { > + ChanDelay *d = &s->chandelay[i]; > + > + if (all_delay < 0) { > + ret = parse_delays(p, &saveptr, &delay, ctx, > inlink->sample_rate); > + if (ret != 0) { > + ret = 0; > + break; > + } > + p = NULL; > + } > + > + ret = s->resize_channel_samples(d, delay); > + if (ret) > + break; > + max_delay = FFMAX(max_delay, d->delay); > + } > + s->max_delay = FFMAX(s->max_delay, max_delay); > + } > + av_freep(&args_cpy); > + } > + return ret; > +} > + > static int filter_frame(AVFilterLink *inlink, AVFrame *frame) > { > AVFilterContext *ctx = inlink->dst; > @@ -330,4 +459,5 @@ const AVFilter ff_af_adelay = { > FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, > AV_SAMPLE_FMT_S32P, > AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP), > .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, > + .process_command = process_command, > }; > -- > 2.34.1 > > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".