This CL makes the playout delay value thread safe.

With the patch, _sndCardPlayDelay is calculated in the DoRenderThread instead of capture thread, an capture thread only gets the _sndCardPlayDelay value.
And _sndCardPlayDelay and _sndCardRecDelay are only changed to be Atomic32 to make them to be accessed by multiple threads.


Test=None
Bug=256
Review URL: https://webrtc-codereview.appspot.com/394001

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1653 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
xians@webrtc.org 2012-02-09 13:50:48 +00:00
parent 9c84b0dc9f
commit 3dbed8597e
2 changed files with 63 additions and 44 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@ -2991,7 +2991,10 @@ WebRtc_Word32 AudioDeviceWindowsCore::StopRecording()
_UnLock(); _UnLock();
return err; // Reset the recording delay value.
_sndCardRecDelay = 0;
return err;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -3166,6 +3169,9 @@ WebRtc_Word32 AudioDeviceWindowsCore::StopPlayout()
} }
} // critScoped } // critScoped
// Reset the playout delay value.
_sndCardPlayDelay = 0;
return 0; return 0;
} }
@ -3175,8 +3181,7 @@ WebRtc_Word32 AudioDeviceWindowsCore::StopPlayout()
WebRtc_Word32 AudioDeviceWindowsCore::PlayoutDelay(WebRtc_UWord16& delayMS) const WebRtc_Word32 AudioDeviceWindowsCore::PlayoutDelay(WebRtc_UWord16& delayMS) const
{ {
CriticalSectionScoped lock(_critSect); delayMS = static_cast<WebRtc_UWord16>(_sndCardPlayDelay.Value());
delayMS = (WebRtc_UWord16)_sndCardPlayDelay;
return 0; return 0;
} }
@ -3186,8 +3191,7 @@ WebRtc_Word32 AudioDeviceWindowsCore::PlayoutDelay(WebRtc_UWord16& delayMS) cons
WebRtc_Word32 AudioDeviceWindowsCore::RecordingDelay(WebRtc_UWord16& delayMS) const WebRtc_Word32 AudioDeviceWindowsCore::RecordingDelay(WebRtc_UWord16& delayMS) const
{ {
CriticalSectionScoped lock(_critSect); delayMS = static_cast<WebRtc_UWord16>(_sndCardRecDelay.Value());
delayMS = (WebRtc_UWord16)_sndCardRecDelay;
return 0; return 0;
} }
@ -3226,19 +3230,21 @@ WebRtc_Word32 AudioDeviceWindowsCore::SetPlayoutBuffer(const AudioDeviceModule::
WebRtc_Word32 AudioDeviceWindowsCore::PlayoutBuffer(AudioDeviceModule::BufferType& type, WebRtc_UWord16& sizeMS) const WebRtc_Word32 AudioDeviceWindowsCore::PlayoutBuffer(AudioDeviceModule::BufferType& type, WebRtc_UWord16& sizeMS) const
{ {
{
CriticalSectionScoped lock(_critSect); CriticalSectionScoped lock(_critSect);
type = _playBufType; type = _playBufType;
}
if (type == AudioDeviceModule::kFixedBufferSize) if (type == AudioDeviceModule::kFixedBufferSize)
{ {
sizeMS = _playBufDelayFixed; CriticalSectionScoped lock(_critSect);
} sizeMS = _playBufDelayFixed;
else }
{ else
// Use same value as for PlayoutDelay {
sizeMS = (WebRtc_UWord16)_sndCardPlayDelay; // Use same value as for PlayoutDelay
} sizeMS = static_cast<WebRtc_UWord16>(_sndCardPlayDelay.Value());
}
return 0; return 0;
} }
@ -3527,9 +3533,12 @@ DWORD AudioDeviceWindowsCore::DoRenderThread()
// Derive inital rendering delay. // Derive inital rendering delay.
// Example: 10*(960/480) + 15 = 20 + 15 = 35ms // Example: 10*(960/480) + 15 = 20 + 15 = 35ms
// //
_sndCardPlayDelay = 10 * (bufferLength / _playBlockSize) + (int)((latency + devPeriod) / 10000); int playout_delay = 10 * (bufferLength / _playBlockSize) +
(int)((latency + devPeriod) / 10000);
_sndCardPlayDelay = playout_delay;
_writtenSamples = 0; _writtenSamples = 0;
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] initial delay : %u", _sndCardPlayDelay); WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id,
"[REND] initial delay : %u", playout_delay);
double endpointBufferSizeMS = 10.0 * ((double)bufferLength / (double)_devicePlayBlockSize); double endpointBufferSizeMS = 10.0 * ((double)bufferLength / (double)_devicePlayBlockSize);
WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] endpointBufferSizeMS : %3.2f", endpointBufferSizeMS); WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, "[REND] endpointBufferSizeMS : %3.2f", endpointBufferSizeMS);
@ -3545,8 +3554,14 @@ DWORD AudioDeviceWindowsCore::DoRenderThread()
_writtenSamples += bufferLength; _writtenSamples += bufferLength;
IAudioClock* clock = NULL;
hr = _ptrClientOut->GetService(__uuidof(IAudioClock), (void**)&clock);
if (FAILED(hr)) {
WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
"failed to get IAudioClock interface from the IAudioClient");
}
// Start up the rendering audio stream. // Start up the rendering audio stream.
//
hr = _ptrClientOut->Start(); hr = _ptrClientOut->Start();
EXIT_ON_ERROR(hr); EXIT_ON_ERROR(hr);
@ -3655,6 +3670,17 @@ DWORD AudioDeviceWindowsCore::DoRenderThread()
_writtenSamples += _playBlockSize; _writtenSamples += _playBlockSize;
} }
// Check the current delay on the playout side.
if (clock) {
UINT64 pos = 0;
UINT64 freq = 1;
clock->GetPosition(&pos, NULL);
clock->GetFrequency(&freq);
playout_delay = ROUND((double(_writtenSamples) /
_devicePlaySampleRate - double(pos) / freq) * 1000.0);
_sndCardPlayDelay = playout_delay;
}
_UnLock(); _UnLock();
} }
} }
@ -3665,6 +3691,8 @@ DWORD AudioDeviceWindowsCore::DoRenderThread()
hr = _ptrClientOut->Stop(); hr = _ptrClientOut->Stop();
Exit: Exit:
SAFE_RELEASE(clock);
if (FAILED(hr)) if (FAILED(hr))
{ {
_UnLock(); _UnLock();
@ -4070,28 +4098,15 @@ DWORD AudioDeviceWindowsCore::DoCaptureThread()
QueryPerformanceCounter(&t1); QueryPerformanceCounter(&t1);
// Check the current delay on the recording side // Get the current recording and playout delay.
// WebRtc_UWord32 sndCardRecDelay = (WebRtc_UWord32)
_sndCardRecDelay = (WebRtc_UWord32)((((UINT64)t1.QuadPart * _perfCounterFactor) - recTime) / 10000) + (10*syncBufIndex) / _recBlockSize - 10; (((((UINT64)t1.QuadPart * _perfCounterFactor) - recTime)
/ 10000) + (10*syncBufIndex) / _recBlockSize - 10);
WebRtc_UWord32 sndCardPlayDelay =
static_cast<WebRtc_UWord32>(_sndCardPlayDelay.Value());
// Check the current delay on the playout side _sndCardRecDelay = sndCardRecDelay;
//
if (_ptrClientOut)
{
IAudioClock* clock = NULL;
UINT64 pos = 0;
UINT64 freq = 1;
hr = _ptrClientOut->GetService(__uuidof(IAudioClock), (void**)&clock);
EXIT_ON_ERROR(hr);
clock->GetPosition(&pos, NULL);
clock->GetFrequency(&freq);
_sndCardPlayDelay = ROUND((double(_writtenSamples) / _devicePlaySampleRate - double(pos) / freq) * 1000.0);
SAFE_RELEASE(clock);
}
// Send the captured data to the registered consumer
//
WebRtc_UWord32 sndCardRecDelay = _sndCardRecDelay; // avoid modifying the "correct" delay
while (syncBufIndex >= _recBlockSize) while (syncBufIndex >= _recBlockSize)
{ {
if (_ptrAudioBuffer) if (_ptrAudioBuffer)
@ -4099,10 +4114,13 @@ DWORD AudioDeviceWindowsCore::DoCaptureThread()
_ptrAudioBuffer->SetRecordedBuffer((const WebRtc_Word8*)syncBuffer, _recBlockSize); _ptrAudioBuffer->SetRecordedBuffer((const WebRtc_Word8*)syncBuffer, _recBlockSize);
_driftAccumulator += _sampleDriftAt48kHz; _driftAccumulator += _sampleDriftAt48kHz;
const WebRtc_Word32 clockDrift = static_cast<WebRtc_Word32>(_driftAccumulator); const WebRtc_Word32 clockDrift =
static_cast<WebRtc_Word32>(_driftAccumulator);
_driftAccumulator -= clockDrift; _driftAccumulator -= clockDrift;
_ptrAudioBuffer->SetVQEData(_sndCardPlayDelay, sndCardRecDelay, clockDrift); _ptrAudioBuffer->SetVQEData(sndCardPlayDelay,
sndCardRecDelay,
clockDrift);
QueryPerformanceCounter(&t1); // measure time: START QueryPerformanceCounter(&t1); // measure time: START

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@ -25,6 +25,7 @@
#include <mediaobj.h> // IMediaObject #include <mediaobj.h> // IMediaObject
#include <Mmdeviceapi.h> // MMDevice #include <Mmdeviceapi.h> // MMDevice
#include "atomic32_wrapper.h"
#include "critical_section_wrapper.h" #include "critical_section_wrapper.h"
#include "scoped_refptr.h" #include "scoped_refptr.h"
@ -319,7 +320,7 @@ private: // WASAPI
WebRtc_UWord32 _playBlockSize; WebRtc_UWord32 _playBlockSize;
WebRtc_UWord32 _devicePlayBlockSize; WebRtc_UWord32 _devicePlayBlockSize;
WebRtc_UWord32 _playChannels; WebRtc_UWord32 _playChannels;
WebRtc_UWord32 _sndCardPlayDelay; Atomic32Wrapper _sndCardPlayDelay;
UINT64 _writtenSamples; UINT64 _writtenSamples;
LONGLONG _playAcc; LONGLONG _playAcc;
@ -328,7 +329,7 @@ private: // WASAPI
WebRtc_UWord32 _recBlockSize; WebRtc_UWord32 _recBlockSize;
WebRtc_UWord32 _recChannels; WebRtc_UWord32 _recChannels;
UINT64 _readSamples; UINT64 _readSamples;
WebRtc_UWord32 _sndCardRecDelay; Atomic32Wrapper _sndCardRecDelay;
float _sampleDriftAt48kHz; float _sampleDriftAt48kHz;
float _driftAccumulator; float _driftAccumulator;