[FFmpeg-devel] [PATCH] lavfi: add showspectrum filter.

Stefano Sabatini stefasab at gmail.com
Sat Aug 11 00:45:59 CEST 2012


On date Friday 2012-08-10 00:30:27 +0200, Clément Bœsch encoded:
> TODO: bump
> ---
>  libavfilter/Makefile           |   1 +
>  libavfilter/allfilters.c       |   1 +
>  libavfilter/avf_showspectrum.c | 318 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 320 insertions(+)
>  create mode 100644 libavfilter/avf_showspectrum.c

Missing docs.
 
> diff --git a/libavfilter/Makefile b/libavfilter/Makefile
> index d50c99d..7ae43f9 100644
> --- a/libavfilter/Makefile
> +++ b/libavfilter/Makefile
> @@ -200,6 +200,7 @@ OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/pullup.o
>  
>  # multimedia filters
>  OBJS-$(CONFIG_CONCAT_FILTER)                 += avf_concat.o
> +OBJS-$(CONFIG_SHOWSPECTRUM_FILTER)           += avf_showspectrum.o
>  OBJS-$(CONFIG_SHOWWAVES_FILTER)              += avf_showwaves.o
>  
>  # multimedia sources
> diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
> index 5dc75a6..5207527 100644
> --- a/libavfilter/allfilters.c
> +++ b/libavfilter/allfilters.c
> @@ -138,6 +138,7 @@ void avfilter_register_all(void)
>  
>      /* multimedia filters */
>      REGISTER_FILTER (CONCAT,      concat,      avf);
> +    REGISTER_FILTER (SHOWSPECTRUM,showspectrum,avf);
>      REGISTER_FILTER (SHOWWAVES,   showwaves,   avf);
>  
>      /* multimedia sources */
> diff --git a/libavfilter/avf_showspectrum.c b/libavfilter/avf_showspectrum.c
> new file mode 100644
> index 0000000..f763646
> --- /dev/null
> +++ b/libavfilter/avf_showspectrum.c
> @@ -0,0 +1,318 @@
> +/*
> + * Copyright (c) 2012 Clément Bœsch
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/**
> + * @file
> + * audio to spectrum (video) transmedia filter, based on ffplay rdft showmode
> + * and lavfi/avf_showwaves
> + */
> +
> +#include <math.h>
> +
> +#include "libavcodec/avfft.h"
> +#include "libavutil/audioconvert.h"
> +#include "libavutil/opt.h"
> +#include "libavutil/parseutils.h"
> +#include "avfilter.h"
> +#include "formats.h"
> +#include "audio.h"
> +#include "video.h"
> +#include "internal.h"

> +#include "drawutils.h"

unused?

