Set actual transport overhead in rtp_rtcp

BUG=webrtc:6557

Review-Url: https://codereview.webrtc.org/2437503004
Cr-Commit-Position: refs/heads/master@{#14968}
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index 7e8e426..fef5b1d 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -268,6 +268,11 @@
   return config_;
 }
 
+void AudioSendStream::SetTransportOverhead(int transport_overhead_per_packet) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  channel_proxy_->SetTransportOverhead(transport_overhead_per_packet);
+}
+
 VoiceEngine* AudioSendStream::voice_engine() const {
   internal::AudioState* audio_state =
       static_cast<internal::AudioState*>(audio_state_.get());
diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h
index 5a2864b..bb619cf 100644
--- a/webrtc/audio/audio_send_stream.h
+++ b/webrtc/audio/audio_send_stream.h
@@ -57,6 +57,7 @@
                             int64_t rtt) override;
 
   const webrtc::AudioSendStream::Config& config() const;
+  void SetTransportOverhead(int transport_overhead_per_packet);
 
  private:
   VoiceEngine* voice_engine() const;
diff --git a/webrtc/call.h b/webrtc/call.h
index 0ea4229..26f8c82 100644
--- a/webrtc/call.h
+++ b/webrtc/call.h
@@ -147,6 +147,10 @@
   virtual void SignalChannelNetworkState(MediaType media,
                                          NetworkState state) = 0;
 
+  virtual void OnTransportOverheadChanged(
+      MediaType media,
+      int transport_overhead_per_packet) = 0;
+
   virtual void OnNetworkRouteChanged(
       const std::string& transport_name,
       const rtc::NetworkRoute& network_route) = 0;
diff --git a/webrtc/call/call.cc b/webrtc/call/call.cc
index d727217..ebc1aeb 100644
--- a/webrtc/call/call.cc
+++ b/webrtc/call/call.cc
@@ -111,6 +111,9 @@
 
   void SignalChannelNetworkState(MediaType media, NetworkState state) override;
 
+  void OnTransportOverheadChanged(MediaType media,
+                                  int transport_overhead_per_packet) override;
+
   void OnNetworkRouteChanged(const std::string& transport_name,
                              const rtc::NetworkRoute& network_route) override;
 
@@ -736,6 +739,30 @@
   }
 }
 
+void Call::OnTransportOverheadChanged(MediaType media,
+                                      int transport_overhead_per_packet) {
+  switch (media) {
+    case MediaType::AUDIO: {
+      ReadLockScoped read_lock(*send_crit_);
+      for (auto& kv : audio_send_ssrcs_) {
+        kv.second->SetTransportOverhead(transport_overhead_per_packet);
+      }
+      break;
+    }
+    case MediaType::VIDEO: {
+      ReadLockScoped read_lock(*send_crit_);
+      for (auto& kv : video_send_ssrcs_) {
+        kv.second->SetTransportOverhead(transport_overhead_per_packet);
+      }
+      break;
+    }
+    case MediaType::ANY:
+    case MediaType::DATA:
+      RTC_NOTREACHED();
+      break;
+  }
+}
+
 // TODO(honghaiz): Add tests for this method.
 void Call::OnNetworkRouteChanged(const std::string& transport_name,
                                  const rtc::NetworkRoute& network_route) {
diff --git a/webrtc/media/base/fakemediaengine.h b/webrtc/media/base/fakemediaengine.h
index 6470624..57062b3 100644
--- a/webrtc/media/base/fakemediaengine.h
+++ b/webrtc/media/base/fakemediaengine.h
@@ -210,6 +210,10 @@
     return ready_to_send_;
   }
 
