Bug 911450: webrtc sndio audio_device backend r=jesup
authorLandry Breuil <landry@openbsd.org>
Mon, 16 Nov 2015 23:14:16 +0100
changeset 306979 69872cd154fdac9b2920c02d377c3e974e2c6678
parent 306978 7e829bb51eed5cbe2f9976c9385878f4ac21aff3
child 306980 5e29baaa9791381320329adef5b0d03a80900812
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs911450
milestone45.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 911450: webrtc sndio audio_device backend r=jesup Most of the code originally from Alexandre Ratchov <alex@caoua.org>
media/webrtc/trunk/webrtc/common_types.h
media/webrtc/trunk/webrtc/modules/audio_device/audio_device_impl.cc
media/webrtc/trunk/webrtc/modules/audio_device/include/audio_device.h
media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_sndio.cc
media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_sndio.h
media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_utility_sndio.cc
media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_utility_sndio.h
media/webrtc/trunk/webrtc/modules/audio_device/test/audio_device_test_api.cc
media/webrtc/trunk/webrtc/modules/audio_device/test/func_test_manager.cc
media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc
--- a/media/webrtc/trunk/webrtc/common_types.h
+++ b/media/webrtc/trunk/webrtc/common_types.h
@@ -486,17 +486,18 @@ enum StereoChannel
 
 // Audio device layers
 enum AudioLayers
 {
     kAudioPlatformDefault = 0,
     kAudioWindowsWave = 1,
     kAudioWindowsCore = 2,
     kAudioLinuxAlsa = 3,
-    kAudioLinuxPulse = 4
+    kAudioLinuxPulse = 4,
+    kAudioSndio = 5
 };
 
 // TODO(henrika): to be removed.
 enum NetEqModes             // NetEQ playout configurations
 {
     // Optimized trade-off between low delay and jitter robustness for two-way
     // communication.
     kNetEqDefault = 0,
--- a/media/webrtc/trunk/webrtc/modules/audio_device/audio_device_impl.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/audio_device_impl.cc
@@ -326,16 +326,17 @@ int32_t AudioDeviceModuleImpl::CreatePla
     }
     // END #if defined(WEBRTC_ANDROID_OPENSLES)
 
 #elif defined(WEBRTC_AUDIO_SNDIO)
     ptrAudioDevice = new AudioDeviceSndio(Id());
     if (ptrAudioDevice != NULL)
     {
         WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "attempting to use the Sndio audio API...");
+        _platformAudioLayer = kSndioAudio;
         // Create the sndio implementation of the Device Utility.
         ptrAudioDeviceUtility = new AudioDeviceUtilitySndio(Id());
     }
 
     // Create the *Linux* implementation of the Audio Device
     //
 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_BSD)
     if ((audioLayer == kLinuxPulseAudio) || (audioLayer == kPlatformDefaultAudio))
@@ -618,16 +619,20 @@ int32_t AudioDeviceModuleImpl::ActiveAud
     else if (*audioLayer == AudioDeviceModule::kWindowsCoreAudio)
     {
         WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id, "output: kWindowsCoreAudio");
     }
     else if (*audioLayer == AudioDeviceModule::kLinuxAlsaAudio)
     {
         WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id, "output: kLinuxAlsaAudio");
     }
+    else if (*audioLayer == AudioDeviceModule::kSndioAudio)
+    {
+        WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id, "output: kSndioAudio");
+    }
     else
     {
         WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id, "output: NOT_SUPPORTED");
     }
 
     return 0;
 }
 
@@ -2064,16 +2069,20 @@ AudioDeviceModule::AudioLayer AudioDevic
     case kWindowsCoreAudio:
         WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
                      "output: kWindowsCoreAudio");
         break;
     case kLinuxAlsaAudio:
         WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
                      "output: kLinuxAlsaAudio");
         break;
+    case kSndioAudio:
+        WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
+                     "output: kSndioAudio");
+        break;
     case kDummyAudio:
         WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
                      "output: kDummyAudio");
         break;
     default:
         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                      "output: INVALID");
         break;
