Bug 942657 - Devirtualize AudioStream. r=doublec,gps
authorMatthew Gregan <kinetik@flim.org>
Thu, 28 Nov 2013 18:09:08 +1300
changeset 172676 6c15f3df605a3d1d9df06bc12673dec99b9c2143
parent 172675 cf8bda6419f415575373b04d6d282324c5a95174
child 172677 41c241079f2515c0ac764516c38564617e02bfc3
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec, gps
bugs942657
milestone28.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
Bug 942657 - Devirtualize AudioStream. r=doublec,gps
config/external/moz.build
configure.in
content/html/content/src/HTMLAudioElement.cpp
content/media/AudioStream.cpp
content/media/AudioStream.h
content/media/MediaDecoderStateMachine.cpp
content/media/MediaStreamGraph.cpp
layout/media/Makefile.in
layout/media/symbols.def.in
media/libcubeb/README_MOZILLA
media/libcubeb/src/cubeb.c
media/webrtc/signaling/test/Makefile.in
toolkit/library/Makefile.in
--- a/config/external/moz.build
+++ b/config/external/moz.build
@@ -28,21 +28,19 @@ if CONFIG['MOZ_WEBM']:
     external_dirs += ['media/libnestegg']
 
 if CONFIG['MOZ_VP8'] and not CONFIG['MOZ_NATIVE_LIBVPX']:
     external_dirs += ['media/libvpx']
 
 if CONFIG['MOZ_OGG']:
     external_dirs += ['media/libogg', 'media/libtheora']
 
-if CONFIG['MOZ_CUBEB']:
-    external_dirs += ['media/libcubeb']
-
 if not CONFIG['MOZ_NATIVE_PNG']:
     external_dirs += ['media/libpng']
 
 external_dirs += [
     'media/kiss_fft',
+    'media/libcubeb',
     'media/libspeex_resampler',
     'media/libsoundtouch',
 ]
 
 PARALLEL_DIRS += ['../../' + i for i in external_dirs]
--- a/configure.in
+++ b/configure.in
@@ -3933,17 +3933,16 @@ ENABLE_SYSTEM_EXTENSION_DIRS=1
 MOZ_BRANDING_DIRECTORY=
 MOZ_OFFICIAL_BRANDING=
 MOZ_FEEDS=1
 MOZ_WEBAPP_RUNTIME=
 MOZ_JSDEBUGGER=1
 MOZ_AUTH_EXTENSION=1
 MOZ_OGG=1
 MOZ_RAW=
-MOZ_CUBEB=
 MOZ_VORBIS=
 MOZ_TREMOR=
 MOZ_WAVE=1
 MOZ_SAMPLE_TYPE_FLOAT32=
 MOZ_SAMPLE_TYPE_S16=
 MOZ_OPUS=1
 MOZ_WEBM=1
 MOZ_DIRECTSHOW=
@@ -5194,17 +5193,16 @@ dnl = Disable Ogg Codecs
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(ogg,
 [  --disable-ogg           Disable support for OGG media (Theora video and Vorbis audio)],
     MOZ_OGG=,
     MOZ_OGG=1)
 
 if test -n "$MOZ_OGG"; then
     AC_DEFINE(MOZ_OGG)