+  int transport_overhead_per_packet() const {
+    return transport_overhead_per_packet_;
+  }
+
   rtc::NetworkRoute last_network_route() const { return last_network_route_; }
   int num_network_route_changes() const { return num_network_route_changes_; }
   void set_num_network_route_changes(int changes) {
@@ -252,6 +256,10 @@
   virtual void OnReadyToSend(bool ready) {
     ready_to_send_ = ready;
   }
+  virtual void OnTransportOverheadChanged(int transport_overhead_per_packet) {
+    transport_overhead_per_packet_ = transport_overhead_per_packet;
+  }
+
   virtual void OnNetworkRouteChanged(const std::string& transport_name,
                                      const rtc::NetworkRoute& network_route) {
     last_network_route_ = network_route;
@@ -277,6 +285,7 @@
   uint32_t send_ssrc_;
   std::string rtcp_cname_;
   bool ready_to_send_;
+  int transport_overhead_per_packet_;
   rtc::NetworkRoute last_network_route_;
   int num_network_route_changes_ = 0;
 };
diff --git a/webrtc/media/base/mediachannel.h b/webrtc/media/base/mediachannel.h
index b21919c..ecb09f0 100644
--- a/webrtc/media/base/mediachannel.h
+++ b/webrtc/media/base/mediachannel.h
@@ -405,6 +405,9 @@
   virtual void OnNetworkRouteChanged(
       const std::string& transport_name,
       const rtc::NetworkRoute& network_route) = 0;
+  // Called when the rtp transport overhead changed.
+  virtual void OnTransportOverheadChanged(
+      int transport_overhead_per_packet) = 0;
   // Creates a new outgoing media stream with SSRCs and CNAME as described
   // by sp.
   virtual bool AddSendStream(const StreamParams& sp) = 0;
diff --git a/webrtc/media/base/rtpdataengine.h b/webrtc/media/base/rtpdataengine.h
index 98f90be..37a84da 100644
--- a/webrtc/media/base/rtpdataengine.h
+++ b/webrtc/media/base/rtpdataengine.h
@@ -83,6 +83,7 @@
   virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                               const rtc::PacketTime& packet_time) {}
   virtual void OnReadyToSend(bool ready) {}
+  virtual void OnTransportOverheadChanged(int transport_overhead_per_packet) {}
   virtual bool SendData(
     const SendDataParams& params,
     const rtc::CopyOnWriteBuffer& payload,
diff --git a/webrtc/media/engine/fakewebrtccall.cc b/webrtc/media/engine/fakewebrtccall.cc
index 43e083f..d2aa7bc1 100644
--- a/webrtc/media/engine/fakewebrtccall.cc
+++ b/webrtc/media/engine/fakewebrtccall.cc
@@ -528,6 +528,22 @@
   }
 }
 
+void FakeCall::OnTransportOverheadChanged(webrtc::MediaType media,
+                                          int transport_overhead_per_packet) {
+  switch (media) {
+    case webrtc::MediaType::AUDIO:
+      audio_transport_overhead_ = transport_overhead_per_packet;
+      break;
+    case webrtc::MediaType::VIDEO:
+      video_transport_overhead_ = transport_overhead_per_packet;
+      break;
+    case webrtc::MediaType::DATA:
+    case webrtc::MediaType::ANY:
+      ADD_FAILURE()
+          << "SignalChannelNetworkState called with unknown parameter.";
+  }
+}
+
 void FakeCall::OnSentPacket(const rtc::SentPacket& sent_packet) {
   last_sent_packet_ = sent_packet;
   if (sent_packet.packet_id >= 0) {
diff --git a/webrtc/media/engine/fakewebrtccall.h b/webrtc/media/engine/fakewebrtccall.h
index 59084fc..7ff80ce 100644
--- a/webrtc/media/engine/fakewebrtccall.h
+++ b/webrtc/media/engine/fakewebrtccall.h
@@ -262,6 +262,8 @@
                              const rtc::NetworkRoute& network_route) override {}
   void SignalChannelNetworkState(webrtc::MediaType media,
                                  webrtc::NetworkState state) override;
+  void OnTransportOverheadChanged(webrtc::MediaType media,
+                                  int transport_overhead_per_packet) override;
   void OnSentPacket(const rtc::SentPacket& sent_packet) override;
 
   webrtc::Call::Config config_;
@@ -277,6 +279,9 @@
 
   int num_created_send_streams_;
   int num_created_receive_streams_;
+
+  int audio_transport_overhead_;
+  int video_transport_overhead_;
 };
 
 }  // namespace cricket
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
index 1456407..3cacc7d 100644
--- a/webrtc/media/engine/webrtcvideoengine2.cc
+++ b/webrtc/media/engine/webrtcvideoengine2.cc
@@ -1482,6 +1482,12 @@
   call_->OnNetworkRouteChanged(transport_name, network_route);
 }
 
