Add PeerConnection option to enable RTX handling in the audio jitter buffer.

Bug: webrtc:10178
Change-Id: I70abce0c7b74124d2b1978d9a5eb8216b6233d1a
Reviewed-on: https://webrtc-review.googlesource.com/c/116784
Commit-Queue: Jakob Ivarsson‎ <jakobi@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26203}
diff --git a/api/audio_options.cc b/api/audio_options.cc
index 6fd90b2..16c0430 100644
--- a/api/audio_options.cc
+++ b/api/audio_options.cc
@@ -52,6 +52,8 @@
           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 @@
              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 @@
                 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 c2d1f44..478bff6 100644
--- a/api/audio_options.h
+++ b/api/audio_options.h
@@ -56,6 +56,8 @@
   absl::optional<bool> audio_jitter_buffer_fast_accelerate;
   // Audio receiver jitter buffer (NetEq) minimum target delay in milliseconds.
   absl::optional<int> audio_jitter_buffer_min_delay_ms;
+  // Audio receiver jitter buffer (NetEq) should handle retransmitted packets.
+  absl::optional<bool> audio_jitter_buffer_enable_rtx_handling;
   // Audio processing to detect typing.
   absl::optional<bool> typing_detection;
   absl::optional<bool> experimental_agc;
diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h
index c2fb6a3..91d71b4 100644
--- a/api/peerconnectioninterface.h
+++ b/api/peerconnectioninterface.h
@@ -454,6 +454,10 @@
     // 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 143c6f7..2e874ba 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -79,8 +79,8 @@
       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 7ae2e26..e5bcad3 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -104,6 +104,7 @@
                  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<AudioDecoderFactory> decoder_factory,
                  absl::optional<AudioCodecPairId> codec_pair_id,
                  rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
@@ -453,6 +454,7 @@
     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<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
@@ -487,6 +489,8 @@
   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 @@
     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<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
@@ -996,8 +1001,8 @@
       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 6bbf990..2c45a8f 100644
--- a/audio/channel_receive.h
+++ b/audio/channel_receive.h
@@ -139,6 +139,7 @@
     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<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h
index 36cc059..476ddab 100644
--- a/call/audio_receive_stream.h
+++ b/call/audio_receive_stream.h
@@ -115,6 +115,7 @@
     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 c7a4169..40abb66 100644
--- a/media/engine/webrtcvoiceengine.cc
+++ b/media/engine/webrtcvoiceengine.cc
@@ -280,6 +280,7 @@
     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 @@
     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 @@
       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<webrtc::FrameDecryptorInterface> frame_decryptor,
       const webrtc::CryptoOptions& crypto_options)
       : call_(call), config_() {
@@ -1110,6 +1118,8 @@
     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 @@
           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 213f1b3..494b4f6 100644
--- a/media/engine/webrtcvoiceengine.h
+++ b/media/engine/webrtcvoiceengine.h
@@ -133,6 +133,7 @@
   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 7e6c3dd..518a2e6 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -706,6 +706,7 @@
     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 @@
              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 @@
   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.