b=865241 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 153776 a867ee21d619a885d5aa8cce589092b70549237b
parent 153775 581e1a7c6a7f92cb4d4f9786426e7604677b467c
child 153777 b085cd4bd4cad752405777968990dd048ee27acf
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs865241
milestone25.0a2
b=865241 Add Blink's HRTFDatabase and HRTFDatabaseLoader to the build r=ehsan (transplanted from 316df2d96b2420f285f9698cd2bacc819d4c9e5a)
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',