+void WebRtcVideoChannel2::OnTransportOverheadChanged(
+    int transport_overhead_per_packet) {
+  call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO,
+                                    transport_overhead_per_packet);
+}
+
 void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
   MediaChannel::SetInterface(iface);
   // Set the RTP recv/send buffer to a bigger size
diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h
index ff62faf..ef893d2 100644
--- a/webrtc/media/engine/webrtcvideoengine2.h
+++ b/webrtc/media/engine/webrtcvideoengine2.h
@@ -172,6 +172,7 @@
   void OnReadyToSend(bool ready) override;
   void OnNetworkRouteChanged(const std::string& transport_name,
                              const rtc::NetworkRoute& network_route) override;
+  void OnTransportOverheadChanged(int transport_overhead_per_packet) override;
   void SetInterface(NetworkInterface* iface) override;
 
   // Implemented for VideoMediaChannelTest.
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index 6f24ef8..a4768db 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -2463,6 +2463,13 @@
       ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
 }
 
+void WebRtcVoiceMediaChannel::OnTransportOverheadChanged(
+    int transport_overhead_per_packet) {
+  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
+  call_->OnTransportOverheadChanged(webrtc::MediaType::AUDIO,
+                                    transport_overhead_per_packet);
+}
+
 bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
   TRACE_EVENT0("webrtc", "WebRtcVoiceMediaChannel::GetStats");
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h
index df2f64d..a0cae71 100644
--- a/webrtc/media/engine/webrtcvoiceengine.h
+++ b/webrtc/media/engine/webrtcvoiceengine.h
@@ -192,6 +192,7 @@
   void OnNetworkRouteChanged(const std::string& transport_name,
                              const rtc::NetworkRoute& network_route) override;
   void OnReadyToSend(bool ready) override;
+  void OnTransportOverheadChanged(int transport_overhead_per_packet) override;
   bool GetStats(VoiceMediaInfo* info) override;
 
   void SetRawAudioSink(
diff --git a/webrtc/media/sctp/sctpdataengine.h b/webrtc/media/sctp/sctpdataengine.h
index 6591383..90011c4 100644
--- a/webrtc/media/sctp/sctpdataengine.h
+++ b/webrtc/media/sctp/sctpdataengine.h
@@ -163,6 +163,7 @@
   virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                               const rtc::PacketTime& packet_time) {}
   virtual void OnReadyToSend(bool ready) {}
+  virtual void OnTransportOverheadChanged(int transport_overhead_per_packet) {}
 
   void OnSendThresholdCallback();
   // Helper for debugging.
diff --git a/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h
index fe88b1b..1e4da64 100644
--- a/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h
+++ b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h
@@ -116,10 +116,14 @@
   // |authentication_overhead| - number of bytes to leave for an authentication
   // header.
   // Returns -1 on failure else 0
+  // TODO(michaelt): deprecate the function.
   virtual int32_t SetTransportOverhead(bool tcp,
                                        bool ipv6,
                                        uint8_t authentication_overhead = 0) = 0;
 
+  // Sets transtport overhead per packet.
+  virtual void SetTransportOverhead(int transport_overhead_per_packet) = 0;
+
   // Returns max payload length, which is a combination of the configuration
   // MaxTransferUnit and TransportOverhead.
   // Does not account for RTP headers and FEC/ULP/RED overhead (when FEC is
diff --git a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
index d39fce8..04603ef 100644
--- a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
+++ b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
@@ -55,6 +55,7 @@
   MOCK_METHOD1(SetMaxTransferUnit, int32_t(uint16_t size));
   MOCK_METHOD3(SetTransportOverhead,
                int32_t(bool tcp, bool ipv6, uint8_t authentication_overhead));
+  MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet));
   MOCK_CONST_METHOD0(MaxPayloadLength, uint16_t());
   MOCK_CONST_METHOD0(MaxDataPayloadLength, uint16_t());
   MOCK_METHOD1(RegisterSendPayload, int32_t(const CodecInst& voice_codec));
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 664bf3a..72a1f11 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -452,6 +452,17 @@
   return 0;
 }
 
