From b446dda0ec7c5f6104efdf33e4958bb2d3f1311c Mon Sep 17 00:00:00 2001 From: Karl Tomlinson Date: Fri, 9 Aug 2013 09:56:28 +1200 Subject: [PATCH] b=815643 Add Blink's HRTFDatabase and HRTFDatabaseLoader to the build r=ehsan --HG-- extra : rebase_source : e7aa0ce1ca436bbb429cb1f6051b3b8210bf767a --- content/media/webaudio/blink/HRTFDatabase.cpp | 51 +++++------ content/media/webaudio/blink/HRTFDatabase.h | 26 +++--- .../webaudio/blink/HRTFDatabaseLoader.cpp | 85 ++++++++++--------- .../media/webaudio/blink/HRTFDatabaseLoader.h | 39 +++++---- content/media/webaudio/blink/moz.build | 2 + 5 files changed, 101 insertions(+), 102 deletions(-) diff --git a/content/media/webaudio/blink/HRTFDatabase.cpp b/content/media/webaudio/blink/HRTFDatabase.cpp index 3a6b7f48cfb2..061281ec771a 100644 --- a/content/media/webaudio/blink/HRTFDatabase.cpp +++ b/content/media/webaudio/blink/HRTFDatabase.cpp @@ -26,15 +26,9 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include "HRTFDatabase.h" -#if ENABLE(WEB_AUDIO) - -#include "core/platform/audio/HRTFDatabase.h" - -#include "core/platform/PlatformMemoryInstrumentation.h" -#include "core/platform/audio/HRTFElevation.h" -#include +#include "HRTFElevation.h" using namespace std; @@ -47,24 +41,24 @@ const unsigned HRTFDatabase::NumberOfRawElevations = 10; // -45 -> +90 (each 15 const unsigned HRTFDatabase::InterpolationFactor = 1; const unsigned HRTFDatabase::NumberOfTotalElevations = NumberOfRawElevations * InterpolationFactor; -PassOwnPtr HRTFDatabase::create(float sampleRate) +nsReturnRef HRTFDatabase::create(float sampleRate) { - OwnPtr hrtfDatabase = adoptPtr(new HRTFDatabase(sampleRate)); - return hrtfDatabase.release(); + return nsReturnRef(new HRTFDatabase(sampleRate)); } HRTFDatabase::HRTFDatabase(float sampleRate) - : m_elevations(NumberOfTotalElevations) - , m_sampleRate(sampleRate) + : m_sampleRate(sampleRate) { + m_elevations.SetLength(NumberOfTotalElevations); + unsigned elevationIndex = 0; for (int elevation = MinElevation; elevation <= MaxElevation; elevation += RawElevationAngleSpacing) { - OwnPtr hrtfElevation = HRTFElevation::createForSubject("Composite", elevation, sampleRate); - ASSERT(hrtfElevation.get()); + nsAutoRef hrtfElevation(HRTFElevation::createBuiltin(elevation, sampleRate)); + MOZ_ASSERT(hrtfElevation.get()); if (!hrtfElevation.get()) return; - m_elevations[elevationIndex] = hrtfElevation.release(); + m_elevations[elevationIndex] = hrtfElevation.out(); elevationIndex += InterpolationFactor; } @@ -79,7 +73,7 @@ HRTFDatabase::HRTFDatabase(float sampleRate) for (unsigned jj = 1; jj < InterpolationFactor; ++jj) { float x = static_cast(jj) / static_cast(InterpolationFactor); m_elevations[i + jj] = HRTFElevation::createByInterpolatingSlices(m_elevations[i].get(), m_elevations[j].get(), x, sampleRate); - ASSERT(m_elevations[i + jj].get()); + MOZ_ASSERT(m_elevations[i + jj].get()); } } } @@ -89,19 +83,19 @@ void HRTFDatabase::getKernelsFromAzimuthElevation(double azimuthBlend, unsigned double& frameDelayL, double& frameDelayR) { unsigned elevationIndex = indexFromElevationAngle(elevationAngle); - ASSERT_WITH_SECURITY_IMPLICATION(elevationIndex < m_elevations.size() && m_elevations.size() > 0); + MOZ_ASSERT(elevationIndex < m_elevations.Length() && m_elevations.Length() > 0); - if (!m_elevations.size()) { + if (!m_elevations.Length()) { kernelL = 0; kernelR = 0; return; } - if (elevationIndex > m_elevations.size() - 1) - elevationIndex = m_elevations.size() - 1; + if (elevationIndex > m_elevations.Length() - 1) + elevationIndex = m_elevations.Length() - 1; HRTFElevation* hrtfElevation = m_elevations[elevationIndex].get(); - ASSERT(hrtfElevation); + MOZ_ASSERT(hrtfElevation); if (!hrtfElevation) { kernelL = 0; kernelR = 0; @@ -114,19 +108,12 @@ void HRTFDatabase::getKernelsFromAzimuthElevation(double azimuthBlend, unsigned unsigned HRTFDatabase::indexFromElevationAngle(double elevationAngle) { // Clamp to allowed range. - elevationAngle = max(static_cast(MinElevation), elevationAngle); - elevationAngle = min(static_cast(MaxElevation), elevationAngle); + elevationAngle = mozilla::clamped(elevationAngle, + static_cast(MinElevation), + static_cast(MaxElevation)); unsigned elevationIndex = static_cast(InterpolationFactor * (elevationAngle - MinElevation) / RawElevationAngleSpacing); return elevationIndex; } -void HRTFDatabase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const -{ - MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::AudioSharedData); - info.addMember(m_elevations, "elevations"); -} - } // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/content/media/webaudio/blink/HRTFDatabase.h b/content/media/webaudio/blink/HRTFDatabase.h index 2709fb46f78b..ef24ff254ee0 100644 --- a/content/media/webaudio/blink/HRTFDatabase.h +++ b/content/media/webaudio/blink/HRTFDatabase.h @@ -29,21 +29,17 @@ #ifndef HRTFDatabase_h #define HRTFDatabase_h -#include "core/platform/audio/HRTFElevation.h" -#include -#include -#include -#include -#include +#include "HRTFElevation.h" +#include "nsAutoRef.h" +#include "nsTArray.h" namespace WebCore { class HRTFKernel; class HRTFDatabase { - WTF_MAKE_NONCOPYABLE(HRTFDatabase); public: - static PassOwnPtr create(float sampleRate); + static nsReturnRef create(float sampleRate); // getKernelsFromAzimuthElevation() returns a left and right ear kernel, and an interpolated left and right frame delay for the given azimuth and elevation. // azimuthBlend must be in the range 0 -> 1. @@ -59,9 +55,10 @@ public: // Number of elevations loaded from resource. static const unsigned NumberOfRawElevations; - void reportMemoryUsage(MemoryObjectInfo*) const; - private: + HRTFDatabase(const HRTFDatabase& other) MOZ_DELETE; + void operator=(const HRTFDatabase& other) MOZ_DELETE; + explicit HRTFDatabase(float sampleRate); // Minimum and maximum elevation angles (inclusive) for a HRTFDatabase. @@ -78,10 +75,17 @@ private: // Returns the index for the correct HRTFElevation given the elevation angle. static unsigned indexFromElevationAngle(double); - Vector > m_elevations; + nsTArray > m_elevations; float m_sampleRate; }; } // namespace WebCore +template <> +class nsAutoRefTraits : + public nsPointerRefTraits { +public: + static void Release(WebCore::HRTFDatabase* ptr) { delete(ptr); } +}; + #endif // HRTFDatabase_h diff --git a/content/media/webaudio/blink/HRTFDatabaseLoader.cpp b/content/media/webaudio/blink/HRTFDatabaseLoader.cpp index ae985893a5ba..e2ebdd85c135 100644 --- a/content/media/webaudio/blink/HRTFDatabaseLoader.cpp +++ b/content/media/webaudio/blink/HRTFDatabaseLoader.cpp @@ -26,39 +26,38 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" +#include "HRTFDatabaseLoader.h" -#if ENABLE(WEB_AUDIO) +#include "HRTFDatabase.h" -#include "core/platform/audio/HRTFDatabaseLoader.h" - -#include "core/platform/PlatformMemoryInstrumentation.h" -#include "core/platform/audio/HRTFDatabase.h" -#include "wtf/MainThread.h" -#include "wtf/MemoryInstrumentationHashMap.h" +using namespace mozilla; namespace WebCore { // Singleton -HRTFDatabaseLoader::LoaderMap* HRTFDatabaseLoader::s_loaderMap = 0; +nsTHashtable* + HRTFDatabaseLoader::s_loaderMap = nullptr; -PassRefPtr HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate) +TemporaryRef HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate) { - ASSERT(isMainThread()); + MOZ_ASSERT(NS_IsMainThread()); RefPtr loader; - if (!s_loaderMap) - s_loaderMap = adoptPtr(new LoaderMap()).leakPtr(); + if (!s_loaderMap) { + s_loaderMap = new nsTHashtable(); + s_loaderMap->Init(); + } - loader = s_loaderMap->get(sampleRate); - if (loader) { - ASSERT(sampleRate == loader->databaseSampleRate()); + LoaderByRateEntry* entry = s_loaderMap->PutEntry(sampleRate); + loader = entry->mLoader; + if (loader) { // existing entry + MOZ_ASSERT(sampleRate == loader->databaseSampleRate()); return loader; } - loader = adoptRef(new HRTFDatabaseLoader(sampleRate)); - s_loaderMap->add(sampleRate, loader.get()); + loader = new HRTFDatabaseLoader(sampleRate); + entry->mLoader = loader; loader->loadAsynchronously(); @@ -66,35 +65,41 @@ PassRefPtr HRTFDatabaseLoader::createAndLoadAsynchronouslyIf } HRTFDatabaseLoader::HRTFDatabaseLoader(float sampleRate) - : m_databaseLoaderThread(0) + : m_threadLock("HRTFDatabaseLoader") + , m_databaseLoaderThread(nullptr) , m_databaseSampleRate(sampleRate) { - ASSERT(isMainThread()); + MOZ_ASSERT(NS_IsMainThread()); } HRTFDatabaseLoader::~HRTFDatabaseLoader() { - ASSERT(isMainThread()); + MOZ_ASSERT(NS_IsMainThread()); waitForLoaderThreadCompletion(); - m_hrtfDatabase.clear(); + m_hrtfDatabase.reset(); // Remove ourself from the map. - if (s_loaderMap) - s_loaderMap->remove(m_databaseSampleRate); + s_loaderMap->RemoveEntry(m_databaseSampleRate); + if (s_loaderMap->Count() == 0) { + delete s_loaderMap; + s_loaderMap = nullptr; + } } // Asynchronously load the database in this thread. static void databaseLoaderEntry(void* threadData) { + PR_SetCurrentThreadName("HRTFDatabaseLdr"); + HRTFDatabaseLoader* loader = reinterpret_cast(threadData); - ASSERT(loader); + MOZ_ASSERT(loader); loader->load(); } void HRTFDatabaseLoader::load() { - ASSERT(!isMainThread()); + MOZ_ASSERT(!NS_IsMainThread()); if (!m_hrtfDatabase.get()) { // Load the default HRTF database. m_hrtfDatabase = HRTFDatabase::create(m_databaseSampleRate); @@ -103,13 +108,16 @@ void HRTFDatabaseLoader::load() void HRTFDatabaseLoader::loadAsynchronously() { - ASSERT(isMainThread()); + MOZ_ASSERT(NS_IsMainThread()); - MutexLocker locker(m_threadLock); + MutexAutoLock locker(m_threadLock); if (!m_hrtfDatabase.get() && !m_databaseLoaderThread) { // Start the asynchronous database loading process. - m_databaseLoaderThread = createThread(databaseLoaderEntry, this, "HRTF database loader"); + m_databaseLoaderThread = + PR_CreateThread(PR_USER_THREAD, databaseLoaderEntry, this, + PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, + PR_JOINABLE_THREAD, 0); } } @@ -120,21 +128,14 @@ bool HRTFDatabaseLoader::isLoaded() const void HRTFDatabaseLoader::waitForLoaderThreadCompletion() { - MutexLocker locker(m_threadLock); + MutexAutoLock locker(m_threadLock); // waitForThreadCompletion() should not be called twice for the same thread. - if (m_databaseLoaderThread) - waitForThreadCompletion(m_databaseLoaderThread); - m_databaseLoaderThread = 0; -} - -void HRTFDatabaseLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const -{ - MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::AudioSharedData); - info.addMember(m_hrtfDatabase, "hrtfDatabase"); - info.addMember(s_loaderMap, "loaderMap", WTF::RetainingPointer); + if (m_databaseLoaderThread) { + DebugOnly status = PR_JoinThread(m_databaseLoaderThread); + MOZ_ASSERT(status == PR_SUCCESS, "PR_JoinThread failed"); + } + m_databaseLoaderThread = nullptr; } } // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/content/media/webaudio/blink/HRTFDatabaseLoader.h b/content/media/webaudio/blink/HRTFDatabaseLoader.h index fd520c1149bc..f03a25333576 100644 --- a/content/media/webaudio/blink/HRTFDatabaseLoader.h +++ b/content/media/webaudio/blink/HRTFDatabaseLoader.h @@ -29,24 +29,23 @@ #ifndef HRTFDatabaseLoader_h #define HRTFDatabaseLoader_h -#include "core/platform/audio/HRTFDatabase.h" -#include "wtf/HashMap.h" -#include "wtf/PassRefPtr.h" -#include "wtf/RefCounted.h" -#include "wtf/RefPtr.h" -#include "wtf/Threading.h" +#include "HRTFDatabase.h" +#include "nsTHashtable.h" +#include "mozilla/RefPtr.h" +#include "nsIThread.h" +#include "mozilla/Mutex.h" namespace WebCore { // HRTFDatabaseLoader will asynchronously load the default HRTFDatabase in a new thread. -class HRTFDatabaseLoader : public RefCounted { +class HRTFDatabaseLoader : public mozilla::RefCounted { public: // Lazily creates a HRTFDatabaseLoader (if not already created) for the given sample-rate // and starts loading asynchronously (when created the first time). // Returns the HRTFDatabaseLoader. // Must be called from the main thread. - static PassRefPtr createAndLoadAsynchronouslyIfNecessary(float sampleRate); + static mozilla::TemporaryRef createAndLoadAsynchronouslyIfNecessary(float sampleRate); // Both constructor and destructor must be called from the main thread. ~HRTFDatabaseLoader(); @@ -54,7 +53,8 @@ public: // Returns true once the default database has been completely loaded. bool isLoaded() const; - // waitForLoaderThreadCompletion() may be called more than once and is thread-safe. + // waitForLoaderThreadCompletion() may be called more than once, + // on any thread except m_databaseLoaderThread. void waitForLoaderThreadCompletion(); HRTFDatabase* database() { return m_hrtfDatabase.get(); } @@ -64,8 +64,6 @@ public: // Called in asynchronous loading thread. void load(); - void reportMemoryUsage(MemoryObjectInfo*) const; - private: // Both constructor and destructor must be called from the main thread. explicit HRTFDatabaseLoader(float sampleRate); @@ -75,16 +73,23 @@ private: void loadAsynchronously(); // Map from sample-rate to loader. - typedef HashMap LoaderMap; - + class LoaderByRateEntry : public nsFloatHashKey { + public: + LoaderByRateEntry(KeyTypePointer aKey) + : nsFloatHashKey(aKey) + , mLoader() // so PutEntry() will zero-initialize + { + } + HRTFDatabaseLoader* mLoader; + }; // Keeps track of loaders on a per-sample-rate basis. - static LoaderMap* s_loaderMap; // singleton + static nsTHashtable *s_loaderMap; // singleton - OwnPtr m_hrtfDatabase; + nsAutoRef m_hrtfDatabase; // Holding a m_threadLock is required when accessing m_databaseLoaderThread. - Mutex m_threadLock; - ThreadIdentifier m_databaseLoaderThread; + mozilla::Mutex m_threadLock; + PRThread* m_databaseLoaderThread; float m_databaseSampleRate; }; diff --git a/content/media/webaudio/blink/moz.build b/content/media/webaudio/blink/moz.build index 9426b2baead4..654b4292311b 100644 --- a/content/media/webaudio/blink/moz.build +++ b/content/media/webaudio/blink/moz.build @@ -12,6 +12,8 @@ CPP_SOURCES += [ 'DynamicsCompressor.cpp', 'DynamicsCompressorKernel.cpp', 'FFTConvolver.cpp', + 'HRTFDatabase.cpp', + 'HRTFDatabaseLoader.cpp', 'HRTFElevation.cpp', 'HRTFKernel.cpp', 'Reverb.cpp',