diff --git a/api/audio_options.cc b/api/audio_options.cc index 6fd90b2b12..16c0430a86 100644 --- a/api/audio_options.cc +++ b/api/audio_options.cc @@ -52,6 +52,8 @@ void AudioOptions::SetAll(const AudioOptions& change) { change.audio_jitter_buffer_fast_accelerate); SetFrom(&audio_jitter_buffer_min_delay_ms, change.audio_jitter_buffer_min_delay_ms); + SetFrom(&audio_jitter_buffer_enable_rtx_handling, + change.audio_jitter_buffer_enable_rtx_handling); SetFrom(&typing_detection, change.typing_detection); SetFrom(&experimental_agc, change.experimental_agc); SetFrom(&extended_filter_aec, change.extended_filter_aec); @@ -81,6 +83,8 @@ bool AudioOptions::operator==(const AudioOptions& o) const { o.audio_jitter_buffer_fast_accelerate && audio_jitter_buffer_min_delay_ms == o.audio_jitter_buffer_min_delay_ms && + audio_jitter_buffer_enable_rtx_handling == + o.audio_jitter_buffer_enable_rtx_handling && typing_detection == o.typing_detection && experimental_agc == o.experimental_agc && extended_filter_aec == o.extended_filter_aec && @@ -114,6 +118,8 @@ std::string AudioOptions::ToString() const { audio_jitter_buffer_fast_accelerate); ToStringIfSet(&result, "audio_jitter_buffer_min_delay_ms", audio_jitter_buffer_min_delay_ms); + ToStringIfSet(&result, "audio_jitter_buffer_enable_rtx_handling", + audio_jitter_buffer_enable_rtx_handling); ToStringIfSet(&result, "typing", typing_detection); ToStringIfSet(&result, "experimental_agc", experimental_agc); ToStringIfSet(&result, "extended_filter_aec", extended_filter_aec); diff --git a/api/audio_options.h b/api/audio_options.h index c2d1f4487c..478bff6040 100644 --- a/api/audio_options.h +++ b/api/audio_options.h @@ -56,6 +56,8 @@ struct AudioOptions { absl::optional audio_jitter_buffer_fast_accelerate; // Audio receiver jitter buffer (NetEq) minimum target delay in milliseconds. absl::optional audio_jitter_buffer_min_delay_ms; + // Audio receiver jitter buffer (NetEq) should handle retransmitted packets. + absl::optional audio_jitter_buffer_enable_rtx_handling; // Audio processing to detect typing. absl::optional typing_detection; absl::optional experimental_agc; diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h index c2fb6a3a31..91d71b49c1 100644 --- a/api/peerconnectioninterface.h +++ b/api/peerconnectioninterface.h @@ -454,6 +454,10 @@ class PeerConnectionInterface : public rtc::RefCountInterface { // The minimum delay in milliseconds for the audio jitter buffer. int audio_jitter_buffer_min_delay_ms = 0; + // Whether the audio jitter buffer adapts the delay to retransmitted + // packets. + bool audio_jitter_buffer_enable_rtx_handling = false; + // Timeout in milliseconds before an ICE candidate pair is considered to be // "not receiving", after which a lower priority candidate pair may be // selected. diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc index 143c6f77f1..2e874ba40b 100644 --- a/audio/audio_receive_stream.cc +++ b/audio/audio_receive_stream.cc @@ -79,8 +79,8 @@ std::unique_ptr CreateChannelReceive( config.media_transport, config.rtcp_send_transport, event_log, config.rtp.remote_ssrc, config.jitter_buffer_max_packets, config.jitter_buffer_fast_accelerate, config.jitter_buffer_min_delay_ms, - config.decoder_factory, config.codec_pair_id, config.frame_decryptor, - config.crypto_options); + config.jitter_buffer_enable_rtx_handling, config.decoder_factory, + config.codec_pair_id, config.frame_decryptor, config.crypto_options); } } // namespace diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc index 7ae2e267b8..e5bcad3961 100644 --- a/audio/channel_receive.cc +++ b/audio/channel_receive.cc @@ -104,6 +104,7 @@ class ChannelReceive : public ChannelReceiveInterface, size_t jitter_buffer_max_packets, bool jitter_buffer_fast_playout, int jitter_buffer_min_delay_ms, + bool jitter_buffer_enable_rtx_handling, rtc::scoped_refptr decoder_factory, absl::optional codec_pair_id, rtc::scoped_refptr frame_decryptor, @@ -453,6 +454,7 @@ ChannelReceive::ChannelReceive( size_t jitter_buffer_max_packets, bool jitter_buffer_fast_playout, int jitter_buffer_min_delay_ms, + bool jitter_buffer_enable_rtx_handling, rtc::scoped_refptr decoder_factory, absl::optional codec_pair_id, rtc::scoped_refptr frame_decryptor, @@ -487,6 +489,8 @@ ChannelReceive::ChannelReceive( acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout; acm_config.neteq_config.min_delay_ms = jitter_buffer_min_delay_ms; acm_config.neteq_config.enable_muted_state = true; + acm_config.neteq_config.enable_rtx_handling = + jitter_buffer_enable_rtx_handling; audio_coding_.reset(AudioCodingModule::Create(acm_config)); _outputAudioLevel.Clear(); @@ -988,6 +992,7 @@ std::unique_ptr CreateChannelReceive( size_t jitter_buffer_max_packets, bool jitter_buffer_fast_playout, int jitter_buffer_min_delay_ms, + bool jitter_buffer_enable_rtx_handling, rtc::scoped_refptr decoder_factory, absl::optional codec_pair_id, rtc::scoped_refptr frame_decryptor, @@ -996,8 +1001,8 @@ std::unique_ptr CreateChannelReceive( module_process_thread, audio_device_module, media_transport, rtcp_send_transport, rtc_event_log, remote_ssrc, jitter_buffer_max_packets, jitter_buffer_fast_playout, - jitter_buffer_min_delay_ms, decoder_factory, codec_pair_id, - frame_decryptor, crypto_options); + jitter_buffer_min_delay_ms, jitter_buffer_enable_rtx_handling, + decoder_factory, codec_pair_id, frame_decryptor, crypto_options); } } // namespace voe diff --git a/audio/channel_receive.h b/audio/channel_receive.h index 6bbf990f1c..2c45a8f50d 100644 --- a/audio/channel_receive.h +++ b/audio/channel_receive.h @@ -139,6 +139,7 @@ std::unique_ptr CreateChannelReceive( size_t jitter_buffer_max_packets, bool jitter_buffer_fast_playout, int jitter_buffer_min_delay_ms, + bool jitter_buffer_enable_rtx_handling, rtc::scoped_refptr decoder_factory, absl::optional codec_pair_id, rtc::scoped_refptr frame_decryptor, diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h index 36cc059396..476ddabe74 100644 --- a/call/audio_receive_stream.h +++ b/call/audio_receive_stream.h @@ -115,6 +115,7 @@ class AudioReceiveStream { size_t jitter_buffer_max_packets = 50; bool jitter_buffer_fast_accelerate = false; int jitter_buffer_min_delay_ms = 0; + bool jitter_buffer_enable_rtx_handling = false; // Identifier for an A/V synchronization group. Empty string to disable. // TODO(pbos): Synchronize streams in a sync group, not just one video diff --git a/media/engine/webrtcvoiceengine.cc b/media/engine/webrtcvoiceengine.cc index c7a41692fe..40abb66acb 100644 --- a/media/engine/webrtcvoiceengine.cc +++ b/media/engine/webrtcvoiceengine.cc @@ -280,6 +280,7 @@ void WebRtcVoiceEngine::Init() { options.audio_jitter_buffer_max_packets = 50; options.audio_jitter_buffer_fast_accelerate = false; options.audio_jitter_buffer_min_delay_ms = 0; + options.audio_jitter_buffer_enable_rtx_handling = false; options.typing_detection = true; options.experimental_agc = false; options.extended_filter_aec = false; @@ -489,6 +490,12 @@ bool WebRtcVoiceEngine::ApplyOptions(const AudioOptions& options_in) { audio_jitter_buffer_min_delay_ms_ = *options.audio_jitter_buffer_min_delay_ms; } + if (options.audio_jitter_buffer_enable_rtx_handling) { + RTC_LOG(LS_INFO) << "NetEq handle reordered packets? " + << *options.audio_jitter_buffer_enable_rtx_handling; + audio_jitter_buffer_enable_rtx_handling_ = + *options.audio_jitter_buffer_enable_rtx_handling; + } if (options.typing_detection) { RTC_LOG(LS_INFO) << "Typing detection is enabled? " @@ -1096,6 +1103,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { size_t jitter_buffer_max_packets, bool jitter_buffer_fast_accelerate, int jitter_buffer_min_delay_ms, + bool jitter_buffer_enable_rtx_handling, rtc::scoped_refptr frame_decryptor, const webrtc::CryptoOptions& crypto_options) : call_(call), config_() { @@ -1110,6 +1118,8 @@ class WebRtcVoiceMediaChannel::WebRtcAudioReceiveStream { config_.jitter_buffer_max_packets = jitter_buffer_max_packets; config_.jitter_buffer_fast_accelerate = jitter_buffer_fast_accelerate; config_.jitter_buffer_min_delay_ms = jitter_buffer_min_delay_ms; + config_.jitter_buffer_enable_rtx_handling = + jitter_buffer_enable_rtx_handling; if (!stream_ids.empty()) { config_.sync_group = stream_ids[0]; } @@ -1909,6 +1919,7 @@ bool WebRtcVoiceMediaChannel::AddRecvStream(const StreamParams& sp) { codec_pair_id_, engine()->audio_jitter_buffer_max_packets_, engine()->audio_jitter_buffer_fast_accelerate_, engine()->audio_jitter_buffer_min_delay_ms_, + engine()->audio_jitter_buffer_enable_rtx_handling_, unsignaled_frame_decryptor_, crypto_options_))); recv_streams_[ssrc]->SetPlayout(playout_); diff --git a/media/engine/webrtcvoiceengine.h b/media/engine/webrtcvoiceengine.h index 213f1b393f..494b4f6609 100644 --- a/media/engine/webrtcvoiceengine.h +++ b/media/engine/webrtcvoiceengine.h @@ -133,6 +133,7 @@ class WebRtcVoiceEngine final : public VoiceEngineInterface { size_t audio_jitter_buffer_max_packets_ = 50; bool audio_jitter_buffer_fast_accelerate_ = false; int audio_jitter_buffer_min_delay_ms_ = 0; + bool audio_jitter_buffer_enable_rtx_handling_ = false; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcVoiceEngine); }; diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index 7e6c3dd9d5..518a2e633b 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -706,6 +706,7 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( int audio_jitter_buffer_max_packets; bool audio_jitter_buffer_fast_accelerate; int audio_jitter_buffer_min_delay_ms; + bool audio_jitter_buffer_enable_rtx_handling; int ice_connection_receiving_timeout; int ice_backup_candidate_pair_ping_interval; ContinualGatheringPolicy continual_gathering_policy; @@ -745,6 +746,8 @@ bool PeerConnectionInterface::RTCConfiguration::operator==( o.audio_jitter_buffer_fast_accelerate && audio_jitter_buffer_min_delay_ms == o.audio_jitter_buffer_min_delay_ms && + audio_jitter_buffer_enable_rtx_handling == + o.audio_jitter_buffer_enable_rtx_handling && ice_connection_receiving_timeout == o.ice_connection_receiving_timeout && ice_backup_candidate_pair_ping_interval == @@ -1071,6 +1074,9 @@ bool PeerConnection::Initialize( audio_options_.audio_jitter_buffer_min_delay_ms = configuration.audio_jitter_buffer_min_delay_ms; + audio_options_.audio_jitter_buffer_enable_rtx_handling = + configuration.audio_jitter_buffer_enable_rtx_handling; + // Whether the certificate generator/certificate is null or not determines // what PeerConnectionDescriptionFactory will do, so make sure that we give it // the right instructions by clearing the variables if needed.