diff --git build/moz.configure/old.configure build/moz.configure/old.configure
index b95dd2b..4cbefd5 100644
--- mozilla/build/moz.configure/old.configure
+++ mozilla/build/moz.configure/old.configure
@@ -305,6 +305,7 @@ def old_configure_options(*options):
     '--with-nspr-prefix',
     '--with-nss-exec-prefix',
     '--with-nss-prefix',
+    '--with-oss',
     '--with-pthreads',
     '--with-qemu-exe',
     '--with-servo',
diff --git old-configure.in configure.in
index 48e60c0..ec08417 100644
--- mozilla/old-configure.in
+++ mozilla/old-configure.in
@@ -5591,6 +5591,67 @@ fi
 AC_SUBST(MOZ_WEBM_ENCODER)
 
 dnl ==================================
+dnl = Check OSS availability
+dnl ==================================
+
+dnl If using Linux, Solaris or BSDs, ensure that OSS is available
+case "$OS_TARGET" in
+Linux|SunOS|DragonFly|FreeBSD|NetBSD|GNU/kFreeBSD)
+    MOZ_OSS=1
+    ;;
+esac
+
+MOZ_ARG_WITH_STRING(oss,
+[  --with-oss[=PFX]        Enable OpenSoundSystem support [installed at prefix PFX]],
+   OSSPREFIX=$withval)
+
+if test -n "$OSSPREFIX"; then
+    if test "$OSSPREFIX" != "no"; then
+        MOZ_OSS=1
+    else
+        MOZ_OSS=
+    fi
+fi
+
+_SAVE_CFLAGS=$CFLAGS
+_SAVE_LIBS=$LIBS
+if test -n "$MOZ_OSS"; then
+    dnl Prefer 4Front implementation
+    AC_MSG_CHECKING([MOZ_OSS_CFLAGS])
+    if test "$OSSPREFIX" != "yes"; then
+        oss_conf=${OSSPREFIX%/usr}/etc/oss.conf
+        if test -f "$oss_conf"; then
+            . "$oss_conf"
+        else
+            OSSLIBDIR=$OSSPREFIX/lib/oss
+        fi
+        if test -d "$OSSLIBDIR"; then
+            MOZ_OSS_CFLAGS="$MOZ_OSS_CFLAGS -I$OSSLIBDIR/include"
+        fi
+    fi
+    AC_MSG_RESULT([$MOZ_OSS_CFLAGS])
+
+    CFLAGS="$CFLAGS $MOZ_OSS_CFLAGS"
+    MOZ_CHECK_HEADERS(sys/soundcard.h soundcard.h)
+
+    if test "$ac_cv_header_sys_soundcard_h" != "yes" -a \
+            "$ac_cv_header_soundcard_h" != "yes"; then
+        AC_MSG_ERROR([Need OSS for Ogg, Wave or WebM decoding on $OS_TARGET.  Disable with --without-oss.])
+    fi
+
+    dnl Assume NetBSD implementation over SunAudio
+    AC_CHECK_LIB(ossaudio, _oss_ioctl,
+        [AC_DEFINE_UNQUOTED(CUBEB_OSS_DEFAULT_OUTPUT, "/dev/sound")
+         MOZ_OSS_LIBS="$MOZ_OSS_LIBS -lossaudio"])
+fi
+CFLAGS=$_SAVE_CFLAGS
+LIBS=$_SAVE_LIBS
+
+AC_SUBST(MOZ_OSS)
+AC_SUBST_LIST(MOZ_OSS_CFLAGS)
+AC_SUBST_LIST(MOZ_OSS_LIBS)
+
+dnl ==================================
 dnl = Check alsa availability on Linux
 dnl ==================================
 
diff --git media/libcubeb/AUTHORS media/libcubeb/AUTHORS
index b441e8a..950d9e5 100644
--- mozilla/media/libcubeb/AUTHORS
+++ mozilla/media/libcubeb/AUTHORS
@@ -4,3 +4,4 @@ Michael Wu <mwu@mozilla.com>
 Paul Adenot <paul@paul.cx>
 David Richards <drichards@mozilla.com>
 Sebastien Alaiwan <sebastien.alaiwan@gmail.com>
+Evgeniy Vodolazskiy <waterlaz@gmail.com>
diff --git media/libcubeb/src/cubeb.c media/libcubeb/src/cubeb.c
index 9c3adcc..45d765b 100644
--- mozilla/media/libcubeb/src/cubeb.c
+++ mozilla/media/libcubeb/src/cubeb.c
@@ -54,6 +54,9 @@ int opensl_init(cubeb ** context, char const * context_name);
 #if defined(USE_AUDIOTRACK)
 int audiotrack_init(cubeb ** context, char const * context_name);
 #endif
+#if defined(USE_OSS)
+int oss_init(cubeb ** context, char const * context_name);
+#endif
 
 int
 validate_stream_params(cubeb_stream_params stream_params)
@@ -120,6 +123,9 @@ cubeb_init(cubeb ** context, char const * context_name)
 #if defined(USE_AUDIOTRACK)
     audiotrack_init,
 #endif
+#if defined(USE_OSS)
+    oss_init,
+#endif
   };
   int i;
 
diff --git media/libcubeb/src/cubeb_alsa.c media/libcubeb/src/cubeb_alsa.c
index a962553..1f780f4 100644
--- mozilla/media/libcubeb/src/cubeb_alsa.c
+++ mozilla/media/libcubeb/src/cubeb_alsa.c
@@ -11,6 +11,7 @@
 #include <sys/time.h>
 #include <assert.h>
 #include <limits.h>
+#include <dlfcn.h>
 #include <poll.h>
 #include <unistd.h>
 #include <alsa/asoundlib.h>
@@ -24,6 +25,50 @@
 
 #define ALSA_PA_PLUGIN "ALSA <-> PulseAudio PCM I/O Plugin"
 
