diff options
author | Andreas Rheinhardt <andreas.rheinhardt@gmail.com> | 2020-11-19 16:54:45 +0100 |
---|---|---|
committer | Andreas Rheinhardt <andreas.rheinhardt@gmail.com> | 2020-11-24 11:35:03 +0100 |
commit | 195d8ce85eb73ff283f85dcee63383ec4081e3e7 (patch) | |
tree | 9e71532be20394daa1fdc4b1e637251ada721d40 /libavcodec/aactab.c | |
parent | c4b4cd775af0f4b83c34fd595c05d2fa99018323 (diff) |
avcodec/aac*: Make initializing ff_aac_pow*sf_tab thread-safe
This table is currently initialized up to three times: Once by the
encoder and twice by the decoders (once by the fixed and once by the
floating-point decoder); each of these initializations is guarded by an
AVOnce, yet the fact that there are three of them implies that there
might be data races (the fact that each entry is only written to once
(to its final value) when initializing means that this is safe in
practice, yet it is still undefined behaviour). Fix this by only
initializing the table from one place that is guarded by a single AVOnce.
This also avoids unnecessary duplications of the init code.
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
Diffstat (limited to 'libavcodec/aactab.c')
-rw-r--r-- | libavcodec/aactab.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/libavcodec/aactab.c b/libavcodec/aactab.c index df551b058f..79dd13d9cb 100644 --- a/libavcodec/aactab.c +++ b/libavcodec/aactab.c @@ -28,7 +28,9 @@ */ #include "libavutil/mem.h" +#include "libavutil/thread.h" #include "aac.h" +#include "aactab.h" #include <stdint.h> @@ -3280,3 +3282,53 @@ const DECLARE_ALIGNED(32, int, ff_aac_eld_window_480_fixed)[1800] = { 0xffecff1c, 0xffed391e, 0xffed740c, 0xffedafb1, 0xffedebe1, 0xffee287d, 0xffee654e, 0xffeea23f, }; + +static void aac_tableinit(void) +{ + /* 2^(i/16) for 0 <= i <= 15 */ + static const float exp2_lut[] = { + 1.00000000000000000000, + 1.04427378242741384032, + 1.09050773266525765921, + 1.13878863475669165370, + 1.18920711500272106672, + 1.24185781207348404859, + 1.29683955465100966593, + 1.35425554693689272830, + 1.41421356237309504880, + 1.47682614593949931139, + 1.54221082540794082361, + 1.61049033194925430818, + 1.68179283050742908606, + 1.75625216037329948311, + 1.83400808640934246349, + 1.91520656139714729387, + }; + float t1 = 8.8817841970012523233890533447265625e-16; // 2^(-50) + float t2 = 3.63797880709171295166015625e-12; // 2^(-38) + int t1_inc_cur, t2_inc_cur; + int t1_inc_prev = 0; + int t2_inc_prev = 8; + + for (int i = 0; i < 428; i++) { + t1_inc_cur = 4 * (i % 4); + t2_inc_cur = (8 + 3*i) % 16; + if (t1_inc_cur < t1_inc_prev) + t1 *= 2; + if (t2_inc_cur < t2_inc_prev) + t2 *= 2; + // A much more efficient and accurate way of doing: + // ff_aac_pow2sf_tab[i] = pow(2, (i - POW_SF2_ZERO) / 4.0); + // ff_aac_pow34sf_tab[i] = pow(ff_aac_pow2sf_tab[i], 3.0/4.0); + ff_aac_pow2sf_tab[i] = t1 * exp2_lut[t1_inc_cur]; + ff_aac_pow34sf_tab[i] = t2 * exp2_lut[t2_inc_cur]; + t1_inc_prev = t1_inc_cur; + t2_inc_prev = t2_inc_cur; + } +} + +void ff_aac_tableinit(void) +{ + static AVOnce init_static_once = AV_ONCE_INIT; + ff_thread_once(&init_static_once, aac_tableinit); +} |