--- a/media/webrtc/trunk/webrtc/modules/audio_device/include/audio_device.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/include/audio_device.h
@@ -24,17 +24,18 @@ class AudioDeviceModule : public RefCoun
   };
 
   enum AudioLayer {
     kPlatformDefaultAudio = 0,
     kWindowsWaveAudio = 1,
     kWindowsCoreAudio = 2,
     kLinuxAlsaAudio = 3,
     kLinuxPulseAudio = 4,
-    kDummyAudio = 5
+    kSndioAudio = 5,
+    kDummyAudio = 6
   };
 
   enum WindowsDeviceType {
     kDefaultCommunicationDevice = -1,
     kDefaultDevice = -2
   };
 
   enum BufferType {
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_sndio.cc
@@ -0,0 +1,1044 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "webrtc/modules/audio_device/audio_device_config.h"
+#include "webrtc/modules/audio_device/audio_device_utility.h"
+#include "webrtc/modules/audio_device/sndio/audio_device_sndio.h"
+
+#include "webrtc/system_wrappers/interface/event_wrapper.h"
+#include "webrtc/system_wrappers/interface/sleep.h"
+#include "webrtc/system_wrappers/interface/thread_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+#include "Latency.h"
+
+#define LOG_FIRST_CAPTURE(x) LogTime(AsyncLatencyLogger::AudioCaptureBase, \
+                                     reinterpret_cast<uint64_t>(x), 0)
+#define LOG_CAPTURE_FRAMES(x, frames) LogLatency(AsyncLatencyLogger::AudioCapture, \
+                                                 reinterpret_cast<uint64_t>(x), frames)
+extern "C"
+{
+    static void playOnmove(void *arg, int delta)
+    {
+        static_cast<webrtc::AudioDeviceSndio *>(arg)->_playDelay -= delta;
+    }
+
+    static void recOnmove(void *arg, int delta)
+    {
+        static_cast<webrtc::AudioDeviceSndio *>(arg)->_recDelay += delta;
+    }
+}
+
+namespace webrtc
+{
+AudioDeviceSndio::AudioDeviceSndio(const int32_t id) :
+    _ptrAudioBuffer(NULL),
+    _critSect(*CriticalSectionWrapper::CreateCriticalSection()),
+    _id(id),
+    _recordingBuffer(NULL),
+    _playoutBuffer(NULL),
+    _playBufType(AudioDeviceModule::kFixedBufferSize),
+    _initialized(false),
+    _playHandle(NULL),
+    _recHandle(NULL),
+    _recording(false),
+    _playing(false),
+    _AGC(false),
+    _playWarning(0),
+    _playError(0),
+    _recWarning(0),
+    _recError(0),
+    _playBufDelay(80),
+    _playBufDelayFixed(80)
+{
+    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id,
+                 "%s created", __FUNCTION__);
+}
+
+AudioDeviceSndio::~AudioDeviceSndio()
+{
+    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
+                 "%s destroyed", __FUNCTION__);
+
+    Terminate();
+
+    // Clean up the recording buffer and playout buffer.
+    if (_recordingBuffer)
+    {
+        delete [] _recordingBuffer;
+        _recordingBuffer = NULL;
+    }
+    if (_playoutBuffer)
+    {
+        delete [] _playoutBuffer;
+        _playoutBuffer = NULL;
+    }
+    delete &_critSect;
+}
+
+void AudioDeviceSndio::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer)
+{
+
+    CriticalSectionScoped lock(&_critSect);
+
+    _ptrAudioBuffer = audioBuffer;
+
+    // Inform the AudioBuffer about default settings for this implementation.
+    // Set all values to zero here since the actual settings will be done by
+    // InitPlayout and InitRecording later.
+    _ptrAudioBuffer->SetRecordingSampleRate(0);
+    _ptrAudioBuffer->SetPlayoutSampleRate(0);
+    _ptrAudioBuffer->SetRecordingChannels(0);
+    _ptrAudioBuffer->SetPlayoutChannels(0);
+}
+
+int32_t AudioDeviceSndio::ActiveAudioLayer(
+    AudioDeviceModule::AudioLayer& audioLayer) const
+{
+    audioLayer = AudioDeviceModule::kSndioAudio;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::Init()
+{
+
+    CriticalSectionScoped lock(&_critSect);
+
+    if (_initialized)
+    {
+        return 0;
+    }
+    _playError = 0;
+    _recError = 0;
+    _initialized = true;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::Terminate()
+{
+    if (!_initialized)
+    {
+        return 0;
+    }
+
+    CriticalSectionScoped lock(&_critSect);
+
+    if (_playing)
+    {
+        StopPlayout();
+    }
+
+    if (_recording)
+    {
+        StopRecording();
+    }
+
+    if (_playHandle)
+    {
+        sio_close(_playHandle);
+        delete [] _playoutBuffer;
+        _playHandle = NULL;
+    }
+
+    if (_recHandle)
+    {
+        sio_close(_recHandle);
+        delete [] _recordingBuffer;
+        _recHandle = NULL;
+    }
+
+    _initialized = false;
+    return 0;
+}
+
+bool AudioDeviceSndio::Initialized() const
+{
+    return (_initialized);
+}
+
+int32_t AudioDeviceSndio::InitSpeaker()
+{
+    return 0;
+}
+
+
+int32_t AudioDeviceSndio::InitMicrophone()
+{
+    return 0;
+}
+
+bool AudioDeviceSndio::SpeakerIsInitialized() const
+{
+    return true;
+}
+
+bool AudioDeviceSndio::MicrophoneIsInitialized() const
+{
+    return true;
+}
+
+int32_t AudioDeviceSndio::SpeakerVolumeIsAvailable(bool& available)
+{
+    available = true;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetSpeakerVolume(uint32_t volume)
+{
+
+    CriticalSectionScoped lock(&_critSect);
+
+    // XXX: call sio_onvol()
+    sio_setvol(_playHandle, volume);
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SpeakerVolume(uint32_t& volume) const
+{
+
+    CriticalSectionScoped lock(&_critSect);
+
+    // XXX: copy value reported by sio_onvol() call-back
+    volume = 0;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetWaveOutVolume(uint16_t volumeLeft,
+                                           uint16_t volumeRight)
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::WaveOutVolume(
+    uint16_t& /*volumeLeft*/,
+    uint16_t& /*volumeRight*/) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MaxSpeakerVolume(
+    uint32_t& maxVolume) const
+{
+    maxVolume = SIO_MAXVOL;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::MinSpeakerVolume(
+    uint32_t& minVolume) const
+{
+    minVolume = 0;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SpeakerVolumeStepSize(
+    uint16_t& stepSize) const
+{
+    stepSize = 1;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SpeakerMuteIsAvailable(bool& available)
+{
+    available = false;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetSpeakerMute(bool enable)
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::SpeakerMute(bool& enabled) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MicrophoneMuteIsAvailable(bool& available)
+{
+    available = false;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetMicrophoneMute(bool enable)
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MicrophoneMute(bool& enabled) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MicrophoneBoostIsAvailable(bool& available)
+{
+    available = false;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetMicrophoneBoost(bool enable)
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MicrophoneBoost(bool& enabled) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::StereoRecordingIsAvailable(bool& available)
+{
+    available = true;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetStereoRecording(bool enable)
+{
+
+    if (enable)
+    {
+        _recChannels = 2;
+    } else {
+        _recChannels = 1;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::StereoRecording(bool& enabled) const
+{
+
+    if (_recChannels == 2)
+    {
+        enabled = true;
+    } else {
+        enabled = false;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::StereoPlayoutIsAvailable(bool& available)
+{
+    available = true;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetStereoPlayout(bool enable)
+{
+
+    if (enable)
+    {
+        _playChannels = 2;
+    } else {
+        _playChannels = 1;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::StereoPlayout(bool& enabled) const
+{
+    if (_playChannels == 2)
+    {
+        enabled = true;
+    } else {
+        enabled = false;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetAGC(bool enable)
+{
+    _AGC = enable;
+
+    return 0;
+}
+
+bool AudioDeviceSndio::AGC() const
+{
+    return _AGC;
+}
+
+int32_t AudioDeviceSndio::MicrophoneVolumeIsAvailable(bool& available)
+{
+    available = false;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetMicrophoneVolume(uint32_t volume)
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MicrophoneVolume(uint32_t& volume) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MaxMicrophoneVolume(
+    uint32_t& maxVolume) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MinMicrophoneVolume(
+    uint32_t& minVolume) const
+{
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::MicrophoneVolumeStepSize(
+    uint16_t& stepSize) const
+{
+    return -1;
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+                 "  API call not supported on this platform");
+}
+
+int16_t AudioDeviceSndio::PlayoutDevices()
+{
+    return 1;
+}
+
+int32_t AudioDeviceSndio::SetPlayoutDevice(uint16_t index)
+{
+    if (index != 0) {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  device index != 0");
+        return -1;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetPlayoutDevice(
+    AudioDeviceModule::WindowsDeviceType /*device*/)
+{
+    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                 "WindowsDeviceType not supported");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::PlayoutDeviceName(
+    uint16_t index,
+    char name[kAdmMaxDeviceNameSize],
+    char guid[kAdmMaxGuidSize])
+{
+
+    if (index != 0 || (name == NULL))
+    {
+        return -1;
+    }
+
+    strlcpy(name, SIO_DEVANY, kAdmMaxDeviceNameSize);
+
+    if (guid != NULL)
+    {
+        memset(guid, 0, kAdmMaxGuidSize);
+    }
+
+    return 0;
+}
+
+int32_t AudioDeviceSndio::RecordingDeviceName(
+    uint16_t index,
+    char name[kAdmMaxDeviceNameSize],
+    char guid[kAdmMaxGuidSize])
+{
+
+    if (index != 0 || (name == NULL))
+    {
+        return -1;
+    }
+
+    strlcpy(name, SIO_DEVANY, kAdmMaxDeviceNameSize);
+
+    if (guid != NULL)
+    {
+        memset(guid, 0, kAdmMaxGuidSize);
+    }
+
+    return 0;
+}
+
+int16_t AudioDeviceSndio::RecordingDevices()
+{
+    return 1;
+}
+
+int32_t AudioDeviceSndio::SetRecordingDevice(uint16_t index)
+{
+    if (index != 0)
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  device index != 0");
+        return -1;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::SetRecordingDevice(
+    AudioDeviceModule::WindowsDeviceType /*device*/)
+{
+    WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                 "WindowsDeviceType not supported");
+    return -1;
+}
+
+int32_t AudioDeviceSndio::PlayoutIsAvailable(bool& available)
+{
+    struct sio_hdl *hdl;
+
+    hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+    if (hdl == NULL)
+    {
+        available = false;
+    } else {
+        sio_close(hdl);
+        available = true;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::RecordingIsAvailable(bool& available)
+{
+    struct sio_hdl *hdl;
+
+    hdl = sio_open(SIO_DEVANY, SIO_REC, 0);
+    if (hdl == NULL)
+    {
+        available = false;
+    } else {
+        sio_close(hdl);
+        available = true;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::InitPlayout()
+{
+    CriticalSectionScoped lock(&_critSect);
+    if (_playing) {
+        return -1;
+    }
+
+    if (_playHandle != NULL)
+    {
+        return 0;
+    }
+
+    _playHandle = sio_open(SIO_DEVANY, SIO_PLAY, 0);
+    if (_playHandle == NULL)
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  Error opening play device");
+        return -1;
+    }
+
+    sio_initpar(&_playParams);
+    _playParams.rate = 48000;
+    _playParams.pchan = 2;
+    _playParams.bits = 16;
+    _playParams.sig = 1;
+    _playParams.le = SIO_LE_NATIVE;
+    _playParams.appbufsz = _playParams.rate * 40 / 1000;
+
+    if (!sio_setpar(_playHandle, &_playParams))
+    {
+       WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                    "  Error setting _playParams");
+        sio_close(_playHandle);
+        _playHandle = NULL;
+        return -1;
+    }
+    if (!sio_getpar(_playHandle, &_playParams))
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  Error getting _playParams");
+        sio_close(_playHandle);
+        _playHandle = NULL;
+        return -1;
+    }
+
+    _playFrames = _playParams.rate / 100;
+    _playoutBuffer = new int8_t[_playFrames *
+                                _playParams.bps *
+                                _playParams.pchan];
+    if (_playoutBuffer == NULL)
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "   failed to alloc play buffer");
+        sio_close(_playHandle);
+        _playHandle = NULL;
+        return -1;
+    }
+
+    if (_ptrAudioBuffer)
+    {
+        // Update webrtc audio buffer with the selected parameters
+        _ptrAudioBuffer->SetPlayoutSampleRate(_playParams.rate);
+        _ptrAudioBuffer->SetPlayoutChannels(_playParams.pchan);
+    }
+
+    _playDelay = 0;
+    sio_onmove(_playHandle, playOnmove, this);
+    return 0;
+}
+
+int32_t AudioDeviceSndio::InitRecording()
+{
+    CriticalSectionScoped lock(&_critSect);
+
+    if (_recording)
+    {
+        return -1;
+    }
+
+    if (_recHandle != NULL)
+    {
+        return 0;
+    }
+
+    _recHandle = sio_open(SIO_DEVANY, SIO_REC, 0);
+    if (_recHandle == NULL)
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  Error opening rec device");
+        return -1;
+    }
+
+    sio_initpar(&_recParams);
+    _recParams.rate = 48000;
+    _recParams.rchan = 2;
+    _recParams.bits = 16;
+    _recParams.sig = 1;
+    _recParams.le = SIO_LE_NATIVE;
+    _recParams.appbufsz = _recParams.rate * 40 / 1000;
+
+    if (!sio_setpar(_recHandle, &_recParams))
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  Error setting _recParams");
+        sio_close(_recHandle);
+        _recHandle = NULL;
+        return -1;
+    }
+    if (!sio_getpar(_recHandle, &_recParams))
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  Error getting _recParams");
+        sio_close(_recHandle);
+        _recHandle = NULL;
+        return -1;
+    }
+
+    _recFrames = _recParams.rate / 100;
+    _recordingBuffer = new int8_t[_recFrames *
+                                  _recParams.bps *
+                                  _recParams.rchan];
+    if (_recordingBuffer == NULL)
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "   failed to alloc rec buffer");
+        sio_close(_recHandle);
+        _recHandle = NULL;
+        return -1;
+    }
+
+    if (_ptrAudioBuffer)
+    {
+        _ptrAudioBuffer->SetRecordingSampleRate(_recParams.rate);
+        _ptrAudioBuffer->SetRecordingChannels(_recParams.rchan);
+    }
+
+    _recDelay = 0;
+    sio_onmove(_recHandle, recOnmove, this);
+    return 0;
+}
+
+int32_t AudioDeviceSndio::StartRecording()
+{
+    unsigned int unused_thread_id;
+    const char* threadName = "webrtc_audio_module_capture_thread";
+
+    if (_recHandle == NULL)
+    {
+        return -1;
+    }
+
+    if (_recording)
+    {
+        return 0;
+    }
+
+    _ptrThreadRec = ThreadWrapper::CreateThread(RecThreadFunc,
+                                                this,
+                                                kRealtimePriority,
+                                                threadName);
+    if (_ptrThreadRec == NULL)
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "  failed to create the rec audio thread");
+        _recording = false;
+        delete [] _recordingBuffer;
+        _recordingBuffer = NULL;
+        return -1;
+    }
+
+    _playDelay = 0;
+
+    if (!sio_start(_recHandle))
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "  couldn't start recording");
+        delete _ptrThreadRec;
+        _ptrThreadRec = NULL;
+        delete [] _recordingBuffer;
+        _recordingBuffer = NULL;
+        return -1;
+    }
+
+    if (!_ptrThreadRec->Start(unused_thread_id))
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "  failed to start the rec audio thread");
+        _recording = false;
+        sio_stop(_recHandle);
+        delete _ptrThreadRec;
+        _ptrThreadRec = NULL;
+        delete [] _recordingBuffer;
+        _recordingBuffer = NULL;
+        return -1;
+    }
+    _recording = true;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::StopRecording()
+{
+
+    CriticalSectionScoped lock(&_critSect);
+
+    if (_recHandle == NULL)
+    {
+        return 0;
+    }
+
+    _recording = false;
+
+    if (_ptrThreadRec && !_ptrThreadRec->Stop())
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "    failed to stop the rec audio thread");
+        return -1;
+    }
+
+    sio_stop(_recHandle);
+
+    delete _ptrThreadRec;
+    _ptrThreadRec = NULL;
+    return 0;
+}
+
+bool AudioDeviceSndio::RecordingIsInitialized() const
+{
+    return (_recHandle != NULL);
+}
+
+bool AudioDeviceSndio::Recording() const
+{
+    return (_recording);
+}
+
+bool AudioDeviceSndio::PlayoutIsInitialized() const
+{
+    return (_playHandle != NULL);
+}
+
+int32_t AudioDeviceSndio::StartPlayout()
+{
+    unsigned int unused_thread_id;
+    const char* threadName = "webrtc_audio_module_play_thread";
+
+    if (_playHandle == NULL)
+    {
+        return -1;
+    }
+
+    if (_playing)
+    {
+        return 0;
+    }
+
+    _ptrThreadPlay =  ThreadWrapper::CreateThread(PlayThreadFunc,
+                                                  this,
+                                                  kRealtimePriority,
+                                                  threadName);
+    if (_ptrThreadPlay == NULL)
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "    failed to create the play audio thread");
+        _playing = false;
+        delete [] _playoutBuffer;
+        _playoutBuffer = NULL;
+        return -1;
+    }
+
+    if (!sio_start(_playHandle)) {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "    failed to start audio playback");
+        delete _ptrThreadPlay;
+        _ptrThreadPlay = NULL;
+        delete [] _playoutBuffer;
+        _playoutBuffer = NULL;
+        return -1;
+    }
+
+    if (!_ptrThreadPlay->Start(unused_thread_id))
+    {
+        WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
+                     "  failed to start the play audio thread");
+        sio_stop(_playHandle);
+        delete _ptrThreadPlay;
+        _ptrThreadPlay = NULL;
+        delete [] _playoutBuffer;
+        _playoutBuffer = NULL;
+        return -1;
+    }
+    _playing = true;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::StopPlayout()
+{
+    CriticalSectionScoped lock(&_critSect);
+    if (_playHandle == NULL)
+    {
+        return 0;
+    }
+    _playing = false;
+
+    if (_ptrThreadPlay && !_ptrThreadPlay->Stop())
+    {
+        WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                     "  failed to stop the play audio thread");
+        return -1;
+    } else {
+        delete _ptrThreadPlay;
+        _ptrThreadPlay = NULL;
+    }
+
+    sio_stop(_playHandle);
+
+    CriticalSectionScoped lock(&_critSect);
+
+    delete [] _playoutBuffer;
+    _playoutBuffer = NULL;
+    delete _ptrThreadPlay;
+    _ptrThreadPlay = NULL;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::PlayoutDelay(uint16_t& delayMS) const
+{
+    CriticalSectionScoped lock(&_critSect);
+    delayMS = (uint16_t) (_playDelay * 1000) / _playParams.rate;
+    return 0;
+}
+
+int32_t AudioDeviceSndio::RecordingDelay(uint16_t& delayMS) const
+{
+    CriticalSectionScoped lock(&_critSect);
+    delayMS = (uint16_t) (_recDelay * 1000) / _recParams.rate;
+    return 0;
+}
+
+bool AudioDeviceSndio::Playing() const
+{
+    return (_playing);
+}
+// ----------------------------------------------------------------------------
+//  SetPlayoutBuffer
+// ----------------------------------------------------------------------------
+
+int32_t AudioDeviceSndio::SetPlayoutBuffer(
+    const AudioDeviceModule::BufferType type,
+    uint16_t sizeMS)
+{
+    _playBufType = type;
+    if (type == AudioDeviceModule::kFixedBufferSize)
+    {
+        _playBufDelayFixed = sizeMS;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::PlayoutBuffer(
+    AudioDeviceModule::BufferType& type,
+    uint16_t& sizeMS) const
+{
+    type = _playBufType;
+    if (type == AudioDeviceModule::kFixedBufferSize)
+    {
+        sizeMS = _playBufDelayFixed;
+    } else {
+        sizeMS = _playBufDelay;
+    }
+    return 0;
+}
+
+int32_t AudioDeviceSndio::CPULoad(uint16_t& load) const
+{
+
+    WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
+               "  API call not supported on this platform");
+    return -1;
+}
+
+bool AudioDeviceSndio::PlayoutWarning() const
+{
+    CriticalSectionScoped lock(&_critSect);
+    return (_playWarning > 0);
+}
+
+bool AudioDeviceSndio::PlayoutError() const
+{
+    CriticalSectionScoped lock(&_critSect);
+    return (_playError > 0);
+}
+
+bool AudioDeviceSndio::RecordingWarning() const
+{
+    CriticalSectionScoped lock(&_critSect);
+    return (_recWarning > 0);
+}
+
+bool AudioDeviceSndio::RecordingError() const
+{
+    CriticalSectionScoped lock(&_critSect);
+    return (_recError > 0);
+}
+
+void AudioDeviceSndio::ClearPlayoutWarning()
+{
+    CriticalSectionScoped lock(&_critSect);
+    _playWarning = 0;
+}
+
+void AudioDeviceSndio::ClearPlayoutError()
+{
+    CriticalSectionScoped lock(&_critSect);
+    _playError = 0;
+}
+
+void AudioDeviceSndio::ClearRecordingWarning()
+{
+    CriticalSectionScoped lock(&_critSect);
+    _recWarning = 0;
+}
+
+void AudioDeviceSndio::ClearRecordingError()
+{
+    CriticalSectionScoped lock(&_critSect);
+    _recError = 0;
+}
+
+bool AudioDeviceSndio::PlayThreadFunc(void* pThis)
+{
+    return (static_cast<AudioDeviceSndio*>(pThis)->PlayThreadProcess());
+}
+
+bool AudioDeviceSndio::RecThreadFunc(void* pThis)
+{
+    return (static_cast<AudioDeviceSndio*>(pThis)->RecThreadProcess());
+}
+
+bool AudioDeviceSndio::PlayThreadProcess()
+{
+    int n;
+    bool res;
+
+    res = true;
+    CriticalSectionScoped lock(&_critSect);
+    // XXX: update volume here
+    _ptrAudioBuffer->RequestPlayoutData(_playFrames);
+    n = _ptrAudioBuffer->GetPlayoutData(_playoutBuffer);
+    sio_write(_playHandle, _playoutBuffer, n *
+             _playParams.bps *
+             _playParams.pchan);
+    if (sio_eof(_playHandle))
+    {
+        res = false;
+        _playError = 1;
+    }
+    _playDelay += n;
+    _critSect.Leave();
+    return res;
+}
+
+bool AudioDeviceSndio::RecThreadProcess()
+{
+    int n, todo;
+    int8_t *data;
+    bool res;
+
+    res = true;
+    CriticalSectionScoped lock(&_critSect);
+    data = _recordingBuffer;
+    todo = _recFrames * _recParams.bps * _recParams.rchan;
+    while (todo > 0)
+    {
+        n = sio_read(_recHandle, data, todo);
+        if (n == 0)
+        {
+             WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
+                          "sio_read failed, device disconnected?");
+            res = false;
+            _recError = 1;
+            break;
+        }
+        data += n;
+        todo -= n;
+    }
+    if (res)
+    {
+        _ptrAudioBuffer->SetVQEData(
+            _playDelay * 1000 / _playParams.rate,
+            _recDelay * 1000 / _recParams.rate, 0);
+        _ptrAudioBuffer->SetRecordedBuffer(_recordingBuffer, _recFrames);
+        _ptrAudioBuffer->DeliverRecordedData();
+    }
+    _recDelay -= _recFrames;
+    return res;
+}
+} // namespace "webrtc"
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_sndio.h
@@ -0,0 +1,203 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_SNDIO_H
+#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_SNDIO_H
+
+#include <sndio.h>
+
+#include "webrtc/modules/audio_device/audio_device_generic.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/thread_wrapper.h"
+
+namespace webrtc
+{
+class AudioDeviceSndio : public AudioDeviceGeneric
+{
+public:
+    AudioDeviceSndio(const int32_t id);
+    virtual ~AudioDeviceSndio();
+
+    // Retrieve the currently utilized audio layer
+    virtual int32_t ActiveAudioLayer(
+        AudioDeviceModule::AudioLayer& audioLayer) const OVERRIDE;
+
+    // Main initializaton and termination
+    virtual int32_t Init() OVERRIDE;
+    virtual int32_t Terminate() OVERRIDE;
+    virtual bool Initialized() const OVERRIDE;
+
+    // Device enumeration
+    virtual int16_t PlayoutDevices() OVERRIDE;
+    virtual int16_t RecordingDevices() OVERRIDE;
+    virtual int32_t PlayoutDeviceName(
+        uint16_t index,
+        char name[kAdmMaxDeviceNameSize],
+        char guid[kAdmMaxGuidSize]) OVERRIDE;
+    virtual int32_t RecordingDeviceName(
+        uint16_t index,
+        char name[kAdmMaxDeviceNameSize],
+        char guid[kAdmMaxGuidSize]) OVERRIDE;
+
+    // Device selection
+    virtual int32_t SetPlayoutDevice(uint16_t index) OVERRIDE;
+    virtual int32_t SetPlayoutDevice(
+        AudioDeviceModule::WindowsDeviceType device) OVERRIDE;
+    virtual int32_t SetRecordingDevice(uint16_t index) OVERRIDE;
+    virtual int32_t SetRecordingDevice(
+        AudioDeviceModule::WindowsDeviceType device) OVERRIDE;
+
+    // Audio transport initialization
+    virtual int32_t PlayoutIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t InitPlayout() OVERRIDE;
+    virtual bool PlayoutIsInitialized() const OVERRIDE;
+    virtual int32_t RecordingIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t InitRecording() OVERRIDE;
+    virtual bool RecordingIsInitialized() const OVERRIDE;
+
+    // Audio transport control
+    virtual int32_t StartPlayout() OVERRIDE;
+    virtual int32_t StopPlayout() OVERRIDE;
+    virtual bool Playing() const OVERRIDE;
+    virtual int32_t StartRecording() OVERRIDE;
+    virtual int32_t StopRecording() OVERRIDE;
+    virtual bool Recording() const OVERRIDE;
+
+    // Microphone Automatic Gain Control (AGC)
+    virtual int32_t SetAGC(bool enable) OVERRIDE;
+    virtual bool AGC() const OVERRIDE;
+
+    // Volume control based on the Windows Wave API (Windows only)
+    virtual int32_t SetWaveOutVolume(uint16_t volumeLeft,
+                                     uint16_t volumeRight) OVERRIDE;
+    virtual int32_t WaveOutVolume(uint16_t& volumeLeft,
+                                  uint16_t& volumeRight) const OVERRIDE;
+
+    // Audio mixer initialization
+    virtual int32_t InitSpeaker() OVERRIDE;
+    virtual bool SpeakerIsInitialized() const OVERRIDE;
+    virtual int32_t InitMicrophone() OVERRIDE;
+    virtual bool MicrophoneIsInitialized() const OVERRIDE;
+
+    // Speaker volume controls
+    virtual int32_t SpeakerVolumeIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetSpeakerVolume(uint32_t volume) OVERRIDE;
+    virtual int32_t SpeakerVolume(uint32_t& volume) const OVERRIDE;
+    virtual int32_t MaxSpeakerVolume(uint32_t& maxVolume) const OVERRIDE;
+    virtual int32_t MinSpeakerVolume(uint32_t& minVolume) const OVERRIDE;
+    virtual int32_t SpeakerVolumeStepSize(uint16_t& stepSize) const OVERRIDE;
+
+    // Microphone volume controls
+    virtual int32_t MicrophoneVolumeIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetMicrophoneVolume(uint32_t volume) OVERRIDE;
+    virtual int32_t MicrophoneVolume(uint32_t& volume) const OVERRIDE;
+    virtual int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const OVERRIDE;
+    virtual int32_t MinMicrophoneVolume(uint32_t& minVolume) const OVERRIDE;
+    virtual int32_t MicrophoneVolumeStepSize(
+        uint16_t& stepSize) const OVERRIDE;
+
+    // Speaker mute control
+    virtual int32_t SpeakerMuteIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetSpeakerMute(bool enable) OVERRIDE;
+    virtual int32_t SpeakerMute(bool& enabled) const OVERRIDE;
+
+    // Microphone mute control
+    virtual int32_t MicrophoneMuteIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetMicrophoneMute(bool enable) OVERRIDE;
+    virtual int32_t MicrophoneMute(bool& enabled) const OVERRIDE;
+
+    // Microphone boost control
+    virtual int32_t MicrophoneBoostIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetMicrophoneBoost(bool enable) OVERRIDE;
+    virtual int32_t MicrophoneBoost(bool& enabled) const OVERRIDE;
+
+    // Stereo support
+    virtual int32_t StereoPlayoutIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetStereoPlayout(bool enable) OVERRIDE;
+    virtual int32_t StereoPlayout(bool& enabled) const OVERRIDE;
+    virtual int32_t StereoRecordingIsAvailable(bool& available) OVERRIDE;
+    virtual int32_t SetStereoRecording(bool enable) OVERRIDE;
+    virtual int32_t StereoRecording(bool& enabled) const OVERRIDE;
+
+    // Delay information and control
+    virtual int32_t SetPlayoutBuffer(
+        const AudioDeviceModule::BufferType type,
+        uint16_t sizeMS) OVERRIDE;
+    virtual int32_t PlayoutBuffer(
+        AudioDeviceModule::BufferType& type,
+        uint16_t& sizeMS) const OVERRIDE;
+    virtual int32_t PlayoutDelay(uint16_t& delayMS) const OVERRIDE;
+    virtual int32_t RecordingDelay(uint16_t& delayMS) const OVERRIDE;
+
+    virtual int32_t CPULoad(uint16_t& load) const OVERRIDE;
+
+public:
+    virtual bool PlayoutWarning() const OVERRIDE;
+    virtual bool PlayoutError() const OVERRIDE;
+    virtual bool RecordingWarning() const OVERRIDE;
+    virtual bool RecordingError() const OVERRIDE;
+    virtual void ClearPlayoutWarning() OVERRIDE;
+    virtual void ClearPlayoutError() OVERRIDE;
+    virtual void ClearRecordingWarning() OVERRIDE;
+    virtual void ClearRecordingError() OVERRIDE;
+
+    virtual void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) OVERRIDE;
+
+    // needs to be public because playOnmove/recOnmove are extern "C" ?
+    int _recDelay, _playDelay;
+
+
+private:
+    static bool RecThreadFunc(void *);
+    static bool PlayThreadFunc(void *);
+    bool RecThreadProcess();
+    bool PlayThreadProcess();
+
+private:
+    AudioDeviceBuffer* _ptrAudioBuffer;
+
+    struct sio_hdl* _playHandle;
+    struct sio_hdl* _recHandle;
+    struct sio_par _playParams, _recParams;
+
+    CriticalSectionWrapper& _critSect;
+
+    ThreadWrapper* _ptrThreadRec;
+    ThreadWrapper* _ptrThreadPlay;
+
+    int32_t _id;
+
+    int8_t* _recordingBuffer;
+    int8_t* _playoutBuffer;
+    uint8_t _recChannels;
+    uint8_t _playChannels;
+
+    unsigned int _recFrames;
+    unsigned int _playFrames;
+
+    AudioDeviceModule::BufferType _playBufType;
+
+    bool _initialized;
+    bool _recording;
+    bool _playing;
+    bool _AGC;
+
+    uint16_t _playWarning;
+    uint16_t _playError;
+    uint16_t _recWarning;
+    uint16_t _recError;
+
+    uint16_t _playBufDelay;                 // playback delay
+    uint16_t _playBufDelayFixed;            // fixed playback delay
+};
+
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_utility_sndio.cc
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_device/sndio/audio_device_utility_sndio.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc
+{
+
+AudioDeviceUtilitySndio::AudioDeviceUtilitySndio(const int32_t id) :
+    _critSect(*CriticalSectionWrapper::CreateCriticalSection()), _id(id)
+{
+    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id,
+                 "%s created", __FUNCTION__);
+}
+
+AudioDeviceUtilitySndio::~AudioDeviceUtilitySndio()
+{
+    WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, _id,
+                 "%s destroyed", __FUNCTION__);
+    {
+        CriticalSectionScoped lock(&_critSect);
+
+        // XXX free stuff here...
+    }
+
+    delete &_critSect;
+}
+
+// ============================================================================
+//                                     API
+// ============================================================================
+
+
+int32_t AudioDeviceUtilitySndio::Init()
+{
+
+    WEBRTC_TRACE(kTraceStateInfo, kTraceAudioDevice, _id,
+                 "  OS info: %s", "POSIX using sndio");
+
+    return 0;
+}
+
+
+}  // namespace webrtc
new file mode 100644
--- /dev/null
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/sndio/audio_device_utility_sndio.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_UTILITY_SNDIO_H
+#define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_UTILITY_SNDIO_H
+
+#include "webrtc/modules/audio_device/audio_device_utility.h"
+#include "webrtc/modules/audio_device/include/audio_device.h"
+
+namespace webrtc
+{
+class CriticalSectionWrapper;
+
+class AudioDeviceUtilitySndio: public AudioDeviceUtility
+{
+public:
+    AudioDeviceUtilitySndio(const int32_t id);
+    virtual ~AudioDeviceUtilitySndio();
+
+    virtual int32_t Init() OVERRIDE;
+
+private:
+    CriticalSectionWrapper& _critSect;
+    int32_t _id;
+};
+
+}  // namespace webrtc
+
+#endif
--- a/media/webrtc/trunk/webrtc/modules/audio_device/test/audio_device_test_api.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/test/audio_device_test_api.cc
@@ -174,16 +174,18 @@ class AudioDeviceAPITest: public testing
     //          user can select between default (Core) or Wave
     //      else
     //          user can select between default (Wave) or Wave
     const int32_t kId = 444;
 
 #if defined(_WIN32)
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kLinuxAlsaAudio)) == NULL);
+    EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
+                kId, AudioDeviceModule::kSndioAudio)) == NULL);
 #if defined(WEBRTC_WINDOWS_CORE_AUDIO_BUILD)
     TEST_LOG("WEBRTC_WINDOWS_CORE_AUDIO_BUILD is defined!\n\n");
     // create default implementation (=Core Audio) instance
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kPlatformDefaultAudio)) != NULL);
     audio_device_->AddRef();
     EXPECT_EQ(0, audio_device_->Release());
     // create non-default (=Wave Audio) instance
