Index: webrtc/modules/audio_device/win/audio_device_core_win.cc |
diff --git a/webrtc/modules/audio_device/win/audio_device_core_win.cc b/webrtc/modules/audio_device/win/audio_device_core_win.cc |
index b4bb8f9c24b440feb11d25ca134cd4d1169a8d1b..370bb599a0d2e852f0d7343b431c7f7c1bd89c2d 100644 |
--- a/webrtc/modules/audio_device/win/audio_device_core_win.cc |
+++ b/webrtc/modules/audio_device/win/audio_device_core_win.cc |
@@ -404,165 +404,167 @@ bool AudioDeviceWindowsCore::CoreAudioIsSupported() |
// AudioDeviceWindowsCore() - ctor |
// ---------------------------------------------------------------------------- |
-AudioDeviceWindowsCore::AudioDeviceWindowsCore(const int32_t id) : |
- _comInit(ScopedCOMInitializer::kMTA), |
- _id(id), |
- _ptrAudioBuffer(NULL), |
- _ptrEnumerator(NULL), |
- _ptrRenderCollection(NULL), |
- _ptrCaptureCollection(NULL), |
- _ptrDeviceOut(NULL), |
- _ptrDeviceIn(NULL), |
- _ptrClientOut(NULL), |
- _ptrClientIn(NULL), |
- _ptrRenderClient(NULL), |
- _ptrCaptureClient(NULL), |
- _ptrCaptureVolume(NULL), |
- _ptrRenderSimpleVolume(NULL), |
- _dmo(NULL), |
- _mediaBuffer(NULL), |
- _builtInAecEnabled(false), |
- _playAudioFrameSize(0), |
- _playSampleRate(0), |
- _playBlockSizePerChannel(0), |
- _playBlockSize(0), |
- _playChannels(2), |
- _sndCardPlayDelay(0), |
- _sndCardRecDelay(0), |
- _writtenSamples(0), |
- _readSamples(0), |
- _playAcc(0), |
- _recAudioFrameSize(0), |
- _recSampleRate(0), |
- _recBlockSize(0), |
- _recChannels(2), |
- _avrtLibrary(NULL), |
- _winSupportAvrt(false), |
- _hRenderSamplesReadyEvent(NULL), |
- _hPlayThread(NULL), |
- _hCaptureSamplesReadyEvent(NULL), |
- _hRecThread(NULL), |
- _hShutdownRenderEvent(NULL), |
- _hShutdownCaptureEvent(NULL), |
- _hRenderStartedEvent(NULL), |
- _hCaptureStartedEvent(NULL), |
- _hGetCaptureVolumeThread(NULL), |
- _hSetCaptureVolumeThread(NULL), |
- _hSetCaptureVolumeEvent(NULL), |
- _hMmTask(NULL), |
- _initialized(false), |
- _recording(false), |
- _playing(false), |
- _recIsInitialized(false), |
- _playIsInitialized(false), |
- _speakerIsInitialized(false), |
- _microphoneIsInitialized(false), |
- _AGC(false), |
- _playWarning(0), |
- _playError(0), |
- _recWarning(0), |
- _recError(0), |
- _playBufType(AudioDeviceModule::kAdaptiveBufferSize), |
- _playBufDelay(80), |
- _playBufDelayFixed(80), |
- _usingInputDeviceIndex(false), |
- _usingOutputDeviceIndex(false), |
- _inputDevice(AudioDeviceModule::kDefaultCommunicationDevice), |
- _outputDevice(AudioDeviceModule::kDefaultCommunicationDevice), |
- _inputDeviceIndex(0), |
- _outputDeviceIndex(0), |
- _newMicLevel(0) |
-{ |
- WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); |
- assert(_comInit.succeeded()); |
- |
- // Try to load the Avrt DLL |
- if (!_avrtLibrary) |
- { |
- // Get handle to the Avrt DLL module. |
- _avrtLibrary = LoadLibrary(TEXT("Avrt.dll")); |
- if (_avrtLibrary) |
- { |
- // Handle is valid (should only happen if OS larger than vista & win7). |
- // Try to get the function addresses. |
- WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() The Avrt DLL module is now loaded"); |
- |
- _PAvRevertMmThreadCharacteristics = (PAvRevertMmThreadCharacteristics)GetProcAddress(_avrtLibrary, "AvRevertMmThreadCharacteristics"); |
- _PAvSetMmThreadCharacteristicsA = (PAvSetMmThreadCharacteristicsA)GetProcAddress(_avrtLibrary, "AvSetMmThreadCharacteristicsA"); |
- _PAvSetMmThreadPriority = (PAvSetMmThreadPriority)GetProcAddress(_avrtLibrary, "AvSetMmThreadPriority"); |
- |
- if ( _PAvRevertMmThreadCharacteristics && |
- _PAvSetMmThreadCharacteristicsA && |
- _PAvSetMmThreadPriority) |
- { |
- WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() AvRevertMmThreadCharacteristics() is OK"); |
- WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() AvSetMmThreadCharacteristicsA() is OK"); |
- WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "AudioDeviceWindowsCore::AudioDeviceWindowsCore() AvSetMmThreadPriority() is OK"); |
- _winSupportAvrt = true; |
- } |
- } |
+AudioDeviceWindowsCore::AudioDeviceWindowsCore(const int32_t id) |
+ : _comInit(ScopedCOMInitializer::kMTA), |
+ _id(id), |
+ _ptrAudioBuffer(NULL), |
+ _ptrEnumerator(NULL), |
+ _ptrRenderCollection(NULL), |
+ _ptrCaptureCollection(NULL), |
+ _ptrDeviceOut(NULL), |
+ _ptrDeviceIn(NULL), |
+ _ptrClientOut(NULL), |
+ _ptrClientIn(NULL), |
+ _ptrRenderClient(NULL), |
+ _ptrCaptureClient(NULL), |
+ _ptrCaptureVolume(NULL), |
+ _ptrRenderSimpleVolume(NULL), |
+ _dmo(NULL), |
+ _mediaBuffer(NULL), |
+ _builtInAecEnabled(false), |
+ _playAudioFrameSize(0), |
+ _playSampleRate(0), |
+ _playBlockSizeInFrames(0), |
+ _playBlockSizeInSamples(0), |
+ _playChannels(2), |
+ _sndCardPlayDelay(0), |
+ _sndCardRecDelay(0), |
+ _writtenSamples(0), |
+ _readSamples(0), |
+ _playAcc(0), |
+ _recAudioFrameSize(0), |
+ _recSampleRate(0), |
+ _recBlockSize(0), |
+ _recChannels(2), |
+ _avrtLibrary(NULL), |
+ _winSupportAvrt(false), |
+ _hRenderSamplesReadyEvent(NULL), |
+ _hPlayThread(NULL), |
+ _hCaptureSamplesReadyEvent(NULL), |
+ _hRecThread(NULL), |
+ _hShutdownRenderEvent(NULL), |
+ _hShutdownCaptureEvent(NULL), |
+ _hRenderStartedEvent(NULL), |
+ _hCaptureStartedEvent(NULL), |
+ _hGetCaptureVolumeThread(NULL), |
+ _hSetCaptureVolumeThread(NULL), |
+ _hSetCaptureVolumeEvent(NULL), |
+ _hMmTask(NULL), |
+ _initialized(false), |
+ _recording(false), |
+ _playing(false), |
+ _recIsInitialized(false), |
+ _playIsInitialized(false), |
+ _speakerIsInitialized(false), |
+ _microphoneIsInitialized(false), |
+ _AGC(false), |
+ _playWarning(0), |
+ _playError(0), |
+ _recWarning(0), |
+ _recError(0), |
+ _playBufType(AudioDeviceModule::kAdaptiveBufferSize), |
+ _playBufDelay(80), |
+ _playBufDelayFixed(80), |
+ _usingInputDeviceIndex(false), |
+ _usingOutputDeviceIndex(false), |
+ _inputDevice(AudioDeviceModule::kDefaultCommunicationDevice), |
+ _outputDevice(AudioDeviceModule::kDefaultCommunicationDevice), |
+ _inputDeviceIndex(0), |
+ _outputDeviceIndex(0), |
+ _newMicLevel(0) { |
+ WEBRTC_TRACE(kTraceMemory, kTraceAudioDevice, id, "%s created", __FUNCTION__); |
+ assert(_comInit.succeeded()); |
+ |
+ // Try to load the Avrt DLL |
+ if (!_avrtLibrary) { |
+ // Get handle to the Avrt DLL module. |
+ _avrtLibrary = LoadLibrary(TEXT("Avrt.dll")); |
+ if (_avrtLibrary) { |
+ // Handle is valid (should only happen if OS larger than vista & win7). |
+ // Try to get the function addresses. |
+ WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
+ "AudioDeviceWindowsCore::AudioDeviceWindowsCore() The Avrt " |
+ "DLL module is now loaded"); |
+ |
+ _PAvRevertMmThreadCharacteristics = |
+ (PAvRevertMmThreadCharacteristics)GetProcAddress( |
+ _avrtLibrary, "AvRevertMmThreadCharacteristics"); |
+ _PAvSetMmThreadCharacteristicsA = |
+ (PAvSetMmThreadCharacteristicsA)GetProcAddress( |
+ _avrtLibrary, "AvSetMmThreadCharacteristicsA"); |
+ _PAvSetMmThreadPriority = (PAvSetMmThreadPriority)GetProcAddress( |
+ _avrtLibrary, "AvSetMmThreadPriority"); |
+ |
+ if (_PAvRevertMmThreadCharacteristics && |
+ _PAvSetMmThreadCharacteristicsA && _PAvSetMmThreadPriority) { |
+ WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
+ "AudioDeviceWindowsCore::AudioDeviceWindowsCore() " |
+ "AvRevertMmThreadCharacteristics() is OK"); |
+ WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
+ "AudioDeviceWindowsCore::AudioDeviceWindowsCore() " |
+ "AvSetMmThreadCharacteristicsA() is OK"); |
+ WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
+ "AudioDeviceWindowsCore::AudioDeviceWindowsCore() " |
+ "AvSetMmThreadPriority() is OK"); |
+ _winSupportAvrt = true; |
+ } |
} |
+ } |
- // Create our samples ready events - we want auto reset events that start in the not-signaled state. |
- // The state of an auto-reset event object remains signaled until a single waiting thread is released, |
- // at which time the system automatically sets the state to nonsignaled. If no threads are waiting, |
- // the event object's state remains signaled. |
- // (Except for _hShutdownCaptureEvent, which is used to shutdown multiple threads). |
- _hRenderSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
- _hCaptureSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
- _hShutdownRenderEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
- _hShutdownCaptureEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
- _hRenderStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
- _hCaptureStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
- _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
- |
- _perfCounterFreq.QuadPart = 1; |
- _perfCounterFactor = 0.0; |
- _avgCPULoad = 0.0; |
- |
- // list of number of channels to use on recording side |
- _recChannelsPrioList[0] = 2; // stereo is prio 1 |
- _recChannelsPrioList[1] = 1; // mono is prio 2 |
- _recChannelsPrioList[2] = 4; // quad is prio 3 |
- |
- // list of number of channels to use on playout side |
- _playChannelsPrioList[0] = 2; // stereo is prio 1 |
- _playChannelsPrioList[1] = 1; // mono is prio 2 |
- |
- HRESULT hr; |
- |
- // We know that this API will work since it has already been verified in |
- // CoreAudioIsSupported, hence no need to check for errors here as well. |
- |
- // Retrive the IMMDeviceEnumerator API (should load the MMDevAPI.dll) |
- // TODO(henrika): we should probably move this allocation to Init() instead |
- // and deallocate in Terminate() to make the implementation more symmetric. |
- CoCreateInstance( |
- __uuidof(MMDeviceEnumerator), |
- NULL, |
- CLSCTX_ALL, |
- __uuidof(IMMDeviceEnumerator), |
- reinterpret_cast<void**>(&_ptrEnumerator)); |
- assert(NULL != _ptrEnumerator); |
- |
- // DMO initialization for built-in WASAPI AEC. |
- { |
- IMediaObject* ptrDMO = NULL; |
- hr = CoCreateInstance(CLSID_CWMAudioAEC, |
- NULL, |
- CLSCTX_INPROC_SERVER, |
- IID_IMediaObject, |
- reinterpret_cast<void**>(&ptrDMO)); |
- if (FAILED(hr) || ptrDMO == NULL) |
- { |
- // Since we check that _dmo is non-NULL in EnableBuiltInAEC(), the |
- // feature is prevented from being enabled. |
- _builtInAecEnabled = false; |
- _TraceCOMError(hr); |
- } |
- _dmo = ptrDMO; |
- SAFE_RELEASE(ptrDMO); |
- } |
+ // Create our samples ready events - we want auto reset events that start in |
+ // the not-signaled state. The state of an auto-reset event object remains |
+ // signaled until a single waiting thread is released, at which time the |
+ // system automatically sets the state to nonsignaled. If no threads are |
+ // waiting, the event object's state remains signaled. (Except for |
+ // _hShutdownCaptureEvent, which is used to shutdown multiple threads). |
+ _hRenderSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ _hCaptureSamplesReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ _hShutdownRenderEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ _hShutdownCaptureEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
+ _hRenderStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ _hCaptureStartedEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ _hSetCaptureVolumeEvent = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ |
+ _perfCounterFreq.QuadPart = 1; |
+ _perfCounterFactor = 0.0; |
+ _avgCPULoad = 0.0; |
+ |
+ // list of number of channels to use on recording side |
+ _recChannelsPrioList[0] = 2; // stereo is prio 1 |
+ _recChannelsPrioList[1] = 1; // mono is prio 2 |
+ _recChannelsPrioList[2] = 4; // quad is prio 3 |
+ |
+ // list of number of channels to use on playout side |
+ _playChannelsPrioList[0] = 2; // stereo is prio 1 |
+ _playChannelsPrioList[1] = 1; // mono is prio 2 |
+ |
+ HRESULT hr; |
+ |
+ // We know that this API will work since it has already been verified in |
+ // CoreAudioIsSupported, hence no need to check for errors here as well. |
+ |
+ // Retrive the IMMDeviceEnumerator API (should load the MMDevAPI.dll) |
+ // TODO(henrika): we should probably move this allocation to Init() instead |
+ // and deallocate in Terminate() to make the implementation more symmetric. |
+ CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, |
+ __uuidof(IMMDeviceEnumerator), |
+ reinterpret_cast<void**>(&_ptrEnumerator)); |
+ assert(NULL != _ptrEnumerator); |
+ |
+ // DMO initialization for built-in WASAPI AEC. |
+ { |
+ IMediaObject* ptrDMO = NULL; |
+ hr = CoCreateInstance(CLSID_CWMAudioAEC, NULL, CLSCTX_INPROC_SERVER, |
+ IID_IMediaObject, reinterpret_cast<void**>(&ptrDMO)); |
+ if (FAILED(hr) || ptrDMO == NULL) { |
+ // Since we check that _dmo is non-NULL in EnableBuiltInAEC(), the |
+ // feature is prevented from being enabled. |
+ _builtInAecEnabled = false; |
+ _TraceCOMError(hr); |
+ } |
+ _dmo = ptrDMO; |
+ SAFE_RELEASE(ptrDMO); |
+ } |
} |
// ---------------------------------------------------------------------------- |
@@ -2283,8 +2285,11 @@ int32_t AudioDeviceWindowsCore::InitPlayout() |
if (hr == S_OK) |
{ |
_playAudioFrameSize = Wfx.nBlockAlign; |
- _playBlockSizePerChannel = Wfx.nSamplesPerSec/100; |
- _playBlockSize = _playBlockSizePerChannel*Wfx.nChannels; |
+ // Block size in frames is the number of samples each channel in 10ms. |
+ _playBlockSizeInFrames = Wfx.nSamplesPerSec / 100; |
+ // Block size in samples is block size in frames times number of |
+ // channels. |
+ _playBlockSizeInSamples = _playBlockSizeInFrames * Wfx.nChannels; |
_playSampleRate = Wfx.nSamplesPerSec; |
_devicePlaySampleRate = Wfx.nSamplesPerSec; // The device itself continues to run at 44.1 kHz. |
_devicePlayBlockSize = Wfx.nSamplesPerSec/100; |
@@ -2300,7 +2305,8 @@ int32_t AudioDeviceWindowsCore::InitPlayout() |
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "cbSize : %d", Wfx.cbSize); |
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "Additional settings:"); |
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playAudioFrameSize: %d", _playAudioFrameSize); |
- WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playBlockSize : %d", _playBlockSize); |
+ WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
+ "_playBlockSizeInFrames : %d", _playBlockSizeInFrames); |
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "_playChannels : %d", _playChannels); |
} |
@@ -3463,8 +3469,8 @@ DWORD AudioDeviceWindowsCore::DoRenderThread() |
// Derive initial rendering delay. |
// Example: 10*(960/480) + 15 = 20 + 15 = 35ms |
// |
- int playout_delay = 10 * (bufferLength / _playBlockSize) + |
- (int)((latency + devPeriod) / 10000); |
+ int playout_delay = 10 * (bufferLength / _playBlockSizeInFrames) + |
+ (int)((latency + devPeriod) / 10000); |
_sndCardPlayDelay = playout_delay; |
_writtenSamples = 0; |
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, |
@@ -3545,38 +3551,38 @@ DWORD AudioDeviceWindowsCore::DoRenderThread() |
// WEBRTC_TRACE(kTraceStream, kTraceAudioDevice, _id, "#avaliable audio frames = %u", framesAvailable); |
// Do we have 10 ms available in the render buffer? |
- if (framesAvailable < _playBlockSize) |
- { |
- // Not enough space in render buffer to store next render packet. |
- _UnLock(); |
- break; |
+ if (framesAvailable < _playBlockSizeInFrames) { |
+ // Not enough space in render buffer to store next render packet. |
+ _UnLock(); |
+ break; |
} |
// Write n*10ms buffers to the render buffer |
- const uint32_t n10msBuffers = (framesAvailable / _playBlockSize); |
+ const uint32_t n10msBuffers = |
+ (framesAvailable / _playBlockSizeInFrames); |
for (uint32_t n = 0; n < n10msBuffers; n++) |
{ |
// Get pointer (i.e., grab the buffer) to next space in the shared render buffer. |
- hr = _ptrRenderClient->GetBuffer(_playBlockSize, &pData); |
+ hr = |
+ _ptrRenderClient->GetBuffer(_playBlockSizeInFrames, &pData); |
EXIT_ON_ERROR(hr); |
QueryPerformanceCounter(&t1); // measure time: START |
if (_ptrAudioBuffer) |
{ |
- // Request data to be played out (#bytes = _playBlockSize*_audioFrameSize) |
+ // Request data to be played out (#bytes = |
+ // _playBlockSizeInFrames*_audioFrameSize) |
+ _UnLock(); |
+ int32_t nSamples = _ptrAudioBuffer->RequestPlayoutData( |
+ _playBlockSizeInFrames); |
+ _Lock(); |
+ |
+ if (nSamples == -1) { |
_UnLock(); |
- int32_t nSamples = |
- _ptrAudioBuffer->RequestPlayoutData( |
- _playBlockSizePerChannel); |
- _Lock(); |
- |
- if (nSamples == -1) |
- { |
- _UnLock(); |
- WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, |
- "failed to read data from render client"); |
- goto Exit; |
+ WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, |
+ "failed to read data from render client"); |
+ goto Exit; |
} |
// Sanity check to ensure that essential states are not modified during the unlocked period |
@@ -3586,9 +3592,12 @@ DWORD AudioDeviceWindowsCore::DoRenderThread() |
WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id, "output state has been modified during unlocked period"); |
goto Exit; |
} |
- if (nSamples != static_cast<int32_t>(_playBlockSize)) |
- { |
- WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id, "nSamples(%d) != _playBlockSize(%d)", nSamples, _playBlockSize); |
+ if (nSamples != |
+ static_cast<int32_t>(_playBlockSizeInSamples)) { |
+ WEBRTC_TRACE( |
+ kTraceWarning, kTraceAudioDevice, _id, |
+ "nSamples(%d) != _playBlockSizeInSamples(%d)", |
+ nSamples, _playBlockSizeInSamples); |
} |
// Get the actual (stored) data |
@@ -3600,12 +3609,13 @@ DWORD AudioDeviceWindowsCore::DoRenderThread() |
_playAcc += time; |
DWORD dwFlags(0); |
- hr = _ptrRenderClient->ReleaseBuffer(_playBlockSize, dwFlags); |
+ hr = _ptrRenderClient->ReleaseBuffer(_playBlockSizeInFrames, |
+ dwFlags); |
// See http://msdn.microsoft.com/en-us/library/dd316605(VS.85).aspx |
// for more details regarding AUDCLNT_E_DEVICE_INVALIDATED. |
EXIT_ON_ERROR(hr); |
- _writtenSamples += _playBlockSize; |
+ _writtenSamples += _playBlockSizeInFrames; |
} |
// Check the current delay on the playout side. |