[FFmpeg-devel] [PATCH] Use ff_thread_once() to initialize sin/cos static tables.

wm4 nfxjfg at googlemail.com
Sat Oct 24 14:43:51 CEST 2015


On Fri, 23 Oct 2015 15:35:15 -0700
Dale Curtis <dalecurtis at chromium.org> wrote:

> Changes from partial initialization which happens for every
> initialize call to a full initialization once per process. Changes
> as discussed on list by wm4 and rbultje.
> 
> Passes fft-test and fate suite.
> 
> Signed-off-by: Dale Curtis <dalecurtis at chromium.org>
> ---
>  libavcodec/fft_template.c | 33 ++++++++++++++++++++++++---------
>  libavcodec/rdft.c         | 41 +++++++++++++++++++++++++++++++++--------
>  libavcodec/rdft.h         |  1 +
>  3 files changed, 58 insertions(+), 17 deletions(-)
> 
> diff --git a/libavcodec/fft_template.c b/libavcodec/fft_template.c
> index 23ea453..a9a3797 100644
> --- a/libavcodec/fft_template.c
> +++ b/libavcodec/fft_template.c
> @@ -28,7 +28,9 @@
> 
>  #include <stdlib.h>
>  #include <string.h>
> +#include "libavutil/avassert.h"
>  #include "libavutil/mathematics.h"
> +#include "libavutil/thread.h"
>  #include "fft.h"
>  #include "fft-internal.h"
> 
> @@ -85,17 +87,30 @@ static int split_radix_permutation(int i, int n,
> int inverse)
>      else                  return split_radix_permutation(i, m, inverse)*4 - 1;
>  }
> 
> -av_cold void ff_init_ff_cos_tabs(int index)
> +#if (!CONFIG_HARDCODED_TABLES) && (!FFT_FIXED_32)
> +static AVOnce ff_cos_tabs_init = AV_ONCE_INIT;
> +static av_cold void ff_init_ff_cos_static_table_init(void)
> +{
> +    int nbits;
> +    for (nbits = 4; nbits < 16; nbits++) {
> +        int i;
> +        int m = 1 << nbits;
> +        double freq = 2*M_PI/m;
> +        FFTSample *tab = FFT_NAME(ff_cos_tabs)[nbits];
> +        for (i = 0; i <= m/4; i++)
> +            tab[i] = FIX15(cos(i*freq));
> +        for (i = 1; i < m/4; i++)
> +            tab[m/2-i] = tab[i];
> +    }
> +}
> +#endif
> +
> +av_cold void ff_init_ff_cos_tabs(int nbits)
>  {
>  #if (!CONFIG_HARDCODED_TABLES) && (!FFT_FIXED_32)
> -    int i;
> -    int m = 1<<index;
> -    double freq = 2*M_PI/m;
> -    FFTSample *tab = FFT_NAME(ff_cos_tabs)[index];
> -    for(i=0; i<=m/4; i++)
> -        tab[i] = FIX15(cos(i*freq));
> -    for(i=1; i<m/4; i++)
> -        tab[m/2-i] = tab[i];
> +    av_assert0(nbits >= 4 && nbits <= 16);
> +    if (ff_thread_once(&ff_cos_tabs_init, &ff_init_ff_cos_static_table_init))
> +        av_log(NULL, AV_LOG_ERROR, "failed to initialize cosine tables.\n");
>  #endif
>  }

Hm, the fact that fft_template.c is included in several other files via
#include makes this quite confusing. In fft.h I see:

    #define ff_init_ff_cos_tabs FFT_NAME(ff_init_ff_cos_tabs)

Well, I guess it's somehow working out.

> diff --git a/libavcodec/rdft.c b/libavcodec/rdft.c
> index c318aa8..d5a5d50 100644
> --- a/libavcodec/rdft.c
> +++ b/libavcodec/rdft.c
> @@ -20,7 +20,9 @@
>   */
>  #include <stdlib.h>
>  #include <math.h>
> +#include "libavutil/avassert.h"
>  #include "libavutil/mathematics.h"
> +#include "libavutil/thread.h"
>  #include "rdft.h"
> 
>  /**
> @@ -96,6 +98,36 @@ static void rdft_calc_c(RDFTContext *s, FFTSample *data)
>      }
>  }
> 
> +#if !CONFIG_HARDCODED_TABLES
> +static AVOnce ff_sin_tabs_init = AV_ONCE_INIT;
> +static av_cold void ff_init_ff_sin_static_table_init(void)
> +{
> +    int nbits;
> +    for (nbits = 4; nbits < 16; nbits++) {
> +        int n = 1 << nbits;
> +        int m = n >> 2;
> +        int offset;
> +        for (offset = 0; offset < 2; offset++) {
> +            int i;
> +            FFTSample* tab = ff_sin_tabs[nbits]+offset*m;
> +            const double theta = (offset ? -1 : 1) * 2 * M_PI / n;
> +            for (i = 0; i < m; i++)
> +                tab[i] = sin(i * theta);
> +        }
> +    }
> +}
> +#endif
> +
> +av_cold void ff_init_ff_sin_tabs(int nbits, enum RDFTransformType trans)
> +{
> +#if !CONFIG_HARDCODED_TABLES
> +    av_assert0(trans == DFT_R2C || trans == IDFT_C2R || trans ==
> IDFT_R2C || trans == DFT_C2R);
> +    av_assert0(nbits >= 4 && nbits <= 16);
> +    if (ff_thread_once(&ff_sin_tabs_init, &ff_init_ff_sin_static_table_init))
> +        av_log(NULL, AV_LOG_ERROR, "Failed to initialize sin tables.\n");
> +#endif
> +}
> +
>  av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum
> RDFTransformType trans)
>  {
>      int n = 1 << nbits;
> @@ -112,16 +144,9 @@ av_cold int ff_rdft_init(RDFTContext *s, int
> nbits, enum RDFTransformType trans)
>          return ret;
> 
>      ff_init_ff_cos_tabs(nbits);
> +    ff_init_ff_sin_tabs(nbits, trans);
>      s->tcos = ff_cos_tabs[nbits];
>      s->tsin = ff_sin_tabs[nbits]+(trans == DFT_R2C || trans == DFT_C2R)*(n>>2);
> -#if !CONFIG_HARDCODED_TABLES
> -    {
> -        int i;
> -        const double theta = (trans == DFT_R2C || trans == DFT_C2R ?
> -1 : 1) * 2 * M_PI / n;

Your mail client is breaking long lines. Either send the patch as
attachment, or use git send-email.

> -        for (i = 0; i < (n >> 2); i++)
> -            s->tsin[i] = sin(i * theta);
> -    }
> -#endif
>      s->rdft_calc   = rdft_calc_c;
> 
>      if (ARCH_ARM) ff_rdft_init_arm(s);
> diff --git a/libavcodec/rdft.h b/libavcodec/rdft.h
> index 37c40e7..75bb6b5 100644
> --- a/libavcodec/rdft.h
> +++ b/libavcodec/rdft.h
> @@ -70,5 +70,6 @@ void ff_rdft_end(RDFTContext *s);
> 
>  void ff_rdft_init_arm(RDFTContext *s);
> 
> +void ff_init_ff_sin_tabs(int nbits, enum RDFTransformType trans);
> 
>  #endif /* AVCODEC_RDFT_H */



More information about the ffmpeg-devel mailing list