+void ModuleRtpRtcpImpl::SetTransportOverhead(
+    int transport_overhead_per_packet) {
+  RTC_DCHECK_GT(transport_overhead_per_packet, 0);
+  int mtu = rtp_sender_.MaxPayloadLength() + packet_overhead_;
+  RTC_DCHECK_LT(transport_overhead_per_packet, mtu);
+  size_t max_payload_length = mtu - transport_overhead_per_packet;
+  packet_overhead_ = transport_overhead_per_packet;
+  rtcp_sender_.SetMaxPayloadLength(max_payload_length);
+  rtp_sender_.SetMaxPayloadLength(max_payload_length);
+}
+
 int32_t ModuleRtpRtcpImpl::SetMaxTransferUnit(uint16_t mtu) {
   RTC_DCHECK_LE(mtu, IP_PACKET_SIZE) << "MTU too large: " << mtu;
   RTC_DCHECK_GT(mtu, packet_overhead_) << "MTU too small: " << mtu;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index 8cd47ed..3bda93b 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -210,10 +210,13 @@
 
   int32_t SetMaxTransferUnit(uint16_t size) override;
 
+  // TODO(michaelt): deprecate the function.
   int32_t SetTransportOverhead(bool tcp,
                                bool ipv6,
                                uint8_t authentication_overhead = 0) override;
 
+  void SetTransportOverhead(int transport_overhead_per_packet) override;
+
   // (NACK) Negative acknowledgment part.
 
   int SelectiveRetransmissions() const override;
diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc
index d1e520d..576557f 100644
--- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc
+++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc
@@ -140,6 +140,11 @@
 
   EXPECT_EQ(0, module_->SetTransportOverhead(false, false, 0));
   EXPECT_EQ(1234 - 20 - 8, module_->MaxPayloadLength());
+
+  module_->SetTransportOverhead(28);
+  EXPECT_EQ(1234 - 28, module_->MaxPayloadLength());
+  module_->SetTransportOverhead(44);
+  EXPECT_EQ(1234 - 44, module_->MaxPayloadLength());
 }
 
 TEST_F(RtpRtcpAPITest, SSRC) {
diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc
index d9eb9b6..7b48329 100644
--- a/webrtc/pc/channel.cc
+++ b/webrtc/pc/channel.cc
@@ -172,7 +172,8 @@
 
       transport_controller_(transport_controller),
       rtcp_enabled_(rtcp),
-      media_channel_(media_channel) {
+      media_channel_(media_channel),
+      selected_candidate_pair_(nullptr) {
   RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
   if (transport_controller) {
     RTC_DCHECK_EQ(network_thread, transport_controller->network_thread());
@@ -388,6 +389,7 @@
 
 void BaseChannel::DisconnectFromTransportChannel(TransportChannel* tc) {
   RTC_DCHECK(network_thread_->IsCurrent());
+  OnSelectedCandidatePairChanged(tc, nullptr, -1, false);
 
   tc->SignalWritableState.disconnect(this);
   tc->SignalReadPacket.disconnect(this);
@@ -581,6 +583,7 @@
   RTC_DCHECK(channel == transport_channel_ ||
              channel == rtcp_transport_channel_);
   RTC_DCHECK(network_thread_->IsCurrent());
+  selected_candidate_pair_ = selected_candidate_pair;
   std::string transport_name = channel->transport_name();
   rtc::NetworkRoute network_route;
   if (selected_candidate_pair) {
@@ -588,6 +591,8 @@
         ready_to_send, selected_candidate_pair->local_candidate().network_id(),
         selected_candidate_pair->remote_candidate().network_id(),
         last_sent_packet_id);
+
+    UpdateTransportOverhead();
   }
   invoker_.AsyncInvoke<void>(
       RTC_FROM_HERE, worker_thread_,
@@ -905,16 +910,12 @@
   LOG(LS_INFO) << "Channel writable (" << content_name_ << ")"
                << (was_ever_writable_ ? "" : " for the first time");
 
-  std::vector<ConnectionInfo> infos;
-  transport_channel_->GetStats(&infos);
-  for (std::vector<ConnectionInfo>::const_iterator it = infos.begin();
-       it != infos.end(); ++it) {
-    if (it->best_connection) {
-      LOG(LS_INFO) << "Using " << it->local_candidate.ToSensitiveString()
-                   << "->" << it->remote_candidate.ToSensitiveString();
-      break;
-    }
-  }
+  if (selected_candidate_pair_)
+    LOG(LS_INFO)
+        << "Using "
+        << selected_candidate_pair_->local_candidate().ToSensitiveString()
+        << "->"
+        << selected_candidate_pair_->remote_candidate().ToSensitiveString();
 
   was_ever_writable_ = true;
   MaybeSetupDtlsSrtp_n();
@@ -1033,11 +1034,12 @@
                                     static_cast<int>(recv_key->size()));
   }
 
-  if (!ret)
+  if (!ret) {
     LOG(LS_WARNING) << "DTLS-SRTP key installation failed";
-  else
+  } else {
     dtls_keyed_ = true;
-
+    UpdateTransportOverhead();
+  }
   return ret;
 }
 
@@ -1665,6 +1667,47 @@
       Bind(&BaseChannel::UpdateMediaSendRecvState_w, this));
 }
 
