b=815643 Add Blink's HRTFDatabase and HRTFDatabaseLoader to the build r=ehsan
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 09 Aug 2013 09:56:28 +1200
changeset 142362 316df2d96b24
parent 142361 395fc5b9593c
child 142363 c19e2f326d15
push id32374
push userktomlinson@mozilla.com
push dateTue, 13 Aug 2013 02:49:14 +0000
treeherdermozilla-inbound@62ad090a94a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs815643
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
b=815643 Add Blink's HRTFDatabase and HRTFDatabaseLoader to the build r=ehsan
content/media/webaudio/blink/HRTFDatabase.cpp
content/media/webaudio/blink/HRTFDatabase.h
content/media/webaudio/blink/HRTFDatabaseLoader.cpp
content/media/webaudio/blink/HRTFDatabaseLoader.h
content/media/webaudio/blink/moz.build
--- a/content/media/webaudio/blink/HRTFDatabase.cpp
+++ b/content/media/webaudio/blink/HRTFDatabase.cpp
@@ -21,112 +21,99 @@
  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
+#include "HRTFDatabase.h"
 
-#include "core/platform/audio/HRTFDatabase.h"
-
-#include "core/platform/PlatformMemoryInstrumentation.h"
-#include "core/platform/audio/HRTFElevation.h"
-#include <wtf/MemoryInstrumentationVector.h>
+#include "HRTFElevation.h"
 
 using namespace std;
 
 namespace WebCore {
 
 const int HRTFDatabase::MinElevation = -45;
 const int HRTFDatabase::MaxElevation = 90;
 const unsigned HRTFDatabase::RawElevationAngleSpacing = 15;
 const unsigned HRTFDatabase::NumberOfRawElevations = 10; // -45 -> +90 (each 15 degrees)
 const unsigned HRTFDatabase::InterpolationFactor = 1;
 const unsigned HRTFDatabase::NumberOfTotalElevations = NumberOfRawElevations * InterpolationFactor;
 
-PassOwnPtr<HRTFDatabase> HRTFDatabase::create(float sampleRate)
+nsReturnRef<HRTFDatabase> HRTFDatabase::create(float sampleRate)
 {
-    OwnPtr<HRTFDatabase> hrtfDatabase = adoptPtr(new HRTFDatabase(sampleRate));
-    return hrtfDatabase.release();
+    return nsReturnRef<HRTFDatabase>(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 = HRTFElevation::createForSubject("Composite", elevation, sampleRate);
-        ASSERT(hrtfElevation.get());
+        nsAutoRef<HRTFElevation> 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;
     }
 
     // Now, go back and interpolate elevations.
     if (InterpolationFactor > 1) {
         for (unsigned i = 0; i < NumberOfTotalElevations; i += InterpolationFactor) {
             unsigned j = (i + InterpolationFactor);
             if (j >= NumberOfTotalElevations)
                 j = i; // for last elevation interpolate with itself
 
             // Create the interpolated convolution kernels and delays.
             for (unsigned jj = 1; jj < InterpolationFactor; ++jj) {
                 float x = static_cast<float>(jj) / static_cast<float>(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());
             }
         }
     }
 }
 
 void HRTFDatabase::getKernelsFromAzimuthElevation(double azimuthBlend, unsigned azimuthIndex, double elevationAngle, HRTFKernel* &kernelL, HRTFKernel* &kernelR,
                                                   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;
         return;
     }
     
     hrtfElevation->getKernelsFromAzimuth(azimuthBlend, azimuthIndex, kernelL, kernelR, frameDelayL, frameDelayR);
 }                                                     
 
 unsigned HRTFDatabase::indexFromElevationAngle(double elevationAngle)
 {
     // Clamp to allowed range.
-    elevationAngle = max(static_cast<double>(MinElevation), elevationAngle);
-    elevationAngle = min(static_cast<double>(MaxElevation), elevationAngle);
+    elevationAngle = mozilla::clamped(elevationAngle,
+                                      static_cast<double>(MinElevation),
+                                      static_cast<double>(MaxElevation));
 
     unsigned elevationIndex = static_cast<int>(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)
--- a/content/media/webaudio/blink/HRTFDatabase.h
+++ b/content/media/webaudio/blink/HRTFDatabase.h
@@ -24,64 +24,68 @@
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef HRTFDatabase_h
 #define HRTFDatabase_h
 
-#include "core/platform/audio/HRTFElevation.h"
-#include <wtf/Forward.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/Vector.h>
+#include "HRTFElevation.h"
+#include "nsAutoRef.h"
+#include "nsTArray.h"
 
 namespace WebCore {
 
 class HRTFKernel;
 
 class HRTFDatabase {
-    WTF_MAKE_NONCOPYABLE(HRTFDatabase);
 public:
-    static PassOwnPtr<HRTFDatabase> create(float sampleRate);
+    static nsReturnRef<HRTFDatabase> 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.
     // Valid values for azimuthIndex are 0 -> HRTFElevation::NumberOfTotalAzimuths - 1 (corresponding to angles of 0 -> 360).
     // Valid values for elevationAngle are MinElevation -> MaxElevation.
     void getKernelsFromAzimuthElevation(double azimuthBlend, unsigned azimuthIndex, double elevationAngle, HRTFKernel* &kernelL, HRTFKernel* &kernelR, double& frameDelayL, double& frameDelayR);
 
     // Returns the number of different azimuth angles.
     static unsigned numberOfAzimuths() { return HRTFElevation::NumberOfTotalAzimuths; }
 
     float sampleRate() const { return m_sampleRate; }
 
     // 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;
 
-private:
     explicit HRTFDatabase(float sampleRate);
 
     // Minimum and maximum elevation angles (inclusive) for a HRTFDatabase.
     static const int MinElevation;
     static const int MaxElevation;
     static const unsigned RawElevationAngleSpacing;
 
     // Interpolates by this factor to get the total number of elevations from every elevation loaded from resource.
     static const unsigned InterpolationFactor;
     
     // Total number of elevations after interpolation.
     static const unsigned NumberOfTotalElevations;
 
     // Returns the index for the correct HRTFElevation given the elevation angle.
     static unsigned indexFromElevationAngle(double);
 
-    Vector<OwnPtr<HRTFElevation> > m_elevations;                                            
+    nsTArray<nsAutoRef<HRTFElevation> > m_elevations;
     float m_sampleRate;
 };
 
 } // namespace WebCore
 
+template <>
+class nsAutoRefTraits<WebCore::HRTFDatabase> :
+    public nsPointerRefTraits<WebCore::HRTFDatabase> {
+public:
+    static void Release(WebCore::HRTFDatabase* ptr) { delete(ptr); }
+};
+
 #endif // HRTFDatabase_h
--- a/content/media/webaudio/blink/HRTFDatabaseLoader.cpp
+++ b/content/media/webaudio/blink/HRTFDatabaseLoader.cpp
@@ -21,120 +21,121 @@
  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
+#include "HRTFDatabaseLoader.h"
 
-#include "core/platform/audio/HRTFDatabaseLoader.h"
+#include "HRTFDatabase.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::LoaderByRateEntry>*
+    HRTFDatabaseLoader::s_loaderMap = nullptr;
 
-PassRefPtr<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate)
+TemporaryRef<HRTFDatabaseLoader> HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(float sampleRate)
 {
-    ASSERT(isMainThread());
+    MOZ_ASSERT(NS_IsMainThread());
 
     RefPtr<HRTFDatabaseLoader> loader;
     
-    if (!s_loaderMap)
-        s_loaderMap = adoptPtr(new LoaderMap()).leakPtr();
+    if (!s_loaderMap) {
+        s_loaderMap = new nsTHashtable<LoaderByRateEntry>();
+        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();
 
     return loader;
 }
 
 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<HRTFDatabaseLoader*>(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);
     }
 }
 
 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);
     }
 }
 
 bool HRTFDatabaseLoader::isLoaded() const
 {
     return m_hrtfDatabase.get();
 }
 
 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<PRStatus> status = PR_JoinThread(m_databaseLoaderThread);
