1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 /* The global function contained in this file initializes SPL function 12 * pointers, currently only for ARM platforms. 13 * 14 * Some code came from common/rtcd.c in the WebM project. 15 */ 16 17 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 18 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" 19 20 /* Declare function pointers. */ 21 MaxAbsValueW16 WebRtcSpl_MaxAbsValueW16; 22 MaxAbsValueW32 WebRtcSpl_MaxAbsValueW32; 23 MaxValueW16 WebRtcSpl_MaxValueW16; 24 MaxValueW32 WebRtcSpl_MaxValueW32; 25 MinValueW16 WebRtcSpl_MinValueW16; 26 MinValueW32 WebRtcSpl_MinValueW32; 27 CrossCorrelation WebRtcSpl_CrossCorrelation; 28 DownsampleFast WebRtcSpl_DownsampleFast; 29 ScaleAndAddVectorsWithRound WebRtcSpl_ScaleAndAddVectorsWithRound; 30 31 #if (defined(WEBRTC_DETECT_ARM_NEON) || !defined(WEBRTC_ARCH_ARM_NEON)) && \ 32 !defined(MIPS32_LE) && !defined(WEBRTC_ARCH_ARM64_NEON) 33 /* Initialize function pointers to the generic C version. */ InitPointersToC()34static void InitPointersToC() { 35 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16C; 36 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; 37 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16C; 38 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32C; 39 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16C; 40 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32C; 41 WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationC; 42 WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastC; 43 WebRtcSpl_ScaleAndAddVectorsWithRound = 44 WebRtcSpl_ScaleAndAddVectorsWithRoundC; 45 } 46 #endif 47 48 #if defined(WEBRTC_DETECT_ARM_NEON) || defined(WEBRTC_ARCH_ARM_NEON) || \ 49 (defined WEBRTC_ARCH_ARM64_NEON) 50 /* Initialize function pointers to the Neon version. */ InitPointersToNeon()51static void InitPointersToNeon() { 52 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16Neon; 53 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32Neon; 54 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16Neon; 55 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32Neon; 56 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16Neon; 57 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32Neon; 58 WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelationNeon; 59 WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFastNeon; 60 /* TODO(henrik.lundin): re-enable NEON when the crash from bug 3243 is 61 understood. */ 62 WebRtcSpl_ScaleAndAddVectorsWithRound = 63 WebRtcSpl_ScaleAndAddVectorsWithRoundC; 64 } 65 #endif 66 67 #if defined(MIPS32_LE) 68 /* Initialize function pointers to the MIPS version. */ InitPointersToMIPS()69static void InitPointersToMIPS() { 70 WebRtcSpl_MaxAbsValueW16 = WebRtcSpl_MaxAbsValueW16_mips; 71 WebRtcSpl_MaxValueW16 = WebRtcSpl_MaxValueW16_mips; 72 WebRtcSpl_MaxValueW32 = WebRtcSpl_MaxValueW32_mips; 73 WebRtcSpl_MinValueW16 = WebRtcSpl_MinValueW16_mips; 74 WebRtcSpl_MinValueW32 = WebRtcSpl_MinValueW32_mips; 75 WebRtcSpl_CrossCorrelation = WebRtcSpl_CrossCorrelation_mips; 76 WebRtcSpl_DownsampleFast = WebRtcSpl_DownsampleFast_mips; 77 #if defined(MIPS_DSP_R1_LE) 78 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32_mips; 79 WebRtcSpl_ScaleAndAddVectorsWithRound = 80 WebRtcSpl_ScaleAndAddVectorsWithRound_mips; 81 #else 82 WebRtcSpl_MaxAbsValueW32 = WebRtcSpl_MaxAbsValueW32C; 83 WebRtcSpl_ScaleAndAddVectorsWithRound = 84 WebRtcSpl_ScaleAndAddVectorsWithRoundC; 85 #endif 86 } 87 #endif 88 InitFunctionPointers(void)89static void InitFunctionPointers(void) { 90 #if defined(WEBRTC_DETECT_ARM_NEON) 91 if ((WebRtc_GetCPUFeaturesARM() & kCPUFeatureNEON) != 0) { 92 InitPointersToNeon(); 93 } else { 94 InitPointersToC(); 95 } 96 #elif defined(WEBRTC_ARCH_ARM_NEON) || defined(WEBRTC_ARCH_ARM64_NEON) 97 InitPointersToNeon(); 98 #elif defined(MIPS32_LE) 99 InitPointersToMIPS(); 100 #else 101 InitPointersToC(); 102 #endif /* WEBRTC_DETECT_ARM_NEON */ 103 } 104 105 #if defined(WEBRTC_POSIX) 106 #include <pthread.h> 107 once(void (* func)(void))108static void once(void (*func)(void)) { 109 static pthread_once_t lock = PTHREAD_ONCE_INIT; 110 pthread_once(&lock, func); 111 } 112 113 #elif defined(_WIN32) 114 #include <windows.h> 115 once(void (* func)(void))116static void once(void (*func)(void)) { 117 /* Didn't use InitializeCriticalSection() since there's no race-free context 118 * in which to execute it. 119 * 120 * TODO(kma): Change to different implementation (e.g. 121 * InterlockedCompareExchangePointer) to avoid issues similar to 122 * http://code.google.com/p/webm/issues/detail?id=467. 123 */ 124 static CRITICAL_SECTION lock = {(void *)((size_t)-1), -1, 0, 0, 0, 0}; 125 static int done = 0; 126 127 EnterCriticalSection(&lock); 128 if (!done) { 129 func(); 130 done = 1; 131 } 132 LeaveCriticalSection(&lock); 133 } 134 135 /* There's no fallback version as an #else block here to ensure thread safety. 136 * In case of neither pthread for WEBRTC_POSIX nor _WIN32 is present, build 137 * system should pick it up. 138 */ 139 #endif /* WEBRTC_POSIX */ 140 WebRtcSpl_Init()141void WebRtcSpl_Init() { 142 once(InitFunctionPointers); 143 } 144