+#ifdef DISABLE_LIBASOUND_DLOPEN
+#define WRAP(x) x
+#else
+#define WRAP(x) cubeb_##x
+#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x
+MAKE_TYPEDEF(snd_config);
+MAKE_TYPEDEF(snd_config_add);
+MAKE_TYPEDEF(snd_config_copy);
+MAKE_TYPEDEF(snd_config_delete);
+MAKE_TYPEDEF(snd_config_get_id);
+MAKE_TYPEDEF(snd_config_get_string);
+MAKE_TYPEDEF(snd_config_imake_integer);
+MAKE_TYPEDEF(snd_config_search);
+MAKE_TYPEDEF(snd_config_search_definition);
+MAKE_TYPEDEF(snd_lib_error_set_handler);
+MAKE_TYPEDEF(snd_pcm_avail_update);
+MAKE_TYPEDEF(snd_pcm_close);
+MAKE_TYPEDEF(snd_pcm_delay);
+MAKE_TYPEDEF(snd_pcm_drain);
+MAKE_TYPEDEF(snd_pcm_frames_to_bytes);
+MAKE_TYPEDEF(snd_pcm_get_params);
+/* snd_pcm_hw_params_alloca is actually a macro */
+/* MAKE_TYPEDEF(snd_pcm_hw_params_alloca); */
+MAKE_TYPEDEF(snd_pcm_hw_params_sizeof);
+#define snd_pcm_hw_params_sizeof cubeb_snd_pcm_hw_params_sizeof
+MAKE_TYPEDEF(snd_pcm_hw_params_any);
+MAKE_TYPEDEF(snd_pcm_hw_params_get_channels_max);
+MAKE_TYPEDEF(snd_pcm_hw_params_get_rate);
+MAKE_TYPEDEF(snd_pcm_hw_params_set_rate_near);
+MAKE_TYPEDEF(snd_pcm_nonblock);
+MAKE_TYPEDEF(snd_pcm_open);
+MAKE_TYPEDEF(snd_pcm_open_lconf);
+MAKE_TYPEDEF(snd_pcm_pause);
+MAKE_TYPEDEF(snd_pcm_poll_descriptors);
+MAKE_TYPEDEF(snd_pcm_poll_descriptors_count);
+MAKE_TYPEDEF(snd_pcm_poll_descriptors_revents);
+MAKE_TYPEDEF(snd_pcm_recover);
+MAKE_TYPEDEF(snd_pcm_set_params);
+MAKE_TYPEDEF(snd_pcm_state);
+MAKE_TYPEDEF(snd_pcm_writei);
+
+#undef MAKE_TYPEDEF
+#endif
+
 /* ALSA is not thread-safe.  snd_pcm_t instances are individually protected
    by the owning cubeb_stream's mutex.  snd_pcm_t creation and destruction
    is not thread-safe until ALSA 1.0.24 (see alsa-lib.git commit 91c9c8f1),
@@ -64,6 +109,8 @@ struct cubeb {
      workaround is not required. */
   snd_config_t * local_config;
   int is_pa;
+
+  void * libasound;
 };
 
 enum stream_state {
@@ -260,10 +307,10 @@ alsa_refill_stream(cubeb_stream * stm)
 
   pthread_mutex_lock(&stm->mutex);
 
-  avail = snd_pcm_avail_update(stm->pcm);
+  avail = WRAP(snd_pcm_avail_update)(stm->pcm);
   if (avail < 0) {
-    snd_pcm_recover(stm->pcm, avail, 1);
-    avail = snd_pcm_avail_update(stm->pcm);
+    WRAP(snd_pcm_recover)(stm->pcm, avail, 1);
+    avail = WRAP(snd_pcm_avail_update)(stm->pcm);
   }
 
   /* Failed to recover from an xrun, this stream must be broken. */
@@ -286,7 +333,7 @@ alsa_refill_stream(cubeb_stream * stm)
     return RUNNING;
   }
 
-  p = calloc(1, snd_pcm_frames_to_bytes(stm->pcm, avail));
+  p = calloc(1, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, avail));
   assert(p);
 
   pthread_mutex_unlock(&stm->mutex);
@@ -312,10 +359,10 @@ alsa_refill_stream(cubeb_stream * stm)
         b[i] *= stm->volume;
       }
     }
-    wrote = snd_pcm_writei(stm->pcm, p, got);
+    wrote = WRAP(snd_pcm_writei)(stm->pcm, p, got);
     if (wrote < 0) {
-      snd_pcm_recover(stm->pcm, wrote, 1);
-      wrote = snd_pcm_writei(stm->pcm, p, got);
+      WRAP(snd_pcm_recover)(stm->pcm, wrote, 1);
+      wrote = WRAP(snd_pcm_writei)(stm->pcm, p, got);
     }
     assert(wrote >= 0 && wrote == got);
     stm->write_position += wrote;
@@ -342,7 +389,7 @@ alsa_refill_stream(cubeb_stream * stm)
 
     /* Fill the remaining buffer with silence to guarantee one full period
        has been written. */
-    snd_pcm_writei(stm->pcm, (char *) p + got, avail - got);
+    WRAP(snd_pcm_writei)(stm->pcm, (char *) p + got, avail - got);
 
     set_timeout(&stm->drain_timeout, buffer_time * 1000);
 
@@ -453,26 +500,26 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
 
   slave_def = NULL;
 
-  r = snd_config_search(root_pcm, "slave", &slave_pcm);
+  r = WRAP(snd_config_search)(root_pcm, "slave", &slave_pcm);
   if (r < 0) {
     return NULL;
   }
 