+        MOZ_ASSERT(status == PR_SUCCESS, "PR_JoinThread failed");
+    }
+    m_databaseLoaderThread = nullptr;
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
--- a/content/media/webaudio/blink/HRTFDatabaseLoader.h
+++ b/content/media/webaudio/blink/HRTFDatabaseLoader.h
@@ -24,71 +24,76 @@
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #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<HRTFDatabaseLoader> {
+class HRTFDatabaseLoader : public mozilla::RefCounted<HRTFDatabaseLoader> {
 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<HRTFDatabaseLoader> createAndLoadAsynchronouslyIfNecessary(float sampleRate);
+    static mozilla::TemporaryRef<HRTFDatabaseLoader> createAndLoadAsynchronouslyIfNecessary(float sampleRate);
 
     // Both constructor and destructor must be called from the main thread.
     ~HRTFDatabaseLoader();
     
     // 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(); }
 
     float databaseSampleRate() const { return m_databaseSampleRate; }
     
     // 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);
     
     // If it hasn't already been loaded, creates a new thread and initiates asynchronous loading of the default database.
     // This must be called from the main thread.
     void loadAsynchronously();
 
     // Map from sample-rate to loader.
-    typedef HashMap<double, HRTFDatabaseLoader*> 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<LoaderByRateEntry> *s_loaderMap; // singleton
 
-    OwnPtr<HRTFDatabase> m_hrtfDatabase;
+    nsAutoRef<HRTFDatabase> 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;
 };
 
 } // namespace WebCore
 
 #endif // HRTFDatabaseLoader_h
--- a/content/media/webaudio/blink/moz.build
+++ b/content/media/webaudio/blink/moz.build
@@ -7,16 +7,18 @@
 MODULE = 'content'
 
 CPP_SOURCES += [
     'Biquad.cpp',
     'DirectConvolver.cpp',
     'DynamicsCompressor.cpp',
     'DynamicsCompressorKernel.cpp',
     'FFTConvolver.cpp',
+    'HRTFDatabase.cpp',
+    'HRTFDatabaseLoader.cpp',
     'HRTFElevation.cpp',
     'HRTFKernel.cpp',
     'Reverb.cpp',
     'ReverbAccumulationBuffer.cpp',
     'ReverbConvolver.cpp',
     'ReverbConvolverStage.cpp',
     'ReverbInputBuffer.cpp',
     'ZeroPole.cpp',