diff options
Diffstat (limited to 'media/webrtc/webrtcvoiceengine.cc')
-rw-r--r-- | media/webrtc/webrtcvoiceengine.cc | 246 |
1 files changed, 175 insertions, 71 deletions
diff --git a/media/webrtc/webrtcvoiceengine.cc b/media/webrtc/webrtcvoiceengine.cc index 5cf53e4..a524bad 100644 --- a/media/webrtc/webrtcvoiceengine.cc +++ b/media/webrtc/webrtcvoiceengine.cc @@ -52,6 +52,7 @@ #include "webrtc/base/stringutils.h" #include "webrtc/common.h" #include "webrtc/modules/audio_processing/include/audio_processing.h" +#include "webrtc/video_engine/include/vie_network.h" #ifdef WIN32 #include <objbase.h> // NOLINT @@ -119,6 +120,7 @@ static const int kOpusStereoBitrate = 64000; // Opus bitrate should be in the range between 6000 and 510000. static const int kOpusMinBitrate = 6000; static 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 @@ -403,6 +405,7 @@ static bool IsOpusStereoEnabled(const AudioCodec& codec) { return codec.GetParam(kCodecParamStereo, &value) && value == 1; } +// TODO(minyue): Clamp bitrate when invalid. static bool IsValidOpusBitrate(int bitrate) { return (bitrate >= kOpusMinBitrate && bitrate <= kOpusMaxBitrate); } @@ -429,6 +432,59 @@ static bool IsOpusFecEnabled(const AudioCodec& codec) { return codec.GetParam(kCodecParamUseInbandFec, &value) && value == 1; } +// Returns kOpusDefaultPlaybackRate if params[kCodecParamMaxPlaybackRate] is not +// defined. Returns the value of params[kCodecParamMaxPlaybackRate] otherwise. +static int GetOpusMaxPlaybackRate(const AudioCodec& codec) { + int value; + if (codec.GetParam(kCodecParamMaxPlaybackRate, &value)) { + return value; + } + return kOpusDefaultMaxPlaybackRate; +} + +static void GetOpusConfig(const AudioCodec& codec, webrtc::CodecInst* voe_codec, + bool* enable_codec_fec, int* max_playback_rate) { + *enable_codec_fec = IsOpusFecEnabled(codec); + *max_playback_rate = GetOpusMaxPlaybackRate(codec); + + // If OPUS, change what we send according to the "stereo" codec + // parameter, and not the "channels" parameter. We set + // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If + // the bitrate is not specified, i.e. is zero, we set it to the + // appropriate default value for mono or stereo Opus. + + // TODO(minyue): The determination of bit rate might take the maximum playback + // rate into account. + + if (IsOpusStereoEnabled(codec)) { + voe_codec->channels = 2; + if (!IsValidOpusBitrate(codec.bitrate)) { + if (codec.bitrate != 0) { + LOG(LS_WARNING) << "Overrides the invalid supplied bitrate(" + << codec.bitrate + << ") with default opus stereo bitrate: " + << kOpusStereoBitrate; + } + voe_codec->rate = kOpusStereoBitrate; + } + } else { + voe_codec->channels = 1; + if (!IsValidOpusBitrate(codec.bitrate)) { + if (codec.bitrate != 0) { + LOG(LS_WARNING) << "Overrides the invalid supplied bitrate(" + << codec.bitrate + << ") with default opus mono bitrate: " + << kOpusMonoBitrate; + } + voe_codec->rate = kOpusMonoBitrate; + } + } + int bitrate_from_params = GetOpusBitrateFromParams(codec); + if (bitrate_from_params != 0) { + voe_codec->rate = bitrate_from_params; + } +} + void WebRtcVoiceEngine::ConstructCodecs() { LOG(LS_INFO) << "WebRtc VoiceEngine codecs:"; int ncodecs = voe_wrapper_->codec()->NumOfCodecs(); @@ -805,30 +861,6 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { } } - bool experimental_ns; - if (options.experimental_ns.Get(&experimental_ns)) { - webrtc::AudioProcessing* audioproc = - voe_wrapper_->base()->audio_processing(); -#ifdef USE_WEBRTC_DEV_BRANCH - webrtc::Config config; - config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs( - experimental_ns)); - audioproc->SetExtraOptions(config); -#else - // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine - // returns NULL on audio_processing(). - if (audioproc) { - if (audioproc->EnableExperimentalNs(experimental_ns) == -1) { - LOG_RTCERR1(EnableExperimentalNs, experimental_ns); - return false; - } - } else { - LOG(LS_VERBOSE) << "Experimental noise suppression set to " - << experimental_ns; - } -#endif - } - bool highpass_filter; if (options.highpass_filter.Get(&highpass_filter)) { LOG(LS_INFO) << "High pass filter enabled? " << highpass_filter; @@ -874,20 +906,50 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { StopAecDump(); } + webrtc::Config config; + + experimental_aec_.SetFrom(options.experimental_aec); bool experimental_aec; - if (options.experimental_aec.Get(&experimental_aec)) { - LOG(LS_INFO) << "Experimental aec is " << experimental_aec; - webrtc::AudioProcessing* audioproc = - voe_wrapper_->base()->audio_processing(); + if (experimental_aec_.Get(&experimental_aec)) { + LOG(LS_INFO) << "Experimental aec is enabled? " << experimental_aec; + config.Set<webrtc::DelayCorrection>( + new webrtc::DelayCorrection(experimental_aec)); + } + +#ifdef USE_WEBRTC_DEV_BRANCH + experimental_ns_.SetFrom(options.experimental_ns); + bool experimental_ns; + if (experimental_ns_.Get(&experimental_ns)) { + LOG(LS_INFO) << "Experimental ns is enabled? " << experimental_ns; + config.Set<webrtc::ExperimentalNs>( + new webrtc::ExperimentalNs(experimental_ns)); + } +#endif + + // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine + // returns NULL on audio_processing(). + webrtc::AudioProcessing* audioproc = voe_wrapper_->base()->audio_processing(); + if (audioproc) { + audioproc->SetExtraOptions(config); + } + +#ifndef USE_WEBRTC_DEV_BRANCH + bool experimental_ns; + if (options.experimental_ns.Get(&experimental_ns)) { + LOG(LS_INFO) << "Experimental ns is enabled? " << experimental_ns; // We check audioproc for the benefit of tests, since FakeWebRtcVoiceEngine // returns NULL on audio_processing(). if (audioproc) { - webrtc::Config config; - config.Set<webrtc::DelayCorrection>( - new webrtc::DelayCorrection(experimental_aec)); - audioproc->SetExtraOptions(config); + if (audioproc->EnableExperimentalNs(experimental_ns) == -1) { + LOG_RTCERR1(EnableExperimentalNs, experimental_ns); + return false; + } + } else { + LOG(LS_VERBOSE) << "Experimental noise suppression set to " + << experimental_ns; } } +#endif uint32 recording_sample_rate; if (options.recording_sample_rate.Get(&recording_sample_rate)) { @@ -1759,6 +1821,8 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine) typing_noise_detected_(false), desired_send_(SEND_NOTHING), send_(SEND_NOTHING), + shared_bwe_vie_(NULL), + shared_bwe_vie_channel_(-1), default_receive_ssrc_(0) { engine->RegisterChannel(this); LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel " @@ -1770,6 +1834,7 @@ WebRtcVoiceMediaChannel::WebRtcVoiceMediaChannel(WebRtcVoiceEngine *engine) WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel() { LOG(LS_VERBOSE) << "WebRtcVoiceMediaChannel::~WebRtcVoiceMediaChannel " << voe_channel(); + SetupSharedBandwidthEstimation(NULL, -1); // Remove any remaining send streams, the default channel will be deleted // later. @@ -1870,6 +1935,12 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) { } } + // Force update of Video Engine BWE forwarding to reflect experiment setting. + if (!SetupSharedBandwidthEstimation(shared_bwe_vie_, + shared_bwe_vie_channel_)) { + return false; + } + LOG(LS_INFO) << "Set voice channel options. Current options: " << options_.ToString(); return true; @@ -1976,6 +2047,10 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( bool nack_enabled = nack_enabled_; bool enable_codec_fec = false; + // max_playback_rate <= 0 will not trigger setting of maximum encoding + // bandwidth. + int max_playback_rate = 0; + // Set send codec (the first non-telephone-event/CN codec) for (std::vector<AudioCodec>::const_iterator it = codecs.begin(); it != codecs.end(); ++it) { @@ -1992,40 +2067,6 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( continue; } - // If OPUS, change what we send according to the "stereo" codec - // parameter, and not the "channels" parameter. We set - // voe_codec.channels to 2 if "stereo=1" and 1 otherwise. If - // the bitrate is not specified, i.e. is zero, we set it to the - // appropriate default value for mono or stereo Opus. - if (IsOpus(*it)) { - if (IsOpusStereoEnabled(*it)) { - voe_codec.channels = 2; - if (!IsValidOpusBitrate(it->bitrate)) { - if (it->bitrate != 0) { - LOG(LS_WARNING) << "Overrides the invalid supplied bitrate(" - << it->bitrate - << ") with default opus stereo bitrate: " - << kOpusStereoBitrate; - } - voe_codec.rate = kOpusStereoBitrate; - } - } else { - voe_codec.channels = 1; - if (!IsValidOpusBitrate(it->bitrate)) { - if (it->bitrate != 0) { - LOG(LS_WARNING) << "Overrides the invalid supplied bitrate(" - << it->bitrate - << ") with default opus mono bitrate: " - << kOpusMonoBitrate; - } - voe_codec.rate = kOpusMonoBitrate; - } - } - int bitrate_from_params = GetOpusBitrateFromParams(*it); - if (bitrate_from_params != 0) { - voe_codec.rate = bitrate_from_params; - } - } // We'll use the first codec in the list to actually send audio data. // Be sure to use the payload type requested by the remote side. @@ -2055,8 +2096,11 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( } else { send_codec = voe_codec; nack_enabled = IsNackEnabled(*it); - // For Opus as the send codec, we enable inband FEC if requested. - enable_codec_fec = IsOpus(*it) && IsOpusFecEnabled(*it); + // For Opus as the send codec, we are to enable inband FEC if requested + // and set maximum playback rate. + if (IsOpus(*it)) { + GetOpusConfig(*it, &send_codec, &enable_codec_fec, &max_playback_rate); + } } found_send_codec = true; break; @@ -2090,6 +2134,21 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs( #endif // USE_WEBRTC_DEV_BRANCH } + // maxplaybackrate should be set after SetSendCodec. + if (max_playback_rate > 0) { + LOG(LS_INFO) << "Attempt to set maximum playback rate to " + << max_playback_rate + << " Hz on channel " + << channel; +#ifdef USE_WEBRTC_DEV_BRANCH + // (max_playback_rate + 1) >> 1 is to obtain ceil(max_playback_rate / 2.0). + if (engine()->voe()->codec()->SetOpusMaxPlaybackRate( + channel, max_playback_rate) == -1) { + LOG(LS_WARNING) << "Could not set maximum playback rate."; + } +#endif + } + // Always update the |send_codec_| to the currently set send codec. send_codec_.reset(new webrtc::CodecInst(send_codec)); @@ -2531,8 +2590,8 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) { } if (engine()->voe()->rtp()->SetRTCP_CNAME(channel, sp.cname.c_str()) == -1) { - LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); - return false; + LOG_RTCERR2(SetRTCP_CNAME, channel, sp.cname); + return false; } // Set the current codecs to be used for the new channel. @@ -2604,6 +2663,9 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { receive_channels_.insert(std::make_pair( default_receive_ssrc_, new WebRtcVoiceChannelRenderer(voe_channel(), audio_transport))); + if (!SetupSharedBweOnChannel(voe_channel())) { + return false; + } return SetPlayout(voe_channel(), playout_); } @@ -2691,6 +2753,11 @@ bool WebRtcVoiceMediaChannel::ConfigureRecvChannel(int channel) { return false; } + // Set up channel to be able to forward incoming packets to video engine BWE. + if (!SetupSharedBweOnChannel(channel)) { + return false; + } + return SetPlayout(channel, playout_); } @@ -3060,7 +3127,8 @@ void WebRtcVoiceMediaChannel::OnPacketReceived( engine()->voe()->network()->ReceivedRTPPacket( which_channel, packet->data(), - static_cast<unsigned int>(packet->length())); + static_cast<unsigned int>(packet->length()), + webrtc::PacketTime(packet_time.timestamp, packet_time.not_before)); } void WebRtcVoiceMediaChannel::OnRtcpReceived( @@ -3454,6 +3522,23 @@ int WebRtcVoiceMediaChannel::GetSendChannelNum(uint32 ssrc) { return -1; } +bool WebRtcVoiceMediaChannel::SetupSharedBandwidthEstimation( + webrtc::VideoEngine* vie, int vie_channel) { + shared_bwe_vie_ = vie; + shared_bwe_vie_channel_ = vie_channel; + + if (!SetupSharedBweOnChannel(voe_channel())) { + return false; + } + for (ChannelMap::iterator it = receive_channels_.begin(); + it != receive_channels_.end(); ++it) { + if (!SetupSharedBweOnChannel(it->second->channel())) { + return false; + } + } + return true; +} + bool WebRtcVoiceMediaChannel::GetRedSendCodec(const AudioCodec& red_codec, const std::vector<AudioCodec>& all_codecs, webrtc::CodecInst* send_codec) { // Get the RED encodings from the parameter with no name. This may @@ -3603,6 +3688,25 @@ bool WebRtcVoiceMediaChannel::SetHeaderExtension(ExtensionSetterFunction setter, return true; } +bool WebRtcVoiceMediaChannel::SetupSharedBweOnChannel(int voe_channel) { + webrtc::ViENetwork* vie_network = NULL; + int vie_channel = -1; + if (options_.combined_audio_video_bwe.GetWithDefaultIfUnset(false) && + shared_bwe_vie_ != NULL && shared_bwe_vie_channel_ != -1) { + vie_network = webrtc::ViENetwork::GetInterface(shared_bwe_vie_); + vie_channel = shared_bwe_vie_channel_; + } + if (engine()->voe()->rtp()->SetVideoEngineBWETarget(voe_channel, vie_network, + vie_channel) == -1) { + LOG_RTCERR3(SetVideoEngineBWETarget, voe_channel, vie_network, vie_channel); + if (vie_network != NULL) { + // Don't fail if we're tearing down. + return false; + } + } + return true; +} + int WebRtcSoundclipStream::Read(void *buf, int len) { size_t res = 0; mem_.Read(buf, len, &res, NULL); |