From 7a973447eb147e60f2184bc42f7a878a1e087f0e Mon Sep 17 00:00:00 2001 From: minyue Date: Thu, 20 Oct 2016 03:27:12 -0700 Subject: [PATCH] Moving WebRtcVoiceMediaChannel::SendSetCodec to AudioSendStream. BUG=webrtc:5806, webrtc:4690 Review-Url: https://codereview.webrtc.org/2405183002 Cr-Commit-Position: refs/heads/master@{#14700} --- webrtc/api/call/audio_send_stream.h | 55 +- webrtc/audio/audio_send_stream.cc | 155 ++++- webrtc/audio/audio_send_stream.h | 2 + webrtc/audio/audio_send_stream_unittest.cc | 77 ++- webrtc/media/engine/webrtcvoiceengine.cc | 353 ++++-------- webrtc/media/engine/webrtcvoiceengine.h | 30 +- .../engine/webrtcvoiceengine_unittest.cc | 541 +++++++----------- 7 files changed, 608 insertions(+), 605 deletions(-) diff --git a/webrtc/api/call/audio_send_stream.h b/webrtc/api/call/audio_send_stream.h index b309f7a221..ae7531cbcb 100644 --- a/webrtc/api/call/audio_send_stream.h +++ b/webrtc/api/call/audio_send_stream.h @@ -83,17 +83,60 @@ class AudioSendStream { // of Call. int voe_channel_id = -1; - // Ownership of the encoder object is transferred to Call when the config is - // passed to Call::CreateAudioSendStream(). - // TODO(solenberg): Implement, once we configure codecs through the new API. - // std::unique_ptr encoder; - int cng_payload_type = -1; // pt, or -1 to disable Comfort Noise Generator. - // Bitrate limits used for variable audio bitrate streams. Set both to -1 to // disable audio bitrate adaptation. // Note: This is still an experimental feature and not ready for real usage. int min_bitrate_kbps = -1; int max_bitrate_kbps = -1; + + struct SendCodecSpec { + SendCodecSpec() { + webrtc::CodecInst empty_inst = {0}; + codec_inst = empty_inst; + codec_inst.pltype = -1; + } + bool 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 (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 operator!=(const SendCodecSpec& rhs) const { + return !(*this == rhs); + } + + bool nack_enabled = false; + bool transport_cc_enabled = false; + bool enable_codec_fec = false; + bool enable_opus_dtx = false; + int opus_max_playback_rate = 0; + int cng_payload_type = -1; + int cng_plfreq = -1; + webrtc::CodecInst codec_inst; + } send_codec_spec; }; // Starts stream activity. diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc index ee84b96aaa..fbed0f12af 100644 --- a/webrtc/audio/audio_send_stream.cc +++ b/webrtc/audio/audio_send_stream.cc @@ -30,6 +30,34 @@ #include "webrtc/voice_engine/voice_engine_impl.h" namespace webrtc { + +namespace { + +constexpr char kOpusCodecName[] = "opus"; + +// TODO(minyue): Remove |LOG_RTCERR2|. +#define LOG_RTCERR2(func, a1, a2, err) \ + LOG(LS_WARNING) << "" << #func << "(" << a1 << ", " << a2 \ + << ") failed, err=" << err + +// TODO(minyue): Remove |LOG_RTCERR3|. +#define LOG_RTCERR3(func, a1, a2, a3, err) \ + LOG(LS_WARNING) << "" << #func << "(" << a1 << ", " << a2 << ", " << a3 \ + << ") failed, err=" << err + +std::string ToString(const webrtc::CodecInst& codec) { + std::stringstream ss; + ss << codec.plname << "/" << codec.plfreq << "/" << codec.channels << " (" + << codec.pltype << ")"; + return ss.str(); +} + +bool IsCodec(const webrtc::CodecInst& codec, const char* ref_name) { + return (_stricmp(codec.plname, ref_name) == 0); +} + +} // namespace + std::string AudioSendStream::Config::Rtp::ToString() const { std::stringstream ss; ss << "{ssrc: " << ssrc; @@ -52,7 +80,7 @@ std::string AudioSendStream::Config::ToString() const { ss << "{rtp: " << rtp.ToString(); ss << ", voe_channel_id: " << voe_channel_id; // TODO(solenberg): Encoder config. - ss << ", cng_payload_type: " << cng_payload_type; + ss << ", cng_payload_type: " << send_codec_spec.cng_payload_type; ss << '}'; return ss.str(); } @@ -102,6 +130,9 @@ AudioSendStream::AudioSendStream( RTC_NOTREACHED() << "Registering unsupported RTP extension."; } } + if (!SetupSendCodec()) { + LOG(LS_ERROR) << "Failed to set up send codec state."; + } } AudioSendStream::~AudioSendStream() { @@ -285,5 +316,127 @@ VoiceEngine* AudioSendStream::voice_engine() const { RTC_DCHECK(voice_engine); return voice_engine; } + +// Apply current codec settings to a single voe::Channel used for sending. +bool AudioSendStream::SetupSendCodec() { + ScopedVoEInterface base(voice_engine()); + ScopedVoEInterface codec(voice_engine()); + + const int channel = config_.voe_channel_id; + + // Disable VAD and FEC unless we know the other side wants them. + codec->SetVADStatus(channel, false); + codec->SetFECStatus(channel, false); + + const auto& send_codec_spec = config_.send_codec_spec; + + // Set the codec immediately, since SetVADStatus() depends on whether + // the current codec is mono or stereo. + LOG(LS_INFO) << "Send channel " << channel << " selected voice codec " + << ToString(send_codec_spec.codec_inst) + << ", bitrate=" << send_codec_spec.codec_inst.rate; + + // If codec is already configured, we do not it again. + // TODO(minyue): check if this check is really needed, or can we move it into + // |codec->SetSendCodec|. + webrtc::CodecInst current_codec = {0}; + if (codec->GetSendCodec(channel, current_codec) != 0 || + (send_codec_spec.codec_inst != current_codec)) { + if (codec->SetSendCodec(channel, send_codec_spec.codec_inst) == -1) { + LOG_RTCERR2(SetSendCodec, channel, ToString(send_codec_spec.codec_inst), + base->LastError()); + 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 (codec->SetFECStatus(channel, true) == -1) { + // Enable codec internal FEC. Treat any failure as fatal internal error. + LOG_RTCERR2(SetFECStatus, channel, true, base->LastError()); + 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 (codec->SetOpusDtx(channel, send_codec_spec.enable_opus_dtx)) { + LOG_RTCERR2(SetOpusDtx, channel, send_codec_spec.enable_opus_dtx, + base->LastError()); + 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 (codec->SetOpusMaxPlaybackRate( + channel, send_codec_spec.opus_max_playback_rate) == -1) { + LOG_RTCERR2(SetOpusMaxPlaybackRate, channel, + send_codec_spec.opus_max_playback_rate, base->LastError()); + return false; + } + } + } + + // 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 (codec->SetSendCNPayloadType(channel, send_codec_spec.cng_payload_type, + cn_freq) == -1) { + LOG_RTCERR3(SetSendCNPayloadType, channel, + send_codec_spec.cng_payload_type, cn_freq, + base->LastError()); + + // 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 (codec->SetVADStatus(channel, true) == -1) { + LOG_RTCERR2(SetVADStatus, channel, true, base->LastError()); + return false; + } + } + } + return true; +} + } // namespace internal } // namespace webrtc diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h index 2e0b7aed58..5a2864b77f 100644 --- a/webrtc/audio/audio_send_stream.h +++ b/webrtc/audio/audio_send_stream.h @@ -61,6 +61,8 @@ class AudioSendStream final : public webrtc::AudioSendStream, private: VoiceEngine* voice_engine() const; + bool SetupSendCodec(); + rtc::ThreadChecker thread_checker_; rtc::TaskQueue* worker_queue_; const webrtc::AudioSendStream::Config config_; diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc index a05c00ba49..c17e8e393c 100644 --- a/webrtc/audio/audio_send_stream_unittest.cc +++ b/webrtc/audio/audio_send_stream_unittest.cc @@ -44,11 +44,11 @@ const int kEchoReturnLossEnhancement = 101; const unsigned int kSpeechInputLevel = 96; const CallStatistics kCallStats = { 1345, 1678, 1901, 1234, 112, 13456, 17890, 1567, -1890, -1123}; -const CodecInst kCodecInst = {-121, "codec_name_send", 48000, -231, 0, -671}; const ReportBlock kReportBlock = {456, 780, 123, 567, 890, 132, 143, 13354}; const int kTelephoneEventPayloadType = 123; const int kTelephoneEventCode = 45; const int kTelephoneEventDuration = 6789; +const CodecInst kIsacCodec = {103, "isac", 16000, 320, 1, 32000}; class MockLimitObserver : public BitrateAllocator::LimitObserver { public: @@ -111,6 +111,7 @@ struct ConfigHelper { .Times(1); // Destructor resets the event log return channel_proxy_; })); + SetupMockForSetupSendCodec(); stream_config_.voe_channel_id = kChannelId; stream_config_.rtp.ssrc = kSsrc; stream_config_.rtp.nack.rtp_history_ms = 200; @@ -121,6 +122,9 @@ struct ConfigHelper { RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId)); stream_config_.rtp.extensions.push_back(RtpExtension( RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId)); + // Use ISAC as default codec so as to prevent unnecessary |voice_engine_| + // calls from the default ctor behavior. + stream_config_.send_codec_spec.codec_inst = kIsacCodec; } AudioSendStream::Config& config() { return stream_config_; } @@ -132,6 +136,19 @@ struct ConfigHelper { BitrateAllocator* bitrate_allocator() { return &bitrate_allocator_; } rtc::TaskQueue* worker_queue() { return &worker_queue_; } RtcEventLog* event_log() { return &event_log_; } + MockVoiceEngine* voice_engine() { return &voice_engine_; } + + void SetupMockForSetupSendCodec() { + EXPECT_CALL(voice_engine_, SetVADStatus(kChannelId, false, _, _)) + .WillOnce(Return(0)); + EXPECT_CALL(voice_engine_, SetFECStatus(kChannelId, false)) + .WillOnce(Return(0)); + // Let |GetSendCodec| return -1 for the first time to indicate that no send + // codec has been set. + EXPECT_CALL(voice_engine_, GetSendCodec(kChannelId, _)) + .WillOnce(Return(-1)); + EXPECT_CALL(voice_engine_, SetSendCodec(kChannelId, _)).WillOnce(Return(0)); + } void SetupMockForSendTelephoneEvent() { EXPECT_TRUE(channel_proxy_); @@ -162,7 +179,7 @@ struct ConfigHelper { .WillRepeatedly(Return(report_blocks)); EXPECT_CALL(voice_engine_, GetSendCodec(kChannelId, _)) - .WillRepeatedly(DoAll(SetArgReferee<1>(kCodecInst), Return(0))); + .WillRepeatedly(DoAll(SetArgReferee<1>(kIsacCodec), Return(0))); EXPECT_CALL(voice_engine_, GetSpeechInputLevelFullRange(_)) .WillRepeatedly(DoAll(SetArgReferee<0>(kSpeechInputLevel), Return(0))); EXPECT_CALL(voice_engine_, GetEcMetricsStatus(_)) @@ -201,7 +218,7 @@ TEST(AudioSendStreamTest, ConfigToString) { RtpExtension(RtpExtension::kAbsSendTimeUri, kAbsSendTimeId)); config.rtp.c_name = kCName; config.voe_channel_id = kChannelId; - config.cng_payload_type = 42; + config.send_codec_spec.cng_payload_type = 42; EXPECT_EQ( "{rtp: {ssrc: 1234, extensions: [{uri: " "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time, id: 3}], " @@ -253,11 +270,11 @@ TEST(AudioSendStreamTest, GetStats) { EXPECT_EQ(static_cast(kReportBlock.cumulative_num_packets_lost), stats.packets_lost); EXPECT_EQ(Q8ToFloat(kReportBlock.fraction_lost), stats.fraction_lost); - EXPECT_EQ(std::string(kCodecInst.plname), stats.codec_name); + EXPECT_EQ(std::string(kIsacCodec.plname), stats.codec_name); EXPECT_EQ(static_cast(kReportBlock.extended_highest_sequence_number), stats.ext_seqnum); EXPECT_EQ(static_cast(kReportBlock.interarrival_jitter / - (kCodecInst.plfreq / 1000)), + (kIsacCodec.plfreq / 1000)), stats.jitter_ms); EXPECT_EQ(kCallStats.rttMs, stats.rtt_ms); EXPECT_EQ(static_cast(kSpeechInputLevel), stats.audio_level); @@ -287,5 +304,55 @@ TEST(AudioSendStreamTest, GetStatsTypingNoiseDetected) { voe_observer->CallbackOnError(-1, VE_TYPING_NOISE_OFF_WARNING); EXPECT_FALSE(send_stream.GetStats().typing_noise_detected); } + +TEST(AudioSendStreamTest, SendCodecAppliesConfigParams) { + ConfigHelper helper; + auto stream_config = helper.config(); + const CodecInst kOpusCodec = {111, "opus", 48000, 960, 2, 64000}; + stream_config.send_codec_spec.codec_inst = kOpusCodec; + stream_config.send_codec_spec.enable_codec_fec = true; + stream_config.send_codec_spec.enable_opus_dtx = true; + stream_config.send_codec_spec.opus_max_playback_rate = 12345; + stream_config.send_codec_spec.cng_plfreq = 16000; + stream_config.send_codec_spec.cng_payload_type = 105; + EXPECT_CALL(*helper.voice_engine(), SetFECStatus(kChannelId, true)) + .WillOnce(Return(0)); + EXPECT_CALL( + *helper.voice_engine(), + SetOpusDtx(kChannelId, stream_config.send_codec_spec.enable_opus_dtx)) + .WillOnce(Return(0)); + EXPECT_CALL( + *helper.voice_engine(), + SetOpusMaxPlaybackRate( + kChannelId, stream_config.send_codec_spec.opus_max_playback_rate)) + .WillOnce(Return(0)); + EXPECT_CALL(*helper.voice_engine(), + SetSendCNPayloadType( + kChannelId, stream_config.send_codec_spec.cng_payload_type, + webrtc::kFreq16000Hz)) + .WillOnce(Return(0)); + internal::AudioSendStream send_stream( + stream_config, helper.audio_state(), helper.worker_queue(), + helper.congestion_controller(), helper.bitrate_allocator(), + helper.event_log()); +} + +// VAD is applied when codec is mono and the CNG frequency matches the codec +// sample rate. +TEST(AudioSendStreamTest, SendCodecCanApplyVad) { + ConfigHelper helper; + auto stream_config = helper.config(); + const CodecInst kG722Codec = {9, "g722", 8000, 160, 1, 16000}; + stream_config.send_codec_spec.codec_inst = kG722Codec; + stream_config.send_codec_spec.cng_plfreq = 8000; + stream_config.send_codec_spec.cng_payload_type = 105; + EXPECT_CALL(*helper.voice_engine(), SetVADStatus(kChannelId, true, _, _)) + .WillOnce(Return(0)); + internal::AudioSendStream send_stream( + stream_config, helper.audio_state(), helper.worker_queue(), + helper.congestion_controller(), helper.bitrate_allocator(), + helper.event_log()); +} + } // namespace test } // namespace webrtc diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc index b9fd1f2a27..d1d5827eac 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -464,42 +464,41 @@ 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; +rtc::Optional ComputeSendBitrate(int max_send_bitrate_bps, + int rtp_max_bitrate_bps, + const webrtc::CodecInst& codec_inst) { + const int bps = MinPositive(max_send_bitrate_bps, rtp_max_bitrate_bps); + const int codec_rate = codec_inst.rate; + + if (bps <= 0) { + return rtc::Optional(codec_rate); } - if (transport_cc_enabled != rhs.transport_cc_enabled) { - return false; + + if (codec_inst.pltype == -1) { + return rtc::Optional(codec_rate); + ; } - if (enable_codec_fec != rhs.enable_codec_fec) { - return false; + + if (WebRtcVoiceCodecs::IsCodecMultiRate(codec_inst)) { + // If codec is multi-rate then just set the bitrate. + return rtc::Optional( + std::min(bps, WebRtcVoiceCodecs::MaxBitrateBps(codec_inst))); } - if (enable_opus_dtx != rhs.enable_opus_dtx) { - return false; + + if (bps < codec_inst.rate) { + // 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. + LOG(LS_ERROR) << "Failed to set codec " << codec_inst.plname + << " to bitrate " << bps << " bps" + << ", requires at least " << codec_inst.rate << " bps."; + return rtc::Optional(); } - 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; + return rtc::Optional(codec_rate); } -bool SendCodecSpec::operator!=(const SendCodecSpec& rhs) const { - return !(*this == rhs); -} +} // namespace { bool WebRtcVoiceEngine::ToCodecInst(const AudioCodec& in, webrtc::CodecInst* out) { @@ -1144,17 +1143,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& 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& 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: @@ -1173,10 +1175,22 @@ 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()); + send_codec_spec_ = send_codec_spec; config_.rtp.nack.rtp_history_ms = - send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0; + send_codec_spec_.nack_enabled ? kNackRtpHistoryMs : 0; + config_.send_codec_spec = send_codec_spec_; + + auto send_rate = ComputeSendBitrate( + max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps, + send_codec_spec.codec_inst); + if (send_rate) { + // Apply a send rate that abides by |max_send_bitrate_bps_| and + // |rtp_parameters_| when possible. Otherwise use the codec rate. + config_.send_codec_spec.codec_inst.rate = *send_rate; + } RecreateAudioSendStream(); } @@ -1187,6 +1201,25 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream RecreateAudioSendStream(); } + bool SetMaxSendBitrate(int bps) { + RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); + auto send_rate = + ComputeSendBitrate(bps, rtp_parameters_.encodings[0].max_bitrate_bps, + send_codec_spec_.codec_inst); + if (!send_rate) { + return false; + } + + max_send_bitrate_bps_ = bps; + + if (config_.send_codec_spec.codec_inst.rate != *send_rate) { + // Recreate AudioSendStream with new bit rate. + config_.send_codec_spec.codec_inst.rate = *send_rate; + RecreateAudioSendStream(); + } + return true; + } + bool SendTelephoneEvent(int payload_type, int event, int duration_ms) { RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); RTC_DCHECK(stream_); @@ -1279,11 +1312,27 @@ 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()); + auto send_rate = ComputeSendBitrate(max_send_bitrate_bps_, + parameters.encodings[0].max_bitrate_bps, + send_codec_spec_.codec_inst); + if (!send_rate) { + return false; + } + rtp_parameters_ = parameters; - // parameters.encodings[0].active could have changed. - UpdateSendState(); + + // parameters.encodings[0].encodings[0].max_bitrate_bps could have changed. + if (config_.send_codec_spec.codec_inst.rate != *send_rate) { + // Recreate AudioSendStream with new bit rate. + config_.send_codec_spec.codec_inst.rate = *send_rate; + RecreateAudioSendStream(); + } else { + // parameters.encodings[0].active could have changed. + UpdateSendState(); + } + return true; } private: @@ -1332,7 +1381,9 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream AudioSource* source_ = nullptr; bool send_ = false; bool muted_ = false; + int max_send_bitrate_bps_; webrtc::RtpParameters rtp_parameters_; + webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream); }; @@ -1592,15 +1643,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( @@ -1760,7 +1814,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; @@ -1834,9 +1888,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; - } } } @@ -1858,131 +1909,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) { TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::SetPlayout"); RTC_DCHECK(worker_thread_checker_.CalledOnValidThread()); @@ -2087,17 +2013,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. @@ -2471,68 +2389,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; + if (!kv.second->SetMaxSendBitrate(max_send_bitrate_bps_)) { + success = 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; - } - 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) { diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h index 71bd874347..b675284e55 100644 --- a/webrtc/media/engine/webrtcvoiceengine.h +++ b/webrtc/media/engine/webrtcvoiceengine.h @@ -37,26 +37,6 @@ class AudioSource; class VoEWrapper; class WebRtcVoiceMediaChannel; -struct SendCodecSpec { - SendCodecSpec() { - webrtc::CodecInst empty_inst = {0}; - codec_inst = empty_inst; - codec_inst.pltype = -1; - } - bool operator==(const SendCodecSpec& rhs) const; - bool operator!=(const SendCodecSpec& rhs) const; - - bool nack_enabled = false; - bool transport_cc_enabled = false; - bool enable_codec_fec = false; - bool enable_opus_dtx = false; - int opus_max_playback_rate = 0; - int red_payload_type = -1; - int cng_payload_type = -1; - int cng_plfreq = -1; - webrtc::CodecInst codec_inst; -}; - // WebRtcVoiceEngine is a class to be used with CompositeMediaEngine. // It uses the WebRtc VoiceEngine library for audio handling. class WebRtcVoiceEngine final : public webrtc::TraceCallback { @@ -237,8 +217,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, bool SetOptions(const AudioOptions& options); bool SetRecvCodecs(const std::vector& codecs); bool SetSendCodecs(const std::vector& codecs); - bool SetSendCodecs(int channel, const webrtc::RtpParameters& rtp_parameters); - bool SetSendCodec(int channel, const webrtc::CodecInst& send_codec); bool SetLocalSource(uint32_t ssrc, AudioSource* source); bool MuteStream(uint32_t ssrc, bool mute); @@ -251,12 +229,6 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, return default_recv_ssrc_ == static_cast(ssrc); } bool SetMaxSendBitrate(int bps); - bool SetChannelSendParameters(int channel, - const webrtc::RtpParameters& parameters); - bool SetMaxSendBitrate(int channel, int bps); - bool HasSendCodec() const { - return send_codec_spec_.codec_inst.pltype != -1; - } bool ValidateRtpParameters(const webrtc::RtpParameters& parameters); void SetupRecording(); @@ -293,7 +265,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, std::map recv_streams_; std::vector recv_rtp_extensions_; - SendCodecSpec send_codec_spec_; + webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceMediaChannel); }; diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc index 80c3fda271..f05254c7c6 100644 --- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc +++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc @@ -241,11 +241,7 @@ class WebRtcVoiceEngineTestFake : public testing::Test { parameters.codecs.push_back(codec); parameters.max_bandwidth_bps = max_bitrate; EXPECT_EQ(expected_result, channel_->SetSendParameters(parameters)); - - int channel_num = voe_.GetLastChannel(); - webrtc::CodecInst temp_codec; - EXPECT_FALSE(voe_.GetSendCodec(channel_num, temp_codec)); - EXPECT_EQ(expected_bitrate, temp_codec.rate); + EXPECT_EQ(expected_bitrate, GetCodecBitrate(kSsrc1)); } // Sets the per-stream maximum bitrate limit for the specified SSRC. @@ -264,14 +260,34 @@ class WebRtcVoiceEngineTestFake : public testing::Test { return channel_->SetSendParameters(send_parameters); } + void CheckSendCodec(int32_t ssrc, + const char expected_name[], + int expected_channels, + int expected_bitrate) { + const auto& codec = GetSendStreamConfig(ssrc).send_codec_spec.codec_inst; + EXPECT_STREQ(expected_name, codec.plname); + EXPECT_EQ(expected_channels, codec.channels); + EXPECT_EQ(expected_bitrate, codec.rate); + } + + int GetOpusMaxPlaybackRate(int32_t ssrc) { + return GetSendStreamConfig(ssrc).send_codec_spec.opus_max_playback_rate; + } + + bool GetOpusDtx(int32_t ssrc) { + return GetSendStreamConfig(ssrc).send_codec_spec.enable_opus_dtx; + } + + bool GetCodecFec(int32_t ssrc) { + return GetSendStreamConfig(ssrc).send_codec_spec.enable_codec_fec; + } + int GetCodecBitrate(int32_t ssrc) { - cricket::WebRtcVoiceMediaChannel* media_channel = - static_cast(channel_); - int channel = media_channel->GetSendChannelId(ssrc); - EXPECT_NE(-1, channel); - webrtc::CodecInst codec; - EXPECT_FALSE(voe_.GetSendCodec(channel, codec)); - return codec.rate; + return GetSendStreamConfig(ssrc).send_codec_spec.codec_inst.rate; + } + + int GetCodecPacSize(int32_t ssrc) { + return GetSendStreamConfig(ssrc).send_codec_spec.codec_inst.pacsize; } void SetAndExpectMaxBitrate(const cricket::AudioCodec& codec, @@ -850,10 +866,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthMultiRateAsCallee) { EXPECT_TRUE(channel_->AddSendStream( cricket::StreamParams::CreateLegacy(kSsrc1))); - int channel_num = voe_.GetLastChannel(); - webrtc::CodecInst codec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); - EXPECT_EQ(kDesiredBitrate, codec.rate); + EXPECT_EQ(kDesiredBitrate, GetCodecBitrate(kSsrc1)); } // Test that bitrate cannot be set for CBR codecs. @@ -864,20 +877,15 @@ TEST_F(WebRtcVoiceEngineTestFake, SetMaxSendBandwidthCbr) { // PCMU, default bitrate == 64000. EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); - int channel_num = voe_.GetLastChannel(); - webrtc::CodecInst codec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); - EXPECT_EQ(64000, codec.rate); + EXPECT_EQ(64000, GetCodecBitrate(kSsrc1)); send_parameters_.max_bandwidth_bps = 128000; EXPECT_TRUE(channel_->SetSendParameters(send_parameters_)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); - EXPECT_EQ(64000, codec.rate); + EXPECT_EQ(64000, GetCodecBitrate(kSsrc1)); send_parameters_.max_bandwidth_bps = 128; EXPECT_FALSE(channel_->SetSendParameters(send_parameters_)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, codec)); - EXPECT_EQ(64000, codec.rate); + EXPECT_EQ(64000, GetCodecBitrate(kSsrc1)); } // Test that the per-stream bitrate limit and the global @@ -1058,17 +1066,16 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecs) { parameters.codecs.push_back(kCn8000Codec); parameters.codecs[0].id = 96; parameters.codecs[0].bitrate = 48000; + const int initial_num = call_.GetNumCreatedSendStreams(); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(1, voe_.GetNumSetSendCodecs()); - int channel_num = voe_.GetLastChannel(); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(96, gcodec.pltype); - EXPECT_EQ(48000, gcodec.rate); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_FALSE(voe_.GetVAD(channel_num)); - EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); - EXPECT_EQ(105, voe_.GetSendCNPayloadType(channel_num, true)); + EXPECT_EQ(initial_num + 1, call_.GetNumCreatedSendStreams()); + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_EQ(96, send_codec_spec.codec_inst.pltype); + EXPECT_EQ(48000, send_codec_spec.codec_inst.rate); + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_NE(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(13, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq8000Hz, send_codec_spec.cng_plfreq); EXPECT_FALSE(channel_->CanInsertDtmf()); } @@ -1082,23 +1089,22 @@ TEST_F(WebRtcVoiceEngineTestFake, DontResetSetSendCodec) { parameters.codecs.push_back(kCn8000Codec); parameters.codecs[0].id = 96; parameters.codecs[0].bitrate = 48000; + const int initial_num = call_.GetNumCreatedSendStreams(); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(1, voe_.GetNumSetSendCodecs()); + EXPECT_EQ(initial_num + 1, call_.GetNumCreatedSendStreams()); // Calling SetSendCodec again with same codec which is already set. // In this case media channel shouldn't send codec to VoE. EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(1, voe_.GetNumSetSendCodecs()); + EXPECT_EQ(initial_num + 1, call_.GetNumCreatedSendStreams()); } // Verify that G722 is set with 16000 samples per second to WebRTC. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecG722) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kG722CodecSdp); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; EXPECT_STREQ("G722", gcodec.plname); EXPECT_EQ(1, gcodec.channels); EXPECT_EQ(16000, gcodec.plfreq); @@ -1171,115 +1177,80 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusBad1Channel1Stereo) { // channels and bitrate are 1 and 32000. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0BitrateNoStereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(32000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 1, 32000); } // Test that with bitrate=0 and stereo=0, // channels and bitrate are 1 and 32000. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0Bitrate0Stereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].params["stereo"] = "0"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(32000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 1, 32000); } // Test that with bitrate=invalid and stereo=0, // channels and bitrate are 1 and 32000. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodXBitrate0Stereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].params["stereo"] = "0"; - webrtc::CodecInst gcodec; - // bitrate that's out of the range between 6000 and 510000 will be clamped. parameters.codecs[0].bitrate = 5999; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(6000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 1, 6000); parameters.codecs[0].bitrate = 510001; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(510000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 1, 510000); } // Test that with bitrate=0 and stereo=1, // channels and bitrate are 2 and 64000. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGood0Bitrate1Stereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].params["stereo"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(2, gcodec.channels); - EXPECT_EQ(64000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 2, 64000); } // Test that with bitrate=invalid and stereo=1, // channels and bitrate are 2 and 64000. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodXBitrate1Stereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].params["stereo"] = "1"; - webrtc::CodecInst gcodec; - // bitrate that's out of the range between 6000 and 510000 will be clamped. parameters.codecs[0].bitrate = 5999; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(2, gcodec.channels); - EXPECT_EQ(6000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 2, 6000); parameters.codecs[0].bitrate = 510001; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(2, gcodec.channels); - EXPECT_EQ(510000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 2, 510000); } // Test that with bitrate=N and stereo unset, // channels and bitrate are 1 and N. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoStereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 96000; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; EXPECT_EQ(111, gcodec.pltype); EXPECT_EQ(96000, gcodec.rate); EXPECT_STREQ("opus", gcodec.plname); @@ -1291,50 +1262,35 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoStereo) { // channels and bitrate are 1 and N. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate0Stereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 30000; parameters.codecs[0].params["stereo"] = "0"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(30000, gcodec.rate); - EXPECT_STREQ("opus", gcodec.plname); + CheckSendCodec(kSsrc1, "opus", 1, 30000); } // Test that with bitrate=N and without any parameters, // channels and bitrate are 1 and N. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrateNoParameters) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 30000; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(30000, gcodec.rate); - EXPECT_STREQ("opus", gcodec.plname); + CheckSendCodec(kSsrc1, "opus", 1, 30000); } // Test that with bitrate=N and stereo=1, // channels and bitrate are 2 and N. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate1Stereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 30000; parameters.codecs[0].params["stereo"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(2, gcodec.channels); - EXPECT_EQ(30000, gcodec.rate); - EXPECT_STREQ("opus", gcodec.plname); + CheckSendCodec(kSsrc1, "opus", 2, 30000); } // Test that bitrate will be overridden by the "maxaveragebitrate" parameter. @@ -1342,28 +1298,22 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusGoodNBitrate1Stereo) { // range of 6000 and 510000 TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusMaxAverageBitrate) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 30000; - webrtc::CodecInst gcodec; - // Ignore if less than 6000. parameters.codecs[0].params["maxaveragebitrate"] = "5999"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(6000, gcodec.rate); + EXPECT_EQ(6000, GetCodecBitrate(kSsrc1)); // Ignore if larger than 510000. parameters.codecs[0].params["maxaveragebitrate"] = "510001"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(510000, gcodec.rate); + EXPECT_EQ(510000, GetCodecBitrate(kSsrc1)); parameters.codecs[0].params["maxaveragebitrate"] = "200000"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(200000, gcodec.rate); + EXPECT_EQ(200000, GetCodecBitrate(kSsrc1)); } // Test that we can enable NACK with opus as caller. @@ -1471,97 +1421,78 @@ TEST_F(WebRtcVoiceEngineTestFake, AddRecvStreamEnableNack) { // Test that without useinbandfec, Opus FEC is off. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecNoOpusFec) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetCodecFEC(channel_num)); + EXPECT_FALSE(GetCodecFec(kSsrc1)); } // Test that with useinbandfec=0, Opus FEC is off. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusDisableFec) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].params["useinbandfec"] = "0"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetCodecFEC(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(32000, gcodec.rate); + CheckSendCodec(kSsrc1, "opus", 1, 32000); } // Test that with useinbandfec=1, Opus FEC is on. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusEnableFec) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].params["useinbandfec"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_TRUE(voe_.GetCodecFEC(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(1, gcodec.channels); - EXPECT_EQ(32000, gcodec.rate); + EXPECT_TRUE(GetCodecFec(kSsrc1)); + CheckSendCodec(kSsrc1, "opus", 1, 32000); } // Test that with useinbandfec=1, stereo=1, Opus FEC is on. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecOpusEnableFecStereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].params["stereo"] = "1"; parameters.codecs[0].params["useinbandfec"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_TRUE(voe_.GetCodecFEC(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(2, gcodec.channels); - EXPECT_EQ(64000, gcodec.rate); + EXPECT_TRUE(GetCodecFec(kSsrc1)); + CheckSendCodec(kSsrc1, "opus", 2, 64000); } // Test that with non-Opus, codec FEC is off. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecIsacNoFec) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetCodecFEC(channel_num)); + EXPECT_FALSE(GetCodecFec(kSsrc1)); } // Test the with non-Opus, even if useinbandfec=1, FEC is off. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecIsacWithParamNoFec) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); parameters.codecs[0].params["useinbandfec"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetCodecFEC(channel_num)); + EXPECT_FALSE(GetCodecFec(kSsrc1)); } // Test that Opus FEC status can be changed. TEST_F(WebRtcVoiceEngineTestFake, ChangeOpusFecStatus) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetCodecFEC(channel_num)); + EXPECT_FALSE(GetCodecFec(kSsrc1)); + parameters.codecs[0].params["useinbandfec"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_TRUE(voe_.GetCodecFEC(channel_num)); + EXPECT_TRUE(GetCodecFec(kSsrc1)); } TEST_F(WebRtcVoiceEngineTestFake, TransportCcCanBeEnabledAndDisabled) { @@ -1589,315 +1520,278 @@ TEST_F(WebRtcVoiceEngineTestFake, TransportCcCanBeEnabledAndDisabled) { // Test maxplaybackrate <= 8000 triggers Opus narrow band mode. TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateNb) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 8000); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthNb, - voe_.GetMaxEncodingBandwidth(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); + EXPECT_EQ(8000, GetOpusMaxPlaybackRate(kSsrc1)); + EXPECT_EQ(12000, GetCodecBitrate(kSsrc1)); - EXPECT_EQ(12000, gcodec.rate); parameters.codecs[0].SetParam(cricket::kCodecParamStereo, "1"); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(24000, gcodec.rate); + EXPECT_EQ(24000, GetCodecBitrate(kSsrc1)); } // Test 8000 < maxplaybackrate <= 12000 triggers Opus medium band mode. TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateMb) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 8001); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthMb, - voe_.GetMaxEncodingBandwidth(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); + EXPECT_EQ(8001, GetOpusMaxPlaybackRate(kSsrc1)); + EXPECT_EQ(20000, GetCodecBitrate(kSsrc1)); - EXPECT_EQ(20000, gcodec.rate); parameters.codecs[0].SetParam(cricket::kCodecParamStereo, "1"); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(40000, gcodec.rate); + EXPECT_EQ(40000, GetCodecBitrate(kSsrc1)); } // Test 12000 < maxplaybackrate <= 16000 triggers Opus wide band mode. TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateWb) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 12001); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthWb, - voe_.GetMaxEncodingBandwidth(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); + EXPECT_EQ(12001, GetOpusMaxPlaybackRate(kSsrc1)); + EXPECT_EQ(20000, GetCodecBitrate(kSsrc1)); - EXPECT_EQ(20000, gcodec.rate); parameters.codecs[0].SetParam(cricket::kCodecParamStereo, "1"); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(40000, gcodec.rate); + EXPECT_EQ(40000, GetCodecBitrate(kSsrc1)); } // Test 16000 < maxplaybackrate <= 24000 triggers Opus super wide band mode. TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateSwb) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 16001); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthSwb, - voe_.GetMaxEncodingBandwidth(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); + EXPECT_EQ(16001, GetOpusMaxPlaybackRate(kSsrc1)); + EXPECT_EQ(32000, GetCodecBitrate(kSsrc1)); - EXPECT_EQ(32000, gcodec.rate); parameters.codecs[0].SetParam(cricket::kCodecParamStereo, "1"); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(64000, gcodec.rate); + EXPECT_EQ(64000, GetCodecBitrate(kSsrc1)); } // Test 24000 < maxplaybackrate triggers Opus full band mode. TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateFb) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].bitrate = 0; parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 24001); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthFb, - voe_.GetMaxEncodingBandwidth(channel_num)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("opus", gcodec.plname); + EXPECT_EQ(24001, GetOpusMaxPlaybackRate(kSsrc1)); + EXPECT_EQ(32000, GetCodecBitrate(kSsrc1)); - EXPECT_EQ(32000, gcodec.rate); parameters.codecs[0].SetParam(cricket::kCodecParamStereo, "1"); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(64000, gcodec.rate); + EXPECT_EQ(64000, GetCodecBitrate(kSsrc1)); } // Test Opus that without maxplaybackrate, default playback rate is used. TEST_F(WebRtcVoiceEngineTestFake, DefaultOpusMaxPlaybackRate) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthFb, - voe_.GetMaxEncodingBandwidth(channel_num)); + EXPECT_EQ(48000, GetOpusMaxPlaybackRate(kSsrc1)); } // Test the with non-Opus, maxplaybackrate has no effect. TEST_F(WebRtcVoiceEngineTestFake, SetNonOpusMaxPlaybackRate) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 32000); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetMaxEncodingBandwidth(channel_num)); + EXPECT_EQ(0, GetOpusMaxPlaybackRate(kSsrc1)); } // Test maxplaybackrate can be set on two streams. TEST_F(WebRtcVoiceEngineTestFake, SetOpusMaxPlaybackRateOnTwoStreams) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - // Default bandwidth is 24000. - EXPECT_EQ(cricket::kOpusBandwidthFb, - voe_.GetMaxEncodingBandwidth(channel_num)); + EXPECT_EQ(48000, GetOpusMaxPlaybackRate(kSsrc1)); parameters.codecs[0].SetParam(cricket::kCodecParamMaxPlaybackRate, 8000); - EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(cricket::kOpusBandwidthNb, - voe_.GetMaxEncodingBandwidth(channel_num)); + EXPECT_EQ(8000, GetOpusMaxPlaybackRate(kSsrc1)); channel_->AddSendStream(cricket::StreamParams::CreateLegacy(kSsrc2)); - channel_num = voe_.GetLastChannel(); - EXPECT_EQ(cricket::kOpusBandwidthNb, - voe_.GetMaxEncodingBandwidth(channel_num)); + EXPECT_EQ(8000, GetOpusMaxPlaybackRate(kSsrc2)); } // Test that with usedtx=0, Opus DTX is off. TEST_F(WebRtcVoiceEngineTestFake, DisableOpusDtxOnOpus) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].params["usedtx"] = "0"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetOpusDtx(channel_num)); + EXPECT_FALSE(GetOpusDtx(kSsrc1)); } // Test that with usedtx=1, Opus DTX is on. TEST_F(WebRtcVoiceEngineTestFake, EnableOpusDtxOnOpus) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].params["usedtx"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_TRUE(voe_.GetOpusDtx(channel_num)); - EXPECT_FALSE(voe_.GetVAD(channel_num)); // Opus DTX should not affect VAD. + EXPECT_TRUE(GetOpusDtx(kSsrc1)); } // Test that usedtx=1 works with stereo Opus. TEST_F(WebRtcVoiceEngineTestFake, EnableOpusDtxOnOpusStereo) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].params["usedtx"] = "1"; parameters.codecs[0].params["stereo"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_TRUE(voe_.GetOpusDtx(channel_num)); - EXPECT_FALSE(voe_.GetVAD(channel_num)); // Opus DTX should not affect VAD. + EXPECT_TRUE(GetOpusDtx(kSsrc1)); } // Test that usedtx=1 does not work with non Opus. TEST_F(WebRtcVoiceEngineTestFake, CannotEnableOpusDtxOnNonOpus) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); parameters.codecs[0].params["usedtx"] = "1"; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_FALSE(voe_.GetOpusDtx(channel_num)); + EXPECT_FALSE(GetOpusDtx(kSsrc1)); } // Test that we can switch back and forth between Opus and ISAC with CN. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsIsacOpusSwitching) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); + cricket::AudioSendParameters opus_parameters; opus_parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(channel_->SetSendParameters(opus_parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(111, gcodec.pltype); - EXPECT_STREQ("opus", gcodec.plname); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(111, gcodec.pltype); + EXPECT_STREQ("opus", gcodec.plname); + } cricket::AudioSendParameters isac_parameters; isac_parameters.codecs.push_back(kIsacCodec); isac_parameters.codecs.push_back(kCn16000Codec); isac_parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(channel_->SetSendParameters(isac_parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(103, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(103, gcodec.pltype); + EXPECT_STREQ("ISAC", gcodec.plname); + } EXPECT_TRUE(channel_->SetSendParameters(opus_parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(111, gcodec.pltype); - EXPECT_STREQ("opus", gcodec.plname); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(111, gcodec.pltype); + EXPECT_STREQ("opus", gcodec.plname); + } } // Test that we handle various ways of specifying bitrate. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsBitrate) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); // bitrate == 32000 EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(103, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_EQ(32000, gcodec.rate); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(103, gcodec.pltype); + EXPECT_STREQ("ISAC", gcodec.plname); + EXPECT_EQ(32000, gcodec.rate); + } parameters.codecs[0].bitrate = 0; // bitrate == default EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(103, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_EQ(-1, gcodec.rate); - + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(103, gcodec.pltype); + EXPECT_STREQ("ISAC", gcodec.plname); + EXPECT_EQ(-1, gcodec.rate); + } parameters.codecs[0].bitrate = 28000; // bitrate == 28000 EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(103, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_EQ(28000, gcodec.rate); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(103, gcodec.pltype); + EXPECT_STREQ("ISAC", gcodec.plname); + EXPECT_EQ(28000, gcodec.rate); + } parameters.codecs[0] = kPcmuCodec; // bitrate == 64000 EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(0, gcodec.pltype); - EXPECT_STREQ("PCMU", gcodec.plname); - EXPECT_EQ(64000, gcodec.rate); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(0, gcodec.pltype); + EXPECT_STREQ("PCMU", gcodec.plname); + EXPECT_EQ(64000, gcodec.rate); + } parameters.codecs[0].bitrate = 0; // bitrate == default EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(0, gcodec.pltype); - EXPECT_STREQ("PCMU", gcodec.plname); - EXPECT_EQ(64000, gcodec.rate); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(0, gcodec.pltype); + EXPECT_STREQ("PCMU", gcodec.plname); + EXPECT_EQ(64000, gcodec.rate); + } parameters.codecs[0] = kOpusCodec; parameters.codecs[0].bitrate = 0; // bitrate == default EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(111, gcodec.pltype); - EXPECT_STREQ("opus", gcodec.plname); - EXPECT_EQ(32000, gcodec.rate); + { + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; + EXPECT_EQ(111, gcodec.pltype); + EXPECT_STREQ("opus", gcodec.plname); + EXPECT_EQ(32000, gcodec.rate); + } } // Test that we could set packet size specified in kCodecParamPTime. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsPTimeAsPacketSize) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kOpusCodec); parameters.codecs[0].SetParam(cricket::kCodecParamPTime, 40); // Within range. EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(1920, gcodec.pacsize); // Opus gets 40ms. + EXPECT_EQ(1920, GetCodecPacSize(kSsrc1)); // Opus gets 40ms. parameters.codecs[0].SetParam(cricket::kCodecParamPTime, 5); // Below range. EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(480, gcodec.pacsize); // Opus gets 10ms. + EXPECT_EQ(480, GetCodecPacSize(kSsrc1)); // Opus gets 10ms. parameters.codecs[0].SetParam(cricket::kCodecParamPTime, 80); // Beyond range. EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(2880, gcodec.pacsize); // Opus gets 60ms. + EXPECT_EQ(2880, GetCodecPacSize(kSsrc1)); // Opus gets 60ms. parameters.codecs[0] = kIsacCodec; // Also try Isac, with unsupported size. parameters.codecs[0].SetParam(cricket::kCodecParamPTime, 40); // Within range. EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(480, gcodec.pacsize); // Isac gets 30ms as the next smallest value. + EXPECT_EQ(480, GetCodecPacSize( + kSsrc1)); // Isac gets 30ms as the next smallest value. parameters.codecs[0] = kG722CodecSdp; // Try G722 @8kHz as negotiated in SDP. parameters.codecs[0].SetParam(cricket::kCodecParamPTime, 40); EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(640, gcodec.pacsize); // G722 gets 40ms @16kHz as defined in VoE. + EXPECT_EQ(640, GetCodecPacSize( + kSsrc1)); // G722 gets 40ms @16kHz as defined in VoE. } // Test that we fail if no codecs are specified. @@ -1911,7 +1805,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsNoCodecs) { // one on the list. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsDTMFOnTop) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kTelephoneEventCodec); parameters.codecs.push_back(kIsacCodec); @@ -1919,8 +1812,7 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsDTMFOnTop) { parameters.codecs[0].id = 98; // DTMF parameters.codecs[1].id = 96; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); + const auto& gcodec = GetSendStreamConfig(kSsrc1).send_codec_spec.codec_inst; EXPECT_EQ(96, gcodec.pltype); EXPECT_STREQ("ISAC", gcodec.plname); EXPECT_TRUE(channel_->CanInsertDtmf()); @@ -1951,7 +1843,6 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsDTMFPayloadTypeOutOfRange) { // one on the list. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNOnTop) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kCn16000Codec); parameters.codecs.push_back(kIsacCodec); @@ -1959,17 +1850,16 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNOnTop) { parameters.codecs[0].id = 98; // wideband CN parameters.codecs[1].id = 96; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(96, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_EQ(98, voe_.GetSendCNPayloadType(channel_num, true)); + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_EQ(96, send_codec_spec.codec_inst.pltype); + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_EQ(98, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); } // Test that we set VAD and DTMF types correctly as caller. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCaller) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); parameters.codecs.push_back(kPcmuCodec); @@ -1981,13 +1871,13 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCaller) { parameters.codecs[2].id = 97; // wideband CN parameters.codecs[4].id = 98; // DTMF EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(96, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_TRUE(voe_.GetVAD(channel_num)); - EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); - EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_EQ(96, send_codec_spec.codec_inst.pltype); + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_EQ(1, send_codec_spec.codec_inst.channels); + EXPECT_EQ(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(97, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); EXPECT_TRUE(channel_->CanInsertDtmf()); } @@ -2007,15 +1897,14 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCallee) { EXPECT_TRUE(channel_->SetSendParameters(parameters)); EXPECT_TRUE(channel_->AddSendStream( cricket::StreamParams::CreateLegacy(kSsrc1))); - int channel_num = voe_.GetLastChannel(); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(96, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_TRUE(voe_.GetVAD(channel_num)); - EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); - EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_EQ(96, send_codec_spec.codec_inst.pltype); + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_EQ(1, send_codec_spec.codec_inst.channels); + EXPECT_EQ(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(97, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); EXPECT_TRUE(channel_->CanInsertDtmf()); } @@ -2023,43 +1912,52 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNandDTMFAsCallee) { // send codec clockrate. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCNNoMatch) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; // Set ISAC(16K) and CN(16K). VAD should be activated. parameters.codecs.push_back(kIsacCodec); parameters.codecs.push_back(kCn16000Codec); parameters.codecs[1].id = 97; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_TRUE(voe_.GetVAD(channel_num)); - EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); + { + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_EQ(1, send_codec_spec.codec_inst.channels); + EXPECT_EQ(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(97, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); + } // Set PCMU(8K) and CN(16K). VAD should not be activated. parameters.codecs[0] = kPcmuCodec; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("PCMU", gcodec.plname); - EXPECT_FALSE(voe_.GetVAD(channel_num)); + { + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_STREQ("PCMU", send_codec_spec.codec_inst.plname); + EXPECT_NE(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + } // Set PCMU(8K) and CN(8K). VAD should be activated. parameters.codecs[1] = kCn8000Codec; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("PCMU", gcodec.plname); - EXPECT_TRUE(voe_.GetVAD(channel_num)); - EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); + { + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_STREQ("PCMU", send_codec_spec.codec_inst.plname); + EXPECT_EQ(1, send_codec_spec.codec_inst.channels); + EXPECT_EQ(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(13, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq8000Hz, send_codec_spec.cng_plfreq); + } // Set ISAC(16K) and CN(8K). VAD should not be activated. parameters.codecs[0] = kIsacCodec; EXPECT_TRUE(channel_->SetSendParameters(parameters)); - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_FALSE(voe_.GetVAD(channel_num)); + { + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_NE(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + } } // Test that we perform case-insensitive matching of codec names. TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) { EXPECT_TRUE(SetupSendStream()); - int channel_num = voe_.GetLastChannel(); cricket::AudioSendParameters parameters; parameters.codecs.push_back(kIsacCodec); parameters.codecs.push_back(kPcmuCodec); @@ -2071,13 +1969,13 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsCaseInsensitive) { parameters.codecs[2].id = 97; // wideband CN parameters.codecs[4].id = 98; // DTMF EXPECT_TRUE(channel_->SetSendParameters(parameters)); - webrtc::CodecInst gcodec; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_EQ(96, gcodec.pltype); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_TRUE(voe_.GetVAD(channel_num)); - EXPECT_EQ(13, voe_.GetSendCNPayloadType(channel_num, false)); - EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); + const auto& send_codec_spec = GetSendStreamConfig(kSsrc1).send_codec_spec; + EXPECT_EQ(96, send_codec_spec.codec_inst.pltype); + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_EQ(1, send_codec_spec.codec_inst.channels); + EXPECT_EQ(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(97, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); EXPECT_TRUE(channel_->CanInsertDtmf()); } @@ -2230,23 +2128,28 @@ TEST_F(WebRtcVoiceEngineTestFake, SetSendCodecsWithMultipleSendStreams) { EXPECT_TRUE(channel_->SetSendParameters(parameters)); // Verify ISAC and VAD are corrected configured on all send channels. - webrtc::CodecInst gcodec; for (uint32_t ssrc : kSsrcs4) { - int channel_num = GetSendStreamConfig(ssrc).voe_channel_id; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("ISAC", gcodec.plname); - EXPECT_TRUE(voe_.GetVAD(channel_num)); - EXPECT_EQ(97, voe_.GetSendCNPayloadType(channel_num, true)); + ASSERT_TRUE(call_.GetAudioSendStream(ssrc) != nullptr); + const auto& send_codec_spec = + call_.GetAudioSendStream(ssrc)->GetConfig().send_codec_spec; + EXPECT_STREQ("ISAC", send_codec_spec.codec_inst.plname); + EXPECT_EQ(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(1, send_codec_spec.codec_inst.channels); + EXPECT_EQ(97, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); } - // Change to PCMU(8K) and CN(16K). VAD should not be activated. + // Change to PCMU(8K) and CN(16K). parameters.codecs[0] = kPcmuCodec; EXPECT_TRUE(channel_->SetSendParameters(parameters)); for (uint32_t ssrc : kSsrcs4) { - int channel_num = GetSendStreamConfig(ssrc).voe_channel_id; - EXPECT_EQ(0, voe_.GetSendCodec(channel_num, gcodec)); - EXPECT_STREQ("PCMU", gcodec.plname); - EXPECT_FALSE(voe_.GetVAD(channel_num)); + ASSERT_TRUE(call_.GetAudioSendStream(ssrc) != nullptr); + const auto& send_codec_spec = + call_.GetAudioSendStream(ssrc)->GetConfig().send_codec_spec; + EXPECT_STREQ("PCMU", send_codec_spec.codec_inst.plname); + EXPECT_NE(send_codec_spec.codec_inst.plfreq, send_codec_spec.cng_plfreq); + EXPECT_EQ(97, send_codec_spec.cng_payload_type); + EXPECT_EQ(webrtc::kFreq16000Hz, send_codec_spec.cng_plfreq); } }