Index: talk/media/webrtc/webrtcvoiceengine.cc |
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc |
index 0b70a1446102dfee107fbb94f810176abbc4ca8b..8a9d6fcf940a79475c6cae393faac877f475d96c 100644 |
--- a/talk/media/webrtc/webrtcvoiceengine.cc |
+++ b/talk/media/webrtc/webrtcvoiceengine.cc |
@@ -54,8 +54,9 @@ |
#include "webrtc/modules/audio_processing/include/audio_processing.h" |
namespace cricket { |
+namespace { |
-static const int kMaxNumPacketSize = 6; |
+const int kMaxNumPacketSize = 6; |
struct CodecPref { |
const char* name; |
int clockrate; |
@@ -65,7 +66,7 @@ struct CodecPref { |
int packet_sizes_ms[kMaxNumPacketSize]; |
}; |
// Note: keep the supported packet sizes in ascending order. |
-static const CodecPref kCodecPrefs[] = { |
+const CodecPref kCodecPrefs[] = { |
{ kOpusCodecName, 48000, 2, 111, true, { 10, 20, 40, 60 } }, |
{ kIsacCodecName, 16000, 1, 103, true, { 30, 60 } }, |
{ kIsacCodecName, 32000, 1, 104, true, { 30 } }, |
@@ -97,14 +98,14 @@ static const CodecPref kCodecPrefs[] = { |
// It's not clear yet whether the -2 index is handled properly on other OSes. |
#ifdef WIN32 |
-static const int kDefaultAudioDeviceId = -1; |
+const int kDefaultAudioDeviceId = -1; |
#else |
-static const int kDefaultAudioDeviceId = 0; |
+const int kDefaultAudioDeviceId = 0; |
#endif |
// Parameter used for NACK. |
// This value is equivalent to 5 seconds of audio data at 20 ms per packet. |
-static const int kNackMaxPackets = 250; |
+const int kNackMaxPackets = 250; |
// Codec parameters for Opus. |
// draft-spittka-payload-rtp-opus-03 |
@@ -117,18 +118,18 @@ static const int kNackMaxPackets = 250; |
// 64-128 kb/s for FB stereo music. |
// The current implementation applies the following values to mono signals, |
// and multiplies them by 2 for stereo. |
-static const int kOpusBitrateNb = 12000; |
-static const int kOpusBitrateWb = 20000; |
-static const int kOpusBitrateFb = 32000; |
+const int kOpusBitrateNb = 12000; |
+const int kOpusBitrateWb = 20000; |
+const int kOpusBitrateFb = 32000; |
// Opus bitrate should be in the range between 6000 and 510000. |
-static const int kOpusMinBitrate = 6000; |
-static const int kOpusMaxBitrate = 510000; |
+const int kOpusMinBitrate = 6000; |
+const int kOpusMaxBitrate = 510000; |
// Default audio dscp value. |
// See http://tools.ietf.org/html/rfc2474 for details. |
// See also http://tools.ietf.org/html/draft-jennings-rtcweb-qos-00 |
-static const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF; |
+const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF; |
// Ensure we open the file in a writeable path on ChromeOS and Android. This |
// workaround can be removed when it's possible to specify a filename for audio |
@@ -140,14 +141,15 @@ static const rtc::DiffServCodePoint kAudioDscpValue = rtc::DSCP_EF; |
// NOTE(ajm): Don't use hardcoded paths on platforms not explicitly specified |
// below. |
#if defined(CHROMEOS) |
-static const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; |
+const char kAecDumpByAudioOptionFilename[] = "/tmp/audio.aecdump"; |
#elif defined(ANDROID) |
-static const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; |
+const char kAecDumpByAudioOptionFilename[] = "/sdcard/audio.aecdump"; |
#else |
-static const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; |
+const char kAecDumpByAudioOptionFilename[] = "audio.aecdump"; |
#endif |
-namespace { |
+// See: https://code.google.com/p/webrtc/issues/detail?id=4740 |
+const int kDefaultRtcpReceiverReportSsrc = 1; |
bool ValidateStreamParams(const StreamParams& sp) { |
if (sp.ssrcs.empty()) { |
@@ -579,13 +581,7 @@ void WebRtcVoiceEngine::Terminate() { |
VoiceMediaChannel* WebRtcVoiceEngine::CreateChannel(webrtc::Call* call, |
const AudioOptions& options) { |
- WebRtcVoiceMediaChannel* ch = |
- new WebRtcVoiceMediaChannel(this, options, call); |
- if (!ch->valid()) { |
- delete ch; |
- return nullptr; |
- } |
- return ch; |
+ return new WebRtcVoiceMediaChannel(this, options, call); |
} |
bool WebRtcVoiceEngine::SetOptions(const AudioOptions& options) { |
@@ -1310,12 +1306,8 @@ void WebRtcVoiceEngine::StopAecDump() { |
} |
} |
-int WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) { |
- return voice_engine_wrapper->base()->CreateChannel(voe_config_); |
-} |
- |
-int WebRtcVoiceEngine::CreateMediaVoiceChannel() { |
- return CreateVoiceChannel(voe_wrapper_.get()); |
+int WebRtcVoiceEngine::CreateVoiceChannel() { |
pthatcher1
2015/10/01 19:57:56
Can we rename this CreateVoeChannel?
the sun
2015/10/13 15:07:03
Done.
|
+ return voe_wrapper_->base()->CreateChannel(voe_config_); |
} |
class WebRtcVoiceMediaChannel::WebRtcVoiceChannelRenderer |
@@ -1405,7 +1397,6 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, |
const AudioOptions& options, |
webrtc::Call* call) |
: engine_(engine), |
- voe_channel_(engine->CreateMediaVoiceChannel()), |
send_bitrate_setting_(false), |
send_bitrate_bps_(0), |
options_(), |
@@ -1419,35 +1410,28 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine* engine, |
call_(call), |
default_recv_ssrc_(0), |
default_recv_channel_id_(-1) { |
- engine->RegisterChannel(this); |
- LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel " |
- << voe_channel(); |
+ LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel"; |
RTC_DCHECK(nullptr != call); |
- ConfigureSendChannel(voe_channel()); |
+ engine->RegisterChannel(this); |
SetOptions(options); |
} |
WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { |
- LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel " |
- << voe_channel(); |
+ LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel"; |
- // Remove any remaining send streams, the default channel will be deleted |
- // later. |
+ // Remove any remaining send streams. |
while (!send_channels_.empty()) { |
RemoveSendStream(send_channels_.begin()->first); |
} |
- // Unregister ourselves from the engine. |
- engine()->UnregisterChannel(this); |
- |
- // Remove any remaining streams. |
+ // Remove any remaining receive streams. |
while (!receive_channels_.empty()) { |
RemoveRecvStream(receive_channels_.begin()->first); |
} |
RTC_DCHECK(receive_streams_.empty()); |
- // Delete the default channel. |
- DeleteChannel(voe_channel()); |
+ // Unregister ourselves from the engine. |
+ engine()->UnregisterChannel(this); |
} |
bool WebRtcVoiceMediaChannel::SetSendParameters( |
@@ -1966,13 +1950,6 @@ bool WebRtcVoiceMediaChannel::SetSendRtpHeaderExtensions( |
return true; |
} |
- // The default channel may or may not be in |send_channels_|. Set the rtp |
- // header extensions for default channel regardless. |
- |
- if (!SetChannelSendRtpHeaderExtensions(voe_channel(), extensions)) { |
- return false; |
- } |
- |
// Loop through all send channels and enable/disable the extensions. |
for (const auto& ch : send_channels_) { |
if (!SetChannelSendRtpHeaderExtensions(ch.second->channel(), extensions)) { |
@@ -2119,107 +2096,106 @@ bool WebRtcVoiceMediaChannel::SetAudioSend(uint32 ssrc, bool enable, |
return true; |
} |
-// TODO(ronghuawu): Change this method to return bool. |
-void WebRtcVoiceMediaChannel::ConfigureSendChannel(int channel) { |
- if (engine()->voe()->network()->RegisterExternalTransport( |
- channel, *this) == -1) { |
- LOG_RTCERR2(RegisterExternalTransport, channel, this); |
+int WebRtcVoiceMediaChannel::CreateChannel() { |
pthatcher1
2015/10/01 19:57:56
Again, can this be called CreateVoeChannel?
the sun
2015/10/13 15:07:03
Done.
|
+ int id = engine()->CreateVoiceChannel(); |
+ if (id == -1) { |
+ LOG_RTCERR0(CreateVoiceChannel); |
+ return -1; |
} |
- // Enable RTCP (for quality stats and feedback messages) |
- EnableRtcp(channel); |
- |
- // Set RTP header extension for the new channel. |
- SetChannelSendRtpHeaderExtensions(channel, send_extensions_); |
+ if (engine()->voe()->network()->RegisterExternalTransport(id, *this) == -1) { |
+ LOG_RTCERR2(RegisterExternalTransport, id, this); |
+ engine()->voe()->base()->DeleteChannel(id); |
+ return -1; |
+ } |
+ return id; |
} |
bool WebRtcVoiceMediaChannel::DeleteChannel(int channel) { |
if (engine()->voe()->network()->DeRegisterExternalTransport(channel) == -1) { |
LOG_RTCERR1(DeRegisterExternalTransport, channel); |
} |
- |
if (engine()->voe()->base()->DeleteChannel(channel) == -1) { |
LOG_RTCERR1(DeleteChannel, channel); |
return false; |
} |
- |
return true; |
} |
bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { |
RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
- // If the default channel is already used for sending create a new channel |
- // otherwise use the default channel for sending. |
- int channel = GetSendChannelNum(sp.first_ssrc()); |
- if (channel != -1) { |
- LOG(LS_ERROR) << "Stream already exists with ssrc " << sp.first_ssrc(); |
+ uint32 ssrc = sp.first_ssrc(); |
+ RTC_DCHECK(0 != ssrc); |
+ |
+ if (-1 != GetSendChannelNum(ssrc)) { |
pthatcher1
2015/10/01 19:57:56
"-1 != X" here and "X == -1" below. Please be con
the sun
2015/10/13 15:07:03
Done.
|
+ LOG(LS_ERROR) << "Stream already exists with ssrc " << ssrc; |
return false; |
} |
- bool default_channel_is_available = true; |
- for (const auto& ch : send_channels_) { |
- if (IsDefaultChannel(ch.second->channel())) { |
- default_channel_is_available = false; |
- break; |
- } |
+ // Create a new channel for sending audio data. |
+ int channel = CreateChannel(); |
+ if (channel == -1) { |
+ return false; |
} |
- if (default_channel_is_available) { |
- channel = voe_channel(); |
- } else { |
- // Create a new channel for sending audio data. |
- channel = engine()->CreateMediaVoiceChannel(); |
- if (channel == -1) { |
- LOG_RTCERR0(CreateChannel); |
- return false; |
- } |
- ConfigureSendChannel(channel); |
+ // Enable RTCP (for quality stats and feedback messages). |
+ if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) { |
+ LOG_RTCERR2(SetRTCPStatus, channel, 1); |
} |
- // Save the channel to send_channels_, so that RemoveSendStream() can still |
- // delete the channel in case failure happens below. |
- webrtc::AudioTransport* audio_transport = |
- engine()->voe()->base()->audio_transport(); |
- send_channels_.insert( |
- std::make_pair(sp.first_ssrc(), |
- new WebRtcVoiceChannelRenderer(channel, audio_transport))); |
+ SetChannelSendRtpHeaderExtensions(channel, send_extensions_); |
// Set the send (local) SSRC. |
// If there are multiple send SSRCs, we can only set the first one here, and |
// the rest of the SSRC(s) need to be set after SetSendCodec has been called |
// (with a codec requires multiple SSRC(s)). |
pthatcher1
2015/10/01 19:57:56
What does "with a codec requires multiple SSRC(s)"
the sun
2015/10/13 15:07:03
We don't support any audio codecs that require mul
|
- if (engine()->voe()->rtp()->SetLocalSSRC(channel, sp.first_ssrc()) == -1) { |
- LOG_RTCERR2(SetSendSSRC, channel, sp.first_ssrc()); |
+ if (engine()->voe()->rtp()->SetLocalSSRC(channel, ssrc) == -1) { |
+ LOG_RTCERR2(SetSendSSRC, channel, ssrc); |
+ DeleteChannel(channel); |
return false; |
} |
- // At this point the channel's local SSRC has been updated. If the channel is |
- // the default channel make sure that all the receive channels are updated as |
- // well. Receive channels have to have the same SSRC as the default channel in |
- // order to send receiver reports with this SSRC. |
- if (IsDefaultChannel(channel)) { |
- for (const auto& ch : receive_channels_) { |
- if (engine()->voe()->rtp()->SetLocalSSRC(ch.second->channel(), |
- sp.first_ssrc()) != 0) { |
- LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), sp.first_ssrc()); |
- return false; |
- } |
- } |
- } |
- |
if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { |
LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); |
+ DeleteChannel(channel); |
return false; |
} |
// Set the current codecs to be used for the new channel. |
- if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) |
+ if (!send_codecs_.empty() && !SetSendCodecs(channel, send_codecs_)) { |
+ DeleteChannel(channel); |
return false; |
+ } |
+ |
+ // Save the channel to send_channels_, so that RemoveSendStream() can still |
+ // delete the channel in case failure happens below. |
+ webrtc::AudioTransport* audio_transport = |
+ engine()->voe()->base()->audio_transport(); |
+ send_channels_.insert( |
+ std::make_pair(ssrc, |
+ new WebRtcVoiceChannelRenderer(channel, audio_transport))); |
+ |
+ // At this point the channel's local SSRC has been updated. If the channel is |
+ // the first send channel make sure that all the receive channels are updated |
+ // with the same SSRC in order to send receiver reports. |
+ if (send_channels_.size() == 1) { |
+ for (const auto& ch : receive_channels_) { |
+ int recv_channel = ch.second->channel(); |
+ if (engine()->voe()->rtp()->SetLocalSSRC(recv_channel, ssrc) != 0) { |
+ LOG_RTCERR2(SetLocalSSRC, ch.second->channel(), ssrc); |
+ return false; |
+ } |
+ engine()->voe()->base()->AssociateSendChannel(recv_channel, channel); |
+ LOG(LS_INFO) << "VoiceEngine channel #" << recv_channel |
+ << " is associated with channel #" << channel << "."; |
+ } |
+ } |
return ChangeSend(channel, desired_send_); |
} |
bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32 ssrc) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
ChannelMap::iterator it = send_channels_.find(ssrc); |
if (it == send_channels_.end()) { |
LOG(LS_WARNING) << "Try to remove stream with ssrc " << ssrc |
@@ -2235,21 +2211,15 @@ bool WebRtcVoiceMediaChannel::RemoveSendStream(uint32 ssrc) { |
delete it->second; |
send_channels_.erase(it); |
- if (IsDefaultChannel(channel)) { |
- // Do not delete the default channel since the receive channels depend on |
- // the default channel, recycle it instead. |
- ChangeSend(channel, SEND_NOTHING); |
- } else { |
- // Clean up and delete the send channel. |
- LOG(LS_INFO) << "Removing audio send stream " << ssrc |
- << " with VoiceEngine channel #" << channel << "."; |
- if (!DeleteChannel(channel)) |
- return false; |
+ // Clean up and delete the send channel. |
+ LOG(LS_INFO) << "Removing audio send stream " << ssrc |
+ << " with VoiceEngine channel #" << channel << "."; |
+ if (!DeleteChannel(channel)) { |
+ return false; |
} |
- |
- if (send_channels_.empty()) |
+ if (send_channels_.empty()) { |
ChangeSend(SEND_NOTHING); |
- |
+ } |
return true; |
} |
@@ -2280,9 +2250,8 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
RTC_DCHECK(receive_stream_params_.find(ssrc) == receive_stream_params_.end()); |
// Create a new channel for receiving audio data. |
- int channel = engine()->CreateMediaVoiceChannel(); |
+ int channel = CreateChannel(); |
if (channel == -1) { |
- LOG_RTCERR0(CreateChannel); |
return false; |
} |
if (!ConfigureRecvChannel(channel)) { |
@@ -2305,37 +2274,26 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { |
} |
bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { |
- // Configure to use external transport. |
- if (engine()->voe()->network()->RegisterExternalTransport( |
- channel, *this) == -1) { |
- LOG_RTCERR2(SetExternalTransport, channel, this); |
- return false; |
- } |
- |
if (!SetRecvOptions(channel)) { |
return false; |
} |
- // Use the same SSRC as our default (send) channel, so the RTCP reports are |
- // correct. |
- unsigned int send_ssrc = 0; |
- webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp(); |
- if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) { |
- LOG_RTCERR1(GetSendSSRC, channel); |
- return false; |
+ uint32 rtcp_ssrc = kDefaultRtcpReceiverReportSsrc; |
+ if (send_channels_.size() > 0) { |
+ rtcp_ssrc = send_channels_.begin()->first; |
+ |
+ // Associate receive channel to default send channel (so the receive channel |
+ // can obtain RTT from the send channel) |
+ int send_channel = send_channels_.begin()->second->channel(); |
+ engine()->voe()->base()->AssociateSendChannel(channel, send_channel); |
+ LOG(LS_INFO) << "VoiceEngine channel #" << channel |
+ << " is associated with channel #" << send_channel << "."; |
} |
- if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) { |
- LOG_RTCERR1(SetSendSSRC, channel); |
+ if (engine()->voe()->rtp()->SetLocalSSRC(channel, rtcp_ssrc) == -1) { |
+ LOG_RTCERR1(SetLocalSSRC, channel); |
return false; |
} |
- // Associate receive channel to default send channel (so the receive channel |
- // can obtain RTT from the send channel) |
- engine()->voe()->base()->AssociateSendChannel(channel, voe_channel()); |
- LOG(LS_INFO) << "VoiceEngine channel #" |
- << channel << " is associated with channel #" |
- << voe_channel() << "."; |
- |
// Turn off all supported codecs. |
int ncodecs = engine()->voe()->codec()->NumOfCodecs(); |
for (int i = 0; i < ncodecs; ++i) { |
@@ -2545,6 +2503,7 @@ bool WebRtcVoiceMediaChannel::CanInsertDtmf() { |
bool WebRtcVoiceMediaChannel::InsertDtmf(uint32 ssrc, int event, |
int duration, int flags) { |
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
if (!dtmf_allowed_) { |
return false; |
} |
@@ -2553,16 +2512,7 @@ bool WebRtcVoiceMediaChannel::InsertDtmf(uint32 ssrc, int event, |
if (flags & cricket::DF_SEND) { |
int channel = -1; |
if (ssrc == 0) { |
- bool default_channel_is_inuse = false; |
- for (const auto& ch : send_channels_) { |
- if (IsDefaultChannel(ch.second->channel())) { |
- default_channel_is_inuse = true; |
- break; |
- } |
- } |
- if (default_channel_is_inuse) { |
- channel = voe_channel(); |
- } else if (!send_channels_.empty()) { |
+ if (send_channels_.size() > 0) { |
channel = send_channels_.begin()->second->channel(); |
} |
} else { |
@@ -2681,7 +2631,14 @@ void WebRtcVoiceMediaChannel::OnRtcpReceived( |
} |
bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { |
- int channel = (ssrc == 0) ? voe_channel() : GetSendChannelNum(ssrc); |
+ int channel = -1; |
+ if (ssrc == 0) { |
+ if (send_channels_.size() > 0) { |
+ channel = send_channels_.begin()->second->channel(); |
+ } |
pthatcher1
2015/10/01 19:57:56
The only thing that ever used ssrc=0 here was GTP,
the sun
2015/10/13 15:07:03
Done.
|
+ } else { |
+ channel = GetSendChannelNum(ssrc); |
+ } |
if (channel == -1) { |
LOG(LS_WARNING) << "The specified ssrc " << ssrc << " is not in use."; |
return false; |
@@ -2707,8 +2664,9 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { |
} |
webrtc::AudioProcessing* ap = engine()->voe()->base()->audio_processing(); |
- if (ap) |
+ if (ap) { |
ap->set_output_will_be_muted(all_muted); |
+ } |
return true; |
} |
@@ -2716,7 +2674,6 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32 ssrc, bool muted) { |
// SetMaxSendBitrate() in future. |
bool WebRtcVoiceMediaChannel::SetMaxSendBandwidth(int bps) { |
LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBandwidth."; |
- |
return SetSendBitrateInternal(bps); |
} |
@@ -2997,15 +2954,18 @@ int WebRtcVoiceMediaChannel::GetOutputLevel(int channel) { |
int WebRtcVoiceMediaChannel::GetReceiveChannelNum(uint32 ssrc) const { |
RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
ChannelMap::const_iterator it = receive_channels_.find(ssrc); |
- if (it != receive_channels_.end()) |
+ if (it != receive_channels_.end()) { |
return it->second->channel(); |
+ } |
return -1; |
} |
int WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) const { |
pthatcher1
2015/10/01 19:57:56
Can you rename this to GetSendChannelBySsrc?
the sun
2015/10/13 15:07:03
Not going to do that right now.
|
+ RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
ChannelMap::const_iterator it = send_channels_.find(ssrc); |
- if (it != send_channels_.end()) |
+ if (it != send_channels_.end()) { |
return it->second->channel(); |
+ } |
return -1; |
} |
@@ -3053,18 +3013,6 @@ bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, |
return false; |
} |
-bool WebRtcVoiceMediaChannel::EnableRtcp(int channel) { |
- if (engine()->voe()->rtp()->SetRTCPStatus(channel, true) == -1) { |
- LOG_RTCERR2(SetRTCPStatus, channel, 1); |
- return false; |
- } |
- // TODO(juberti): Enable VQMon and RTCP XR reports, once we know what |
- // what we want to do with them. |
- // engine()->voe().EnableVQMon(voe_channel(), true); |
- // engine()->voe().EnableRTCP_XR(voe_channel(), true); |
- return true; |
-} |
- |
bool WebRtcVoiceMediaChannel::SetPlayout(int channel, bool playout) { |
if (playout) { |
LOG(LS_INFO) << "Starting playout for channel #" << channel; |