-    MOZ_CUBEB=1
 
     dnl Checks for __attribute__(aligned()) directive
     AC_CACHE_CHECK([__attribute__ ((aligned ())) support],
         [ac_cv_c_attribute_aligned],
         [ac_cv_c_attribute_aligned=0
          CFLAGS_save="${CFLAGS}"
          CFLAGS="${CFLAGS} -Werror"
          for ac_cv_c_attr_align_try in 64 32 16 8; do
@@ -5254,17 +5252,16 @@ fi
 
 MOZ_ARG_DISABLE_BOOL(directshow,
 [  --disable-directshow  Disable support for DirectShow],
     MOZ_DIRECTSHOW=,
     MOZ_DIRECTSHOW=1)
 
 if test -n "$MOZ_DIRECTSHOW"; then
     AC_DEFINE(MOZ_DIRECTSHOW)
-    MOZ_CUBEB=1
 fi;
 
 dnl ========================================================
 dnl = Windows Media Foundation support
 dnl ========================================================
 if test "$OS_ARCH" = "WINNT"; then
     dnl Enable Windows Media Foundation support by default.
     dnl Note our minimum SDK version is Windows 7 SDK, so we are (currently)
@@ -5274,17 +5271,16 @@ fi
 
 MOZ_ARG_DISABLE_BOOL(wmf,
 [  --disable-wmf  Disable support for Windows Media Foundation],
     MOZ_WMF=,
     MOZ_WMF=1)
 
 if test -n "$MOZ_WMF"; then
     AC_DEFINE(MOZ_WMF)
-    MOZ_CUBEB=1
 fi;
 
 dnl ========================================================
 dnl = Built-in fragmented MP4 support.
 dnl ========================================================
 if test -n "$MOZ_WMF"; then
     dnl Enable fragmented MP4 parser on Windows by default.
     dnl We will also need to enable it on other platforms as we implement
@@ -5405,17 +5401,16 @@ if test -n "$MOZ_VP8"; then
     fi
 fi
 
 AC_SUBST(MOZ_NATIVE_LIBVPX)
 AC_SUBST(MOZ_LIBVPX_CFLAGS)
 AC_SUBST(MOZ_LIBVPX_LIBS)
 
 if test "$MOZ_WEBM" -o "$MOZ_OGG"; then
-    MOZ_CUBEB=1
     if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then
         MOZ_VORBIS=1
     else
         MOZ_TREMOR=1
     fi
 fi
 
 if test -n "$MOZ_VP8" -a -z "$MOZ_NATIVE_LIBVPX"; then
@@ -5507,26 +5502,21 @@ dnl = Disable Wave decoder support
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(wave,
 [  --disable-wave          Disable Wave decoder support],
     MOZ_WAVE=,
     MOZ_WAVE=1)
 
 if test -n "$MOZ_WAVE"; then
     AC_DEFINE(MOZ_WAVE)
-    MOZ_CUBEB=1
-fi
-
-dnl ========================================================
-dnl = Handle dependent CUBEB and MEDIA defines
-dnl ========================================================
-
-if test -n "$MOZ_CUBEB"; then
-    AC_DEFINE(MOZ_CUBEB)
-fi
+fi
+
+dnl ========================================================
+dnl = Handle dependent MEDIA defines
+dnl ========================================================
 
 if test -n "$MOZ_OPUS" -a -z "$MOZ_OGG"; then
     AC_MSG_ERROR([MOZ_OPUS requires MOZ_OGG which is disabled.])
 fi
 
 if test -n "$MOZ_VORBIS" -a -z "$MOZ_OGG"; then
     AC_MSG_ERROR([MOZ_VORBIS requires MOZ_OGG which is disabled.
 Note that you need vorbis support for WebM playback.])
@@ -5547,57 +5537,55 @@ fi
 if test -n "$MOZ_TREMOR"; then
     AC_DEFINE(MOZ_TREMOR)
 fi
 
 if test -n "$MOZ_OPUS"; then
     AC_DEFINE(MOZ_OPUS)
 fi
 
-dnl ====================================================
-dnl = Check alsa availability on Linux if using libcubeb
-dnl ====================================================
-
-dnl If using libcubeb with Linux, ensure that the alsa library is available
-if test -n "$MOZ_CUBEB" -a "$OS_TARGET" = "Linux"; then
+dnl ==================================
+dnl = Check alsa availability on Linux
+dnl ==================================
+
+dnl If using Linux, ensure that the alsa library is available
+if test "$OS_TARGET" = "Linux"; then
     MOZ_ALSA=1
 fi
 
 MOZ_ARG_ENABLE_BOOL(alsa,
 [  --enable-alsa          Enable Alsa support (default on Linux)],
    MOZ_ALSA=1,
    MOZ_ALSA=)
 
 if test -n "$MOZ_ALSA"; then
-    AC_DEFINE(MOZ_CUBEB)
     PKG_CHECK_MODULES(MOZ_ALSA, alsa, ,
          [echo "$MOZ_ALSA_PKG_ERRORS"
           AC_MSG_ERROR([Need alsa for Ogg, Wave or WebM decoding on Linux.  Disable with --disable-ogg --disable-wave --disable-webm.  (On Ubuntu, you might try installing the package libasound2-dev.)])])
 fi
 
 AC_SUBST(MOZ_ALSA)
 AC_SUBST(MOZ_ALSA_CFLAGS)
 AC_SUBST(MOZ_ALSA_LIBS)
 
 dnl ========================================================
 dnl = Disable PulseAudio
 dnl ========================================================
 
-dnl If using libcubeb with Linux, ensure that the PA library is available
-if test -n "$MOZ_CUBEB" -a "$OS_TARGET" = "Linux" -a -z "$MOZ_B2G"; then
+dnl If using Linux, ensure that the PA library is available
+if test "$OS_TARGET" = "Linux" -a -z "$MOZ_B2G"; then
     MOZ_PULSEAUDIO=1
 fi
 
 MOZ_ARG_DISABLE_BOOL(pulseaudio,
 [  --disable-pulseaudio          Disable PulseAudio support],
    MOZ_PULSEAUDIO=,
    MOZ_PULSEAUDIO=1)
 
 if test -n "$MOZ_PULSEAUDIO"; then
-    AC_DEFINE(MOZ_CUBEB)
     if test -z "$gonkdir"; then
         PKG_CHECK_MODULES(MOZ_PULSEAUDIO, libpulse, ,
              [echo "$MOZ_PULSEAUDIO_PKG_ERRORS"
               AC_MSG_ERROR([pulseaudio audio backend requires libpulse development package])])
     else
         MOZ_PULSEAUDIO_CFLAGS="-I$gonkdir/external/pulseaudio/pulseaudio/src"
     fi
 fi
@@ -8650,17 +8638,16 @@ AC_SUBST(USE_N32)
 AC_SUBST(CC_VERSION)
 AC_SUBST(CXX_VERSION)
 AC_SUBST(MSMANIFEST_TOOL)
 AC_SUBST(NS_ENABLE_TSF)
 AC_SUBST(MOZ_NSS_PATCH)
 AC_SUBST(MOZ_APP_COMPONENT_LIBS)
 AC_SUBST(MOZ_APP_EXTRA_LIBS)
 
-AC_SUBST(MOZ_CUBEB)
 AC_SUBST(MOZ_WAVE)
 AC_SUBST(MOZ_VORBIS)
 AC_SUBST(MOZ_TREMOR)
 AC_SUBST(MOZ_OPUS)
 AC_SUBST(MOZ_WEBM)
 AC_SUBST(MOZ_WMF)
 AC_SUBST(MOZ_FMP4)
 AC_SUBST(MOZ_DIRECTSHOW)
--- a/content/html/content/src/HTMLAudioElement.cpp
+++ b/content/html/content/src/HTMLAudioElement.cpp
@@ -106,17 +106,17 @@ HTMLAudioElement::MozSetup(uint32_t aCha
 #ifdef MOZ_B2G
   if (mTimerActivated) {
     mDeferStopPlayTimer->Cancel();
     mTimerActivated = false;
     UpdateAudioChannelPlayingState();
   }
 #endif
 
-  mAudioStream = AudioStream::AllocateStream();
+  mAudioStream = new AudioStream();
   aRv = mAudioStream->Init(aChannels, aRate, mAudioChannelType, AudioStream::HighLatency);
   if (aRv.Failed()) {
     mAudioStream->Shutdown();
     mAudioStream = nullptr;
     return;
   }
 
   MetadataLoaded(aChannels, aRate, true, false, nullptr);
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -11,114 +11,101 @@
 #include "VideoUtils.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Mutex.h"
 #include <algorithm>
 #include "mozilla/Preferences.h"
 #include "soundtouch/SoundTouch.h"
 #include "Latency.h"
 
-#if defined(MOZ_CUBEB)
-#include "nsAutoRef.h"
-#include "cubeb/cubeb.h"
-
-template <>
-class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream>
-{
-public:
-  static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); }
-};
-
-#endif
-
 namespace mozilla {
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gAudioStreamLog = nullptr;
 #endif
 
-#define PREF_VOLUME_SCALE "media.volume_scale"
-#define PREF_CUBEB_LATENCY "media.cubeb_latency_ms"
-
-static Mutex* gAudioPrefsLock = nullptr;
-static double gVolumeScale;
-static uint32_t gCubebLatency;
-static bool gCubebLatencyPrefSet;
-static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100;
-
-StaticMutex AudioStream::mMutex;
-uint32_t AudioStream::mPreferredSampleRate = 0;
-
 /**
  * When MOZ_DUMP_AUDIO is set in the environment (to anything),
  * we'll drop a series of files in the current working directory named
- * dumped-audio-<nnn>.wav, one per nsBufferedAudioStream created, containing
+ * dumped-audio-<nnn>.wav, one per AudioStream created, containing
  * the audio for the stream including any skips due to underruns.
  */
-#if defined(MOZ_CUBEB)
 static int gDumpedAudioCount = 0;
-#endif
+
+#define PREF_VOLUME_SCALE "media.volume_scale"
+#define PREF_CUBEB_LATENCY "media.cubeb_latency_ms"
+
+static const uint32_t CUBEB_NORMAL_LATENCY_MS = 100;
 
-static int PrefChanged(const char* aPref, void* aClosure)
+StaticMutex AudioStream::sMutex;
+cubeb* AudioStream::sCubebContext;
+uint32_t AudioStream::sPreferredSampleRate;
+double AudioStream::sVolumeScale;
+uint32_t AudioStream::sCubebLatency;
+bool AudioStream::sCubebLatencyPrefSet;
+
+/*static*/ int AudioStream::PrefChanged(const char* aPref, void* aClosure)
 {
   if (strcmp(aPref, PREF_VOLUME_SCALE) == 0) {
     nsAdoptingString value = Preferences::GetString(aPref);
-    MutexAutoLock lock(*gAudioPrefsLock);
+    StaticMutexAutoLock lock(sMutex);
     if (value.IsEmpty()) {
-      gVolumeScale = 1.0;
+      sVolumeScale = 1.0;
     } else {
       NS_ConvertUTF16toUTF8 utf8(value);
-      gVolumeScale = std::max<double>(0, PR_strtod(utf8.get(), nullptr));
+      sVolumeScale = std::max<double>(0, PR_strtod(utf8.get(), nullptr));
     }
   } else if (strcmp(aPref, PREF_CUBEB_LATENCY) == 0) {
     // Arbitrary default stream latency of 100ms.  The higher this
     // value, the longer stream volume changes will take to become
     // audible.
-    gCubebLatencyPrefSet = Preferences::HasUserValue(aPref);
+    sCubebLatencyPrefSet = Preferences::HasUserValue(aPref);
     uint32_t value = Preferences::GetUint(aPref, CUBEB_NORMAL_LATENCY_MS);
-    MutexAutoLock lock(*gAudioPrefsLock);
-    gCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000);
+    StaticMutexAutoLock lock(sMutex);
+    sCubebLatency = std::min<uint32_t>(std::max<uint32_t>(value, 1), 1000);
   }
   return 0;
 }
 
-#if defined(MOZ_CUBEB)
-static double GetVolumeScale()
+/*static*/ double AudioStream::GetVolumeScale()
 {
-  MutexAutoLock lock(*gAudioPrefsLock);
-  return gVolumeScale;
+  StaticMutexAutoLock lock(sMutex);
+  return sVolumeScale;
 }
 
-static cubeb* gCubebContext;
-
-static cubeb* GetCubebContext()
+/*static*/ cubeb* AudioStream::GetCubebContext()
 {
-  MutexAutoLock lock(*gAudioPrefsLock);
-  if (gCubebContext ||
-      cubeb_init(&gCubebContext, "AudioStream") == CUBEB_OK) {
-    return gCubebContext;
+  StaticMutexAutoLock lock(sMutex);
+  return GetCubebContextUnlocked();
+}
+
+/*static*/ cubeb* AudioStream::GetCubebContextUnlocked()
+{
+  sMutex.AssertCurrentThreadOwns();
+  if (sCubebContext ||
+      cubeb_init(&sCubebContext, "AudioStream") == CUBEB_OK) {
+    return sCubebContext;
   }
   NS_WARNING("cubeb_init failed");
   return nullptr;
 }
 
-static uint32_t GetCubebLatency()
+/*static*/ uint32_t AudioStream::GetCubebLatency()
 {
-  MutexAutoLock lock(*gAudioPrefsLock);
-  return gCubebLatency;
+  StaticMutexAutoLock lock(sMutex);
+  return sCubebLatency;
 }
 
-static bool CubebLatencyPrefSet()
+/*static*/ bool AudioStream::CubebLatencyPrefSet()
 {
-  MutexAutoLock lock(*gAudioPrefsLock);
-  return gCubebLatencyPrefSet;
+  StaticMutexAutoLock lock(sMutex);
+  return sCubebLatencyPrefSet;
 }
-#endif
 
-#if defined(MOZ_CUBEB) && defined(__ANDROID__) && defined(MOZ_B2G)
+#if defined(__ANDROID__) && defined(MOZ_B2G)
 static cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannelType aType)
 {
   switch(aType) {
     case dom::AUDIO_CHANNEL_NORMAL:
       return CUBEB_STREAM_TYPE_SYSTEM;
     case dom::AUDIO_CHANNEL_CONTENT:
       return CUBEB_STREAM_TYPE_MUSIC;
     case dom::AUDIO_CHANNEL_NOTIFICATION:
@@ -134,62 +121,74 @@ static cubeb_stream_type ConvertChannelT
     default:
       NS_ERROR("The value of AudioChannelType is invalid");
       return CUBEB_STREAM_TYPE_MAX;
   }
 }
 #endif
 
 AudioStream::AudioStream()
-: mInRate(0),
-  mOutRate(0),
-  mChannels(0),
-  mWritten(0),
-  mAudioClock(MOZ_THIS_IN_INITIALIZER_LIST()),
-  mLatencyRequest(HighLatency),
-  mReadPoint(0)
-{}
+  : mMonitor("AudioStream")
+  , mInRate(0)
+  , mOutRate(0)
+  , mChannels(0)
+  , mWritten(0)
+  , mAudioClock(MOZ_THIS_IN_INITIALIZER_LIST())
+  , mLatencyRequest(HighLatency)
+  , mReadPoint(0)
+  , mLostFrames(0)
+  , mDumpFile(nullptr)
+  , mVolume(1.0)
+  , mBytesPerFrame(0)
+  , mState(INITIALIZED)
+{
+  // keep a ref in case we shut down later than nsLayoutStatics
+  mLatencyLog = AsyncLatencyLogger::Get(true);
+}
 
-void AudioStream::InitLibrary()
+AudioStream::~AudioStream()
+{
+  Shutdown();
+  if (mDumpFile) {
+    fclose(mDumpFile);
+  }
+}
+
+/*static*/ void AudioStream::InitLibrary()
 {
 #ifdef PR_LOGGING
   gAudioStreamLog = PR_NewLogModule("AudioStream");
 #endif
-  gAudioPrefsLock = new Mutex("AudioStream::gAudioPrefsLock");
   PrefChanged(PREF_VOLUME_SCALE, nullptr);
   Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
-#if defined(MOZ_CUBEB)
   PrefChanged(PREF_CUBEB_LATENCY, nullptr);
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
-#endif
 }
 
-void AudioStream::ShutdownLibrary()
+/*static*/ void AudioStream::ShutdownLibrary()
 {
   Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
-#if defined(MOZ_CUBEB)
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
-#endif
-  delete gAudioPrefsLock;
-  gAudioPrefsLock = nullptr;
 
-#if defined(MOZ_CUBEB)
-  if (gCubebContext) {
-    cubeb_destroy(gCubebContext);
-    gCubebContext = nullptr;
+  StaticMutexAutoLock lock(sMutex);
+  if (sCubebContext) {
+    cubeb_destroy(sCubebContext);
+    sCubebContext = nullptr;
   }
-#endif
-}
-
-AudioStream::~AudioStream()
-{
 }
 
 nsresult AudioStream::EnsureTimeStretcherInitialized()
 {
+  MonitorAutoLock mon(mMonitor);
+  return EnsureTimeStretcherInitializedUnlocked();
+}
+
+nsresult AudioStream::EnsureTimeStretcherInitializedUnlocked()
+{
+  mMonitor.AssertCurrentThreadOwns();
   if (!mTimeStretcher) {
     // SoundTouch does not support a number of channels > 2
     if (mChannels > 2) {
       return NS_ERROR_FAILURE;
     }
     mTimeStretcher = new soundtouch::SoundTouch();
     mTimeStretcher->setSampleRate(mInRate);
     mTimeStretcher->setChannels(mChannels);
@@ -209,17 +208,16 @@ nsresult AudioStream::SetPlaybackRate(do
 
   if (EnsureTimeStretcherInitialized() != NS_OK) {
     return NS_ERROR_FAILURE;
   }
 
   mAudioClock.SetPlaybackRate(aPlaybackRate);
   mOutRate = mInRate / aPlaybackRate;
 
-
   if (mAudioClock.GetPreservesPitch()) {
     mTimeStretcher->setTempo(aPlaybackRate);
     mTimeStretcher->setRate(1.0f);
   } else {
     mTimeStretcher->setTempo(1.0f);
     mTimeStretcher->setRate(aPlaybackRate);
   }
   return NS_OK;
@@ -249,234 +247,53 @@ nsresult AudioStream::SetPreservesPitch(
   return NS_OK;
 }
 
 int64_t AudioStream::GetWritten()
 {
   return mWritten;
 }
 
-#if defined(MOZ_CUBEB)
-class nsCircularByteBuffer
-{
-public:
-  nsCircularByteBuffer()
-    : mBuffer(nullptr), mCapacity(0), mStart(0), mCount(0)
-  {}
-
-  // Set the capacity of the buffer in bytes.  Must be called before any
-  // call to append or pop elements.
-  void SetCapacity(uint32_t aCapacity) {
-    NS_ABORT_IF_FALSE(!mBuffer, "Buffer allocated.");
-    mCapacity = aCapacity;
-    mBuffer = new uint8_t[mCapacity];
-  }
-
-  uint32_t Length() {
-    return mCount;
-  }
-
-  uint32_t Capacity() {
-    return mCapacity;
-  }
-
-  uint32_t Available() {
-    return Capacity() - Length();
-  }
-
-  // Append aLength bytes from aSrc to the buffer.  Caller must check that
-  // sufficient space is available.
-  void AppendElements(const uint8_t* aSrc, uint32_t aLength) {
-    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
-    NS_ABORT_IF_FALSE(aLength <= Available(), "Buffer full.");
-
-    uint32_t end = (mStart + mCount) % mCapacity;
-
-    uint32_t toCopy = std::min(mCapacity - end, aLength);
-    memcpy(&mBuffer[end], aSrc, toCopy);
-    memcpy(&mBuffer[0], aSrc + toCopy, aLength - toCopy);
-    mCount += aLength;
-  }
-
-  // Remove aSize bytes from the buffer.  Caller must check returned size in
-  // aSize{1,2} before using the pointer returned in aData{1,2}.  Caller
-  // must not specify an aSize larger than Length().
-  void PopElements(uint32_t aSize, void** aData1, uint32_t* aSize1,
-                   void** aData2, uint32_t* aSize2) {
-    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
-    NS_ABORT_IF_FALSE(aSize <= Length(), "Request too large.");
-
-    *aData1 = &mBuffer[mStart];
-    *aSize1 = std::min(mCapacity - mStart, aSize);
-    *aData2 = &mBuffer[0];
-    *aSize2 = aSize - *aSize1;
-    mCount -= *aSize1 + *aSize2;
-    mStart += *aSize1 + *aSize2;
-    mStart %= mCapacity;
-  }
-
-private:
-  nsAutoArrayPtr<uint8_t> mBuffer;
-  uint32_t mCapacity;
-  uint32_t mStart;
-  uint32_t mCount;
-};
-
-class BufferedAudioStream : public AudioStream
+/*static*/ int AudioStream::MaxNumberOfChannels()
 {
- public:
-  BufferedAudioStream();
-  ~BufferedAudioStream();
-
-  nsresult Init(int32_t aNumChannels, int32_t aRate,
-                const dom::AudioChannelType aAudioChannelType,
-                AudioStream::LatencyRequest aLatencyRequest);
-  void Shutdown();
-  nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames, TimeStamp *aTime = nullptr);
-  uint32_t Available();
-  void SetVolume(double aVolume);
-  void Drain();
-  void Start();
-  void Pause();
-  void Resume();
-  int64_t GetPosition();
-  int64_t GetPositionInFrames();
-  int64_t GetPositionInFramesInternal();
-  int64_t GetLatencyInFrames();
-  bool IsPaused();
-  void GetBufferInsertTime(int64_t &aTimeMs);
-  // This method acquires the monitor and forward the call to the base
-  // class, to prevent a race on |mTimeStretcher|, in
-  // |AudioStream::EnsureTimeStretcherInitialized|.
-  nsresult EnsureTimeStretcherInitialized();
-
-private:
-  static long DataCallback_S(cubeb_stream*, void* aThis, void* aBuffer, long aFrames)
-  {
-    return static_cast<BufferedAudioStream*>(aThis)->DataCallback(aBuffer, aFrames);
-  }
-
-  static void StateCallback_S(cubeb_stream*, void* aThis, cubeb_state aState)
-  {
-    static_cast<BufferedAudioStream*>(aThis)->StateCallback(aState);
-  }
-
-  long DataCallback(void* aBuffer, long aFrames);
-  void StateCallback(cubeb_state aState);
-
-  // aTime is the time in ms the samples were inserted into MediaStreamGraph
-  long GetUnprocessed(void* aBuffer, long aFrames, int64_t &aTime);
-  long GetTimeStretched(void* aBuffer, long aFrames, int64_t &aTime);
-  long GetUnprocessedWithSilencePadding(void* aBuffer, long aFrames, int64_t &aTime);
-
-  // Shared implementation of underflow adjusted position calculation.
-  // Caller must own the monitor.
-  int64_t GetPositionInFramesUnlocked();
-
-  void StartUnlocked();
-
-  // The monitor is held to protect all access to member variables.  Write()
-  // waits while mBuffer is full; DataCallback() notifies as it consumes
-  // data from mBuffer.  Drain() waits while mState is DRAINING;
-  // StateCallback() notifies when mState is DRAINED.
-  Monitor mMonitor;
-
-  // Sum of silent frames written when DataCallback requests more frames
-  // than are available in mBuffer.
-  uint64_t mLostFrames;
-
-  // Output file for dumping audio
-  FILE* mDumpFile;
-
-  // Temporary audio buffer.  Filled by Write() and consumed by
-  // DataCallback().  Once mBuffer is full, Write() blocks until sufficient
-  // space becomes available in mBuffer.  mBuffer is sized in bytes, not
-  // frames.
-  nsCircularByteBuffer mBuffer;
-
-  // Software volume level.  Applied during the servicing of DataCallback().
-  double mVolume;
-
-  // Owning reference to a cubeb_stream.  cubeb_stream_destroy is called by
-  // nsAutoRef's destructor.
-  nsAutoRef<cubeb_stream> mCubebStream;
-
-  uint32_t mBytesPerFrame;
-
-  uint32_t BytesToFrames(uint32_t aBytes) {
-    NS_ASSERTION(aBytes % mBytesPerFrame == 0,
-                 "Byte count not aligned on frames size.");
-    return aBytes / mBytesPerFrame;
-  }
-
-  uint32_t FramesToBytes(uint32_t aFrames) {
-    return aFrames * mBytesPerFrame;
-  }
-
-
-  enum StreamState {
-    INITIALIZED, // Initialized, playback has not begun.
-    STARTED,     // Started by a call to Write() (iff INITIALIZED) or Resume().
-    STOPPED,     // Stopped by a call to Pause().
-    DRAINING,    // Drain requested.  DataCallback will indicate end of stream
-                 // once the remaining contents of mBuffer are requested by
-                 // cubeb, after which StateCallback will indicate drain
-                 // completion.
-    DRAINED,     // StateCallback has indicated that the drain is complete.
-    ERRORED      // Stream disabled due to an internal error.
-  };
-
-  StreamState mState;
-};
-#endif
-
-AudioStream* AudioStream::AllocateStream()
-{
-#if defined(MOZ_CUBEB)
-  return new BufferedAudioStream();
-#endif
-  return nullptr;
-}
-
-int AudioStream::MaxNumberOfChannels()
-{
-#if defined(MOZ_CUBEB)
+  cubeb* cubebContext = GetCubebContext();
   uint32_t maxNumberOfChannels;
-
-  if (cubeb_get_max_channel_count(GetCubebContext(),
+  if (cubebContext &&
+      cubeb_get_max_channel_count(cubebContext,
                                   &maxNumberOfChannels) == CUBEB_OK) {
     return static_cast<int>(maxNumberOfChannels);
   }
-#endif
 
   return 0;
 }
 
-int AudioStream::PreferredSampleRate()
+/*static*/ int AudioStream::PreferredSampleRate()
 {
-  StaticMutexAutoLock lock(AudioStream::mMutex);
+  const int fallbackSampleRate = 44100;
+  StaticMutexAutoLock lock(sMutex);
+  if (sPreferredSampleRate != 0) {
+    return sPreferredSampleRate;
+  }
+
+  cubeb* cubebContext = GetCubebContextUnlocked();
+  if (!cubebContext) {
+    sPreferredSampleRate = fallbackSampleRate;
+  }
   // Get the preferred samplerate for this platform, or fallback to something
   // sensible if we fail. We cache the value, because this might be accessed
   // often, and the complexity of the function call below depends on the
   // backend used.
-  const int fallbackSampleRate = 44100;
-  if (mPreferredSampleRate == 0) {
-#if defined(MOZ_CUBEB)
-    if (cubeb_get_preferred_sample_rate(GetCubebContext(),
-                                        &mPreferredSampleRate) == CUBEB_OK) {
-      return mPreferredSampleRate;
-    }
-#endif
-    mPreferredSampleRate = fallbackSampleRate;
+  if (cubeb_get_preferred_sample_rate(cubebContext,
+                                      &sPreferredSampleRate) != CUBEB_OK) {
+    sPreferredSampleRate = fallbackSampleRate;
   }
 
-  return mPreferredSampleRate;
+  return sPreferredSampleRate;
 }
 
-#if defined(MOZ_CUBEB)
 static void SetUint16LE(uint8_t* aDest, uint16_t aValue)
 {
   aDest[0] = aValue & 0xFF;
   aDest[1] = aValue >> 8;
 }
 
 static void SetUint32LE(uint8_t* aDest, uint32_t aValue)
 {
@@ -536,43 +353,20 @@ WriteDumpFile(FILE* aDumpFile, AudioStre
   uint8_t* output = buf.Elements();
   for (uint32_t i = 0; i < samples; ++i) {
     SetUint16LE(output + i*2, int16_t(input[i]*32767.0f));
   }
   fwrite(output, 2, samples, aDumpFile);
   fflush(aDumpFile);
 }
 
-BufferedAudioStream::BufferedAudioStream()
-  : mMonitor("BufferedAudioStream"), mLostFrames(0), mDumpFile(nullptr),
-    mVolume(1.0), mBytesPerFrame(0), mState(INITIALIZED)
-{
-  // keep a ref in case we shut down later than nsLayoutStatics
-  mLatencyLog = AsyncLatencyLogger::Get(true);
-}
-
-BufferedAudioStream::~BufferedAudioStream()
-{
-  Shutdown();
-  if (mDumpFile) {
-    fclose(mDumpFile);
-  }
-}
-
 nsresult
-BufferedAudioStream::EnsureTimeStretcherInitialized()
-{
-  MonitorAutoLock mon(mMonitor);
-  return AudioStream::EnsureTimeStretcherInitialized();
-}
-
-nsresult
-BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
-                          const dom::AudioChannelType aAudioChannelType,
-                          AudioStream::LatencyRequest aLatencyRequest)
+AudioStream::Init(int32_t aNumChannels, int32_t aRate,
+                  const dom::AudioChannelType aAudioChannelType,
+                  LatencyRequest aLatencyRequest)
 {
   cubeb* cubebContext = GetCubebContext();
 
   if (!cubebContext || aNumChannels < 0 || aRate < 0) {
     return NS_ERROR_FAILURE;
   }
 
   PR_LOG(gAudioStreamLog, PR_LOG_DEBUG,
@@ -605,27 +399,27 @@ BufferedAudioStream::Init(int32_t aNumCh
   mBytesPerFrame = sizeof(AudioDataValue) * aNumChannels;
 
   mAudioClock.Init();
 
   // If the latency pref is set, use it. Otherwise, if this stream is intended
   // for low latency playback, try to get the lowest latency possible.
   // Otherwise, for normal streams, use 100ms.
   uint32_t latency;
-  if (aLatencyRequest == AudioStream::LowLatency && !CubebLatencyPrefSet()) {
+  if (aLatencyRequest == LowLatency && !CubebLatencyPrefSet()) {
     if (cubeb_get_min_latency(cubebContext, params, &latency) != CUBEB_OK) {
       latency = GetCubebLatency();
     }
   } else {
     latency = GetCubebLatency();
   }
 
   {
     cubeb_stream* stream;
-    if (cubeb_stream_init(cubebContext, &stream, "BufferedAudioStream", params,
+    if (cubeb_stream_init(cubebContext, &stream, "AudioStream", params,
                           latency, DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
       mCubebStream.own(stream);
     }
   }
 
   if (!mCubebStream) {
     return NS_ERROR_FAILURE;
   }
@@ -634,38 +428,38 @@ BufferedAudioStream::Init(int32_t aNumCh
   // selected based on the observed behaviour of the existing AudioStream
   // implementations.
   uint32_t bufferLimit = FramesToBytes(aRate);
   NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
   mBuffer.SetCapacity(bufferLimit);
 
   // Start the stream right away when low latency has been requested. This means
   // that the DataCallback will feed silence to cubeb, until the first frames
-  // are writtent to this BufferedAudioStream.
-  if (mLatencyRequest == AudioStream::LowLatency) {
+  // are writtent to this AudioStream.
+  if (mLatencyRequest == LowLatency) {
     Start();
   }
 
   return NS_OK;
 }
 
 void
-BufferedAudioStream::Shutdown()
+AudioStream::Shutdown()
 {
   if (mState == STARTED) {
     Pause();
   }
   if (mCubebStream) {
     mCubebStream.reset();
   }
 }
 
 // aTime is the time in ms the samples were inserted into MediaStreamGraph
 nsresult
-BufferedAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames, TimeStamp *aTime)
+AudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames, TimeStamp *aTime)
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState == ERRORED) {
     return NS_ERROR_FAILURE;
   }
   NS_ASSERTION(mState == INITIALIZED || mState == STARTED,
     "Stream write in unexpected state.");
 
@@ -710,54 +504,54 @@ BufferedAudioStream::Write(const AudioDa
     }
   }
 
   mWritten += aFrames;
   return NS_OK;
 }
 
 uint32_t
-BufferedAudioStream::Available()
+AudioStream::Available()
 {
   MonitorAutoLock mon(mMonitor);
   NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
   return BytesToFrames(mBuffer.Available());
 }
 
 void
-BufferedAudioStream::SetVolume(double aVolume)
+AudioStream::SetVolume(double aVolume)
 {
   MonitorAutoLock mon(mMonitor);
   NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
   mVolume = aVolume;
 }
 
 void
-BufferedAudioStream::Drain()
+AudioStream::Drain()
 {
   MonitorAutoLock mon(mMonitor);
   if (mState != STARTED) {
     NS_ASSERTION(mBuffer.Available() == 0, "Draining with unplayed audio");
     return;
   }
   mState = DRAINING;
   while (mState == DRAINING) {
     mon.Wait();
   }
 }
 
 void
-BufferedAudioStream::Start()
+AudioStream::Start()
 {
   MonitorAutoLock mon(mMonitor);
   StartUnlocked();
 }
 
 void
-BufferedAudioStream::StartUnlocked()
+AudioStream::StartUnlocked()
 {
   mMonitor.AssertCurrentThreadOwns();
   if (!mCubebStream || mState != INITIALIZED) {
     return;
   }
   if (mState != STARTED) {
     int r;
     {
@@ -766,17 +560,17 @@ BufferedAudioStream::StartUnlocked()
     }
     if (mState != ERRORED) {
       mState = r == CUBEB_OK ? STARTED : ERRORED;
     }
   }
 }
 
 void
-BufferedAudioStream::Pause()
+AudioStream::Pause()
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState != STARTED) {
     return;
   }
 
   int r;
   {
@@ -784,17 +578,17 @@ BufferedAudioStream::Pause()
     r = cubeb_stream_stop(mCubebStream);
   }
   if (mState != ERRORED && r == CUBEB_OK) {
     mState = STOPPED;
   }
 }
 
 void
-BufferedAudioStream::Resume()
+AudioStream::Resume()
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState != STOPPED) {
     return;
   }
 
   int r;
   {
@@ -802,43 +596,43 @@ BufferedAudioStream::Resume()
     r = cubeb_stream_start(mCubebStream);
   }
   if (mState != ERRORED && r == CUBEB_OK) {
     mState = STARTED;
   }
 }
 
 int64_t
-BufferedAudioStream::GetPosition()
+AudioStream::GetPosition()
 {
   return mAudioClock.GetPosition();
 }
 
 // This function is miscompiled by PGO with MSVC 2010.  See bug 768333.
 #ifdef _MSC_VER
 #pragma optimize("", off)
 #endif
 int64_t
-BufferedAudioStream::GetPositionInFrames()
+AudioStream::GetPositionInFrames()
 {
   return mAudioClock.GetPositionInFrames();
 }
 #ifdef _MSC_VER
 #pragma optimize("", on)
 #endif
 
 int64_t
-BufferedAudioStream::GetPositionInFramesInternal()
+AudioStream::GetPositionInFramesInternal()
 {
   MonitorAutoLock mon(mMonitor);
   return GetPositionInFramesUnlocked();
 }
 
 int64_t
-BufferedAudioStream::GetPositionInFramesUnlocked()
+AudioStream::GetPositionInFramesUnlocked()
 {
   mMonitor.AssertCurrentThreadOwns();
 
   if (!mCubebStream || mState == ERRORED) {
     return -1;
   }
 
   uint64_t position = 0;
@@ -854,52 +648,52 @@ BufferedAudioStream::GetPositionInFrames
   uint64_t adjustedPosition = 0;
   if (position >= mLostFrames) {
     adjustedPosition = position - mLostFrames;
   }
   return std::min<uint64_t>(adjustedPosition, INT64_MAX);
 }
 
 int64_t
-BufferedAudioStream::GetLatencyInFrames()
+AudioStream::GetLatencyInFrames()
 {
   uint32_t latency;
-  if(cubeb_stream_get_latency(mCubebStream, &latency)) {
+  if (cubeb_stream_get_latency(mCubebStream, &latency)) {
     NS_WARNING("Could not get cubeb latency.");
     return 0;
   }
   return static_cast<int64_t>(latency);
 }
 
 bool
-BufferedAudioStream::IsPaused()
+AudioStream::IsPaused()
 {
   MonitorAutoLock mon(mMonitor);
   return mState == STOPPED;
 }
 
 void
-BufferedAudioStream::GetBufferInsertTime(int64_t &aTimeMs)
+AudioStream::GetBufferInsertTime(int64_t &aTimeMs)
 {
   if (mInserts.Length() > 0) {
     // Find the right block, but don't leave the array empty
     while (mInserts.Length() > 1 && mReadPoint >= mInserts[0].mFrames) {
       mReadPoint -= mInserts[0].mFrames;
       mInserts.RemoveElementAt(0);
     }
     // offset for amount already read
     // XXX Note: could misreport if we couldn't find a block in the right timeframe
     aTimeMs = mInserts[0].mTimeMs + ((mReadPoint * 1000) / mOutRate);
   } else {
     aTimeMs = INT64_MAX;
   }
 }
 
 long
-BufferedAudioStream::GetUnprocessed(void* aBuffer, long aFrames, int64_t &aTimeMs)
+AudioStream::GetUnprocessed(void* aBuffer, long aFrames, int64_t &aTimeMs)
 {
   uint8_t* wpos = reinterpret_cast<uint8_t*>(aBuffer);
 
   // Flush the timestretcher pipeline, if we were playing using a playback rate
   // other than 1.0.
   uint32_t flushedFrames = 0;
   if (mTimeStretcher && mTimeStretcher->numSamples()) {
     flushedFrames = mTimeStretcher->receiveSamples(reinterpret_cast<AudioDataValue*>(wpos), aFrames);
@@ -920,17 +714,17 @@ BufferedAudioStream::GetUnprocessed(void
   GetBufferInsertTime(aTimeMs);
 
   return BytesToFrames(available) + flushedFrames;
 }
 
 // Get unprocessed samples, and pad the beginning of the buffer with silence if
 // there is not enough data.
 long
-BufferedAudioStream::GetUnprocessedWithSilencePadding(void* aBuffer, long aFrames, int64_t& aTimeMs)
+AudioStream::GetUnprocessedWithSilencePadding(void* aBuffer, long aFrames, int64_t& aTimeMs)
 {
   uint32_t toPopBytes = FramesToBytes(aFrames);
   uint32_t available = std::min(toPopBytes, mBuffer.Length());
   uint32_t silenceOffset = toPopBytes - available;
 
   uint8_t* wpos = reinterpret_cast<uint8_t*>(aBuffer);
 
   memset(wpos, 0, silenceOffset);
@@ -944,22 +738,22 @@ BufferedAudioStream::GetUnprocessedWithS
   memcpy(wpos, input[1], input_size[1]);
 
   GetBufferInsertTime(aTimeMs);
 
   return aFrames;
 }
 
 long
-BufferedAudioStream::GetTimeStretched(void* aBuffer, long aFrames, int64_t &aTimeMs)
+AudioStream::GetTimeStretched(void* aBuffer, long aFrames, int64_t &aTimeMs)
 {
   long processedFrames = 0;
 
   // We need to call the non-locking version, because we already have the lock.
-  if (AudioStream::EnsureTimeStretcherInitialized() != NS_OK) {
+  if (EnsureTimeStretcherInitializedUnlocked() != NS_OK) {
     return 0;
   }
 
   uint8_t* wpos = reinterpret_cast<uint8_t*>(aBuffer);
   double playbackRate = static_cast<double>(mInRate) / mOutRate;
   uint32_t toPopBytes = FramesToBytes(ceil(aFrames / playbackRate));
   uint32_t available = 0;
   bool lowOnBufferedData = false;
@@ -985,33 +779,33 @@ BufferedAudioStream::GetTimeStretched(vo
   } while (processedFrames < aFrames && !lowOnBufferedData);
 
   GetBufferInsertTime(aTimeMs);
 
   return processedFrames;
 }
 
 long
-BufferedAudioStream::DataCallback(void* aBuffer, long aFrames)
+AudioStream::DataCallback(void* aBuffer, long aFrames)
 {
   MonitorAutoLock mon(mMonitor);
   uint32_t available = std::min(static_cast<uint32_t>(FramesToBytes(aFrames)), mBuffer.Length());
   NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames");
   AudioDataValue* output = reinterpret_cast<AudioDataValue*>(aBuffer);
   uint32_t underrunFrames = 0;
   uint32_t servicedFrames = 0;
   int64_t insertTime;
 
   if (available) {
     // When we are playing a low latency stream, and it is the first time we are
     // getting data from the buffer, we prefer to add the silence for an
     // underrun at the beginning of the buffer, so the first buffer is not cut
     // in half by the silence inserted to compensate for the underrun.
     if (mInRate == mOutRate) {
-      if (mLatencyRequest == AudioStream::LowLatency && !mWritten) {
+      if (mLatencyRequest == LowLatency && !mWritten) {
         servicedFrames = GetUnprocessedWithSilencePadding(output, aFrames, insertTime);
       } else {
         servicedFrames = GetUnprocessed(output, aFrames, insertTime);
       }
     } else {
       servicedFrames = GetTimeStretched(output, aFrames, insertTime);
     }
     float scaled_volume = float(GetVolumeScale() * mVolume);
@@ -1055,29 +849,27 @@ BufferedAudioStream::DataCallback(void* 
                      (latency * 1000) / mOutRate, now);
   }
 
   mAudioClock.UpdateWritePosition(servicedFrames);
   return servicedFrames;
 }
 
 void
-BufferedAudioStream::StateCallback(cubeb_state aState)
+AudioStream::StateCallback(cubeb_state aState)
 {
   MonitorAutoLock mon(mMonitor);
   if (aState == CUBEB_STATE_DRAINED) {
     mState = DRAINED;
   } else if (aState == CUBEB_STATE_ERROR) {
     mState = ERRORED;
   }
   mon.NotifyAll();
 }
 
-#endif
-
 AudioClock::AudioClock(AudioStream* aStream)
  :mAudioStream(aStream),
   mOldOutRate(0),
   mBasePosition(0),
   mBaseOffset(0),
   mOldBaseOffset(0),
   mOldBasePosition(0),
   mPlaybackRateChangeOffset(0),
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -4,201 +4,308 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(AudioStream_h_)
 #define AudioStream_h_
 
 #include "AudioSampleFormat.h"
 #include "AudioChannelCommon.h"
 #include "nsAutoPtr.h"
+#include "nsAutoRef.h"
 #include "nsCOMPtr.h"
 #include "Latency.h"
 #include "mozilla/StaticMutex.h"
 
+#include "cubeb/cubeb.h"
+
+template <>
+class nsAutoRefTraits<cubeb_stream> : public nsPointerRefTraits<cubeb_stream>
+{
+public:
+  static void Release(cubeb_stream* aStream) { cubeb_stream_destroy(aStream); }
+};
+
 namespace soundtouch {
 class SoundTouch;
 }
 
 namespace mozilla {
 
 class AudioStream;
 
 class AudioClock
 {
-  public:
-    AudioClock(mozilla::AudioStream* aStream);
-    // Initialize the clock with the current AudioStream. Need to be called
-    // before querying the clock. Called on the audio thread.
-    void Init();
-    // Update the number of samples that has been written in the audio backend.
-    // Called on the state machine thread.
-    void UpdateWritePosition(uint32_t aCount);
-    // Get the read position of the stream, in microseconds.
-    // Called on the state machine thead.
-    uint64_t GetPosition();
-    // Get the read position of the stream, in frames.
-    // Called on the state machine thead.
-    uint64_t GetPositionInFrames();
-    // Set the playback rate.
-    // Called on the audio thread.
-    void SetPlaybackRate(double aPlaybackRate);
-    // Get the current playback rate.
-    // Called on the audio thread.
-    double GetPlaybackRate();
-    // Set if we are preserving the pitch.
-    // Called on the audio thread.
-    void SetPreservesPitch(bool aPreservesPitch);
-    // Get the current pitch preservation state.
-    // Called on the audio thread.
-    bool GetPreservesPitch();
-    // Get the number of frames written to the backend.
-    int64_t GetWritten();
-  private:
-    // This AudioStream holds a strong reference to this AudioClock. This
-    // pointer is garanteed to always be valid.
-    AudioStream* mAudioStream;
-    // The old output rate, to compensate audio latency for the period inbetween
-    // the moment resampled buffers are pushed to the hardware and the moment the
-    // clock should take the new rate into account for A/V sync.
-    int mOldOutRate;
-    // Position at which the last playback rate change occured
-    int64_t mBasePosition;
-    // Offset, in frames, at which the last playback rate change occured
-    int64_t mBaseOffset;
-    // Old base offset (number of samples), used when changing rate to compute the
-    // position in the stream.
-    int64_t mOldBaseOffset;
-    // Old base position (number of microseconds), when changing rate. This is the
-    // time in the media, not wall clock position.
-    int64_t mOldBasePosition;
-    // Write position at which the playbackRate change occured.
-    int64_t mPlaybackRateChangeOffset;
-    // The previous position reached in the media, used when compensating
-    // latency, to have the position at which the playbackRate change occured.
-    int64_t mPreviousPosition;
-    // Number of samples effectivelly written in backend, i.e. write position.
-    int64_t mWritten;
-    // Output rate in Hz (characteristic of the playback rate)
-    int mOutRate;
-    // Input rate in Hz (characteristic of the media being played)
-    int mInRate;
-    // True if the we are timestretching, false if we are resampling.
-    bool mPreservesPitch;
-    // True if we are playing at the old playbackRate after it has been changed.
-    bool mCompensatingLatency;
+public:
+  AudioClock(AudioStream* aStream);
+  // Initialize the clock with the current AudioStream. Need to be called
+  // before querying the clock. Called on the audio thread.
+  void Init();
+  // Update the number of samples that has been written in the audio backend.
+  // Called on the state machine thread.
+  void UpdateWritePosition(uint32_t aCount);
+  // Get the read position of the stream, in microseconds.
+  // Called on the state machine thead.
+  uint64_t GetPosition();
+  // Get the read position of the stream, in frames.
+  // Called on the state machine thead.
+  uint64_t GetPositionInFrames();
+  // Set the playback rate.
+  // Called on the audio thread.
+  void SetPlaybackRate(double aPlaybackRate);
+  // Get the current playback rate.
+  // Called on the audio thread.
+  double GetPlaybackRate();
+  // Set if we are preserving the pitch.
+  // Called on the audio thread.
+  void SetPreservesPitch(bool aPreservesPitch);
+  // Get the current pitch preservation state.
+  // Called on the audio thread.
+  bool GetPreservesPitch();
+  // Get the number of frames written to the backend.
+  int64_t GetWritten();
+private:
+  // This AudioStream holds a strong reference to this AudioClock. This
+  // pointer is garanteed to always be valid.
+  AudioStream* mAudioStream;
+  // The old output rate, to compensate audio latency for the period inbetween
+  // the moment resampled buffers are pushed to the hardware and the moment the
+  // clock should take the new rate into account for A/V sync.
+  int mOldOutRate;
+  // Position at which the last playback rate change occured
+  int64_t mBasePosition;
+  // Offset, in frames, at which the last playback rate change occured
+  int64_t mBaseOffset;
+  // Old base offset (number of samples), used when changing rate to compute the
+  // position in the stream.
+  int64_t mOldBaseOffset;
+  // Old base position (number of microseconds), when changing rate. This is the
+  // time in the media, not wall clock position.
+  int64_t mOldBasePosition;
+  // Write position at which the playbackRate change occured.
+  int64_t mPlaybackRateChangeOffset;
+  // The previous position reached in the media, used when compensating
+  // latency, to have the position at which the playbackRate change occured.
+  int64_t mPreviousPosition;
+  // Number of samples effectivelly written in backend, i.e. write position.
+  int64_t mWritten;
+  // Output rate in Hz (characteristic of the playback rate)
+  int mOutRate;
+  // Input rate in Hz (characteristic of the media being played)
+  int mInRate;
+  // True if the we are timestretching, false if we are resampling.
+  bool mPreservesPitch;
+  // True if we are playing at the old playbackRate after it has been changed.
+  bool mCompensatingLatency;
+};
+
+class CircularByteBuffer
+{
+public:
+  CircularByteBuffer()
+    : mBuffer(nullptr), mCapacity(0), mStart(0), mCount(0)
+  {}
+
+  // Set the capacity of the buffer in bytes.  Must be called before any
+  // call to append or pop elements.
+  void SetCapacity(uint32_t aCapacity) {
+    NS_ABORT_IF_FALSE(!mBuffer, "Buffer allocated.");
+    mCapacity = aCapacity;
+    mBuffer = new uint8_t[mCapacity];
+  }
+
+  uint32_t Length() {
+    return mCount;
+  }
+
+  uint32_t Capacity() {
+    return mCapacity;
+  }
+
+  uint32_t Available() {
+    return Capacity() - Length();
+  }
+
+  // Append aLength bytes from aSrc to the buffer.  Caller must check that
+  // sufficient space is available.
+  void AppendElements(const uint8_t* aSrc, uint32_t aLength) {
+    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
+    NS_ABORT_IF_FALSE(aLength <= Available(), "Buffer full.");
+
+    uint32_t end = (mStart + mCount) % mCapacity;
+
+    uint32_t toCopy = std::min(mCapacity - end, aLength);
+    memcpy(&mBuffer[end], aSrc, toCopy);
+    memcpy(&mBuffer[0], aSrc + toCopy, aLength - toCopy);
+    mCount += aLength;
+  }
+
+  // Remove aSize bytes from the buffer.  Caller must check returned size in
+  // aSize{1,2} before using the pointer returned in aData{1,2}.  Caller
+  // must not specify an aSize larger than Length().
+  void PopElements(uint32_t aSize, void** aData1, uint32_t* aSize1,
+                   void** aData2, uint32_t* aSize2) {
+    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
+    NS_ABORT_IF_FALSE(aSize <= Length(), "Request too large.");
+
+    *aData1 = &mBuffer[mStart];
+    *aSize1 = std::min(mCapacity - mStart, aSize);
+    *aData2 = &mBuffer[0];
+    *aSize2 = aSize - *aSize1;
+    mCount -= *aSize1 + *aSize2;
+    mStart += *aSize1 + *aSize2;
+    mStart %= mCapacity;
+  }
+
+private:
+  nsAutoArrayPtr<uint8_t> mBuffer;
+  uint32_t mCapacity;
+  uint32_t mStart;
+  uint32_t mCount;
 };
 
 // Access to a single instance of this class must be synchronized by
 // callers, or made from a single thread.  One exception is that access to
 // GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels}
 // is thread-safe without external synchronization.
-class AudioStream
+class AudioStream MOZ_FINAL
 {
 public:
-  enum LatencyRequest {
-    HighLatency,
-    LowLatency
-  };
-  AudioStream();
-
-  virtual ~AudioStream();
-
   // Initialize Audio Library. Some Audio backends require initializing the
   // library before using it.
   static void InitLibrary();
 
   // Shutdown Audio Library. Some Audio backends require shutting down the
   // library after using it.
   static void ShutdownLibrary();
 
-  // AllocateStream will return either a local stream or a remoted stream
-  // depending on where you call it from.  If you call this from a child process,
-  // you may receive an implementation which forwards to a compositing process.
-  static AudioStream* AllocateStream();
-
   // Returns the maximum number of channels supported by the audio hardware.
   static int MaxNumberOfChannels();
 
   // Returns the samplerate the systems prefer, because it is the
   // samplerate the hardware/mixer supports.
   static int PreferredSampleRate();
 
+  AudioStream();
+  ~AudioStream();
+
+  enum LatencyRequest {
+    HighLatency,
+    LowLatency
+  };
+
   // Initialize the audio stream. aNumChannels is the number of audio
   // channels (1 for mono, 2 for stereo, etc) and aRate is the sample rate
   // (22050Hz, 44100Hz, etc).
-  virtual nsresult Init(int32_t aNumChannels, int32_t aRate,
-                        const dom::AudioChannelType aAudioStreamType,
-                        LatencyRequest aLatencyRequest) = 0;
+  nsresult Init(int32_t aNumChannels, int32_t aRate,
+                const dom::AudioChannelType aAudioStreamType,
+                LatencyRequest aLatencyRequest);
 
   // Closes the stream. All future use of the stream is an error.
-  virtual void Shutdown() = 0;
+  void Shutdown();
 
   // Write audio data to the audio hardware.  aBuf is an array of AudioDataValues
   // AudioDataValue of length aFrames*mChannels.  If aFrames is larger
   // than the result of Available(), the write will block until sufficient
   // buffer space is available.  aTime is the time in ms associated with the first sample
   // for latency calculations
-  virtual nsresult Write(const mozilla::AudioDataValue* aBuf, uint32_t aFrames, TimeStamp *aTime = nullptr) = 0;
+  nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames, TimeStamp* aTime = nullptr);
 
   // Return the number of audio frames that can be written without blocking.
-  virtual uint32_t Available() = 0;
+  uint32_t Available();
 
   // Set the current volume of the audio playback. This is a value from
   // 0 (meaning muted) to 1 (meaning full volume).  Thread-safe.
-  virtual void SetVolume(double aVolume) = 0;
+  void SetVolume(double aVolume);
 
   // Block until buffered audio data has been consumed.
-  virtual void Drain() = 0;
+  void Drain();
 
   // Start the stream.
-  virtual void Start() = 0;
+  void Start();
 
   // Return the number of frames written so far in the stream. This allow the
   // caller to check if it is safe to start the stream, if needed.
-  virtual int64_t GetWritten();
+  int64_t GetWritten();
 
   // Pause audio playback.
-  virtual void Pause() = 0;
+  void Pause();
 
   // Resume audio playback.
-  virtual void Resume() = 0;
+  void Resume();
 
   // Return the position in microseconds of the audio frame being played by
   // the audio hardware, compensated for playback rate change. Thread-safe.
-  virtual int64_t GetPosition() = 0;
+  int64_t GetPosition();
 
   // Return the position, measured in audio frames played since the stream
   // was opened, of the audio hardware.  Thread-safe.
-  virtual int64_t GetPositionInFrames() = 0;
+  int64_t GetPositionInFrames();
 
   // Return the position, measured in audio framed played since the stream was
   // opened, of the audio hardware, not adjusted for the changes of playback
   // rate.
-  virtual int64_t GetPositionInFramesInternal() = 0;
+  int64_t GetPositionInFramesInternal();
 
   // Returns true when the audio stream is paused.
-  virtual bool IsPaused() = 0;
+  bool IsPaused();
 
   int GetRate() { return mOutRate; }
   int GetChannels() { return mChannels; }
 
   // This should be called before attempting to use the time stretcher.
-  virtual nsresult EnsureTimeStretcherInitialized();
+  nsresult EnsureTimeStretcherInitialized();
   // Set playback rate as a multiple of the intrinsic playback rate. This is to
   // be called only with aPlaybackRate > 0.0.
-  virtual nsresult SetPlaybackRate(double aPlaybackRate);
+  nsresult SetPlaybackRate(double aPlaybackRate);
   // Switch between resampling (if false) and time stretching (if true, default).
-  virtual nsresult SetPreservesPitch(bool aPreservesPitch);
+  nsresult SetPreservesPitch(bool aPreservesPitch);
+
+private:
+  static int PrefChanged(const char* aPref, void* aClosure);
+  static double GetVolumeScale();
+  static cubeb* GetCubebContext();
+  static cubeb* GetCubebContextUnlocked();
+  static uint32_t GetCubebLatency();
+  static bool CubebLatencyPrefSet();
+
+  static long DataCallback_S(cubeb_stream*, void* aThis, void* aBuffer, long aFrames)
+  {
+    return static_cast<AudioStream*>(aThis)->DataCallback(aBuffer, aFrames);
+  }
+
+  static void StateCallback_S(cubeb_stream*, void* aThis, cubeb_state aState)
+  {
+    static_cast<AudioStream*>(aThis)->StateCallback(aState);
+  }
 
-protected:
-  // This mutex protects the mPreferedSamplerate member below.
-  static StaticMutex mMutex;
-  // Prefered samplerate, in Hz (characteristic of the
-  // hardware/mixer/platform/API used).
-  static uint32_t mPreferredSampleRate;
+  long DataCallback(void* aBuffer, long aFrames);
+  void StateCallback(cubeb_state aState);
+
+  nsresult EnsureTimeStretcherInitializedUnlocked();
+
+  // aTime is the time in ms the samples were inserted into MediaStreamGraph
+  long GetUnprocessed(void* aBuffer, long aFrames, int64_t &aTime);
+  long GetTimeStretched(void* aBuffer, long aFrames, int64_t &aTime);
+  long GetUnprocessedWithSilencePadding(void* aBuffer, long aFrames, int64_t &aTime);
+
+  // Shared implementation of underflow adjusted position calculation.
+  // Caller must own the monitor.
+  int64_t GetPositionInFramesUnlocked();
+
+  int64_t GetLatencyInFrames();
+  void GetBufferInsertTime(int64_t &aTimeMs);
+
+  void StartUnlocked();
+
+  // The monitor is held to protect all access to member variables.  Write()
+  // waits while mBuffer is full; DataCallback() notifies as it consumes
+  // data from mBuffer.  Drain() waits while mState is DRAINING;
+  // StateCallback() notifies when mState is DRAINED.
+  Monitor mMonitor;
+
   // Input rate in Hz (characteristic of the media being played)
   int mInRate;
   // Output rate in Hz (characteristic of the playback rate)
   int mOutRate;
   int mChannels;
   // Number of frames written to the buffers.
   int64_t mWritten;
   AudioClock mAudioClock;
@@ -213,14 +320,72 @@ protected:
   int64_t mReadPoint;
   // Keep track of each inserted block of samples and the time it was inserted
   // so we can estimate the clock time for a specific sample's insertion (for when
   // we send data to cubeb).  Blocks are aged out as needed.
   struct Inserts {
     int64_t mTimeMs;
     int64_t mFrames;
   };
-  nsAutoTArray<Inserts,8> mInserts;
+  nsAutoTArray<Inserts, 8> mInserts;
+
+  // Sum of silent frames written when DataCallback requests more frames
+  // than are available in mBuffer.
+  uint64_t mLostFrames;
+
+  // Output file for dumping audio
+  FILE* mDumpFile;
+
+  // Temporary audio buffer.  Filled by Write() and consumed by
+  // DataCallback().  Once mBuffer is full, Write() blocks until sufficient
+  // space becomes available in mBuffer.  mBuffer is sized in bytes, not
+  // frames.
+  CircularByteBuffer mBuffer;
+
+  // Software volume level.  Applied during the servicing of DataCallback().
+  double mVolume;
+
+  // Owning reference to a cubeb_stream.  cubeb_stream_destroy is called by
+  // nsAutoRef's destructor.
+  nsAutoRef<cubeb_stream> mCubebStream;
+
+  uint32_t mBytesPerFrame;
+
+  uint32_t BytesToFrames(uint32_t aBytes) {
+    NS_ASSERTION(aBytes % mBytesPerFrame == 0,
+                 "Byte count not aligned on frames size.");
+    return aBytes / mBytesPerFrame;
+  }
+
+  uint32_t FramesToBytes(uint32_t aFrames) {
+    return aFrames * mBytesPerFrame;
+  }
+
+  enum StreamState {
+    INITIALIZED, // Initialized, playback has not begun.
+    STARTED,     // Started by a call to Write() (iff INITIALIZED) or Resume().
+    STOPPED,     // Stopped by a call to Pause().
+    DRAINING,    // Drain requested.  DataCallback will indicate end of stream
+                 // once the remaining contents of mBuffer are requested by
+                 // cubeb, after which StateCallback will indicate drain
+                 // completion.
+    DRAINED,     // StateCallback has indicated that the drain is complete.
+    ERRORED      // Stream disabled due to an internal error.
+  };
+
+  StreamState mState;
+
+  // This mutex protects the static members below.
+  static StaticMutex sMutex;
+  static cubeb* sCubebContext;
+
+  // Prefered samplerate, in Hz (characteristic of the
+  // hardware/mixer/platform/API used).
+  static uint32_t sPreferredSampleRate;
+
+  static double sVolumeScale;
+  static uint32_t sCubebLatency;
+  static bool sCubebLatencyPrefSet;
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1051,17 +1051,17 @@ void MediaDecoderStateMachine::AudioLoop
     preservesPitch = mPreservesPitch;
     playbackRate = mPlaybackRate;
   }
 
   {
     // AudioStream initialization can block for extended periods in unusual
     // circumstances, so we take care to drop the decoder monitor while
     // initializing.
-    nsAutoPtr<AudioStream> audioStream(AudioStream::AllocateStream());
+    nsAutoPtr<AudioStream> audioStream(new AudioStream());
     audioStream->Init(channels, rate, audioChannelType, AudioStream::HighLatency);
     audioStream->SetVolume(volume);
     if (audioStream->SetPreservesPitch(preservesPitch) != NS_OK) {
       NS_WARNING("Setting the pitch preservation failed at AudioLoop start.");
     }
     if (playbackRate != 1.0) {
       NS_ASSERTION(playbackRate != 0,
                    "Don't set the playbackRate to 0 on an AudioStream.");
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -773,17 +773,17 @@ MediaStreamGraphImpl::CreateOrDestroyAud
 
         // XXX allocating a AudioStream could be slow so we're going to have to do
         // something here ... preallocation, async allocation, multiplexing onto a single
         // stream ...
         MediaStream::AudioOutputStream* audioOutputStream =
           aStream->mAudioOutputStreams.AppendElement();
         audioOutputStream->mAudioPlaybackStartTime = aAudioOutputStartTime;
         audioOutputStream->mBlockedAudioTime = 0;
-        audioOutputStream->mStream = AudioStream::AllocateStream();
+        audioOutputStream->mStream = new AudioStream();
         // XXX for now, allocate stereo output. But we need to fix this to
         // match the system's ideal channel configuration.
         audioOutputStream->mStream->Init(2, tracks->GetRate(), AUDIO_CHANNEL_NORMAL, AudioStream::LowLatency);
         audioOutputStream->mTrackID = tracks->GetID();
 
         LogLatency(AsyncLatencyLogger::AudioStreamCreate,
                    reinterpret_cast<uint64_t>(aStream),
                    reinterpret_cast<int64_t>(audioOutputStream->mStream.get()));
--- a/layout/media/Makefile.in
+++ b/layout/media/Makefile.in
@@ -12,15 +12,10 @@ DEFFILE = symbols.def
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 ifeq (WINNT,$(OS_TARGET))
 symbols.def: symbols.def.in $(GLOBAL_DEPS)
 	$(call py_action,preprocessor,$(ACDEFINES) $< -o $@)
 
-OS_LIBS += $(call EXPAND_LIBNAME, msimg32)
-
-ifdef MOZ_CUBEB
-OS_LIBS += $(call EXPAND_LIBNAME, winmm)
+OS_LIBS += $(call EXPAND_LIBNAME, msimg32 winmm)
 endif
-
-endif
--- a/layout/media/symbols.def.in
+++ b/layout/media/symbols.def.in
@@ -112,29 +112,27 @@ speex_resampler_set_input_stride
 speex_resampler_get_input_stride
 speex_resampler_set_output_stride
 speex_resampler_get_output_stride
 speex_resampler_get_input_latency
 speex_resampler_get_output_latency
 speex_resampler_skip_zeros
 speex_resampler_reset_mem
 speex_resampler_strerror
-#ifdef MOZ_CUBEB
 cubeb_destroy
 cubeb_init
 cubeb_get_max_channel_count
 cubeb_get_min_latency
 cubeb_get_preferred_sample_rate
 cubeb_stream_destroy
 cubeb_stream_get_position
 cubeb_stream_init
 cubeb_stream_start
 cubeb_stream_stop
 cubeb_stream_get_latency
-#endif
 #ifdef MOZ_OGG
 th_comment_clear
 th_comment_init
 th_decode_alloc
 th_decode_free
 th_decode_headerin
 th_decode_packetin
 th_decode_ycbcr_out
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 8c78a282aa0320e997436d6832024efe1527ca1c.
+The git commit ID used was e92a27c96c0efd33acf983e4c873376ff4cae3d8.
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -154,26 +154,26 @@ cubeb_get_max_channel_count(cubeb * cont
   }
 
   return context->ops->get_max_channel_count(context, max_channels);
 }
 
 int
 cubeb_get_min_latency(cubeb * context, cubeb_stream_params params, uint32_t * latency_ms)
 {
-  if (!latency_ms) {
+  if (!context || !latency_ms) {
     return CUBEB_ERROR_INVALID_PARAMETER;
   }
   return context->ops->get_min_latency(context, params, latency_ms);
 }
 
 int
 cubeb_get_preferred_sample_rate(cubeb * context, uint32_t * rate)
 {
-  if (!rate) {
+  if (!context || !rate) {
     return CUBEB_ERROR_INVALID_PARAMETER;
   }
   return context->ops->get_preferred_sample_rate(context, rate);
 }
 
 void
 cubeb_destroy(cubeb * context)
 {
--- a/media/webrtc/signaling/test/Makefile.in
+++ b/media/webrtc/signaling/test/Makefile.in
@@ -12,23 +12,21 @@ LIBS = \
   $(DEPTH)/media/webrtc/signalingtest/signaling_ecc/$(LIB_PREFIX)ecc.$(LIB_SUFFIX) \
   $(DEPTH)/media/webrtc/signalingtest/signaling_sipcc/$(LIB_PREFIX)sipcc.$(LIB_SUFFIX) \
   $(DEPTH)/layout/media/webrtc/$(LIB_PREFIX)webrtc.$(LIB_SUFFIX) \
   $(DEPTH)/layout/media/$(LIB_PREFIX)gkmedias.$(LIB_SUFFIX) \
   $(DEPTH)/media/webrtc/trunk/testing/gtest_gtest/$(LIB_PREFIX)gtest.$(LIB_SUFFIX) \
   $(DEPTH)/netwerk/srtp/src/$(LIB_PREFIX)nksrtp_s.$(LIB_SUFFIX) \
   $(NULL)
 
-ifdef MOZ_CUBEB
 ifdef MOZ_ALSA
 LIBS += \
   $(MOZ_ALSA_LIBS) \
   $(NULL)
 endif
-endif
 
 ifeq ($(OS_TARGET),Android)
 LIBS += \
   $(STLPORT_LDFLAGS) \
   $(STLPORT_LIBS) \
   $(NULL)
 CPPFLAGS += \
   $(STLPORT_CPPFLAGS) \
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -175,21 +175,19 @@ ifeq (WINNT,$(OS_TARGET))
 EXTRA_DSO_LDOPTS += \
   -LIBPATH:"$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_DIRECTX_SDK_CPU_SUFFIX)" \
   $(NULL)
 OS_LIBS += $(call EXPAND_LIBNAME,secur32 crypt32 iphlpapi strmiids dmoguids wmcodecdspuuid amstrmid msdmo wininet)
 endif
 endif
 
 
-ifdef MOZ_CUBEB
 ifdef MOZ_ALSA
 EXTRA_DSO_LDOPTS += $(MOZ_ALSA_LIBS)
 endif
-endif
 
 ifdef HAVE_CLOCK_MONOTONIC
 EXTRA_DSO_LDOPTS += $(REALTIME_LIBS)
 endif
 
 ifeq (android,$(MOZ_WIDGET_TOOLKIT))
 OS_LIBS += -lGLESv2
 endif
@@ -242,20 +240,18 @@ OS_LIBS += \
   -framework QTKit \
   -framework IOKit \
   -F$(MACOS_PRIVATE_FRAMEWORKS_DIR) -framework CoreUI \
   $(TK_LIBS) \
   $(NULL)
 endif
 
 ifeq (OpenBSD,$(OS_ARCH))
-ifdef MOZ_CUBEB
 EXTRA_DSO_LDOPTS += -lsndio
 endif
-endif
 
 ifdef MOZ_ENABLE_DBUS
 EXTRA_DSO_LDOPTS += $(MOZ_DBUS_GLIB_LIBS)
 endif
 
 ifdef MOZ_WIDGET_GTK
 EXTRA_DSO_LDOPTS += $(TK_LIBS)
 EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(XEXT_LIBS) $(XCOMPOSITE_LIBS) $(MOZ_PANGO_LIBS) $(XT_LIBS) -lgthread-2.0