diff --git a/src/voice_engine/main/source/channel.cc b/src/voice_engine/main/source/channel.cc index 5b1a0df2fd..940414e26c 100644 --- a/src/voice_engine/main/source/channel.cc +++ b/src/voice_engine/main/source/channel.cc @@ -1694,18 +1694,28 @@ Channel::StartSend() { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::StartSend()"); - if (_sending) { - return 0; + // 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; } + if (_rtpRtcpModule.SetSendingStatus(true) != 0) { _engineStatisticsPtr->SetLastError( VE_RTP_RTCP_MODULE_ERROR, kTraceError, "StartSend() RTP/RTCP failed to start sending"); + CriticalSectionScoped cs(_callbackCritSect); + _sending = false; return -1; } - _sending = true; + return 0; } @@ -1714,10 +1724,18 @@ Channel::StopSend() { WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId,_channelId), "Channel::StopSend()"); - if (!_sending) { - return 0; + // 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; } + // Reset sending SSRC and sequence number and triggers direct transmission // of RTCP BYE if (_rtpRtcpModule.SetSendingStatus(false) == -1 || @@ -1728,7 +1746,6 @@ Channel::StopSend() "StartSend() RTP/RTCP failed to stop sending"); } - _sending = false; return 0; } diff --git a/src/voice_engine/main/source/channel.h b/src/voice_engine/main/source/channel.h index e06acd324c..25e410d963 100644 --- a/src/voice_engine/main/source/channel.h +++ b/src/voice_engine/main/source/channel.h @@ -464,52 +464,56 @@ public: WebRtc_UWord32 InstanceId() const { return _instanceId; - }; + } WebRtc_Word32 ChannelId() const { return _channelId; - }; + } bool Playing() const { return _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; - }; + } bool Receiving() const { return _receiving; - }; + } bool ExternalTransport() const { return _externalTransport; - }; + } bool OutputIsOnHold() const { return _outputIsOnHold; - }; + } bool InputIsOnHold() const { return _inputIsOnHold; - }; + } RtpRtcp* RtpRtcpModulePtr() const { return &_rtpRtcpModule; - }; + } WebRtc_Word8 OutputEnergyLevel() const { return _outputAudioLevel.Level(); - }; + } #ifndef WEBRTC_EXTERNAL_TRANSPORT bool SendSocketsInitialized() const { return _socketTransportModule.SendSocketsInitialized(); - }; + } bool ReceiveSocketsInitialized() const { return _socketTransportModule.ReceiveSocketsInitialized(); - }; + } #endif WebRtc_UWord32 Demultiplex(const AudioFrame& audioFrame); WebRtc_UWord32 PrepareEncodeAndSend(int mixingFrequency);