> +typedef struct {
> +    const AVClass *class;
> +    int w, h;

> +    int xpos;

please document this

> +    AVFilterBufferRef *outpicref;

> +    FFDrawContext draw;

unused

> +    int req_fullfilled;
> +    RDFTContext *rdft;          ///< Real Discrete Fourier Transform context
> +    int rdft_bits;              ///< number of bits (RDFT window size = 1<<rdft_bits)
> +    FFTSample *rdft_data;       ///< bins holder for each (displayed) channels
> +    int filled;                 ///< number of samples (per channel) filled in current rdft_buffer
> +    int consumed;               ///< number of samples (per channel) consumed from the input frame
> +    float *windowing;           ///< Window function LUT
> +} ShowSpectrumContext;
> +
> +#define OFFSET(x) offsetof(ShowSpectrumContext, x)
> +
[...]
> +static int config_output(AVFilterLink *outlink)
> +{
> +    AVFilterContext *ctx = outlink->src;
> +    ShowSpectrumContext *showspectrum = ctx->priv;
> +    int i, rdft_bits, win_size;
> +
> +    outlink->w = showspectrum->w;
> +    outlink->h = showspectrum->h;
> +
> +    /* RDFT window size (precision) according to the requested output frame height */
> +    for (rdft_bits = 1; 1<<rdft_bits < 2*outlink->h; rdft_bits++);
> +    win_size = 1 << rdft_bits;
> +
> +    /* (re-)configuration if the video output changed (or first init) */
> +    if (rdft_bits != showspectrum->rdft_bits) {
> +        AVFilterBufferRef *outpicref;
> +
> +        av_rdft_end(showspectrum->rdft);
> +        showspectrum->rdft = av_rdft_init(rdft_bits, DFT_R2C);
> +        showspectrum->rdft_bits = rdft_bits;
> +
> +        /* RDFT buffers: x2 for each (display) channel buffer */
> +        av_free(showspectrum->rdft_data);
> +        showspectrum->rdft_data = av_malloc(2 * win_size * sizeof(*showspectrum->rdft_data));
> +        if (!showspectrum->rdft_data)
> +            return AVERROR(ENOMEM);
> +        showspectrum->filled = 0;
> +
> +        /* pre-calc windowing function (hann here) */
> +        av_free(showspectrum->windowing);
> +        showspectrum->windowing = av_malloc(win_size * sizeof(*showspectrum->windowing));
> +        if (!showspectrum->windowing)
> +            return AVERROR(ENOMEM);
> +        for (i = 0; i < win_size; i++)
> +            showspectrum->windowing[i] = .5f * (1 - cos(2*M_PI*i / (win_size-1)));
> +
> +        /* prepare the initial picref buffer (black frame) */
> +        avfilter_unref_bufferp(&showspectrum->outpicref);
> +        showspectrum->outpicref = outpicref =
> +            ff_get_video_buffer(outlink, AV_PERM_WRITE|AV_PERM_PRESERVE|AV_PERM_REUSE,
> +                                outlink->w, outlink->h);

#define AV_PERM_REUSE2   0x10   ///< can output the buffer multiple times, modified each time

It won't make any difference since no allocator currently supports
REUSE2, but that may help in the future.

Missing check on outpicref != NULL.

> +        outpicref->video->w = outlink->w;
> +        outpicref->video->h = outlink->h;
> +        outlink->sample_aspect_ratio = (AVRational){1,1};

Are these required?

> +        memset(outpicref->data[0], 0, outlink->h * outpicref->linesize[0]);
> +    }
> +
> +    if (showspectrum->xpos >= outlink->w)
> +        showspectrum->xpos = 0;
> +
> +    av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d RDFT window size:%d\n",
> +           showspectrum->w, showspectrum->h, win_size);
> +    return 0;
> +}
> +
> +inline static void push_frame(AVFilterLink *outlink)
> +{
> +    ShowSpectrumContext *showspectrum = outlink->src->priv;
> +

> +    showspectrum->xpos++;
> +    if (showspectrum->xpos == outlink->w)
> +        showspectrum->xpos = 0;

Doesn't this belong to plot_spectrum_column()?

> +    showspectrum->filled = 0;
> +    showspectrum->req_fullfilled = 1;
> +
> +    ff_start_frame(outlink, avfilter_ref_buffer(showspectrum->outpicref, ~AV_PERM_READ));
> +    ff_draw_slice(outlink, 0, outlink->h, 1);
> +    ff_end_frame(outlink);
> +}
> +
[...]
> +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
> +{
> +    AVFilterContext *ctx = inlink->dst;
> +    ShowSpectrumContext *showspectrum = ctx->priv;
> +    int left_samples = insamples->audio->nb_samples;
> +
> +    showspectrum->consumed = 0;
> +    while (left_samples) {

> +        const int added_samples = plot_spectrum_column(inlink, insamples, left_samples);

why const?

> +        showspectrum->consumed += added_samples;
> +        left_samples -= added_samples;
> +    }
> +
> +    avfilter_unref_buffer(insamples);
> +    return 0;
> +}
[...]
-- 
FFmpeg = Free & Frightening Mean Power Empowered Guide


More information about the ffmpeg-devel mailing list