+int BaseChannel::GetTransportOverheadPerPacket() const {
+  RTC_DCHECK(network_thread_->IsCurrent());
+
+  if (!selected_candidate_pair_)
+    return 0;
+
+  int transport_overhead_per_packet = 0;
+
+  constexpr int kIpv4Overhaed = 20;
+  constexpr int kIpv6Overhaed = 40;
+  transport_overhead_per_packet +=
+      selected_candidate_pair_->local_candidate().address().family() == AF_INET
+          ? kIpv4Overhaed
+          : kIpv6Overhaed;
+
+  constexpr int kUdpOverhaed = 8;
+  constexpr int kTcpOverhaed = 20;
+  transport_overhead_per_packet +=
+      selected_candidate_pair_->local_candidate().protocol() ==
+              TCP_PROTOCOL_NAME
+          ? kTcpOverhaed
+          : kUdpOverhaed;
+
+  if (secure()) {
+    int srtp_overhead = 0;
+    if (srtp_filter_.GetSrtpOverhead(&srtp_overhead))
+      transport_overhead_per_packet += srtp_overhead;
+  }
+
+  return transport_overhead_per_packet;
+}
+
+void BaseChannel::UpdateTransportOverhead() {
+  int transport_overhead_per_packet = GetTransportOverheadPerPacket();
+  if (transport_overhead_per_packet)
+    invoker_.AsyncInvoke<void>(
+        RTC_FROM_HERE, worker_thread_,
+        Bind(&MediaChannel::OnTransportOverheadChanged, media_channel_,
+             transport_overhead_per_packet));
+}
+
 void VoiceChannel::UpdateMediaSendRecvState_w() {
   // Render incoming data if we're the active call, and we have the local
   // content. We receive data on the default channel and multiplexed streams.
diff --git a/webrtc/pc/channel.h b/webrtc/pc/channel.h
index 45918ff..e69609e 100644
--- a/webrtc/pc/channel.h
+++ b/webrtc/pc/channel.h
@@ -366,6 +366,8 @@
   void SignalSentPacket_w(const rtc::SentPacket& sent_packet);
   bool IsReadyToSendMedia_n() const;
   void CacheRtpAbsSendTimeHeaderExtension_n(int rtp_abs_sendtime_extn_id);
+  int GetTransportOverheadPerPacket() const;
+  void UpdateTransportOverhead();
 
   rtc::Thread* const worker_thread_;
   rtc::Thread* const network_thread_;
@@ -410,6 +412,7 @@
   std::vector<StreamParams> remote_streams_;
   MediaContentDirection local_content_direction_ = MD_INACTIVE;
   MediaContentDirection remote_content_direction_ = MD_INACTIVE;
+  CandidatePairInterface* selected_candidate_pair_;
 };
 
 // VoiceChannel is a specialization that adds support for early media, DTMF,
diff --git a/webrtc/pc/channel_unittest.cc b/webrtc/pc/channel_unittest.cc
index 0bea6dc..16b5be7 100644
--- a/webrtc/pc/channel_unittest.cc
+++ b/webrtc/pc/channel_unittest.cc
@@ -962,6 +962,9 @@
     EXPECT_EQ(expected_network_route, media_channel1->last_network_route());
     EXPECT_EQ(kLastPacketId,
               media_channel1->last_network_route().last_sent_packet_id);
