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

Dale Curtis dalecurtis at chromium.org
Sat Oct 24 00:35:15 CEST 2015


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
 }

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;
-        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 */
-- 
2.6.0.rc2.230.g3dd15c0


More information about the ffmpeg-devel mailing list