[FFmpeg-devel] [PATCH 2/2] avfilter/avf_showspectrumpic: switch to internal queue
Paul B Mahol
onemda at gmail.com
Sat Apr 18 14:59:31 EEST 2020
Fixes filtering audio with more than 1.5h length.
Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
libavfilter/avf_showspectrum.c | 119 ++++++++++++++++-----------------
1 file changed, 59 insertions(+), 60 deletions(-)
diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
index a4dd7b7879..9425c4ded6 100644
--- a/libavfilter/avf_showspectrum.c
+++ b/libavfilter/avf_showspectrum.c
@@ -1606,91 +1606,90 @@ static const AVOption showspectrumpic_options[] = {
AVFILTER_DEFINE_CLASS(showspectrumpic);
-static int showspectrumpic_request_frame(AVFilterLink *outlink)
+static int showspectrumpic_request_frame(AVFilterLink *outlink, int64_t samples)
{
AVFilterContext *ctx = outlink->src;
ShowSpectrumContext *s = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0];
- int ret, samples;
+ int consumed = 0;
+ int x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
+ int ret, ch, spf, spb;
+ AVFrame *fin = NULL;
- ret = ff_request_frame(inlink);
- samples = av_audio_fifo_size(s->fifo);
- if (ret == AVERROR_EOF && s->outpicref && samples > 0) {
- int consumed = 0;
- int x = 0, sz = s->orientation == VERTICAL ? s->w : s->h;
- int ch, spf, spb;
- AVFrame *fin;
+ spf = s->win_size * (samples / ((s->win_size * sz) * ceil(samples / (float)(s->win_size * sz))));
+ spf = FFMAX(1, spf);
- spf = s->win_size * (samples / ((s->win_size * sz) * ceil(samples / (float)(s->win_size * sz))));
- spf = FFMAX(1, spf);
+ spb = (samples / (spf * sz)) * spf;
- spb = (samples / (spf * sz)) * spf;
-
- fin = ff_get_audio_buffer(inlink, s->win_size);
- if (!fin)
- return AVERROR(ENOMEM);
-
- while (x < sz) {
- ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size);
- if (ret < 0) {
- av_frame_free(&fin);
- return ret;
- }
-
- av_audio_fifo_drain(s->fifo, spf);
-
- if (ret < s->win_size) {
- for (ch = 0; ch < s->nb_display_channels; ch++) {
- memset(fin->extended_data[ch] + ret * sizeof(float), 0,
- (s->win_size - ret) * sizeof(float));
- }
- }
-
- ctx->internal->execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);
- acalc_magnitudes(s);
-
- consumed += spf;
- if (consumed >= spb) {
- int h = s->orientation == VERTICAL ? s->h : s->w;
+ while (x < sz) {
+ ret = ff_inlink_peek_samples(inlink, s->win_size, &fin);
+ if (ret < 0)
+ return ret;
+ if (ret == 0)
+ break;
- scale_magnitudes(s, 1.f / (consumed / spf));
- plot_spectrum_column(inlink, fin);
- consumed = 0;
- x++;
- for (ch = 0; ch < s->nb_display_channels; ch++)
- memset(s->magnitudes[ch], 0, h * sizeof(float));
- }
+ ctx->internal->execute(ctx, run_channel_fft, fin, NULL, s->nb_display_channels);
+ acalc_magnitudes(s);
+
+ consumed += spf;
+ if (consumed >= spb) {
+ int h = s->orientation == VERTICAL ? s->h : s->w;
+
+ scale_magnitudes(s, 1.f / (consumed / spf));
+ plot_spectrum_column(inlink, fin);
+ consumed = 0;
+ x++;
+ for (ch = 0; ch < s->nb_display_channels; ch++)
+ memset(s->magnitudes[ch], 0, h * sizeof(float));
}
-
av_frame_free(&fin);
- s->outpicref->pts = 0;
+ ff_inlink_skip_samples(inlink, spf);
+ }
- if (s->legend)
- draw_legend(ctx, samples);
+ s->outpicref->pts = 0;
- ret = ff_filter_frame(outlink, s->outpicref);
- s->outpicref = NULL;
- }
+ if (s->legend)
+ draw_legend(ctx, samples);
+
+ ret = ff_filter_frame(outlink, s->outpicref);
+ s->outpicref = NULL;
return ret;
}
-static int showspectrumpic_filter_frame(AVFilterLink *inlink, AVFrame *insamples)
+static int showspectrumpic_activate(AVFilterContext *ctx)
{
- AVFilterContext *ctx = inlink->dst;
+ AVFilterLink *inlink = ctx->inputs[0];
+ AVFilterLink *outlink = ctx->outputs[0];
ShowSpectrumContext *s = ctx->priv;
int ret;
- ret = av_audio_fifo_write(s->fifo, (void **)insamples->extended_data, insamples->nb_samples);
- av_frame_free(&insamples);
- return ret;
+ FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
+
+ if (ff_outlink_get_status(inlink) == AVERROR_EOF &&
+ s->outpicref) {
+ int64_t samples = 0;
+
+ for (int i = 0; i < ff_inlink_queued_frames(inlink); i++) {
+ AVFrame *frame = ff_inlink_peek_frame(inlink, i);
+
+ samples += frame->nb_samples;
+ }
+
+ ret = showspectrumpic_request_frame(outlink, samples);
+ ff_outlink_set_status(outlink, AVERROR_EOF, 0);
+ return ret;
+ }
+
+ FF_FILTER_FORWARD_WANTED(outlink, inlink);
+
+ return FFERROR_NOT_READY;
}
static const AVFilterPad showspectrumpic_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_frame = showspectrumpic_filter_frame,
},
{ NULL }
};
@@ -1700,7 +1699,6 @@ static const AVFilterPad showspectrumpic_outputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_output,
- .request_frame = showspectrumpic_request_frame,
},
{ NULL }
};
@@ -1711,6 +1709,7 @@ AVFilter ff_avf_showspectrumpic = {
.uninit = uninit,
.query_formats = query_formats,
.priv_size = sizeof(ShowSpectrumContext),
+ .activate = showspectrumpic_activate,
.inputs = showspectrumpic_inputs,
.outputs = showspectrumpic_outputs,
.priv_class = &showspectrumpic_class,
--
2.17.1
More information about the ffmpeg-devel
mailing list