Store/restore RTP state for audio streams with same SSRC within a call

This functionality already exists for video streams, so not having it
for audio is unexpected and has lead to problems.

BUG=webrtc:7631

Review-Url: https://codereview.webrtc.org/2887733002
Cr-Commit-Position: refs/heads/master@{#18231}
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index 3d636c2..1a5f28e 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -28,7 +28,6 @@
 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
 #include "webrtc/modules/congestion_controller/include/send_side_congestion_controller.h"
 #include "webrtc/modules/pacing/paced_sender.h"
-#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "webrtc/voice_engine/channel_proxy.h"
 #include "webrtc/voice_engine/include/voe_base.h"
 #include "webrtc/voice_engine/transmit_mixer.h"
@@ -59,7 +58,8 @@
     RtpTransportControllerSendInterface* transport,
     BitrateAllocator* bitrate_allocator,
     RtcEventLog* event_log,
-    RtcpRttStats* rtcp_rtt_stats)
+    RtcpRttStats* rtcp_rtt_stats,
+    const rtc::Optional<RtpState>& suspended_rtp_state)
     : worker_queue_(worker_queue),
       config_(Config(nullptr)),
       audio_state_(audio_state),
@@ -68,7 +68,9 @@
       transport_(transport),
       packet_loss_tracker_(kPacketLossTrackerMaxWindowSizeMs,
                            kPacketLossRateMinNumAckedPackets,
-                           kRecoverablePacketLossRateMinNumAckedPairs) {
+                           kRecoverablePacketLossRateMinNumAckedPairs),
+      rtp_rtcp_module_(nullptr),
+      suspended_rtp_state_(suspended_rtp_state) {
   LOG(LS_INFO) << "AudioSendStream: " << config.ToString();
   RTC_DCHECK_NE(config.voe_channel_id, -1);
   RTC_DCHECK(audio_state_.get());
@@ -81,6 +83,9 @@
   channel_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
   channel_proxy_->SetRTCPStatus(true);
   transport_->send_side_cc()->RegisterPacketFeedbackObserver(this);
+  RtpReceiver* rtpReceiver = nullptr;  // Unused, but required for call.
+  channel_proxy_->GetRtpRtcp(&rtp_rtcp_module_, &rtpReceiver);
+  RTC_DCHECK(rtp_rtcp_module_);
 
   ConfigureStream(this, config, true);
 
@@ -112,6 +117,9 @@
 
   if (first_time || old_config.rtp.ssrc != new_config.rtp.ssrc) {
     channel_proxy->SetLocalSSRC(new_config.rtp.ssrc);
+    if (stream->suspended_rtp_state_) {
+      stream->rtp_rtcp_module_->SetRtpState(*stream->suspended_rtp_state_);
+    }
   }
   if (first_time || old_config.rtp.c_name != new_config.rtp.c_name) {
     channel_proxy->SetRTCP_CNAME(new_config.rtp.c_name);
@@ -375,6 +383,10 @@
   channel_proxy_->SetTransportOverhead(transport_overhead_per_packet);
 }
 
+RtpState AudioSendStream::GetRtpState() const {
+  return rtp_rtcp_module_->GetRtpState();
+}
+
 VoiceEngine* AudioSendStream::voice_engine() const {
   internal::AudioState* audio_state =
       static_cast<internal::AudioState*>(audio_state_.get());
@@ -588,13 +600,10 @@
 
 void AudioSendStream::RegisterCngPayloadType(int payload_type,
                                              int clockrate_hz) {
-  RtpRtcp* rtpRtcpModule = nullptr;
-  RtpReceiver* rtpReceiver = nullptr;  // Unused, but required for call.
-  channel_proxy_->GetRtpRtcp(&rtpRtcpModule, &rtpReceiver);
   const CodecInst codec = {payload_type, "CN", clockrate_hz, 0, 1, 0};
-  if (rtpRtcpModule->RegisterSendPayload(codec) != 0) {
-    rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
-    if (rtpRtcpModule->RegisterSendPayload(codec) != 0) {
+  if (rtp_rtcp_module_->RegisterSendPayload(codec) != 0) {
+    rtp_rtcp_module_->DeRegisterSendPayload(codec.pltype);
+    if (rtp_rtcp_module_->RegisterSendPayload(codec) != 0) {
       LOG(LS_ERROR) << "RegisterCngPayloadType() failed to register CN to "
                        "RTP/RTCP module";
     }
diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h
index 065fee7..881c68e 100644
--- a/webrtc/audio/audio_send_stream.h
+++ b/webrtc/audio/audio_send_stream.h
@@ -19,7 +19,7 @@
 #include "webrtc/call/audio_send_stream.h"
 #include "webrtc/call/audio_state.h"
 #include "webrtc/call/bitrate_allocator.h"
-#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h"
 
 namespace webrtc {
@@ -44,7 +44,8 @@
                   RtpTransportControllerSendInterface* transport,
                   BitrateAllocator* bitrate_allocator,
                   RtcEventLog* event_log,
-                  RtcpRttStats* rtcp_rtt_stats);
+                  RtcpRttStats* rtcp_rtt_stats,
+                  const rtc::Optional<RtpState>& suspended_rtp_state);
   ~AudioSendStream() override;
 
   // webrtc::AudioSendStream implementation.
@@ -74,6 +75,8 @@
   const webrtc::AudioSendStream::Config& config() const;
   void SetTransportOverhead(int transport_overhead_per_packet);
 
+  RtpState GetRtpState() const;
+
  private:
   VoiceEngine* voice_engine() const;
 
@@ -111,6 +114,9 @@
   TransportFeedbackPacketLossTracker packet_loss_tracker_
       GUARDED_BY(&packet_loss_tracker_cs_);
 
+  RtpRtcp* rtp_rtcp_module_;
+  rtc::Optional<RtpState> const suspended_rtp_state_;
+
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
 };
 }  // namespace internal
diff --git a/webrtc/audio/audio_send_stream_unittest.cc b/webrtc/audio/audio_send_stream_unittest.cc
index 69ac2e4..e6acf92 100644
--- a/webrtc/audio/audio_send_stream_unittest.cc
+++ b/webrtc/audio/audio_send_stream_unittest.cc
@@ -354,7 +354,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
 }
 
 TEST(AudioSendStreamTest, SendTelephoneEvent) {
@@ -362,7 +362,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   helper.SetupMockForSendTelephoneEvent();
   EXPECT_TRUE(send_stream.SendTelephoneEvent(kTelephoneEventPayloadType,
       kTelephoneEventPayloadFrequency, kTelephoneEventCode,
@@ -374,7 +374,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   EXPECT_CALL(*helper.channel_proxy(), SetInputMute(true));
   send_stream.SetMuted(true);
 }
@@ -384,7 +384,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
 }
 
 TEST(AudioSendStreamTest, NoAudioBweCorrectObjectsOnChannelProxy) {
@@ -392,7 +392,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
 }
 
 TEST(AudioSendStreamTest, GetStats) {
@@ -400,7 +400,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   helper.SetupMockForGetStats();
   AudioSendStream::Stats stats = send_stream.GetStats();
   EXPECT_EQ(kSsrc, stats.local_ssrc);
@@ -431,7 +431,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   helper.SetupMockForGetStats();
   EXPECT_FALSE(send_stream.GetStats().typing_noise_detected);
 
@@ -465,7 +465,7 @@
   internal::AudioSendStream send_stream(
       stream_config, helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
 }
 
 // VAD is applied when codec is mono and the CNG frequency matches the codec
@@ -489,7 +489,7 @@
   internal::AudioSendStream send_stream(
       stream_config, helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
 
   // We cannot truly determine if the encoder created is an AudioEncoderCng.  It
   // is the only reasonable implementation that will return something from
@@ -503,7 +503,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   EXPECT_CALL(*helper.channel_proxy(),
               SetBitrate(helper.config().max_bitrate_bps, _));
   send_stream.OnBitrateUpdated(helper.config().max_bitrate_bps + 5000, 0.0, 50,
@@ -515,7 +515,7 @@
   internal::AudioSendStream send_stream(
       helper.config(), helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   EXPECT_CALL(*helper.channel_proxy(), SetBitrate(_, 5000));
   send_stream.OnBitrateUpdated(50000, 0.0, 50, 5000);
 }
@@ -538,7 +538,7 @@
   internal::AudioSendStream send_stream(
       stream_config, helper.audio_state(), helper.worker_queue(),
       helper.transport(), helper.bitrate_allocator(), helper.event_log(),
-      helper.rtcp_rtt_stats());
+      helper.rtcp_rtt_stats(), rtc::Optional<RtpState>());
   send_stream.Reconfigure(stream_config);
 }
 
diff --git a/webrtc/call/BUILD.gn b/webrtc/call/BUILD.gn
index 7728104..a6afe30 100644
--- a/webrtc/call/BUILD.gn
+++ b/webrtc/call/BUILD.gn
@@ -93,6 +93,7 @@
     ]
     deps = [
       ":call",
+      "../api:mock_audio_mixer",
       "../base:rtc_base_approved",
       "../logging:rtc_event_log_api",
       "../modules/audio_device:mock_audio_device",
diff --git a/webrtc/call/call.cc b/webrtc/call/call.cc
index 87e41b0..a1aa1de 100644
--- a/webrtc/call/call.cc
+++ b/webrtc/call/call.cc
@@ -305,7 +305,12 @@
   std::map<uint32_t, VideoSendStream*> video_send_ssrcs_ GUARDED_BY(send_crit_);
   std::set<VideoSendStream*> video_send_streams_ GUARDED_BY(send_crit_);
 
-  VideoSendStream::RtpStateMap suspended_video_send_ssrcs_;
+  using RtpStateMap = std::map<uint32_t, RtpState>;
+  RtpStateMap suspended_audio_send_ssrcs_
+      GUARDED_BY(configuration_thread_checker_);
+  RtpStateMap suspended_video_send_ssrcs_
+      GUARDED_BY(configuration_thread_checker_);
+
   webrtc::RtcEventLog* event_log_;
 
   // The following members are only accessed (exclusively) from one thread and
@@ -392,7 +397,7 @@
       video_send_delay_stats_(new SendDelayStats(clock_)),
       start_ms_(clock_->TimeInMilliseconds()),
       worker_queue_("call_worker_queue") {
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   RTC_DCHECK(config.event_log != nullptr);
   RTC_DCHECK_GE(config.bitrate_config.min_bitrate_bps, 0);
   RTC_DCHECK_GE(config.bitrate_config.start_bitrate_bps,
@@ -426,7 +431,7 @@
 }
 
 Call::~Call() {
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   RTC_CHECK(audio_send_ssrcs_.empty());
   RTC_CHECK(video_send_ssrcs_.empty());
@@ -553,18 +558,28 @@
 PacketReceiver* Call::Receiver() {
   // TODO(solenberg): Some test cases in EndToEndTest use this from a different
   // thread. Re-enable once that is fixed.
-  // RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  // RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   return this;
 }
 
 webrtc::AudioSendStream* Call::CreateAudioSendStream(
     const webrtc::AudioSendStream::Config& config) {
   TRACE_EVENT0("webrtc", "Call::CreateAudioSendStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   event_log_->LogAudioSendStreamConfig(CreateRtcLogStreamConfig(config));
+
+  rtc::Optional<RtpState> suspended_rtp_state;
+  {
+    const auto& iter = suspended_audio_send_ssrcs_.find(config.rtp.ssrc);
+    if (iter != suspended_audio_send_ssrcs_.end()) {
+      suspended_rtp_state.emplace(iter->second);
+    }
+  }
+
   AudioSendStream* send_stream = new AudioSendStream(
       config, config_.audio_state, &worker_queue_, transport_send_.get(),
-      bitrate_allocator_.get(), event_log_, call_stats_->rtcp_rtt_stats());
+      bitrate_allocator_.get(), event_log_, call_stats_->rtcp_rtt_stats(),
+      suspended_rtp_state);
   {
     WriteLockScoped write_lock(*send_crit_);
     RTC_DCHECK(audio_send_ssrcs_.find(config.rtp.ssrc) ==
@@ -586,14 +601,15 @@
 
 void Call::DestroyAudioSendStream(webrtc::AudioSendStream* send_stream) {
   TRACE_EVENT0("webrtc", "Call::DestroyAudioSendStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   RTC_DCHECK(send_stream != nullptr);
 
   send_stream->Stop();
 
   webrtc::internal::AudioSendStream* audio_send_stream =
       static_cast<webrtc::internal::AudioSendStream*>(send_stream);
-  uint32_t ssrc = audio_send_stream->config().rtp.ssrc;
+  const uint32_t ssrc = audio_send_stream->config().rtp.ssrc;
+  suspended_audio_send_ssrcs_[ssrc] = audio_send_stream->GetRtpState();
   {
     WriteLockScoped write_lock(*send_crit_);
     size_t num_deleted = audio_send_ssrcs_.erase(ssrc);
@@ -614,7 +630,7 @@
 webrtc::AudioReceiveStream* Call::CreateAudioReceiveStream(
     const webrtc::AudioReceiveStream::Config& config) {
   TRACE_EVENT0("webrtc", "Call::CreateAudioReceiveStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   event_log_->LogAudioReceiveStreamConfig(CreateRtcLogStreamConfig(config));
   AudioReceiveStream* receive_stream =
       new AudioReceiveStream(transport_send_->packet_router(), config,
@@ -643,7 +659,7 @@
 void Call::DestroyAudioReceiveStream(
     webrtc::AudioReceiveStream* receive_stream) {
   TRACE_EVENT0("webrtc", "Call::DestroyAudioReceiveStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   RTC_DCHECK(receive_stream != nullptr);
   webrtc::internal::AudioReceiveStream* audio_receive_stream =
       static_cast<webrtc::internal::AudioReceiveStream*>(receive_stream);
@@ -673,7 +689,7 @@
     webrtc::VideoSendStream::Config config,
     VideoEncoderConfig encoder_config) {
   TRACE_EVENT0("webrtc", "Call::CreateVideoSendStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   video_send_delay_stats_->AddSsrcs(config);
   for (size_t ssrc_index = 0; ssrc_index < config.rtp.ssrcs.size();
@@ -709,7 +725,7 @@
 void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
   TRACE_EVENT0("webrtc", "Call::DestroyVideoSendStream");
   RTC_DCHECK(send_stream != nullptr);
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   send_stream->Stop();
 
@@ -744,7 +760,7 @@
 webrtc::VideoReceiveStream* Call::CreateVideoReceiveStream(
     webrtc::VideoReceiveStream::Config configuration) {
   TRACE_EVENT0("webrtc", "Call::CreateVideoReceiveStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   VideoReceiveStream* receive_stream =
       new VideoReceiveStream(num_cpu_cores_, transport_send_->packet_router(),
@@ -778,7 +794,7 @@
 void Call::DestroyVideoReceiveStream(
     webrtc::VideoReceiveStream* receive_stream) {
   TRACE_EVENT0("webrtc", "Call::DestroyVideoReceiveStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   RTC_DCHECK(receive_stream != nullptr);
   VideoReceiveStream* receive_stream_impl =
       static_cast<VideoReceiveStream*>(receive_stream);
@@ -807,7 +823,7 @@
 FlexfecReceiveStream* Call::CreateFlexfecReceiveStream(
     const FlexfecReceiveStream::Config& config) {
   TRACE_EVENT0("webrtc", "Call::CreateFlexfecReceiveStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   RecoveredPacketReceiver* recovered_packet_receiver = this;
   FlexfecReceiveStreamImpl* receive_stream = new FlexfecReceiveStreamImpl(
@@ -834,7 +850,7 @@
 
 void Call::DestroyFlexfecReceiveStream(FlexfecReceiveStream* receive_stream) {
   TRACE_EVENT0("webrtc", "Call::DestroyFlexfecReceiveStream");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   RTC_DCHECK(receive_stream != nullptr);
   // There exist no other derived classes of FlexfecReceiveStream,
@@ -862,7 +878,7 @@
 Call::Stats Call::GetStats() const {
   // TODO(solenberg): Some test cases in EndToEndTest use this from a different
   // thread. Re-enable once that is fixed.
-  // RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  // RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   Stats stats;
   // Fetch available send/receive bitrates.
   uint32_t send_bandwidth = 0;
@@ -887,7 +903,7 @@
 void Call::SetBitrateConfig(
     const webrtc::Call::Config::BitrateConfig& bitrate_config) {
   TRACE_EVENT0("webrtc", "Call::SetBitrateConfig");
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   RTC_DCHECK_GE(bitrate_config.min_bitrate_bps, 0);
   if (bitrate_config.max_bitrate_bps != -1)
     RTC_DCHECK_GT(bitrate_config.max_bitrate_bps, 0);
@@ -914,7 +930,7 @@
 }
 
 void Call::SignalChannelNetworkState(MediaType media, NetworkState state) {
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   switch (media) {
     case MediaType::AUDIO:
       audio_network_state_ = state;
@@ -976,7 +992,7 @@
 // TODO(honghaiz): Add tests for this method.
 void Call::OnNetworkRouteChanged(const std::string& transport_name,
                                  const rtc::NetworkRoute& network_route) {
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
   // Check if the network route is connected.
   if (!network_route.connected) {
     LOG(LS_INFO) << "Transport " << transport_name << " is disconnected";
@@ -1013,7 +1029,7 @@
 }
 
 void Call::UpdateAggregateNetworkState() {
-  RTC_DCHECK(configuration_thread_checker_.CalledOnValidThread());
+  RTC_DCHECK_RUN_ON(&configuration_thread_checker_);
 
   bool have_audio = false;
   bool have_video = false;
diff --git a/webrtc/call/call_unittest.cc b/webrtc/call/call_unittest.cc
index 9576beb..06ee200 100644
--- a/webrtc/call/call_unittest.cc
+++ b/webrtc/call/call_unittest.cc
@@ -13,13 +13,16 @@
 #include <memory>
 #include <utility>
 
+#include "webrtc/api/test/mock_audio_mixer.h"
 #include "webrtc/base/ptr_util.h"
 #include "webrtc/call/audio_state.h"
 #include "webrtc/call/call.h"
 #include "webrtc/call/fake_rtp_transport_controller_send.h"
 #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
+#include "webrtc/modules/audio_device/include/mock_audio_device.h"
 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
 #include "webrtc/modules/congestion_controller/include/mock/mock_send_side_congestion_controller.h"
+#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "webrtc/test/gtest.h"
 #include "webrtc/test/mock_audio_decoder_factory.h"
 #include "webrtc/test/mock_transport.h"
@@ -134,6 +137,7 @@
   rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
       new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
   CallHelper call(decoder_factory);
+  ::testing::NiceMock<MockRtpRtcp> mock_rtp_rtcp;
 
   constexpr int kRecvChannelId = 101;
 
@@ -151,6 +155,8 @@
                 [](const std::map<int, SdpAudioFormat>& codecs) {
                   EXPECT_THAT(codecs, testing::IsEmpty());
                 }));
+        EXPECT_CALL(*channel_proxy, GetRtpRtcp(testing::_, testing::_))
+            .WillRepeatedly(testing::SetArgPointee<0>(&mock_rtp_rtcp));
         // If being called for the send channel, save a pointer to the channel
         // proxy for later.
         if (channel_id == kRecvChannelId) {
@@ -186,6 +192,7 @@
   rtc::scoped_refptr<webrtc::AudioDecoderFactory> decoder_factory(
       new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>);
   CallHelper call(decoder_factory);
+  ::testing::NiceMock<MockRtpRtcp> mock_rtp_rtcp;
 
   constexpr int kRecvChannelId = 101;
 
@@ -203,6 +210,8 @@
                 [](const std::map<int, SdpAudioFormat>& codecs) {
                   EXPECT_THAT(codecs, testing::IsEmpty());
                 }));
+        EXPECT_CALL(*channel_proxy, GetRtpRtcp(testing::_, testing::_))
+            .WillRepeatedly(testing::SetArgPointee<0>(&mock_rtp_rtcp));
         // If being called for the send channel, save a pointer to the channel
         // proxy for later.
         if (channel_id == kRecvChannelId) {
@@ -416,4 +425,69 @@
   call->SetBitrateConfig(bitrate_config);
 }
 
+TEST(CallTest, RecreatingAudioStreamWithSameSsrcReusesRtpState) {
+  constexpr uint32_t kSSRC = 12345;
+  testing::NiceMock<test::MockAudioDeviceModule> mock_adm;
+  // Reply with a 10ms timer every time TimeUntilNextProcess is called to
+  // avoid entering a tight loop on the process thread.
+  EXPECT_CALL(mock_adm, TimeUntilNextProcess())
+       .WillRepeatedly(testing::Return(10));
+  rtc::scoped_refptr<test::MockAudioMixer> mock_mixer(
+      new rtc::RefCountedObject<test::MockAudioMixer>);
+
+  // There's similar functionality in cricket::VoEWrapper but it's not reachable
+  // from here. Since we're working on removing VoE interfaces, I doubt it's
+  // worth making VoEWrapper more easily available.
+  struct ScopedVoiceEngine {
+    ScopedVoiceEngine()
+        : voe(VoiceEngine::Create()),
+          base(VoEBase::GetInterface(voe)) {}
+    ~ScopedVoiceEngine() {
+      base->Release();
+      EXPECT_TRUE(VoiceEngine::Delete(voe));
+    }
+
+    VoiceEngine* voe;
+    VoEBase* base;
+  };
+  ScopedVoiceEngine voice_engine;
+
+  voice_engine.base->Init(&mock_adm);
+  AudioState::Config audio_state_config;
+  audio_state_config.voice_engine = voice_engine.voe;
+  audio_state_config.audio_mixer = mock_mixer;
+  auto audio_state = AudioState::Create(audio_state_config);
+  RtcEventLogNullImpl event_log;
+  Call::Config call_config(&event_log);
+  call_config.audio_state = audio_state;
+  std::unique_ptr<Call> call(Call::Create(call_config));
+
+  auto create_stream_and_get_rtp_state = [&](uint32_t ssrc) {
+    AudioSendStream::Config config(nullptr);
+    config.rtp.ssrc = ssrc;
+    config.voe_channel_id = voice_engine.base->CreateChannel();
+    AudioSendStream* stream = call->CreateAudioSendStream(config);
+    VoiceEngineImpl* voe_impl = static_cast<VoiceEngineImpl*>(voice_engine.voe);
+    auto channel_proxy = voe_impl->GetChannelProxy(config.voe_channel_id);
+    RtpRtcp* rtp_rtcp = nullptr;
+    RtpReceiver* rtp_receiver = nullptr;  // Unused but required for call.
+    channel_proxy->GetRtpRtcp(&rtp_rtcp, &rtp_receiver);
+    const RtpState rtp_state = rtp_rtcp->GetRtpState();
+    call->DestroyAudioSendStream(stream);
+    voice_engine.base->DeleteChannel(config.voe_channel_id);
+    return rtp_state;
+  };
+
+  const RtpState rtp_state1 = create_stream_and_get_rtp_state(kSSRC);
+  const RtpState rtp_state2 = create_stream_and_get_rtp_state(kSSRC);
+
+  EXPECT_EQ(rtp_state1.sequence_number, rtp_state2.sequence_number);
+  EXPECT_EQ(rtp_state1.start_timestamp, rtp_state2.start_timestamp);
+  EXPECT_EQ(rtp_state1.timestamp, rtp_state2.timestamp);
+  EXPECT_EQ(rtp_state1.capture_time_ms, rtp_state2.capture_time_ms);
+  EXPECT_EQ(rtp_state1.last_timestamp_time_ms,
+            rtp_state2.last_timestamp_time_ms);
+  EXPECT_EQ(rtp_state1.media_has_been_sent, rtp_state2.media_has_been_sent);
+}
+
 }  // namespace webrtc
diff --git a/webrtc/test/mock_voice_engine.h b/webrtc/test/mock_voice_engine.h
index 6b1f9cf..7655d3b 100644
--- a/webrtc/test/mock_voice_engine.h
+++ b/webrtc/test/mock_voice_engine.h
@@ -16,6 +16,7 @@
 #include "webrtc/modules/audio_device/include/mock_audio_device.h"
 #include "webrtc/modules/audio_device/include/mock_audio_transport.h"
 #include "webrtc/modules/audio_processing/include/mock_audio_processing.h"
+#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
 #include "webrtc/test/gmock.h"
 #include "webrtc/test/mock_voe_channel_proxy.h"
 #include "webrtc/voice_engine/voice_engine_impl.h"
@@ -57,6 +58,9 @@
                   [](const std::map<int, SdpAudioFormat>& codecs) {
                     EXPECT_THAT(codecs, testing::IsEmpty());
                   }));
+          EXPECT_CALL(*proxy, GetRtpRtcp(testing::_, testing::_))
+              .WillRepeatedly(
+                  testing::SetArgPointee<0>(GetMockRtpRtcp(channel_id)));
           return proxy;
         }));
 
@@ -74,6 +78,15 @@
     // trigger an assertion.
     --_ref_count;
   }
+
+  // These need to be the same each call to channel_id and must not leak.
+  MockRtpRtcp* GetMockRtpRtcp(int channel_id) {
+    if (mock_rtp_rtcps_.find(channel_id) == mock_rtp_rtcps_.end()) {
+      mock_rtp_rtcps_[channel_id].reset(new ::testing::NiceMock<MockRtpRtcp>);
+    }
+    return mock_rtp_rtcps_[channel_id].get();
+  }
+
   // Allows injecting a ChannelProxy factory.
   MOCK_METHOD1(ChannelProxyFactory, voe::ChannelProxy*(int channel_id));
 
@@ -241,6 +254,8 @@
   // voe::Channel does.
   rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
 
+  std::map<int, std::unique_ptr<MockRtpRtcp>> mock_rtp_rtcps_;
+
   MockAudioDeviceModule mock_audio_device_;
   MockAudioProcessing mock_audio_processing_;
   MockAudioTransport mock_audio_transport_;