-  r = snd_config_get_string(slave_pcm, &string);
+  r = WRAP(snd_config_get_string)(slave_pcm, &string);
   if (r >= 0) {
-    r = snd_config_search_definition(lconf, "pcm_slave", string, &slave_def);
+    r = WRAP(snd_config_search_definition)(lconf, "pcm_slave", string, &slave_def);
     if (r < 0) {
       return NULL;
     }
   }
 
   do {
-    r = snd_config_search(slave_def ? slave_def : slave_pcm, "pcm", &pcm);
+    r = WRAP(snd_config_search)(slave_def ? slave_def : slave_pcm, "pcm", &pcm);
     if (r < 0) {
       break;
     }
 
-    r = snd_config_get_string(slave_def ? slave_def : slave_pcm, &string);
+    r = WRAP(snd_config_get_string)(slave_def ? slave_def : slave_pcm, &string);
     if (r < 0) {
       break;
     }
@@ -481,7 +528,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
     if (r < 0 || r > (int) sizeof(node_name)) {
       break;
     }
-    r = snd_config_search(lconf, node_name, &pcm);
+    r = WRAP(snd_config_search)(lconf, node_name, &pcm);
     if (r < 0) {
       break;
     }
@@ -490,7 +537,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm)
   } while (0);
 
   if (slave_def) {
-    snd_config_delete(slave_def);
+    WRAP(snd_config_delete)(slave_def);
   }
 
   return NULL;
@@ -513,22 +560,22 @@ init_local_config_with_workaround(char const * pcm_name)
 
   lconf = NULL;
 
-  if (snd_config == NULL) {
+  if (*WRAP(snd_config) == NULL) {
     return NULL;
   }
 
-  r = snd_config_copy(&lconf, snd_config);
+  r = WRAP(snd_config_copy)(&lconf, *WRAP(snd_config));
   if (r < 0) {
     return NULL;
   }
 
   do {
-    r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node);
+    r = WRAP(snd_config_search_definition)(lconf, "pcm", pcm_name, &pcm_node);
     if (r < 0) {
       break;
     }
 
-    r = snd_config_get_id(pcm_node, &string);
+    r = WRAP(snd_config_get_id)(pcm_node, &string);
     if (r < 0) {
       break;
     }
@@ -537,7 +584,7 @@ init_local_config_with_workaround(char const * pcm_name)
     if (r < 0 || r > (int) sizeof(node_name)) {
       break;
     }
-    r = snd_config_search(lconf, node_name, &pcm_node);
+    r = WRAP(snd_config_search)(lconf, node_name, &pcm_node);
     if (r < 0) {
       break;
     }
@@ -548,12 +595,12 @@ init_local_config_with_workaround(char const * pcm_name)
     }
 
     /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */
-    r = snd_config_search(pcm_node, "type", &node);
+    r = WRAP(snd_config_search)(pcm_node, "type", &node);
     if (r < 0) {
       break;
     }
 
-    r = snd_config_get_string(node, &string);
+    r = WRAP(snd_config_get_string)(node, &string);
     if (r < 0) {
       break;
     }
@@ -564,18 +611,18 @@ init_local_config_with_workaround(char const * pcm_name)
 
     /* Don't clobber an explicit existing handle_underrun value, set it only
        if it doesn't already exist. */
-    r = snd_config_search(pcm_node, "handle_underrun", &node);
+    r = WRAP(snd_config_search)(pcm_node, "handle_underrun", &node);
     if (r != -ENOENT) {
       break;
     }
 
     /* Disable pcm_pulse's asynchronous underrun handling. */
-    r = snd_config_imake_integer(&node, "handle_underrun", 0);
+    r = WRAP(snd_config_imake_integer)(&node, "handle_underrun", 0);
     if (r < 0) {
       break;
     }
 
-    r = snd_config_add(pcm_node, node);
+    r = WRAP(snd_config_add)(pcm_node, node);
     if (r < 0) {
       break;
     }
@@ -583,7 +630,7 @@ init_local_config_with_workaround(char const * pcm_name)
     return lconf;
   } while (0);
 
-  snd_config_delete(lconf);
+  WRAP(snd_config_delete)(lconf);
 
   return NULL;
 }