@@ -213,16 +215,18 @@ class AudioDeviceAPITest: public testing
     // Fails tests
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kWindowsWaveAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kWindowsCoreAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kLinuxAlsaAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
+                kId, AudioDeviceModule::kSndioAudio)) == NULL);
+    EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kLinuxPulseAudio)) == NULL);
     // Create default implementation instance
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kPlatformDefaultAudio)) != NULL);
 #elif defined(WEBRTC_LINUX) || defined(WEBRTC_BSD)
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kWindowsWaveAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
@@ -243,16 +247,18 @@ class AudioDeviceAPITest: public testing
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kWindowsWaveAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kWindowsCoreAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kLinuxAlsaAudio)) == NULL);
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kLinuxPulseAudio)) == NULL);
+    EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
+                kId, AudioDeviceModule::kSndioAudio)) == NULL);
     // Create default implementation instance
     EXPECT_TRUE((audio_device_ = AudioDeviceModuleImpl::Create(
                 kId, AudioDeviceModule::kPlatformDefaultAudio)) != NULL);
 #endif
 
     if (audio_device_ == NULL) {
       FAIL() << "Failed creating audio device object!";
     }
--- a/media/webrtc/trunk/webrtc/modules/audio_device/test/func_test_manager.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/test/func_test_manager.cc
@@ -731,16 +731,19 @@ int32_t FuncTestManager::TestAudioLayerS
     {
         TEST_LOG("\nActiveAudioLayer: kWindowsCoreAudio\n \n");
     } else if (audioLayer == AudioDeviceModule::kLinuxAlsaAudio)
     {
         TEST_LOG("\nActiveAudioLayer: kLinuxAlsaAudio\n \n");
     } else if (audioLayer == AudioDeviceModule::kLinuxPulseAudio)
     {
         TEST_LOG("\nActiveAudioLayer: kLinuxPulseAudio\n \n");
+    } else if (audioLayer == AudioDeviceModule::kSndioAudio)
+    {
+        TEST_LOG("\nActiveAudioLayer: kSndioAudio\n \n");
     } else
     {
         TEST_LOG("\nActiveAudioLayer: INVALID\n \n");
     }
 
     char ch;
     bool tryWinWave(false);
     bool tryWinCore(false);
