| @@ -63,6 +63,7 @@ typedef struct AudioDeclickContext { | |||
| int hop_size; | |||
| int overlap_skip; | |||
| AVFrame *enabled; | |||
| AVFrame *in; | |||
| AVFrame *out; | |||
| AVFrame *buffer; | |||
| @@ -77,6 +78,7 @@ typedef struct AudioDeclickContext { | |||
| int samples_left; | |||
| int eof; | |||
| AVAudioFifo *efifo; | |||
| AVAudioFifo *fifo; | |||
| double *window_func_lut; | |||
| @@ -159,13 +161,17 @@ static int config_input(AVFilterLink *inlink) | |||
| av_frame_free(&s->out); | |||
| av_frame_free(&s->buffer); | |||
| av_frame_free(&s->is); | |||
| s->enabled = ff_get_audio_buffer(inlink, s->window_size); | |||
| s->in = ff_get_audio_buffer(inlink, s->window_size); | |||
| s->out = ff_get_audio_buffer(inlink, s->window_size); | |||
| s->buffer = ff_get_audio_buffer(inlink, s->window_size * 2); | |||
| s->is = ff_get_audio_buffer(inlink, s->window_size); | |||
| if (!s->in || !s->out || !s->buffer || !s->is) | |||
| if (!s->in || !s->out || !s->buffer || !s->is || !s->enabled) | |||
| return AVERROR(ENOMEM); | |||
| s->efifo = av_audio_fifo_alloc(inlink->format, 1, s->window_size); | |||
| if (!s->efifo) | |||
| return AVERROR(ENOMEM); | |||
| s->fifo = av_audio_fifo_alloc(inlink->format, inlink->channels, s->window_size); | |||
| if (!s->fifo) | |||
| return AVERROR(ENOMEM); | |||
| @@ -513,14 +519,20 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) | |||
| nb_errors = s->detector(s, c, sigmae, c->detection, c->acoefficients, | |||
| c->click, index, src, dst); | |||
| if (nb_errors > 0) { | |||
| double *enabled = (double *)s->enabled->extended_data[0]; | |||
| ret = interpolation(c, src, s->ar_order, c->acoefficients, index, | |||
| nb_errors, c->auxiliary, interpolated); | |||
| if (ret < 0) | |||
| return ret; | |||
| av_audio_fifo_peek(s->efifo, (void**)s->enabled->extended_data, s->window_size); | |||
| for (j = 0; j < nb_errors; j++) { | |||
| dst[index[j]] = interpolated[j]; | |||
| is[index[j]] = 1; | |||
| if (enabled[index[j]]) { | |||
| dst[index[j]] = interpolated[j]; | |||
| is[index[j]] = 1; | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| @@ -580,6 +592,7 @@ static int filter_frame(AVFilterLink *inlink) | |||
| } | |||
| av_audio_fifo_drain(s->fifo, s->hop_size); | |||
| av_audio_fifo_drain(s->efifo, s->hop_size); | |||
| if (s->samples_left > 0) | |||
| out->nb_samples = FFMIN(s->hop_size, s->samples_left); | |||
| @@ -621,11 +634,17 @@ static int activate(AVFilterContext *ctx) | |||
| if (ret < 0) | |||
| return ret; | |||
| if (ret > 0) { | |||
| double *e = (double *)s->enabled->extended_data[0]; | |||
| if (s->pts == AV_NOPTS_VALUE) | |||
| s->pts = in->pts; | |||
| ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, | |||
| in->nb_samples); | |||
| for (int i = 0; i < in->nb_samples; i++) | |||
| e[i] = !ctx->is_disabled; | |||
| av_audio_fifo_write(s->efifo, (void**)s->enabled->extended_data, in->nb_samples); | |||
| av_frame_free(&in); | |||
| if (ret < 0) | |||
| return ret; | |||
| @@ -684,7 +703,9 @@ static av_cold void uninit(AVFilterContext *ctx) | |||
| s->nb_samples, 100. * s->detected_errors / s->nb_samples); | |||
| av_audio_fifo_free(s->fifo); | |||
| av_audio_fifo_free(s->efifo); | |||
| av_freep(&s->window_func_lut); | |||
| av_frame_free(&s->enabled); | |||
| av_frame_free(&s->in); | |||
| av_frame_free(&s->out); | |||
| av_frame_free(&s->buffer); | |||
| @@ -744,7 +765,7 @@ AVFilter ff_af_adeclick = { | |||
| .uninit = uninit, | |||
| .inputs = inputs, | |||
| .outputs = outputs, | |||
| .flags = AVFILTER_FLAG_SLICE_THREADS, | |||
| .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, | |||
| }; | |||
| static const AVOption adeclip_options[] = { | |||
| @@ -772,5 +793,5 @@ AVFilter ff_af_adeclip = { | |||
| .uninit = uninit, | |||
| .inputs = inputs, | |||
| .outputs = outputs, | |||
| .flags = AVFILTER_FLAG_SLICE_THREADS, | |||
| .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, | |||
| }; | |||