diff options
author | Paul B Mahol <onemda@gmail.com> | 2019-05-08 15:03:22 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2019-05-08 15:03:22 +0200 |
commit | c539dd992cea8313ecb7565bb74645c81d7bf333 (patch) | |
tree | b60facd0d3cf57d293c3753ba44f2688d4878889 /libavfilter | |
parent | cc86982fc5f6ae7a25f448931dd3fc2b80c2ce0b (diff) |
avfilter/af_afftfilt: switch to activate
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/af_afftfilt.c | 228 |
1 files changed, 126 insertions, 102 deletions
diff --git a/libavfilter/af_afftfilt.c b/libavfilter/af_afftfilt.c index 8518f08dc5..fcbebdde26 100644 --- a/libavfilter/af_afftfilt.c +++ b/libavfilter/af_afftfilt.c @@ -26,6 +26,7 @@ #include "libavcodec/avfft.h" #include "libavutil/eval.h" #include "audio.h" +#include "filters.h" #include "window_func.h" typedef struct AFFTFiltContext { @@ -46,7 +47,7 @@ typedef struct AFFTFiltContext { int hop_size; float overlap; AVFrame *buffer; - int start, end; + int eof; int win_func; float win_scale; float *window_func_lut; @@ -240,7 +241,7 @@ static int config_input(AVFilterLink *inlink) return ret; } -static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +static int filter_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; @@ -249,140 +250,163 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) const float f = 1. / s->win_scale; double values[VAR_VARS_NB]; AVFrame *out, *in = NULL; - int ch, n, ret, i, j, k; - int start = s->start, end = s->end; + int ch, n, ret, i; - if (s->pts == AV_NOPTS_VALUE) - s->pts = frame->pts; + if (!in) { + in = ff_get_audio_buffer(outlink, window_size); + if (!in) + return AVERROR(ENOMEM); + } - ret = av_audio_fifo_write(s->fifo, (void **)frame->extended_data, frame->nb_samples); - av_frame_free(&frame); + ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, window_size); if (ret < 0) - return ret; + goto fail; - while (av_audio_fifo_size(s->fifo) >= window_size) { - if (!in) { - in = ff_get_audio_buffer(outlink, window_size); - if (!in) - return AVERROR(ENOMEM); + for (ch = 0; ch < inlink->channels; ch++) { + const float *src = (float *)in->extended_data[ch]; + FFTComplex *fft_data = s->fft_data[ch]; + + for (n = 0; n < in->nb_samples; n++) { + fft_data[n].re = src[n] * s->window_func_lut[n]; + fft_data[n].im = 0; } - ret = av_audio_fifo_peek(s->fifo, (void **)in->extended_data, window_size); - if (ret < 0) - break; + for (; n < window_size; n++) { + fft_data[n].re = 0; + fft_data[n].im = 0; + } + } - for (ch = 0; ch < inlink->channels; ch++) { - const float *src = (float *)in->extended_data[ch]; - FFTComplex *fft_data = s->fft_data[ch]; + values[VAR_PTS] = s->pts; + values[VAR_SAMPLE_RATE] = inlink->sample_rate; + values[VAR_NBBINS] = window_size / 2; + values[VAR_CHANNELS] = inlink->channels; - for (n = 0; n < in->nb_samples; n++) { - fft_data[n].re = src[n] * s->window_func_lut[n]; - fft_data[n].im = 0; - } + for (ch = 0; ch < inlink->channels; ch++) { + FFTComplex *fft_data = s->fft_data[ch]; - for (; n < window_size; n++) { - fft_data[n].re = 0; - fft_data[n].im = 0; - } - } + av_fft_permute(s->fft, fft_data); + av_fft_calc(s->fft, fft_data); + } - values[VAR_PTS] = s->pts; - values[VAR_SAMPLE_RATE] = inlink->sample_rate; - values[VAR_NBBINS] = window_size / 2; - values[VAR_CHANNELS] = inlink->channels; + for (ch = 0; ch < inlink->channels; ch++) { + FFTComplex *fft_data = s->fft_data[ch]; + FFTComplex *fft_temp = s->fft_temp[ch]; + float *buf = (float *)s->buffer->extended_data[ch]; + int x; + values[VAR_CHANNEL] = ch; - for (ch = 0; ch < inlink->channels; ch++) { - FFTComplex *fft_data = s->fft_data[ch]; + for (n = 0; n <= window_size / 2; n++) { + float fr, fi; - av_fft_permute(s->fft, fft_data); - av_fft_calc(s->fft, fft_data); - } + values[VAR_BIN] = n; + values[VAR_REAL] = fft_data[n].re; + values[VAR_IMAG] = fft_data[n].im; - for (ch = 0; ch < inlink->channels; ch++) { - FFTComplex *fft_data = s->fft_data[ch]; - FFTComplex *fft_temp = s->fft_temp[ch]; - float *buf = (float *)s->buffer->extended_data[ch]; - int x; - values[VAR_CHANNEL] = ch; + fr = av_expr_eval(s->real[ch], values, s); + fi = av_expr_eval(s->imag[ch], values, s); - for (n = 0; n <= window_size / 2; n++) { - float fr, fi; + fft_temp[n].re = fr; + fft_temp[n].im = fi; + } - values[VAR_BIN] = n; - values[VAR_REAL] = fft_data[n].re; - values[VAR_IMAG] = fft_data[n].im; + for (n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) { + fft_temp[n].re = fft_temp[x].re; + fft_temp[n].im = -fft_temp[x].im; + } - fr = av_expr_eval(s->real[ch], values, s); - fi = av_expr_eval(s->imag[ch], values, s); + av_fft_permute(s->ifft, fft_temp); + av_fft_calc(s->ifft, fft_temp); - fft_temp[n].re = fr; - fft_temp[n].im = fi; - } + for (i = 0; i < window_size; i++) { + buf[i] += s->fft_temp[ch][i].re * f; + } + } - for (n = window_size / 2 + 1, x = window_size / 2 - 1; n < window_size; n++, x--) { - fft_temp[n].re = fft_temp[x].re; - fft_temp[n].im = -fft_temp[x].im; - } + out = ff_get_audio_buffer(outlink, s->hop_size); + if (!out) { + ret = AVERROR(ENOMEM); + goto fail; + } - av_fft_permute(s->ifft, fft_temp); - av_fft_calc(s->ifft, fft_temp); + out->pts = s->pts; + s->pts += s->hop_size; - start = s->start; - end = s->end; - k = end; - for (i = 0, j = start; j < k && i < window_size; i++, j++) { - buf[j] += s->fft_temp[ch][i].re * f; - } + for (ch = 0; ch < inlink->channels; ch++) { + float *dst = (float *)out->extended_data[ch]; + float *buf = (float *)s->buffer->extended_data[ch]; - for (; i < window_size; i++, j++) { - buf[j] = s->fft_temp[ch][i].re * f; - } + for (n = 0; n < s->hop_size; n++) + dst[n] = buf[n] * (1.f - s->overlap); + memmove(buf, buf + s->hop_size, window_size * 4); + } - start += s->hop_size; - end = j; - } + ret = ff_filter_frame(outlink, out); + if (ret < 0) + goto fail; - s->start = start; - s->end = end; + av_audio_fifo_drain(s->fifo, s->hop_size); - if (start >= window_size) { - float *dst, *buf; +fail: + av_frame_free(&in); + return ret < 0 ? ret : 0; +} - start -= window_size; - end -= window_size; +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AFFTFiltContext *s = ctx->priv; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; - s->start = start; - s->end = end; + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - out = ff_get_audio_buffer(outlink, window_size); - if (!out) { - ret = AVERROR(ENOMEM); - break; - } + if (!s->eof && av_audio_fifo_size(s->fifo) < s->window_size) { + ret = ff_inlink_consume_frame(inlink, &in); + if (ret < 0) + return ret; - out->pts = s->pts; - s->pts += window_size; + if (ret > 0) { + ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, + in->nb_samples); + if (ret >= 0 && s->pts == AV_NOPTS_VALUE) + s->pts = in->pts; - for (ch = 0; ch < inlink->channels; ch++) { - dst = (float *)out->extended_data[ch]; - buf = (float *)s->buffer->extended_data[ch]; + av_frame_free(&in); + if (ret < 0) + return ret; + } + } - for (n = 0; n < window_size; n++) { - dst[n] = buf[n] * (1 - s->overlap); - } - memmove(buf, buf + window_size, window_size * 4); - } + if ((av_audio_fifo_size(s->fifo) >= s->window_size) || + (av_audio_fifo_size(s->fifo) > 0 && s->eof)) { + ret = filter_frame(inlink); + if (av_audio_fifo_size(s->fifo) >= s->window_size) + ff_filter_set_ready(ctx, 100); + return ret; + } - ret = ff_filter_frame(outlink, out); - if (ret < 0) - break; + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + s->eof = 1; + if (av_audio_fifo_size(s->fifo) >= 0) { + ff_filter_set_ready(ctx, 100); + return 0; + } } + } - av_audio_fifo_drain(s->fifo, s->hop_size); + if (s->eof && av_audio_fifo_size(s->fifo) <= 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; } - av_frame_free(&in); - return ret < 0 ? ret : 0; + if (!s->eof) + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; } static int query_formats(AVFilterContext *ctx) @@ -450,7 +474,6 @@ static const AVFilterPad inputs[] = { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .config_props = config_input, - .filter_frame = filter_frame, }, { NULL } }; @@ -470,6 +493,7 @@ AVFilter ff_af_afftfilt = { .priv_class = &afftfilt_class, .inputs = inputs, .outputs = outputs, + .activate = activate, .query_formats = query_formats, .uninit = uninit, }; |