X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Favf_showfreqs.c;h=645754ded366617708f585be9baed4f7911dadeb;hb=1aa4fc1ec204fabed5c40873b86751976167272f;hp=ff6a762547fe7b64710500deebe282b4b9e6f0e6;hpb=40ac622460284f4aad10a13b786d03d6c2cfa868;p=ffmpeg diff --git a/libavfilter/avf_showfreqs.c b/libavfilter/avf_showfreqs.c index ff6a762547f..645754ded36 100644 --- a/libavfilter/avf_showfreqs.c +++ b/libavfilter/avf_showfreqs.c @@ -30,6 +30,7 @@ #include "libavutil/opt.h" #include "libavutil/parseutils.h" #include "audio.h" +#include "filters.h" #include "video.h" #include "avfilter.h" #include "internal.h" @@ -45,6 +46,7 @@ typedef struct ShowFreqsContext { int w, h; int mode; int cmode; + int fft_size; int fft_bits; int ascale, fscale; int avg; @@ -84,20 +86,7 @@ static const AVOption showfreqs_options[] = { { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=FS_LINEAR}, 0, 0, FLAGS, "fscale" }, { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=FS_LOG}, 0, 0, FLAGS, "fscale" }, { "rlog", "reverse logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=FS_RLOG}, 0, 0, FLAGS, "fscale" }, - { "win_size", "set window size", OFFSET(fft_bits), AV_OPT_TYPE_INT, {.i64=11}, 4, 16, FLAGS, "fft" }, - { "w16", 0, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "fft" }, - { "w32", 0, 0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, FLAGS, "fft" }, - { "w64", 0, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, FLAGS, "fft" }, - { "w128", 0, 0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, FLAGS, "fft" }, - { "w256", 0, 0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, FLAGS, "fft" }, - { "w512", 0, 0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, FLAGS, "fft" }, - { "w1024", 0, 0, AV_OPT_TYPE_CONST, {.i64=10}, 0, 0, FLAGS, "fft" }, - { "w2048", 0, 0, AV_OPT_TYPE_CONST, {.i64=11}, 0, 0, FLAGS, "fft" }, - { "w4096", 0, 0, AV_OPT_TYPE_CONST, {.i64=12}, 0, 0, FLAGS, "fft" }, - { "w8192", 0, 0, AV_OPT_TYPE_CONST, {.i64=13}, 0, 0, FLAGS, "fft" }, - { "w16384", 0, 0, AV_OPT_TYPE_CONST, {.i64=14}, 0, 0, FLAGS, "fft" }, - { "w32768", 0, 0, AV_OPT_TYPE_CONST, {.i64=15}, 0, 0, FLAGS, "fft" }, - { "w65536", 0, 0, AV_OPT_TYPE_CONST, {.i64=16}, 0, 0, FLAGS, "fft" }, + { "win_size", "set window size", OFFSET(fft_size), AV_OPT_TYPE_INT, {.i64=2048}, 16, 65536, FLAGS }, { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64=WFUNC_HANNING}, 0, NB_WFUNC-1, FLAGS, "win_func" }, { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" }, { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" }, @@ -179,6 +168,7 @@ static int config_output(AVFilterLink *outlink) float overlap; int i; + s->fft_bits = av_log2(s->fft_size); s->nb_freq = 1 << (s->fft_bits - 1); s->win_size = s->nb_freq << 1; av_audio_fifo_free(s->fifo); @@ -205,7 +195,7 @@ static int config_output(AVFilterLink *outlink) if (!s->fft_data) return AVERROR(ENOMEM); s->avg_data = av_calloc(s->nb_channels, sizeof(*s->avg_data)); - if (!s->fft_data) + if (!s->avg_data) return AVERROR(ENOMEM); for (i = 0; i < s->nb_channels; i++) { s->fft_data[i] = av_calloc(s->win_size, sizeof(**s->fft_data)); @@ -439,45 +429,67 @@ static int plot_freqs(AVFilterLink *inlink, AVFrame *in) return ff_filter_frame(outlink, out); } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) +static int filter_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; ShowFreqsContext *s = ctx->priv; AVFrame *fin = NULL; - int consumed = 0; int ret = 0; - if (s->pts == AV_NOPTS_VALUE) - s->pts = in->pts - av_audio_fifo_size(s->fifo); + fin = ff_get_audio_buffer(inlink, s->win_size); + if (!fin) { + ret = AVERROR(ENOMEM); + goto fail; + } - av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); - while (av_audio_fifo_size(s->fifo) >= s->win_size) { - fin = ff_get_audio_buffer(inlink, s->win_size); - if (!fin) { - ret = AVERROR(ENOMEM); - goto fail; - } + fin->pts = s->pts; + s->pts += s->hop_size; + ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size); + if (ret < 0) + goto fail; - fin->pts = s->pts + consumed; - consumed += s->hop_size; - ret = av_audio_fifo_peek(s->fifo, (void **)fin->extended_data, s->win_size); - if (ret < 0) - goto fail; - - ret = plot_freqs(inlink, fin); - av_frame_free(&fin); - av_audio_fifo_drain(s->fifo, s->hop_size); - if (ret < 0) - goto fail; - } + ret = plot_freqs(inlink, fin); + av_frame_free(&fin); + av_audio_fifo_drain(s->fifo, s->hop_size); fail: - s->pts = AV_NOPTS_VALUE; av_frame_free(&fin); - av_frame_free(&in); return ret; } +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + ShowFreqsContext *s = ctx->priv; + AVFrame *in = NULL; + int ret = 0; + + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); + + if (av_audio_fifo_size(s->fifo) < s->win_size) + ret = ff_inlink_consume_samples(inlink, s->win_size, s->win_size, &in); + if (ret < 0) + return ret; + if (ret > 0) { + av_audio_fifo_write(s->fifo, (void **)in->extended_data, in->nb_samples); + if (s->pts == AV_NOPTS_VALUE) + s->pts = in->pts; + av_frame_free(&in); + } + + if (av_audio_fifo_size(s->fifo) >= s->win_size) { + ret = filter_frame(inlink); + if (ret <= 0) + return ret; + } + + FF_FILTER_FORWARD_STATUS(inlink, outlink); + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + static av_cold void uninit(AVFilterContext *ctx) { ShowFreqsContext *s = ctx->priv; @@ -500,7 +512,6 @@ static const AVFilterPad showfreqs_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, }, { NULL } }; @@ -521,6 +532,7 @@ AVFilter ff_avf_showfreqs = { .uninit = uninit, .query_formats = query_formats, .priv_size = sizeof(ShowFreqsContext), + .activate = activate, .inputs = showfreqs_inputs, .outputs = showfreqs_outputs, .priv_class = &showfreqs_class,