| Index: webrtc/media/engine/webrtcvoiceengine.cc
|
| diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
|
| index 71803cbee38c845e1cf4afbfa90c15ca94f062e3..4596b6fbceefbb99ed1d312668e46ce9692261f9 100644
|
| --- a/webrtc/media/engine/webrtcvoiceengine.cc
|
| +++ b/webrtc/media/engine/webrtcvoiceengine.cc
|
| @@ -464,42 +464,8 @@ const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[11] = {
|
| {kCnCodecName, 8000, 1, 13, false, {}},
|
| {kDtmfCodecName, 8000, 1, 126, false, {}}
|
| };
|
| -} // namespace {
|
|
|
| -bool SendCodecSpec::operator==(const SendCodecSpec& rhs) const {
|
| - if (nack_enabled != rhs.nack_enabled) {
|
| - return false;
|
| - }
|
| - if (transport_cc_enabled != rhs.transport_cc_enabled) {
|
| - return false;
|
| - }
|
| - if (enable_codec_fec != rhs.enable_codec_fec) {
|
| - return false;
|
| - }
|
| - if (enable_opus_dtx != rhs.enable_opus_dtx) {
|
| - return false;
|
| - }
|
| - if (opus_max_playback_rate != rhs.opus_max_playback_rate) {
|
| - return false;
|
| - }
|
| - if (red_payload_type != rhs.red_payload_type) {
|
| - return false;
|
| - }
|
| - if (cng_payload_type != rhs.cng_payload_type) {
|
| - return false;
|
| - }
|
| - if (cng_plfreq != rhs.cng_plfreq) {
|
| - return false;
|
| - }
|
| - if (codec_inst != rhs.codec_inst) {
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool SendCodecSpec::operator!=(const SendCodecSpec& rhs) const {
|
| - return !(*this == rhs);
|
| -}
|
| +} // namespace {
|
|
|
| bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in,
|
| webrtc::CodecInst* out) {
|
| @@ -1140,17 +1106,20 @@ AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const {
|
| class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| : public AudioSource::Sink {
|
| public:
|
| - WebRtcAudioSendStream(int ch,
|
| - webrtc::AudioTransport* voe_audio_transport,
|
| - uint32_t ssrc,
|
| - const std::string& c_name,
|
| - const SendCodecSpec& send_codec_spec,
|
| - const std::vector<webrtc::RtpExtension>& extensions,
|
| - webrtc::Call* call,
|
| - webrtc::Transport* send_transport)
|
| + WebRtcAudioSendStream(
|
| + int ch,
|
| + webrtc::AudioTransport* voe_audio_transport,
|
| + uint32_t ssrc,
|
| + const std::string& c_name,
|
| + const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec,
|
| + const std::vector<webrtc::RtpExtension>& extensions,
|
| + int max_send_bitrate_bps,
|
| + webrtc::Call* call,
|
| + webrtc::Transport* send_transport)
|
| : voe_audio_transport_(voe_audio_transport),
|
| call_(call),
|
| config_(send_transport),
|
| + max_send_bitrate_bps_(max_send_bitrate_bps),
|
| rtp_parameters_(CreateRtpParametersWithOneEncoding()) {
|
| RTC_DCHECK_GE(ch, 0);
|
| // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
|
| @@ -1169,7 +1138,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| call_->DestroyAudioSendStream(stream_);
|
| }
|
|
|
| - void RecreateAudioSendStream(const SendCodecSpec& send_codec_spec) {
|
| + void RecreateAudioSendStream(
|
| + const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
|
| RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
| if (stream_) {
|
| call_->DestroyAudioSendStream(stream_);
|
| @@ -1177,6 +1147,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| }
|
| config_.rtp.nack.rtp_history_ms =
|
| send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
|
| + config_.send_codec_spec = send_codec_spec;
|
| + config_.send_codec_spec.codec_inst.rate = DecideSendBitrate();
|
| RTC_DCHECK(!stream_);
|
| stream_ = call_->CreateAudioSendStream(config_);
|
| RTC_CHECK(stream_);
|
| @@ -1205,6 +1177,31 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| UpdateSendState();
|
| }
|
|
|
| + bool SetMaxSendBitrate(int bps) {
|
| + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
| + if (!IsMaxSendBitrateValid(
|
| + MinPositive(bps, rtp_parameters_.encodings[0].max_bitrate_bps))) {
|
| + return false;
|
| + }
|
| + max_send_bitrate_bps_ = bps;
|
| +
|
| + int new_sent_bitrate_bps = DecideSendBitrate();
|
| + if (config_.send_codec_spec.codec_inst.rate == new_sent_bitrate_bps)
|
| + return true;
|
| +
|
| + // Recreate AudioSendStream with new bit rate.
|
| + config_.send_codec_spec.codec_inst.rate = new_sent_bitrate_bps;
|
| + if (stream_) {
|
| + call_->DestroyAudioSendStream(stream_);
|
| + stream_ = nullptr;
|
| + }
|
| + RTC_DCHECK(!stream_);
|
| + stream_ = call_->CreateAudioSendStream(config_);
|
| + RTC_CHECK(stream_);
|
| + UpdateSendState();
|
| + return true;
|
| + }
|
| +
|
| bool SendTelephoneEvent(int payload_type, int event, int duration_ms) {
|
| RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
|
| RTC_DCHECK(stream_);
|
| @@ -1297,11 +1294,23 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| return rtp_parameters_;
|
| }
|
|
|
| - void SetRtpParameters(const webrtc::RtpParameters& parameters) {
|
| + bool SetRtpParameters(const webrtc::RtpParameters& parameters) {
|
| RTC_CHECK_EQ(1UL, parameters.encodings.size());
|
| +
|
| + if (!IsMaxSendBitrateValid(MinPositive(
|
| + max_send_bitrate_bps_, parameters.encodings[0].max_bitrate_bps))) {
|
| + return false;
|
| + }
|
| +
|
| rtp_parameters_ = parameters;
|
| +
|
| + // parameters.encodings[0].encodings[0].max_bitrate_bps could have changed.
|
| + SetMaxSendBitrate(max_send_bitrate_bps_);
|
| +
|
| // parameters.encodings[0].active could have changed.
|
| UpdateSendState();
|
| +
|
| + return true;
|
| }
|
|
|
| private:
|
| @@ -1316,6 +1325,61 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| }
|
| }
|
|
|
| + bool IsMaxSendBitrateValid(int bps) const {
|
| + if (bps <= 0) {
|
| + return true;
|
| + }
|
| +
|
| + if (config_.send_codec_spec.codec_inst.pltype == -1) {
|
| + LOG(LS_INFO) << "The send codec has not been set up yet. "
|
| + << "The send bitrate setting will be applied later.";
|
| + return true;
|
| + }
|
| +
|
| + if (!WebRtcVoiceCodecs::IsCodecMultiRate(
|
| + config_.send_codec_spec.codec_inst) &&
|
| + bps < config_.send_codec_spec.codec_inst.rate) {
|
| + // If codec is not multi-rate and |max_send_bit_rate_| is less than the
|
| + // fixed bitrate then fail. If codec is not multi-rate and |bps| exceeds
|
| + // or
|
| + // equal the fixed bitrate then ignore.
|
| + LOG(LS_ERROR) << "Failed to set codec "
|
| + << config_.send_codec_spec.codec_inst.plname
|
| + << " to bitrate " << bps << " bps"
|
| + << ", requires at least "
|
| + << config_.send_codec_spec.codec_inst.rate << " bps.";
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| + }
|
| +
|
| + int DecideSendBitrate() const {
|
| + const int bps = MinPositive(max_send_bitrate_bps_,
|
| + rtp_parameters_.encodings[0].max_bitrate_bps);
|
| + const int current_rate = config_.send_codec_spec.codec_inst.rate;
|
| +
|
| + // Bitrate is auto by default.
|
| + // TODO(bemasc): Fix this so that if SetMaxSendBitrate(50) is followed by
|
| + // SetMaxSendBitrate(0), the second call removes the previous limit.
|
| + if (bps <= 0) {
|
| + return current_rate;
|
| + }
|
| +
|
| + if (config_.send_codec_spec.codec_inst.pltype == -1) {
|
| + return current_rate;
|
| + }
|
| +
|
| + if (!WebRtcVoiceCodecs::IsCodecMultiRate(
|
| + config_.send_codec_spec.codec_inst)) {
|
| + return current_rate;
|
| + }
|
| +
|
| + // If codec is multi-rate then just set the bitrate.
|
| + return std::min(bps, WebRtcVoiceCodecs::MaxBitrateBps(
|
| + config_.send_codec_spec.codec_inst));
|
| + }
|
| +
|
| rtc::ThreadChecker worker_thread_checker_;
|
| rtc::RaceChecker audio_capture_race_checker_;
|
| webrtc::AudioTransport* const voe_audio_transport_ = nullptr;
|
| @@ -1331,6 +1395,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
|
| AudioSource* source_ = nullptr;
|
| bool send_ = false;
|
| bool muted_ = false;
|
| + int max_send_bitrate_bps_;
|
| webrtc::RtpParameters rtp_parameters_;
|
|
|
| RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
|
| @@ -1591,15 +1656,18 @@ bool WebRtcVoiceMediaChannel::SetRtpSendParameters(
|
| return false;
|
| }
|
|
|
| - if (!SetChannelSendParameters(it->second->channel(), parameters)) {
|
| - LOG(LS_WARNING) << "Failed to set send RtpParameters.";
|
| - return false;
|
| - }
|
| + // TODO(minyue): The following legacy actions go into
|
| + // |WebRtcAudioSendStream::SetRtpParameters()| which is called at the end,
|
| + // though there are two difference:
|
| + // 1. |WebRtcVoiceMediaChannel::SetChannelSendParameters()| only calls
|
| + // |SetSendCodec| while |WebRtcAudioSendStream::SetRtpParameters()| calls
|
| + // |SetSendCodecs|. The outcome should be the same.
|
| + // 2. AudioSendStream can be recreated.
|
| +
|
| // Codecs are handled at the WebRtcVoiceMediaChannel level.
|
| webrtc::RtpParameters reduced_params = parameters;
|
| reduced_params.codecs.clear();
|
| - it->second->SetRtpParameters(reduced_params);
|
| - return true;
|
| + return it->second->SetRtpParameters(reduced_params);
|
| }
|
|
|
| webrtc::RtpParameters WebRtcVoiceMediaChannel::GetRtpReceiveParameters(
|
| @@ -1768,7 +1836,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
| // with the proper configuration for VAD, CNG, NACK and Opus-specific
|
| // parameters.
|
| // TODO(solenberg): Refactor this logic once we create AudioEncoders here.
|
| - SendCodecSpec send_codec_spec;
|
| + webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec;
|
| {
|
| send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled;
|
|
|
| @@ -1842,9 +1910,6 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
| send_codec_spec_ = std::move(send_codec_spec);
|
| for (const auto& kv : send_streams_) {
|
| kv.second->RecreateAudioSendStream(send_codec_spec_);
|
| - if (!SetSendCodecs(kv.second->channel(), kv.second->rtp_parameters())) {
|
| - return false;
|
| - }
|
| }
|
| }
|
|
|
| @@ -1866,131 +1931,6 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
| return true;
|
| }
|
|
|
| -// Apply current codec settings to a single voe::Channel used for sending.
|
| -bool WebRtcVoiceMediaChannel::SetSendCodecs(
|
| - int channel,
|
| - const webrtc::RtpParameters& rtp_parameters) {
|
| - // Disable VAD and FEC unless we know the other side wants them.
|
| - engine()->voe()->codec()->SetVADStatus(channel, false);
|
| - engine()->voe()->codec()->SetFECStatus(channel, false);
|
| -
|
| - // Set the codec immediately, since SetVADStatus() depends on whether
|
| - // the current codec is mono or stereo.
|
| - if (!SetSendCodec(channel, send_codec_spec_.codec_inst)) {
|
| - return false;
|
| - }
|
| -
|
| - // FEC should be enabled after SetSendCodec.
|
| - if (send_codec_spec_.enable_codec_fec) {
|
| - LOG(LS_INFO) << "Attempt to enable codec internal FEC on channel "
|
| - << channel;
|
| - if (engine()->voe()->codec()->SetFECStatus(channel, true) == -1) {
|
| - // Enable codec internal FEC. Treat any failure as fatal internal error.
|
| - LOG_RTCERR2(SetFECStatus, channel, true);
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - if (IsCodec(send_codec_spec_.codec_inst, kOpusCodecName)) {
|
| - // DTX and maxplaybackrate should be set after SetSendCodec. Because current
|
| - // send codec has to be Opus.
|
| -
|
| - // Set Opus internal DTX.
|
| - LOG(LS_INFO) << "Attempt to "
|
| - << (send_codec_spec_.enable_opus_dtx ? "enable" : "disable")
|
| - << " Opus DTX on channel "
|
| - << channel;
|
| - if (engine()->voe()->codec()->SetOpusDtx(channel,
|
| - send_codec_spec_.enable_opus_dtx)) {
|
| - LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec_.enable_opus_dtx);
|
| - return false;
|
| - }
|
| -
|
| - // If opus_max_playback_rate <= 0, the default maximum playback rate
|
| - // (48 kHz) will be used.
|
| - if (send_codec_spec_.opus_max_playback_rate > 0) {
|
| - LOG(LS_INFO) << "Attempt to set maximum playback rate to "
|
| - << send_codec_spec_.opus_max_playback_rate
|
| - << " Hz on channel "
|
| - << channel;
|
| - if (engine()->voe()->codec()->SetOpusMaxPlaybackRate(
|
| - channel, send_codec_spec_.opus_max_playback_rate) == -1) {
|
| - LOG_RTCERR2(SetOpusMaxPlaybackRate, channel,
|
| - send_codec_spec_.opus_max_playback_rate);
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - // TODO(solenberg): SetMaxSendBitrate() yields another call to SetSendCodec().
|
| - // Check if it is possible to fuse with the previous call in this function.
|
| - SetChannelSendParameters(channel, rtp_parameters);
|
| -
|
| - // Set the CN payloadtype and the VAD status.
|
| - if (send_codec_spec_.cng_payload_type != -1) {
|
| - // The CN payload type for 8000 Hz clockrate is fixed at 13.
|
| - if (send_codec_spec_.cng_plfreq != 8000) {
|
| - webrtc::PayloadFrequencies cn_freq;
|
| - switch (send_codec_spec_.cng_plfreq) {
|
| - case 16000:
|
| - cn_freq = webrtc::kFreq16000Hz;
|
| - break;
|
| - case 32000:
|
| - cn_freq = webrtc::kFreq32000Hz;
|
| - break;
|
| - default:
|
| - RTC_NOTREACHED();
|
| - return false;
|
| - }
|
| - if (engine()->voe()->codec()->SetSendCNPayloadType(
|
| - channel, send_codec_spec_.cng_payload_type, cn_freq) == -1) {
|
| - LOG_RTCERR3(SetSendCNPayloadType, channel,
|
| - send_codec_spec_.cng_payload_type, cn_freq);
|
| - // TODO(ajm): This failure condition will be removed from VoE.
|
| - // Restore the return here when we update to a new enough webrtc.
|
| - //
|
| - // Not returning false because the SetSendCNPayloadType will fail if
|
| - // the channel is already sending.
|
| - // This can happen if the remote description is applied twice, for
|
| - // example in the case of ROAP on top of JSEP, where both side will
|
| - // send the offer.
|
| - }
|
| - }
|
| -
|
| - // Only turn on VAD if we have a CN payload type that matches the
|
| - // clockrate for the codec we are going to use.
|
| - if (send_codec_spec_.cng_plfreq == send_codec_spec_.codec_inst.plfreq &&
|
| - send_codec_spec_.codec_inst.channels == 1) {
|
| - // TODO(minyue): If CN frequency == 48000 Hz is allowed, consider the
|
| - // interaction between VAD and Opus FEC.
|
| - LOG(LS_INFO) << "Enabling VAD";
|
| - if (engine()->voe()->codec()->SetVADStatus(channel, true) == -1) {
|
| - LOG_RTCERR2(SetVADStatus, channel, true);
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool WebRtcVoiceMediaChannel::SetSendCodec(
|
| - int channel, const webrtc::CodecInst& send_codec) {
|
| - LOG(LS_INFO) << "Send channel " << channel << " selected voice codec "
|
| - << ToString(send_codec) << ", bitrate=" << send_codec.rate;
|
| -
|
| - webrtc::CodecInst current_codec = {0};
|
| - if (engine()->voe()->codec()->GetSendCodec(channel, current_codec) == 0 &&
|
| - (send_codec == current_codec)) {
|
| - // Codec is already configured, we can return without setting it again.
|
| - return true;
|
| - }
|
| -
|
| - if (engine()->voe()->codec()->SetSendCodec(channel, send_codec) == -1) {
|
| - LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec));
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| void WebRtcVoiceMediaChannel::SetPlayout(bool playout) {
|
| desired_playout_ = playout;
|
| return ChangePlayout(desired_playout_);
|
| @@ -2100,17 +2040,9 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
|
|
|
| WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
|
| channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
|
| - send_rtp_extensions_, call_, this);
|
| + send_rtp_extensions_, max_send_bitrate_bps_, call_, this);
|
| send_streams_.insert(std::make_pair(ssrc, stream));
|
|
|
| - // Set the current codecs to be used for the new channel. We need to do this
|
| - // after adding the channel to send_channels_, because of how max bitrate is
|
| - // currently being configured by SetSendCodec().
|
| - if (HasSendCodec() && !SetSendCodecs(channel, stream->rtp_parameters())) {
|
| - RemoveSendStream(ssrc);
|
| - return false;
|
| - }
|
| -
|
| // At this point the stream's local SSRC has been updated. If it is the first
|
| // send stream, make sure that all the receive streams are updated with the
|
| // same SSRC in order to send receiver reports.
|
| @@ -2484,68 +2416,13 @@ bool WebRtcVoiceMediaChannel::MuteStream(uint32_t ssrc, bool muted) {
|
| bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int bps) {
|
| LOG(LS_INFO) << "WebRtcVoiceMediaChannel::SetMaxSendBitrate.";
|
| max_send_bitrate_bps_ = bps;
|
| -
|
| + bool success = true;
|
| for (const auto& kv : send_streams_) {
|
| - if (!SetChannelSendParameters(kv.second->channel(),
|
| - kv.second->rtp_parameters())) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool WebRtcVoiceMediaChannel::SetChannelSendParameters(
|
| - int channel,
|
| - const webrtc::RtpParameters& parameters) {
|
| - RTC_CHECK_EQ(1UL, parameters.encodings.size());
|
| - // TODO(deadbeef): Handle setting parameters with a list of codecs in a
|
| - // different order (which should change the send codec).
|
| - return SetMaxSendBitrate(
|
| - channel, MinPositive(max_send_bitrate_bps_,
|
| - parameters.encodings[0].max_bitrate_bps));
|
| -}
|
| -
|
| -bool WebRtcVoiceMediaChannel::SetMaxSendBitrate(int channel, int bps) {
|
| - // Bitrate is auto by default.
|
| - // TODO(bemasc): Fix this so that if SetMaxSendBandwidth(50) is followed by
|
| - // SetMaxSendBandwith(0), the second call removes the previous limit.
|
| - if (bps <= 0) {
|
| - return true;
|
| - }
|
| -
|
| - if (!HasSendCodec()) {
|
| - LOG(LS_INFO) << "The send codec has not been set up yet. "
|
| - << "The send bitrate setting will be applied later.";
|
| - return true;
|
| - }
|
| -
|
| - webrtc::CodecInst codec = send_codec_spec_.codec_inst;
|
| - bool is_multi_rate = WebRtcVoiceCodecs::IsCodecMultiRate(codec);
|
| -
|
| - if (is_multi_rate) {
|
| - // If codec is multi-rate then just set the bitrate.
|
| - int max_bitrate_bps = WebRtcVoiceCodecs::MaxBitrateBps(codec);
|
| - codec.rate = std::min(bps, max_bitrate_bps);
|
| - LOG(LS_INFO) << "Setting codec " << codec.plname << " to bitrate " << bps
|
| - << " bps.";
|
| - if (!SetSendCodec(channel, codec)) {
|
| - LOG(LS_ERROR) << "Failed to set codec " << codec.plname << " to bitrate "
|
| - << bps << " bps.";
|
| - return false;
|
| + if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) {
|
| + success = false;
|
| }
|
| - return true;
|
| - } else {
|
| - // If codec is not multi-rate and |bps| is less than the fixed bitrate
|
| - // then fail. If codec is not multi-rate and |bps| exceeds or equal the
|
| - // fixed bitrate then ignore.
|
| - if (bps < codec.rate) {
|
| - LOG(LS_ERROR) << "Failed to set codec " << codec.plname << " to bitrate "
|
| - << bps << " bps"
|
| - << ", requires at least " << codec.rate << " bps.";
|
| - return false;
|
| - }
|
| - return true;
|
| }
|
| + return success;
|
| }
|
|
|
| void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) {
|
|
|