@@ -595,9 +642,9 @@ alsa_locked_pcm_open(snd_pcm_t ** pcm, snd_pcm_stream_t stream, snd_config_t * l
 
   pthread_mutex_lock(&cubeb_alsa_mutex);
   if (local_config) {
-    r = snd_pcm_open_lconf(pcm, CUBEB_ALSA_PCM_NAME, stream, SND_PCM_NONBLOCK, local_config);
+    r = WRAP(snd_pcm_open_lconf)(pcm, CUBEB_ALSA_PCM_NAME, stream, SND_PCM_NONBLOCK, local_config);
   } else {
-    r = snd_pcm_open(pcm, CUBEB_ALSA_PCM_NAME, stream, SND_PCM_NONBLOCK);
+    r = WRAP(snd_pcm_open)(pcm, CUBEB_ALSA_PCM_NAME, stream, SND_PCM_NONBLOCK);
   }
   pthread_mutex_unlock(&cubeb_alsa_mutex);
 
@@ -610,7 +657,7 @@ alsa_locked_pcm_close(snd_pcm_t * pcm)
   int r;
 
   pthread_mutex_lock(&cubeb_alsa_mutex);
-  r = snd_pcm_close(pcm);
+  r = WRAP(snd_pcm_close)(pcm);
   pthread_mutex_unlock(&cubeb_alsa_mutex);
 
   return r;
@@ -667,12 +714,65 @@ alsa_init(cubeb ** context, char const * context_name)
   pthread_attr_t attr;
   snd_pcm_t * dummy;
 
+  void * libasound = NULL;
+
+#ifndef DISABLE_LIBASOUND_DLOPEN
+  libasound = dlopen("libasound.so", RTLD_LAZY);
+  if (!libasound) {
+    return CUBEB_ERROR;
+  }
+
+#define LOAD(x) do { \
+    cubeb_##x = dlsym(libasound, #x); \
+    if (!cubeb_##x) { \
+      dlclose(libasound); \
+      return CUBEB_ERROR; \
+    } \
+  } while(0)
+
+  LOAD(snd_config);
+  LOAD(snd_config_add);
+  LOAD(snd_config_copy);
+  LOAD(snd_config_delete);
+  LOAD(snd_config_get_id);
+  LOAD(snd_config_get_string);
+  LOAD(snd_config_imake_integer);
+  LOAD(snd_config_search);
+  LOAD(snd_config_search_definition);
+  LOAD(snd_lib_error_set_handler);
+  LOAD(snd_pcm_avail_update);
+  LOAD(snd_pcm_close);
+  LOAD(snd_pcm_delay);
+  LOAD(snd_pcm_drain);
+  LOAD(snd_pcm_frames_to_bytes);
+  LOAD(snd_pcm_get_params);
+  /* snd_pcm_hw_params_alloca is actually a macro */
+  /* LOAD(snd_pcm_hw_params_alloca); */
+  LOAD(snd_pcm_hw_params_sizeof);
+  LOAD(snd_pcm_hw_params_any);
+  LOAD(snd_pcm_hw_params_get_channels_max);
+  LOAD(snd_pcm_hw_params_get_rate);
+  LOAD(snd_pcm_hw_params_set_rate_near);
+  LOAD(snd_pcm_nonblock);
+  LOAD(snd_pcm_open);
+  LOAD(snd_pcm_open_lconf);
+  LOAD(snd_pcm_pause);
+  LOAD(snd_pcm_poll_descriptors);
+  LOAD(snd_pcm_poll_descriptors_count);
+  LOAD(snd_pcm_poll_descriptors_revents);
+  LOAD(snd_pcm_recover);
+  LOAD(snd_pcm_set_params);
+  LOAD(snd_pcm_state);
+  LOAD(snd_pcm_writei);
+
+#undef LOAD
+#endif
   assert(context);
   *context = NULL;
 
   pthread_mutex_lock(&cubeb_alsa_mutex);
   if (!cubeb_alsa_error_handler_set) {
-    snd_lib_error_set_handler(silent_error_handler);
+    WRAP(snd_lib_error_set_handler)(silent_error_handler);
     cubeb_alsa_error_handler_set = 1;
   }
   pthread_mutex_unlock(&cubeb_alsa_mutex);
@@ -680,6 +780,8 @@ alsa_init(cubeb ** context, char const * context_name)
   ctx = calloc(1, sizeof(*ctx));
   assert(ctx);
 
+  ctx->libasound = libasound;
+
   ctx->ops = &alsa_ops;
 
   r = pthread_mutex_init(&ctx->mutex, NULL);
@@ -729,7 +831,7 @@ alsa_init(cubeb ** context, char const * context_name)
        config fails with EINVAL, the PA PCM is too old for this workaround. */
     if (r == -EINVAL) {
       pthread_mutex_lock(&cubeb_alsa_mutex);
-      snd_config_delete(ctx->local_config);
+      WRAP(snd_config_delete)(ctx->local_config);
       pthread_mutex_unlock(&cubeb_alsa_mutex);
       ctx->local_config = NULL;
     } else if (r >= 0) {
@@ -768,9 +870,13 @@ alsa_destroy(cubeb * ctx)
   pthread_mutex_destroy(&ctx->mutex);
   free(ctx->fds);
 
+  if (ctx->libasound) {
+    dlclose(ctx->libasound);
+  }
+
   if (ctx->local_config) {
     pthread_mutex_lock(&cubeb_alsa_mutex);
-    snd_config_delete(ctx->local_config);
+    WRAP(snd_config_delete)(ctx->local_config);
     pthread_mutex_unlock(&cubeb_alsa_mutex);
   }
 
@@ -838,7 +944,7 @@ alsa_stream_init(cubeb * ctx, cubeb_stream ** stream, char const * stream_name,
     return CUBEB_ERROR;
   }
 
-  r = snd_pcm_nonblock(stm->pcm, 1);
+  r = WRAP(snd_pcm_nonblock)(stm->pcm, 1);
   assert(r == 0);
 
   latency_us = latency_frames * 1e6 / stm->params.rate;
@@ -855,7 +961,7 @@ alsa_stream_init(cubeb * ctx, cubeb_stre
     latency_us = latency_us < min_latency ? min_latency: latency_us;
   }
 
-  r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED,
+  r = WRAP(snd_pcm_set_params)(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED,
                          stm->params.channels, stm->params.rate, 1,
                          latency_us);
   if (r < 0) {
@@ -867,15 +973,15 @@ alsa_stream_init(cubeb * ctx, cubeb_stre
     return CUBEB_ERROR_INVALID_FORMAT;
   }
 
-  r = snd_pcm_get_params(stm->pcm, &stm->buffer_size, &period_size);
+  r = WRAP(snd_pcm_get_params)(stm->pcm, &stm->buffer_size, &period_size);
   assert(r == 0);
 
-  stm->nfds = snd_pcm_poll_descriptors_count(stm->pcm);
+  stm->nfds = WRAP(snd_pcm_poll_descriptors_count)(stm->pcm);
   assert(stm->nfds > 0);
 
   stm->saved_fds = calloc(stm->nfds, sizeof(struct pollfd));
   assert(stm->saved_fds);
-  r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds);
+  r = WRAP(snd_pcm_poll_descriptors)(stm->pcm, stm->saved_fds, stm->nfds);
   assert((nfds_t) r == stm->nfds);
 
   r = pthread_cond_init(&stm->cond, NULL);
@@ -895,7 +1001,7 @@ alsa_stream_destroy(cubeb_stream * stm)
   pthread_mutex_lock(&stm->mutex);
   if (stm->pcm) {
     if (stm->state == DRAINING) {
-      snd_pcm_drain(stm->pcm);
+      WRAP(snd_pcm_drain)(stm->pcm);
     }
     alsa_locked_pcm_close(stm->pcm);
     stm->pcm = NULL;
@@ -938,12 +1044,12 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
     return CUBEB_ERROR;
   }
 
-  r = snd_pcm_hw_params_any(stm->pcm, hw_params);
+  r = WRAP(snd_pcm_hw_params_any)(stm->pcm, hw_params);
   if (r < 0) {
     return CUBEB_ERROR;
   }
 
-  r = snd_pcm_hw_params_get_channels_max(hw_params, max_channels);
+  r = WRAP(snd_pcm_hw_params_get_channels_max)(hw_params, max_channels);
   if (r < 0) {
     return CUBEB_ERROR;
   }
@@ -969,34 +1075,34 @@ alsa_get_preferred_sample_rate(cubeb * c
 
   /* get a pcm, disabling resampling, so we get a rate the
    * hardware/dmix/pulse/etc. supports. */
-  r = snd_pcm_open(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE);
+  r = WRAP(snd_pcm_open)(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE);
   if (r < 0) {
     return CUBEB_ERROR;
   }
 
-  r = snd_pcm_hw_params_any(pcm, hw_params);
+  r = WRAP(snd_pcm_hw_params_any)(pcm, hw_params);
   if (r < 0) {
-    snd_pcm_close(pcm);
+    WRAP(snd_pcm_close)(pcm);
     return CUBEB_ERROR;
   }
 
-  r = snd_pcm_hw_params_get_rate(hw_params, rate, &dir);
+  r = WRAP(snd_pcm_hw_params_get_rate)(hw_params, rate, &dir);
   if (r >= 0) {
     /* There is a default rate: use it. */
-    snd_pcm_close(pcm);
+    WRAP(snd_pcm_close)(pcm);
     return CUBEB_OK;
   }
 
   /* Use a common rate, alsa may adjust it based on hw/etc. capabilities. */
   *rate = 44100;
 
-  r = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL);
+  r = WRAP(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, NULL);
   if (r < 0) {
-    snd_pcm_close(pcm);
+    WRAP(snd_pcm_close)(pcm);
     return CUBEB_ERROR;
   }
 
-  snd_pcm_close(pcm);
+  WRAP(snd_pcm_close)(pcm);
 
   return CUBEB_OK;
 }