--- a/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc
+++ b/media/webrtc/trunk/webrtc/voice_engine/voe_hardware_impl.cc
@@ -76,16 +76,19 @@ int VoEHardwareImpl::SetAudioDeviceLayer
             wantedLayer = AudioDeviceModule::kWindowsWaveAudio;
             break;
         case kAudioLinuxAlsa:
             wantedLayer = AudioDeviceModule::kLinuxAlsaAudio;
             break;
         case kAudioLinuxPulse:
             wantedLayer = AudioDeviceModule::kLinuxPulseAudio;
             break;
+        case kAudioSndio:
+            wantedLayer = AudioDeviceModule::kSndioAudio;
+            break;
     }
 
     // Save the audio device layer for Init()
     _shared->set_audio_device_layer(wantedLayer);
 
     return 0;
 }
 
@@ -128,16 +131,19 @@ int VoEHardwareImpl::GetAudioDeviceLayer
             audioLayer = kAudioWindowsWave;
             break;
         case AudioDeviceModule::kLinuxAlsaAudio:
             audioLayer = kAudioLinuxAlsa;
             break;
         case AudioDeviceModule::kLinuxPulseAudio:
             audioLayer = kAudioLinuxPulse;
             break;
+        case AudioDeviceModule::kSndioAudio:
+            audioLayer = kAudioSndio;
+            break;
         default:
             _shared->SetLastError(VE_UNDEFINED_SC_ERR, kTraceError,
                 "  unknown audio layer");
     }
 
     WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
         VoEId(_shared->instance_id(), -1),
         "  Output: audioLayer=%d", audioLayer);