summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhenrika@webrtc.org <henrika@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2014-03-18 10:32:33 +0000
committerhenrika@webrtc.org <henrika@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d>2014-03-18 10:32:33 +0000
commitdf08c5d53f4b11b7687e419e04f99f55b85490c4 (patch)
tree87f072a20c2f8841e6d35936185ddd473effe4ca
parent0c0c604cc69b862daffd3f825c335cdc39e0a223 (diff)
downloadwebrtc-df08c5d53f4b11b7687e419e04f99f55b85490c4.tar.gz
Resolves TSan v2 warnings in voe_auto_test.
See bug report for details. BUG=1590 R=tommi@webrtc.org, xians@webrtc.org Review URL: https://webrtc-codereview.appspot.com/9859004 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@5714 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r--voice_engine/channel.cc176
-rw-r--r--voice_engine/channel.h110
-rw-r--r--voice_engine/dtmf_inband_queue.cc8
-rw-r--r--voice_engine/output_mixer.cc23
-rw-r--r--voice_engine/transmit_mixer.cc21
-rw-r--r--voice_engine/voice_engine_impl.cc6
6 files changed, 206 insertions, 138 deletions
diff --git a/voice_engine/channel.cc b/voice_engine/channel.cc
index ff064d9d..e14ee78d 100644
--- a/voice_engine/channel.cc
+++ b/voice_engine/channel.cc
@@ -410,7 +410,7 @@ Channel::OnPacketTimeout(int32_t id)
CriticalSectionScoped cs(_callbackCritSectPtr);
if (_voiceEngineObserverPtr)
{
- if (_receiving || _externalTransport)
+ if (channel_state_.Get().receiving || _externalTransport)
{
int32_t channel = VoEChannelId(id);
assert(channel == _channelId);
@@ -488,7 +488,7 @@ Channel::OnPeriodicDeadOrAlive(int32_t id,
// It is possible that the connection is alive even if no RTP packet has
// been received for a long time since the other side might use VAD/DTX
// and a low SID-packet update rate.
- if ((kRtpNoRtp == alive) && _playing)
+ if ((kRtpNoRtp == alive) && channel_state_.Get().playing)
{
// Detect Alive for all NetEQ states except for the case when we are
// in PLC_CNG state.
@@ -527,7 +527,7 @@ Channel::OnReceivedPayloadData(const uint8_t* payloadData,
_lastRemoteTimeStamp = rtpHeader->header.timestamp;
- if (!_playing)
+ if (!channel_state_.Get().playing)
{
// Avoid inserting into NetEQ when we are not playing. Count the
// packet as discarded.
@@ -612,7 +612,9 @@ int32_t Channel::GetAudioFrame(int32_t id, AudioFrame& audioFrame)
// Store speech type for dead-or-alive detection
_outputSpeechType = audioFrame.speech_type_;
- if (_rxApmIsEnabled) {
+ ChannelState::State state = channel_state_.Get();
+
+ if (state.rx_apm_is_enabled) {
int err = rx_audioproc_->ProcessStream(&audioFrame);
if (err) {
LOG(LS_ERROR) << "ProcessStream() error: " << err;
@@ -656,13 +658,13 @@ int32_t Channel::GetAudioFrame(int32_t id, AudioFrame& audioFrame)
}
// Mix decoded PCM output with file if file mixing is enabled
- if (_outputFilePlaying)
+ if (state.output_file_playing)
{
MixAudioWithFile(audioFrame, audioFrame.sample_rate_hz_);
}
// Place channel in on-hold state (~muted) if on-hold is activated
- if (_outputIsOnHold)
+ if (state.output_is_on_hold)
{
AudioFrameOperations::Mute(audioFrame);
}
@@ -725,10 +727,10 @@ Channel::NeededFrequency(int32_t id)
// we take that frequency into consideration as well
// This is not needed on sending side, since the codec will
// limit the spectrum anyway.
- if (_outputFilePlaying)
+ if (channel_state_.Get().output_file_playing)
{
CriticalSectionScoped cs(&_fileCritSect);
- if (_outputFilePlayerPtr && _outputFilePlaying)
+ if (_outputFilePlayerPtr)
{
if(_outputFilePlayerPtr->Frequency()>highestNeeded)
{
@@ -790,9 +792,7 @@ Channel::PlayFileEnded(int32_t id)
if (id == _inputFilePlayerId)
{
- CriticalSectionScoped cs(&_fileCritSect);
-
- _inputFilePlaying = false;
+ channel_state_.SetInputFilePlaying(false);
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId,_channelId),
"Channel::PlayFileEnded() => input file player module is"
@@ -800,9 +800,7 @@ Channel::PlayFileEnded(int32_t id)
}
else if (id == _outputFilePlayerId)
{
- CriticalSectionScoped cs(&_fileCritSect);
-
- _outputFilePlaying = false;
+ channel_state_.SetOutputFilePlaying(false);
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
VoEId(_instanceId,_channelId),
"Channel::PlayFileEnded() => output file player module is"
@@ -860,12 +858,9 @@ Channel::Channel(int32_t channelId,
_inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
_outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
_outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
- _inputFilePlaying(false),
- _outputFilePlaying(false),
_outputFileRecording(false),
_inbandDtmfQueue(VoEModuleId(instanceId, channelId)),
_inbandDtmfGenerator(VoEModuleId(instanceId, channelId)),
- _inputExternalMedia(false),
_outputExternalMedia(false),
_inputExternalMediaCallbackPtr(NULL),
_outputExternalMediaCallbackPtr(NULL),
@@ -891,13 +886,9 @@ Channel::Channel(int32_t channelId,
_sendFrameType(0),
_rtpObserverPtr(NULL),
_rtcpObserverPtr(NULL),
- _outputIsOnHold(false),
_externalPlayout(false),
_externalMixing(false),
_inputIsOnHold(false),
- _playing(false),
- _sending(false),
- _receiving(false),
_mixFileWithMicrophone(false),
_rtpObserver(false),
_rtcpObserver(false),
@@ -924,7 +915,6 @@ Channel::Channel(int32_t channelId,
_previousTimestamp(0),
_recPacketDelayMs(20),
_RxVadDetection(false),
- _rxApmIsEnabled(false),
_rxAgcIsEnabled(false),
_rxNsIsEnabled(false),
restored_packet_in_use_(false)
@@ -960,7 +950,7 @@ Channel::~Channel()
{
DeRegisterExternalMediaProcessing(kPlaybackPerChannel);
}
- if (_inputExternalMedia)
+ if (channel_state_.Get().input_external_media)
{
DeRegisterExternalMediaProcessing(kRecordingPerChannel);
}
@@ -1033,6 +1023,8 @@ Channel::Init()
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::Init()");
+ channel_state_.Reset();
+
// --- Initial sanity
if ((_engineStatisticsPtr == NULL) ||
@@ -1231,7 +1223,7 @@ Channel::StartPlayout()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StartPlayout()");
- if (_playing)
+ if (channel_state_.Get().playing)
{
return 0;
}
@@ -1247,8 +1239,7 @@ Channel::StartPlayout()
}
}
- _playing = true;
-
+ channel_state_.SetPlaying(true);
if (RegisterFilePlayingToMixer() != 0)
return -1;
@@ -1260,7 +1251,7 @@ Channel::StopPlayout()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StopPlayout()");
- if (!_playing)
+ if (!channel_state_.Get().playing)
{
return 0;
}
@@ -1276,7 +1267,7 @@ Channel::StopPlayout()
}
}
- _playing = false;
+ channel_state_.SetPlaying(false);
_outputAudioLevel.Clear();
return 0;
@@ -1288,21 +1279,15 @@ Channel::StartSend()
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StartSend()");
// Resume the previous sequence number which was reset by StopSend().
- // This needs to be done before |_sending| is set to true.
+ // This needs to be done before |sending| is set to true.
if (send_sequence_number_)
SetInitSequenceNumber(send_sequence_number_);
+ if (channel_state_.Get().sending)
{
- // A lock is needed because |_sending| can be accessed or modified by
- // another thread at the same time.
- CriticalSectionScoped cs(&_callbackCritSect);
-
- if (_sending)
- {
- return 0;
- }
- _sending = true;
+ return 0;
}
+ channel_state_.SetSending(true);
if (_rtpRtcpModule->SetSendingStatus(true) != 0)
{
@@ -1310,7 +1295,7 @@ Channel::StartSend()
VE_RTP_RTCP_MODULE_ERROR, kTraceError,
"StartSend() RTP/RTCP failed to start sending");
CriticalSectionScoped cs(&_callbackCritSect);
- _sending = false;
+ channel_state_.SetSending(false);
return -1;
}
@@ -1322,17 +1307,11 @@ Channel::StopSend()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StopSend()");
+ if (!channel_state_.Get().sending)
{
- // A lock is needed because |_sending| can be accessed or modified by
- // another thread at the same time.
- CriticalSectionScoped cs(&_callbackCritSect);
-
- if (!_sending)
- {
- return 0;
- }
- _sending = false;
+ return 0;
}
+ channel_state_.SetSending(false);
// Store the sequence number to be able to pick up the same sequence for
// the next StartSend(). This is needed for restarting device, otherwise
@@ -1360,11 +1339,11 @@ Channel::StartReceiving()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StartReceiving()");
- if (_receiving)
+ if (channel_state_.Get().receiving)
{
return 0;
}
- _receiving = true;
+ channel_state_.SetReceiving(true);
_numberOfDiscardedPackets = 0;
return 0;
}
@@ -1374,7 +1353,7 @@ Channel::StopReceiving()
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StopReceiving()");
- if (!_receiving)
+ if (!channel_state_.Get().receiving)
{
return 0;
}
@@ -1382,7 +1361,7 @@ Channel::StopReceiving()
// Recover DTMF detection status.
telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
RegisterReceiveCodecsToRTPModule();
- _receiving = false;
+ channel_state_.SetReceiving(false);
return 0;
}
@@ -1448,12 +1427,12 @@ Channel::SetOnHoldStatus(bool enable, OnHoldModes mode)
"Channel::SetOnHoldStatus()");
if (mode == kHoldSendAndPlay)
{
- _outputIsOnHold = enable;
+ channel_state_.SetOutputIsOnHold(enable);
_inputIsOnHold = enable;
}
else if (mode == kHoldPlayOnly)
{
- _outputIsOnHold = enable;
+ channel_state_.SetOutputIsOnHold(enable);
}
if (mode == kHoldSendOnly)
{
@@ -1467,16 +1446,17 @@ Channel::GetOnHoldStatus(bool& enabled, OnHoldModes& mode)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::GetOnHoldStatus()");
- enabled = (_outputIsOnHold || _inputIsOnHold);
- if (_outputIsOnHold && _inputIsOnHold)
+ bool output_is_on_hold = channel_state_.Get().output_is_on_hold;
+ enabled = (output_is_on_hold || _inputIsOnHold);
+ if (output_is_on_hold && _inputIsOnHold)
{
mode = kHoldSendAndPlay;
}
- else if (_outputIsOnHold && !_inputIsOnHold)
+ else if (output_is_on_hold && !_inputIsOnHold)
{
mode = kHoldPlayOnly;
}
- else if (!_outputIsOnHold && _inputIsOnHold)
+ else if (!output_is_on_hold && _inputIsOnHold)
{
mode = kHoldSendOnly;
}
@@ -1609,14 +1589,14 @@ Channel::SetRecPayloadType(const CodecInst& codec)
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::SetRecPayloadType()");
- if (_playing)
+ if (channel_state_.Get().playing)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceError,
"SetRecPayloadType() unable to set PT while playing");
return -1;
}
- if (_receiving)
+ if (channel_state_.Get().receiving)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_LISTENING, kTraceError,
@@ -1921,7 +1901,7 @@ Channel::SetISACMaxRate(int rateBps)
return -1;
}
}
- if (_sending)
+ if (channel_state_.Get().sending)
{
_engineStatisticsPtr->SetLastError(
VE_SENDING, kTraceError,
@@ -1984,7 +1964,7 @@ Channel::SetISACMaxPayloadSize(int sizeBytes)
return -1;
}
}
- if (_sending)
+ if (channel_state_.Get().sending)
{
_engineStatisticsPtr->SetLastError(
VE_SENDING, kTraceError,
@@ -2187,7 +2167,7 @@ int Channel::StartPlayingFileLocally(const char* fileName,
"stopPosition=%d)", fileName, loop, format, volumeScaling,
startPosition, stopPosition);
- if (_outputFilePlaying)
+ if (channel_state_.Get().output_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceError,
@@ -2236,7 +2216,7 @@ int Channel::StartPlayingFileLocally(const char* fileName,
return -1;
}
_outputFilePlayerPtr->RegisterModuleFileCallback(this);
- _outputFilePlaying = true;
+ channel_state_.SetOutputFilePlaying(true);
}
if (RegisterFilePlayingToMixer() != 0)
@@ -2266,7 +2246,7 @@ int Channel::StartPlayingFileLocally(InStream* stream,
}
- if (_outputFilePlaying)
+ if (channel_state_.Get().output_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceError,
@@ -2314,7 +2294,7 @@ int Channel::StartPlayingFileLocally(InStream* stream,
return -1;
}
_outputFilePlayerPtr->RegisterModuleFileCallback(this);
- _outputFilePlaying = true;
+ channel_state_.SetOutputFilePlaying(true);
}
if (RegisterFilePlayingToMixer() != 0)
@@ -2328,7 +2308,7 @@ int Channel::StopPlayingFileLocally()
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StopPlayingFileLocally()");
- if (!_outputFilePlaying)
+ if (!channel_state_.Get().output_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_INVALID_OPERATION, kTraceWarning,
@@ -2349,7 +2329,7 @@ int Channel::StopPlayingFileLocally()
_outputFilePlayerPtr->RegisterModuleFileCallback(NULL);
FilePlayer::DestroyFilePlayer(_outputFilePlayerPtr);
_outputFilePlayerPtr = NULL;
- _outputFilePlaying = false;
+ channel_state_.SetOutputFilePlaying(false);
}
// _fileCritSect cannot be taken while calling
// SetAnonymousMixibilityStatus. Refer to comments in
@@ -2371,7 +2351,7 @@ int Channel::IsPlayingFileLocally() const
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::IsPlayingFileLocally()");
- return (int32_t)_outputFilePlaying;
+ return channel_state_.Get().output_file_playing;
}
int Channel::RegisterFilePlayingToMixer()
@@ -2379,7 +2359,8 @@ int Channel::RegisterFilePlayingToMixer()
// Return success for not registering for file playing to mixer if:
// 1. playing file before playout is started on that channel.
// 2. starting playout without file playing on that channel.
- if (!_playing || !_outputFilePlaying)
+ if (!channel_state_.Get().playing ||
+ !channel_state_.Get().output_file_playing)
{
return 0;
}
@@ -2390,8 +2371,8 @@ int Channel::RegisterFilePlayingToMixer()
// the file, _fileCritSect will be taken. This would result in a deadlock.
if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0)
{
+ channel_state_.SetOutputFilePlaying(false);
CriticalSectionScoped cs(&_fileCritSect);
- _outputFilePlaying = false;
_engineStatisticsPtr->SetLastError(
VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
"StartPlayingFile() failed to add participant as file to mixer");
@@ -2411,7 +2392,7 @@ int Channel::ScaleLocalFilePlayout(float scale)
CriticalSectionScoped cs(&_fileCritSect);
- if (!_outputFilePlaying)
+ if (!channel_state_.Get().output_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_INVALID_OPERATION, kTraceError,
@@ -2473,7 +2454,9 @@ int Channel::StartPlayingFileAsMicrophone(const char* fileName,
"stopPosition=%d)", fileName, loop, format, volumeScaling,
startPosition, stopPosition);
- if (_inputFilePlaying)
+ CriticalSectionScoped cs(&_fileCritSect);
+
+ if (channel_state_.Get().input_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceWarning,
@@ -2481,8 +2464,6 @@ int Channel::StartPlayingFileAsMicrophone(const char* fileName,
return 0;
}
- CriticalSectionScoped cs(&_fileCritSect);
-
// Destroy the old instance
if (_inputFilePlayerPtr)
{
@@ -2523,7 +2504,7 @@ int Channel::StartPlayingFileAsMicrophone(const char* fileName,
return -1;
}
_inputFilePlayerPtr->RegisterModuleFileCallback(this);
- _inputFilePlaying = true;
+ channel_state_.SetInputFilePlaying(true);
return 0;
}
@@ -2548,7 +2529,9 @@ int Channel::StartPlayingFileAsMicrophone(InStream* stream,
return -1;
}
- if (_inputFilePlaying)
+ CriticalSectionScoped cs(&_fileCritSect);
+
+ if (channel_state_.Get().input_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_PLAYING, kTraceWarning,
@@ -2556,8 +2539,6 @@ int Channel::StartPlayingFileAsMicrophone(InStream* stream,
return 0;
}
- CriticalSectionScoped cs(&_fileCritSect);
-
// Destroy the old instance
if (_inputFilePlayerPtr)
{
@@ -2594,7 +2575,7 @@ int Channel::StartPlayingFileAsMicrophone(InStream* stream,
}
_inputFilePlayerPtr->RegisterModuleFileCallback(this);
- _inputFilePlaying = true;
+ channel_state_.SetInputFilePlaying(true);
return 0;
}
@@ -2604,7 +2585,9 @@ int Channel::StopPlayingFileAsMicrophone()
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::StopPlayingFileAsMicrophone()");
- if (!_inputFilePlaying)
+ CriticalSectionScoped cs(&_fileCritSect);
+
+ if (!channel_state_.Get().input_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_INVALID_OPERATION, kTraceWarning,
@@ -2612,7 +2595,6 @@ int Channel::StopPlayingFileAsMicrophone()
return 0;
}
- CriticalSectionScoped cs(&_fileCritSect);
if (_inputFilePlayerPtr->StopPlayingFile() != 0)
{
_engineStatisticsPtr->SetLastError(
@@ -2623,7 +2605,7 @@ int Channel::StopPlayingFileAsMicrophone()
_inputFilePlayerPtr->RegisterModuleFileCallback(NULL);
FilePlayer::DestroyFilePlayer(_inputFilePlayerPtr);
_inputFilePlayerPtr = NULL;
- _inputFilePlaying = false;
+ channel_state_.SetInputFilePlaying(false);
return 0;
}
@@ -2632,8 +2614,7 @@ int Channel::IsPlayingFileAsMicrophone() const
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::IsPlayingFileAsMicrophone()");
-
- return _inputFilePlaying;
+ return channel_state_.Get().input_file_playing;
}
int Channel::ScaleFileAsMicrophonePlayout(float scale)
@@ -2643,7 +2624,7 @@ int Channel::ScaleFileAsMicrophonePlayout(float scale)
CriticalSectionScoped cs(&_fileCritSect);
- if (!_inputFilePlaying)
+ if (!channel_state_.Get().input_file_playing)
{
_engineStatisticsPtr->SetLastError(
VE_INVALID_OPERATION, kTraceError,
@@ -2852,6 +2833,7 @@ int Channel::StopRecordingPlayout()
void
Channel::SetMixWithMicStatus(bool mix)
{
+ CriticalSectionScoped cs(&_fileCritSect);
_mixFileWithMicrophone=mix;
}
@@ -3155,7 +3137,7 @@ Channel::SetRxAgcStatus(bool enable, AgcModes mode)
}
_rxAgcIsEnabled = enable;
- _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
+ channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled);
return 0;
}
@@ -3304,7 +3286,7 @@ Channel::SetRxNsStatus(bool enable, NsModes mode)
}
_rxNsIsEnabled = enable;
- _rxApmIsEnabled = ((_rxAgcIsEnabled == true) || (_rxNsIsEnabled == true));
+ channel_state_.SetRxApmIsEnabled(_rxAgcIsEnabled || _rxNsIsEnabled);
return 0;
}
@@ -3435,7 +3417,7 @@ Channel::SetLocalSSRC(unsigned int ssrc)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::SetLocalSSRC()");
- if (_sending)
+ if (channel_state_.Get().sending)
{
_engineStatisticsPtr->SetLastError(
VE_ALREADY_SENDING, kTraceError,
@@ -3722,7 +3704,7 @@ Channel::SendApplicationDefinedRTCPPacket(unsigned char subType,
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
"Channel::SendApplicationDefinedRTCPPacket()");
- if (!_sending)
+ if (!channel_state_.Get().sending)
{
_engineStatisticsPtr->SetLastError(
VE_NOT_SENDING, kTraceError,
@@ -4202,7 +4184,7 @@ Channel::PrepareEncodeAndSend(int mixingFrequency)
return -1;
}
- if (_inputFilePlaying)
+ if (channel_state_.Get().input_file_playing)
{
MixOrReplaceAudioWithFile(mixingFrequency);
}
@@ -4212,7 +4194,7 @@ Channel::PrepareEncodeAndSend(int mixingFrequency)
AudioFrameOperations::Mute(_audioFrame);
}
- if (_inputExternalMedia)
+ if (channel_state_.Get().input_external_media)
{
CriticalSectionScoped cs(&_callbackCritSect);
const bool isStereo = (_audioFrame.num_channels_ == 2);
@@ -4311,7 +4293,7 @@ int Channel::RegisterExternalMediaProcessing(
return -1;
}
_inputExternalMediaCallbackPtr = &processObject;
- _inputExternalMedia = true;
+ channel_state_.SetInputExternalMedia(true);
}
return 0;
}
@@ -4346,7 +4328,7 @@ int Channel::DeRegisterExternalMediaProcessing(ProcessingTypes type)
"input external media already disabled");
return 0;
}
- _inputExternalMedia = false;
+ channel_state_.SetInputExternalMedia(false);
_inputExternalMediaCallbackPtr = NULL;
}
@@ -4357,7 +4339,7 @@ int Channel::SetExternalMixing(bool enabled) {
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::SetExternalMixing(enabled=%d)", enabled);
- if (_playing)
+ if (channel_state_.Get().playing)
{
_engineStatisticsPtr->SetLastError(
VE_INVALID_OPERATION, kTraceError,
@@ -4583,7 +4565,7 @@ Channel::SetInitTimestamp(unsigned int timestamp)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::SetInitTimestamp()");
- if (_sending)
+ if (channel_state_.Get().sending)
{
_engineStatisticsPtr->SetLastError(
VE_SENDING, kTraceError, "SetInitTimestamp() already sending");
@@ -4604,7 +4586,7 @@ Channel::SetInitSequenceNumber(short sequenceNumber)
{
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId),
"Channel::SetInitSequenceNumber()");
- if (_sending)
+ if (channel_state_.Get().sending)
{
_engineStatisticsPtr->SetLastError(
VE_SENDING, kTraceError,
diff --git a/voice_engine/channel.h b/voice_engine/channel.h
index 954d6ea3..f3bc0966 100644
--- a/voice_engine/channel.h
+++ b/voice_engine/channel.h
@@ -63,6 +63,91 @@ class StatisticsProxy;
class TransmitMixer;
class OutputMixer;
+// Helper class to simplify locking scheme for members that are accessed from
+// multiple threads.
+// Example: a member can be set on thread T1 and read by an internal audio
+// thread T2. Accessing the member via this class ensures that we are
+// safe and also avoid TSan v2 warnings.
+class ChannelState {
+ public:
+ struct State {
+ State() : rx_apm_is_enabled(false),
+ input_external_media(false),
+ output_is_on_hold(false),
+ output_file_playing(false),
+ input_file_playing(false),
+ playing(false),
+ sending(false),
+ receiving(false) {}
+
+ bool rx_apm_is_enabled;
+ bool input_external_media;
+ bool output_is_on_hold;
+ bool output_file_playing;
+ bool input_file_playing;
+ bool playing;
+ bool sending;
+ bool receiving;
+ };
+
+ ChannelState() : lock_(CriticalSectionWrapper::CreateCriticalSection()) {
+ }
+ virtual ~ChannelState() {}
+
+ void Reset() {
+ CriticalSectionScoped lock(lock_.get());
+ state_ = State();
+ }
+
+ State Get() const {
+ CriticalSectionScoped lock(lock_.get());
+ return state_;
+ }
+
+ void SetRxApmIsEnabled(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.rx_apm_is_enabled = enable;
+ }
+
+ void SetInputExternalMedia(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.input_external_media = enable;
+ }
+
+ void SetOutputIsOnHold(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.output_is_on_hold = enable;
+ }
+
+ void SetOutputFilePlaying(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.output_file_playing = enable;
+ }
+
+ void SetInputFilePlaying(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.input_file_playing = enable;
+ }
+
+ void SetPlaying(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.playing = enable;
+ }
+
+ void SetSending(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.sending = enable;
+ }
+
+ void SetReceiving(bool enable) {
+ CriticalSectionScoped lock(lock_.get());
+ state_.receiving = enable;
+ }
+
+private:
+ scoped_ptr<CriticalSectionWrapper> lock_;
+ State state_;
+};
class Channel:
public RtpData,
@@ -371,32 +456,25 @@ public:
}
bool Playing() const
{
- return _playing;
+ return channel_state_.Get().playing;
}
bool Sending() const
{
- // A lock is needed because |_sending| is accessed by both
- // TransmitMixer::PrepareDemux() and StartSend()/StopSend(), which
- // are called by different threads.
- CriticalSectionScoped cs(&_callbackCritSect);
- return _sending;
+ return channel_state_.Get().sending;
}
bool Receiving() const
{
- return _receiving;
+ return channel_state_.Get().receiving;
}
bool ExternalTransport() const
{
+ CriticalSectionScoped cs(&_callbackCritSect);
return _externalTransport;
}
bool ExternalMixing() const
{
return _externalMixing;
}
- bool OutputIsOnHold() const
- {
- return _outputIsOnHold;
- }
bool InputIsOnHold() const
{
return _inputIsOnHold;
@@ -448,6 +526,8 @@ private:
uint32_t _instanceId;
int32_t _channelId;
+ ChannelState channel_state_;
+
scoped_ptr<RtpHeaderParser> rtp_header_parser_;
scoped_ptr<RTPPayloadRegistry> rtp_payload_registry_;
scoped_ptr<ReceiveStatistics> rtp_receive_statistics_;
@@ -471,12 +551,9 @@ private:
int _inputFilePlayerId;
int _outputFilePlayerId;
int _outputFileRecorderId;
- bool _inputFilePlaying;
- bool _outputFilePlaying;
bool _outputFileRecording;
DtmfInbandQueue _inbandDtmfQueue;
DtmfInband _inbandDtmfGenerator;
- bool _inputExternalMedia;
bool _outputExternalMedia;
VoEMediaProcess* _inputExternalMediaCallbackPtr;
VoEMediaProcess* _outputExternalMediaCallbackPtr;
@@ -509,13 +586,9 @@ private:
VoERTPObserver* _rtpObserverPtr;
VoERTCPObserver* _rtcpObserverPtr;
// VoEBase
- bool _outputIsOnHold;
bool _externalPlayout;
bool _externalMixing;
bool _inputIsOnHold;
- bool _playing;
- bool _sending;
- bool _receiving;
bool _mixFileWithMicrophone;
bool _rtpObserver;
bool _rtcpObserver;
@@ -548,7 +621,6 @@ private:
uint16_t _recPacketDelayMs;
// VoEAudioProcessing
bool _RxVadDetection;
- bool _rxApmIsEnabled;
bool _rxAgcIsEnabled;
bool _rxNsIsEnabled;
bool restored_packet_in_use_;
diff --git a/voice_engine/dtmf_inband_queue.cc b/voice_engine/dtmf_inband_queue.cc
index e2331db1..86e8d62b 100644
--- a/voice_engine/dtmf_inband_queue.cc
+++ b/voice_engine/dtmf_inband_queue.cc
@@ -71,15 +71,17 @@ DtmfInbandQueue::NextDtmf(uint16_t* len, uint8_t* level)
return nextDtmf;
}
-bool
+bool
DtmfInbandQueue::PendingDtmf()
{
- return(_nextEmptyIndex>0);
+ CriticalSectionScoped lock(&_DtmfCritsect);
+ return _nextEmptyIndex > 0;
}
-void
+void
DtmfInbandQueue::ResetDtmf()
{
+ CriticalSectionScoped lock(&_DtmfCritsect);
_nextEmptyIndex = 0;
}
diff --git a/voice_engine/output_mixer.cc b/voice_engine/output_mixer.cc
index dba96fe7..5503361c 100644
--- a/voice_engine/output_mixer.cc
+++ b/voice_engine/output_mixer.cc
@@ -569,20 +569,21 @@ OutputMixer::DoOperationsOnCombinedSignal()
APMAnalyzeReverseStream();
// --- External media processing
-
- if (_externalMedia)
{
CriticalSectionScoped cs(&_callbackCritSect);
- const bool isStereo = (_audioFrame.num_channels_ == 2);
- if (_externalMediaCallbackPtr)
+ if (_externalMedia)
{
- _externalMediaCallbackPtr->Process(
- -1,
- kPlaybackAllChannelsMixed,
- (int16_t*)_audioFrame.data_,
- _audioFrame.samples_per_channel_,
- _audioFrame.sample_rate_hz_,
- isStereo);
+ const bool is_stereo = (_audioFrame.num_channels_ == 2);
+ if (_externalMediaCallbackPtr)
+ {
+ _externalMediaCallbackPtr->Process(
+ -1,
+ kPlaybackAllChannelsMixed,
+ (int16_t*)_audioFrame.data_,
+ _audioFrame.samples_per_channel_,
+ _audioFrame.sample_rate_hz_,
+ is_stereo);
+ }
}
}
diff --git a/voice_engine/transmit_mixer.cc b/voice_engine/transmit_mixer.cc
index e9394f7b..318df316 100644
--- a/voice_engine/transmit_mixer.cc
+++ b/voice_engine/transmit_mixer.cc
@@ -397,7 +397,12 @@ TransmitMixer::PrepareDemux(const void* audioSamples,
}
// --- Record to file
- if (_fileRecording)
+ bool file_recording = false;
+ {
+ CriticalSectionScoped cs(&_critSect);
+ file_recording = _fileRecording;
+ }
+ if (file_recording)
{
RecordAudioToFile(_audioFrame.sample_rate_hz_);
}
@@ -728,6 +733,8 @@ int TransmitMixer::StartRecordingMicrophone(const char* fileName,
"TransmitMixer::StartRecordingMicrophone(fileName=%s)",
fileName);
+ CriticalSectionScoped cs(&_critSect);
+
if (_fileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
@@ -761,8 +768,6 @@ int TransmitMixer::StartRecordingMicrophone(const char* fileName,
format = kFileFormatCompressedFile;
}
- CriticalSectionScoped cs(&_critSect);
-
// Destroy the old instance
if (_fileRecorderPtr)
{
@@ -807,6 +812,8 @@ int TransmitMixer::StartRecordingMicrophone(OutStream* stream,
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StartRecordingMicrophone()");
+ CriticalSectionScoped cs(&_critSect);
+
if (_fileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
@@ -839,8 +846,6 @@ int TransmitMixer::StartRecordingMicrophone(OutStream* stream,
format = kFileFormatCompressedFile;
}
- CriticalSectionScoped cs(&_critSect);
-
// Destroy the old instance
if (_fileRecorderPtr)
{
@@ -884,6 +889,8 @@ int TransmitMixer::StopRecordingMicrophone()
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
"TransmitMixer::StopRecordingMicrophone()");
+ CriticalSectionScoped cs(&_critSect);
+
if (!_fileRecording)
{
WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
@@ -891,8 +898,6 @@ int TransmitMixer::StopRecordingMicrophone()
return 0;
}
- CriticalSectionScoped cs(&_critSect);
-
if (_fileRecorderPtr->StopRecording() != 0)
{
_engineStatisticsPtr->SetLastError(
@@ -1170,7 +1175,7 @@ bool TransmitMixer::IsRecordingCall()
bool TransmitMixer::IsRecordingMic()
{
-
+ CriticalSectionScoped cs(&_critSect);
return _fileRecording;
}
diff --git a/voice_engine/voice_engine_impl.cc b/voice_engine/voice_engine_impl.cc
index 396a6c14..4c02d8d2 100644
--- a/voice_engine/voice_engine_impl.cc
+++ b/voice_engine/voice_engine_impl.cc
@@ -70,6 +70,12 @@ int VoiceEngineImpl::Release() {
"VoiceEngineImpl self deleting (voiceEngine=0x%p)",
this);
+ // Clear any pointers before starting destruction. Otherwise worker-
+ // threads will still have pointers to a partially destructed object.
+ // Example: AudioDeviceBuffer::RequestPlayoutData() can access a
+ // partially deconstructed |_ptrCbAudioTransport| during destruction
+ // if we don't call Terminate here.
+ Terminate();
delete this;
}