+    constexpr int kTransportOverheadPerPacket = 28;  // Ipv4(20) + UDP(8).
+    EXPECT_EQ(kTransportOverheadPerPacket,
+              media_channel1->transport_overhead_per_packet());
   }
 
   // Test setting up a call.
diff --git a/webrtc/pc/srtpfilter.cc b/webrtc/pc/srtpfilter.cc
index 5e2dbb0..7000ed9 100644
--- a/webrtc/pc/srtpfilter.cc
+++ b/webrtc/pc/srtpfilter.cc
@@ -215,6 +215,17 @@
   return send_session_->GetRtpAuthParams(key, key_len, tag_len);
 }
 
+bool SrtpFilter::GetSrtpOverhead(int* srtp_overhead) const {
+  if (!IsActive()) {
+    LOG(LS_WARNING) << "Failed to GetSrtpOverhead: SRTP not active";
+    return false;
+  }
+
+  RTC_CHECK(send_session_);
+  *srtp_overhead = send_session_->GetSrtpOverhead();
+  return true;
+}
+
 void SrtpFilter::set_signal_silent_time(int signal_silent_time_in_ms) {
   signal_silent_time_in_ms_ = signal_silent_time_in_ms;
   if (IsActive()) {
@@ -606,6 +617,10 @@
 #endif
 }
 
+int SrtpSession::GetSrtpOverhead() const {
+  return rtp_auth_tag_len_;
+}
+
 bool SrtpSession::GetSendStreamPacketIndex(void* p,
                                            int in_len,
                                            int64_t* index) {
diff --git a/webrtc/pc/srtpfilter.h b/webrtc/pc/srtpfilter.h
index ec91805..06edddf 100644
--- a/webrtc/pc/srtpfilter.h
+++ b/webrtc/pc/srtpfilter.h
@@ -111,6 +111,9 @@
   // Returns rtp auth params from srtp context.
   bool GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len);
 
+  // Returns srtp overhead for rtp packets.
+  bool GetSrtpOverhead(int* srtp_overhead) const;
+
   // Update the silent threshold (in ms) for signaling errors.
   void set_signal_silent_time(int signal_silent_time_in_ms);
 
@@ -201,6 +204,8 @@
   // Helper method to get authentication params.
   bool GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len);
 
+  int GetSrtpOverhead() const;
+
   // Update the silent threshold (in ms) for signaling errors.
   void set_signal_silent_time(int signal_silent_time_in_ms);
 
diff --git a/webrtc/test/mock_voe_channel_proxy.h b/webrtc/test/mock_voe_channel_proxy.h
index 2383519..1f4b14f 100644
--- a/webrtc/test/mock_voe_channel_proxy.h
+++ b/webrtc/test/mock_voe_channel_proxy.h
@@ -57,6 +57,7 @@
                      const rtc::scoped_refptr<AudioDecoderFactory>&());
   MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
   MOCK_METHOD1(SetRtcEventLog, void(RtcEventLog* event_log));
+  MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet));
   MOCK_METHOD1(SetBitrate, void(int bitrate_bps));
   MOCK_METHOD1(EnableAudioNetworkAdaptor,
                void(const std::string& config_string));
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index 827b54b..26082ab 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -274,6 +274,8 @@
   void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
                                    size_t byte_limit);
 
+  void SetTransportOverhead(int transport_overhead_per_packet);
+
  private:
   class CheckEncoderActivityTask;
   class EncoderReconfiguredTask;
@@ -617,6 +619,14 @@
   return state_map;
 }
 
+void VideoSendStream::SetTransportOverhead(int transport_overhead_per_packet) {
+  RTC_DCHECK_RUN_ON(&thread_checker_);
+  VideoSendStreamImpl* send_stream = send_stream_.get();
+  worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
+    send_stream->SetTransportOverhead(transport_overhead_per_packet);
+  });
+}
+
 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
   // Called on a network thread.
   return send_stream_->DeliverRtcp(packet, length);
@@ -1122,5 +1132,11 @@
   return 0;
 }
 
+void VideoSendStreamImpl::SetTransportOverhead(
+    int transport_overhead_per_packet) {
+  for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
+    rtp_rtcp->SetTransportOverhead(transport_overhead_per_packet);
+}
+
 }  // namespace internal
 }  // namespace webrtc
diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h
index e2c3616..2845aed 100644
--- a/webrtc/video/video_send_stream.h
+++ b/webrtc/video/video_send_stream.h
@@ -90,6 +90,8 @@
 
   RtpStateMap StopPermanentlyAndGetRtpStates();
 
+  void SetTransportOverhead(int transport_overhead_per_packet);
+
  private:
   class ConstructionTask;
   class DestructAndGetRtpStateTask;
diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc
index 2b28f4f..2b5c6e6 100644
--- a/webrtc/video/video_send_stream_tests.cc
+++ b/webrtc/video/video_send_stream_tests.cc
@@ -1321,6 +1321,48 @@
   RunBaseTest(&test);
 }
 
+TEST_F(VideoSendStreamTest, ChangingTransportOverhead) {
+  class ChangingTransportOverheadTest : public test::EndToEndTest {
+   public:
+    ChangingTransportOverheadTest()
+        : EndToEndTest(test::CallTest::kDefaultTimeoutMs),
+          call_(nullptr),
+          packets_sent_(0) {}
+
+    void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
+      call_ = sender_call;
+    }
+
+    Action OnSendRtp(const uint8_t* packet, size_t length) override {
+      EXPECT_LE(length,
+                IP_PACKET_SIZE - static_cast<size_t>(transport_overhead_));
+      if (++packets_sent_ < 100)
+        return SEND_PACKET;
+      observation_complete_.Set();
+      return SEND_PACKET;
+    }
+
+    void PerformTest() override {
+      transport_overhead_ = 500;
+      call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO,
+                                        transport_overhead_);
+      EXPECT_TRUE(Wait());
+      packets_sent_ = 0;
+      transport_overhead_ = 1000;
+      call_->OnTransportOverheadChanged(webrtc::MediaType::VIDEO,
+                                        transport_overhead_);
+      EXPECT_TRUE(Wait());
+    }
+
+   private:
+    Call* call_;
+    int packets_sent_;
+    int transport_overhead_;
+  } test;
+
+  RunBaseTest(&test);
+}
+
 class MaxPaddingSetTest : public test::SendTest {
  public:
   static const uint32_t kMinTransmitBitrateBps = 400000;
diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index 3d195eb..66f14bd 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -2828,6 +2828,10 @@
   event_log_proxy_->SetEventLog(event_log);
 }
 
+void Channel::SetTransportOverhead(int transport_overhead_per_packet) {
+  _rtpRtcpModule->SetTransportOverhead(transport_overhead_per_packet);
+}
+
 int Channel::RegisterExternalMediaProcessing(ProcessingTypes type,
                                              VoEMediaProcess& processObject) {
   WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
diff --git a/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h
index c86820f..4bfcd74 100644
--- a/webrtc/voice_engine/channel.h
+++ b/webrtc/voice_engine/channel.h
@@ -417,6 +417,8 @@
   // Set a RtcEventLog logging object.
   void SetRtcEventLog(RtcEventLog* event_log);
 
+  void SetTransportOverhead(int transport_overhead_per_packet);
+
  protected:
   void OnIncomingFractionLoss(int fraction_lost);
 
diff --git a/webrtc/voice_engine/channel_proxy.cc b/webrtc/voice_engine/channel_proxy.cc
index 6aef29c..1f9d7f3 100644
--- a/webrtc/voice_engine/channel_proxy.cc
+++ b/webrtc/voice_engine/channel_proxy.cc
@@ -231,6 +231,11 @@
   return static_cast<int>(channel()->NeededFrequency(-1));
 }
 
+void ChannelProxy::SetTransportOverhead(int transport_overhead_per_packet) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  channel()->SetTransportOverhead(transport_overhead_per_packet);
+}
+
 Channel* ChannelProxy::channel() const {
   RTC_DCHECK(channel_owner_.channel());
   return channel_owner_.channel();
diff --git a/webrtc/voice_engine/channel_proxy.h b/webrtc/voice_engine/channel_proxy.h
index ea0446e..44b25fd 100644
--- a/webrtc/voice_engine/channel_proxy.h
+++ b/webrtc/voice_engine/channel_proxy.h
@@ -94,6 +94,8 @@
 
   virtual int NeededFrequency() const;
 
+  virtual void SetTransportOverhead(int transport_overhead_per_packet);
+
  private:
   Channel* channel() const;