@@ -1013,7 +1119,7 @@ alsa_stream_start(cubeb_stream * stm)
   ctx = stm->context;
 
   pthread_mutex_lock(&stm->mutex);
-  snd_pcm_pause(stm->pcm, 0);
+  WRAP(snd_pcm_pause)(stm->pcm, 0);
   gettimeofday(&stm->last_activity, NULL);
   pthread_mutex_unlock(&stm->mutex);
 
@@ -1047,7 +1153,7 @@ alsa_stream_stop(cubeb_stream * stm)
   pthread_mutex_unlock(&ctx->mutex);
 
   pthread_mutex_lock(&stm->mutex);
-  snd_pcm_pause(stm->pcm, 1);
+  WRAP(snd_pcm_pause)(stm->pcm, 1);
   pthread_mutex_unlock(&stm->mutex);
 
   return CUBEB_OK;
@@ -1063,8 +1169,8 @@ alsa_stream_get_position(cubeb_stream * stm, uint64_t * position)
   pthread_mutex_lock(&stm->mutex);
 
   delay = -1;
-  if (snd_pcm_state(stm->pcm) != SND_PCM_STATE_RUNNING ||
-      snd_pcm_delay(stm->pcm, &delay) != 0) {
+  if (WRAP(snd_pcm_state)(stm->pcm) != SND_PCM_STATE_RUNNING ||
+      WRAP(snd_pcm_delay)(stm->pcm, &delay) != 0) {
     *position = stm->last_position;
     pthread_mutex_unlock(&stm->mutex);
     return CUBEB_OK;
@@ -1089,7 +1195,7 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
   snd_pcm_sframes_t delay;
   /* This function returns the delay in frames until a frame written using
      snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */
-  if (snd_pcm_delay(stm->pcm, &delay)) {
+  if (WRAP(snd_pcm_delay)(stm->pcm, &delay)) {
     return CUBEB_ERROR;
   }
 
diff --git media/libcubeb/src/cubeb_oss.c media/libcubeb/src/cubeb_oss.c
new file mode 100644
index 0000000..5e38e27
--- /dev/null
+++ mozilla/media/libcubeb/src/cubeb_oss.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright © 2014 Mozilla Foundation
+ *
+ * This program is made available under an ISC-style license.  See the
+ * accompanying file LICENSE for details.
+ */
+#if defined(HAVE_SYS_SOUNDCARD_H)
+#include <sys/soundcard.h>
+#else
+#include <soundcard.h>
+#endif
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "cubeb/cubeb.h"
+#include "cubeb-internal.h"
+
+#ifndef CUBEB_OSS_DEFAULT_OUTPUT
+#define CUBEB_OSS_DEFAULT_OUTPUT "/dev/dsp"
+#endif
+
+#define OSS_BUFFER_SIZE 1024
+
+struct cubeb {
+  struct cubeb_ops const * ops;
+};
+
+struct cubeb_stream {
+  cubeb * context;
+
+  cubeb_data_callback data_callback;
+  cubeb_state_callback state_callback;
+  void * user_ptr;
+  float volume;
+  float panning;
+
+  pthread_mutex_t state_mutex;
+  pthread_cond_t state_cond;
+
+  int running;
+  int stopped;
+  int floating;
+
+  /* These two vars are needed to support old versions of OSS */
+  unsigned int position_bytes;
+  unsigned int last_position_bytes;
+
+  uint64_t written_frags; /* The number of fragments written to /dev/dsp */
+  uint64_t missed_frags; /* fragments output with stopped stream */
+
+  cubeb_stream_params params;
+  int fd;
+  pthread_t th;
+};
+
+static struct cubeb_ops const oss_ops;
+
+int oss_init(cubeb ** context, char const * context_name)
+{
+  cubeb* ctx = (cubeb*)malloc(sizeof(cubeb));
+  ctx->ops = &oss_ops;
+  *context = ctx;
+  return CUBEB_OK;
+}
+
+static void oss_destroy(cubeb *ctx)
+{
+  free(ctx);
+}
+
+static char const * oss_get_backend_id(cubeb * context)
+{
+  static char oss_name[] = "oss";
+  return oss_name;
+}
+
+static int oss_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
+{
+  *max_channels = 2; /* Let's support only stereo for now */
+  return CUBEB_OK;
+}
+
+static int oss_get_min_latency(cubeb * context, cubeb_stream_params params,
+                               uint32_t * latency_ms)
+{
+  /* 40ms is a big enough number to work ok */
+  *latency_ms = 40;
+  return CUBEB_OK;
+}
+
+static int oss_get_preferred_sample_rate(cubeb *context, uint32_t * rate)
+{
+  /* 48000 seems a prefered choice for most audio devices
+   * and a good choice for OSS */
+  *rate = 48000;
+  return CUBEB_OK;
+}
+
+static void run_state_callback(cubeb_stream *stream, cubeb_state state)
+{
+  if (stream->state_callback) {
+    stream->state_callback(stream, stream->user_ptr, state);
+  }
+}
+
+static long run_data_callback(cubeb_stream *stream, void *buffer, long nframes)
+{
+  long got = 0;
+  pthread_mutex_lock(&stream->state_mutex);
+  if (stream->data_callback && stream->running && !stream->stopped) {
+    pthread_mutex_unlock(&stream->state_mutex);
+    got = stream->data_callback(stream, stream->user_ptr, NULL, buffer, nframes);
+  } else {
+    pthread_mutex_unlock(&stream->state_mutex);
+  }
+  return got;
+}
+
+static void apply_volume_int(int16_t* buffer, unsigned int n,
+                             float volume, float panning)
+{
+  float left = volume;
+  float right = volume;
+  unsigned int i;
+  int pan[2];
+  if (panning<0) {
+    right *= (1+panning);
+  } else {
+    left *= (1-panning);
+  }
+  pan[0] = 128.0*left;
+  pan[1] = 128.0*right;
+  for(i=0; i<n; i++){
+    buffer[i] = ((int)buffer[i])*pan[i%2]/128;
+  }
+}
+
+static void apply_volume_float(float* buffer, unsigned int n,
+                               float volume, float panning)
+{
+  float left = volume;
+  float right = volume;
+  unsigned int i;
+  float pan[2];
+  if (panning<0) {
+    right *= (1+panning);
+  } else {
+    left *= (1-panning);
+  }
+  pan[0] = left;
+  pan[1] = right;
+  for(i=0; i<n; i++){
+    buffer[i] = buffer[i]*pan[i%2];
+  }
+}
+
+
+static void *writer(void *stm)
+{
+  cubeb_stream* stream = (cubeb_stream*)stm;
+  int16_t buffer[OSS_BUFFER_SIZE];
+  float f_buffer[OSS_BUFFER_SIZE];
+  int got;
+  unsigned long i;
+  while (stream->running) {
+    pthread_mutex_lock(&stream->state_mutex);
+    if (stream->stopped) {
+      pthread_mutex_unlock(&stream->state_mutex);
+      run_state_callback(stream, CUBEB_STATE_STOPPED);
+      pthread_mutex_lock(&stream->state_mutex);
+      while (stream->stopped) {
+        pthread_cond_wait(&stream->state_cond, &stream->state_mutex);
+      }
+      pthread_mutex_unlock(&stream->state_mutex);
+      run_state_callback(stream, CUBEB_STATE_STARTED);
+      continue;
+    }
+    pthread_mutex_unlock(&stream->state_mutex);
+    if (stream->floating) {
+      got = run_data_callback(stream, f_buffer,
+                              OSS_BUFFER_SIZE/stream->params.channels);
+      apply_volume_float(f_buffer, got*stream->params.channels,
+                                   stream->volume, stream->panning);
+      for (i=0; i<((unsigned long)got)*stream->params.channels; i++) {
+        /* Clipping is prefered to overflow */
+	if(f_buffer[i]>=1.0){
+	  f_buffer[i]=1.0;
+	}
+        if(f_buffer[i]<=-1.0){
+	  f_buffer[i]=-1.0;
+	}
+        /* One might think that multipling by 32767.0 is logical but results in clipping */
+        buffer[i] = f_buffer[i]*32767.0;
+      }
+    } else {
+      got = run_data_callback(stream, buffer,
+                              OSS_BUFFER_SIZE/stream->params.channels);
+      apply_volume_int(buffer, got*stream->params.channels,
+                               stream->volume, stream->panning);
+    }
+    if (got<0) {
+      run_state_callback(stream, CUBEB_STATE_ERROR);
+      break;
+    }
+    if (!got) {
+      run_state_callback(stream, CUBEB_STATE_DRAINED);
+    }
+    if (got) {
+      size_t i = 0;
+      size_t s = got*stream->params.channels*sizeof(int16_t);
+      while (i < s) {
+        ssize_t n = write(stream->fd, ((char*)buffer) + i, s - i);
+        if (n<=0) {
+          run_state_callback(stream, CUBEB_STATE_ERROR);
+          break;
+        }
+        i+=n;
+      }
+      stream->written_frags+=got;
+    }
+  }
+  return NULL;
+}
+
+static void oss_try_set_latency(cubeb_stream* stream, unsigned int latency)
+{
+  unsigned int latency_bytes, n_frag;
+  int frag;
+  /* fragment size of 1024 is a good choice with good chances to be accepted */
+  unsigned int frag_size=1024;
+  unsigned int frag_log=10; /* 2^frag_log = frag_size */
+  latency_bytes =
+    latency*stream->params.rate*stream->params.channels*sizeof(uint16_t)/1000;
+  n_frag = latency_bytes>>frag_log;
+  frag = (n_frag<<16) | frag_log;
+  /* Even if this fails we wish to continue, not checking for errors */
+  ioctl(stream->fd, SNDCTL_DSP_SETFRAGMENT, &frag);
+}
+
+static int oss_stream_init(cubeb * context, cubeb_stream ** stm,
+                           char const * stream_name,
+                           cubeb_devid input_device,
+                           cubeb_stream_params * input_stream_params,
+                           cubeb_devid output_device,
+                           cubeb_stream_params * output_stream_params,
+                           unsigned int latency,
+                           cubeb_data_callback data_callback,
+                           cubeb_state_callback state_callback, void * user_ptr)
+{
+  cubeb_stream* stream = (cubeb_stream*)malloc(sizeof(cubeb_stream));
+  stream->context = context;
+  stream->data_callback = data_callback;
+  stream->state_callback = state_callback;
+  stream->user_ptr = user_ptr;
+
+  assert(!input_stream_params && "not supported.");
+  if (input_device || output_device) {
+    /* Device selection not yet implemented. */
+    return CUBEB_ERROR_DEVICE_UNAVAILABLE;
+  }
+
+  if ((stream->fd = open(CUBEB_OSS_DEFAULT_OUTPUT, O_WRONLY)) == -1) {
+    free(stream);
+    return CUBEB_ERROR;
+  }
+#define SET(what, to) do { unsigned int i = to; \
+    int j = ioctl(stream->fd, what, &i); \
+    if (j == -1 || i != to) { \
+      close(stream->fd); \
+      free(stream); \
+      return CUBEB_ERROR_INVALID_FORMAT; } } while (0)
+
+  stream->params = *output_stream_params;
+  stream->volume = 1.0;
+  stream->panning = 0.0;
+
+  oss_try_set_latency(stream, latency); 
+
+  stream->floating = 0;
+  SET(SNDCTL_DSP_CHANNELS, stream->params.channels);
+  SET(SNDCTL_DSP_SPEED, stream->params.rate);
+  switch (stream->params.format) {
+    case CUBEB_SAMPLE_S16LE:
+      SET(SNDCTL_DSP_SETFMT, AFMT_S16_LE);
+    break;
+    case CUBEB_SAMPLE_S16BE:
+      SET(SNDCTL_DSP_SETFMT, AFMT_S16_BE);
+    break;
+    case CUBEB_SAMPLE_FLOAT32LE:
+      SET(SNDCTL_DSP_SETFMT, AFMT_S16_NE);
+      stream->floating = 1;
+    break;
+    default:
+      close(stream->fd);
+      free(stream);
+      return CUBEB_ERROR;
+  }
+
+
+  pthread_mutex_init(&stream->state_mutex, NULL);
+  pthread_cond_init(&stream->state_cond, NULL);
+
+  stream->running = 1;
+  stream->stopped = 1;
+  stream->position_bytes = 0;
+  stream->last_position_bytes = 0;
+  stream->written_frags = 0;
+  stream->missed_frags = 0;
+
+  pthread_create(&stream->th, NULL, writer, (void*)stream);
+
+  *stm = stream;
+
+  return CUBEB_OK;
+}
+
+static void oss_stream_destroy(cubeb_stream * stream)
+{
+  pthread_mutex_lock(&stream->state_mutex);
+
+  stream->running = 0;
+  stream->stopped = 0;
+  pthread_cond_signal(&stream->state_cond);
+
+  pthread_mutex_unlock(&stream->state_mutex);
+
+  pthread_join(stream->th, NULL);
+
+  pthread_mutex_destroy(&stream->state_mutex);
+  pthread_cond_destroy(&stream->state_cond);
+  close(stream->fd);
+  free(stream);
+}
+
+static int oss_stream_get_latency(cubeb_stream * stream, uint32_t * latency)
+{
+  if (ioctl(stream->fd, SNDCTL_DSP_GETODELAY, latency)==-1) {
+    return CUBEB_ERROR;
+  }
+  /* Convert latency from bytes to frames */
+  *latency /= stream->params.channels*sizeof(int16_t);
+  return CUBEB_OK;
+}
+
+
+static int oss_stream_current_optr(cubeb_stream * stream, uint64_t * position)
+{
+  count_info ci;
+  /* Unfortunately, this ioctl is only available in OSS 4.x */
+#ifdef SNDCTL_DSP_CURRENT_OPTR
+  oss_count_t count;
+  if (ioctl(stream->fd, SNDCTL_DSP_CURRENT_OPTR, &count) != -1) {
+    *position = count.samples;// + count.fifo_samples;
+    return CUBEB_OK;
+  }
+#endif
+  /* Fall back to this ioctl in case the previous one fails */
+  if (ioctl(stream->fd, SNDCTL_DSP_GETOPTR, &ci) == -1) {
+    return CUBEB_ERROR;
+  }
+  /* ci.bytes is only 32 bit and will start to wrap after arithmetic overflow */
+  stream->position_bytes += ci.bytes - stream->last_position_bytes;
+  stream->last_position_bytes = ci.bytes;
+  *position = stream->position_bytes/stream->params.channels/sizeof(int16_t);
+  return CUBEB_OK;
+}
+
+static int oss_stream_get_position(cubeb_stream * stream, uint64_t * position)
+{
+  if ( oss_stream_current_optr(stream, position) == CUBEB_OK ){
+    *position -= stream->missed_frags;
+    return CUBEB_OK;
+  }
+  /* If no correct method to get position works we resort to this */
+  *position = stream->written_frags;
+  return CUBEB_OK;
+}
+
+
+static int oss_stream_start(cubeb_stream * stream)
+{
+  pthread_mutex_lock(&stream->state_mutex);
+  if (stream->stopped) {
+    uint64_t ptr;
+    oss_stream_current_optr(stream, &ptr);
+    stream->missed_frags = ptr - stream->written_frags;
+    stream->stopped = 0;
+    pthread_cond_signal(&stream->state_cond);
+  }
+  pthread_mutex_unlock(&stream->state_mutex);
+  return CUBEB_OK;
+}
+
+static int oss_stream_stop(cubeb_stream * stream)
+{
+  pthread_mutex_lock(&stream->state_mutex);
+  stream->stopped = 1;
+  pthread_mutex_unlock(&stream->state_mutex);
+  return CUBEB_OK;
+}
+
+int oss_stream_set_panning(cubeb_stream * stream, float panning)
+{
+  if (stream->params.channels == 2) {
+    stream->panning=panning;
+  }
+  return CUBEB_OK;
+}
+
+int oss_stream_set_volume(cubeb_stream * stream, float volume)
+{
+  stream->volume=volume;
+  return CUBEB_OK;
+}
+
+static struct cubeb_ops const oss_ops = {
+  .init = oss_init,
+  .get_backend_id = oss_get_backend_id,
+  .get_max_channel_count = oss_get_max_channel_count,
+  .get_min_latency = oss_get_min_latency,
+  .get_preferred_sample_rate = oss_get_preferred_sample_rate,
+  .destroy = oss_destroy,
+  .stream_init = oss_stream_init,
+  .stream_destroy = oss_stream_destroy,
+  .stream_start = oss_stream_start,
+  .stream_stop = oss_stream_stop,
+  .stream_get_position = oss_stream_get_position,
+  .stream_get_latency = oss_stream_get_latency,
+  .stream_set_volume = oss_stream_set_volume,
+  .stream_set_panning = oss_stream_set_panning,
+  .stream_get_current_device = NULL,
+  .stream_device_destroy = NULL,
+  .stream_register_device_changed_callback = NULL
+};
diff --git media/libcubeb/src/moz.build media/libcubeb/src/moz.build
index 8b7a0dd..31212ce 100644
--- mozilla/media/libcubeb/src/moz.build
+++ mozilla/media/libcubeb/src/moz.build
@@ -17,6 +17,12 @@ if CONFIG['MOZ_ALSA']:
     ]
     DEFINES['USE_ALSA'] = True
 
+if CONFIG['MOZ_OSS']:
+    SOURCES += [
+        'cubeb_oss.c',
+    ]
+    DEFINES['USE_OSS'] = True
+
 if CONFIG['MOZ_PULSEAUDIO']:
     SOURCES += [
         'cubeb_pulse.c',
@@ -75,5 +81,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
 
 FAIL_ON_WARNINGS = True
 
+CFLAGS += CONFIG['MOZ_OSS_CFLAGS']
 CFLAGS += CONFIG['MOZ_ALSA_CFLAGS']
 CFLAGS += CONFIG['MOZ_PULSEAUDIO_CFLAGS']
 
diff --git media/libcubeb/tests/moz.build media/libcubeb/tests/moz.build
index 1b17c7b..48b56c2 100644
--- mozilla/media/libcubeb/tests/moz.build
+++ mozilla/media/libcubeb/tests/moz.build
@@ -73,7 +73,6 @@ elif CONFIG['OS_TARGET'] == 'OpenBSD':
         'sndio',
     ]
 else:
-    OS_LIBS += CONFIG['MOZ_ALSA_LIBS']
     OS_LIBS += CONFIG['MOZ_PULSEAUDIO_LIBS']
 
 if CONFIG['GNU_CXX']:
diff --git media/libcubeb/update.sh media/libcubeb/update.sh
index a96badd..2f9585e 100755
--- mozilla/media/libcubeb/update.sh
+++ mozilla/media/libcubeb/update.sh
@@ -16,6 +16,7 @@ cp $1/src/cubeb_audiounit.cpp src
 cp $1/src/cubeb_osx_run_loop.h src
 cp $1/src/cubeb_jack.cpp src
 cp $1/src/cubeb_opensl.c src
+cp $1/src/cubeb_oss.c src
 cp $1/src/cubeb_panner.cpp src
 cp $1/src/cubeb_panner.h src
 cp $1/src/cubeb_pulse.c src
diff --git media/webrtc/signaling/test/common.build media/webrtc/signaling/test/common.build
index 991f03f..3d99eb5 100644
--- mozilla/media/webrtc/signaling/test/common.build
+++ mozilla/media/webrtc/signaling/test/common.build
@@ -102,8 +102,8 @@ USE_LIBS += ['mozglue']
 OS_LIBS += CONFIG['MOZ_WEBRTC_X11_LIBS']
 OS_LIBS += CONFIG['REALTIME_LIBS']
 
-if CONFIG['MOZ_ALSA']:
-    OS_LIBS += CONFIG['MOZ_ALSA_LIBS']
+if CONFIG['MOZ_OSS']:
+    OS_LIBS += CONFIG['MOZ_OSS_LIBS']
 
 if CONFIG['MOZ_SYSTEM_JPEG']:
     OS_LIBS += CONFIG['MOZ_JPEG_LIBS']
diff --git toolkit/library/moz.build toolkit/library/moz.build
index e191f13..4fb268a 100644
--- mozilla/toolkit/library/moz.build
+++ mozilla/toolkit/library/moz.build
@@ -234,8 +234,8 @@ if CONFIG['MOZ_SYSTEM_LIBVPX']:
 if not CONFIG['MOZ_TREE_PIXMAN']:
     OS_LIBS += CONFIG['MOZ_PIXMAN_LIBS']
 
-if CONFIG['MOZ_ALSA']:
-    OS_LIBS += CONFIG['MOZ_ALSA_LIBS']
+if CONFIG['MOZ_OSS']:
+    OS_LIBS += CONFIG['MOZ_OSS_LIBS']
 
 if CONFIG['HAVE_CLOCK_MONOTONIC']:
     OS_LIBS += CONFIG['REALTIME_LIBS']
