From 79e05888e8f47ac7e19eb10decf0f1b490aa31ca Mon Sep 17 00:00:00 2001 From: michaelt Date: Tue, 8 Nov 2016 02:50:09 -0800 Subject: [PATCH] Set actual transport overhead in rtp_rtcp BUG=webrtc:6557 Review-Url: https://codereview.webrtc.org/2437503004 Cr-Commit-Position: refs/heads/master@{#14968} --- webrtc/audio/audio_send_stream.cc | 5 ++ webrtc/audio/audio_send_stream.h | 1 + webrtc/call.h | 4 ++ webrtc/call/call.cc | 27 +++++++ webrtc/media/base/fakemediaengine.h | 9 +++ webrtc/media/base/mediachannel.h | 3 + webrtc/media/base/rtpdataengine.h | 1 + webrtc/media/engine/fakewebrtccall.cc | 16 +++++ webrtc/media/engine/fakewebrtccall.h | 5 ++ webrtc/media/engine/webrtcvideoengine2.cc | 6 ++ webrtc/media/engine/webrtcvideoengine2.h | 1 + webrtc/media/engine/webrtcvoiceengine.cc | 7 ++ webrtc/media/engine/webrtcvoiceengine.h | 1 + webrtc/media/sctp/sctpdataengine.h | 1 + webrtc/modules/rtp_rtcp/include/rtp_rtcp.h | 4 ++ webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h | 1 + .../modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 11 +++ .../modules/rtp_rtcp/source/rtp_rtcp_impl.h | 3 + .../modules/rtp_rtcp/test/testAPI/test_api.cc | 5 ++ webrtc/pc/channel.cc | 71 +++++++++++++++---- webrtc/pc/channel.h | 3 + webrtc/pc/channel_unittest.cc | 3 + webrtc/pc/srtpfilter.cc | 15 ++++ webrtc/pc/srtpfilter.h | 5 ++ webrtc/test/mock_voe_channel_proxy.h | 1 + webrtc/video/video_send_stream.cc | 16 +++++ webrtc/video/video_send_stream.h | 2 + webrtc/video/video_send_stream_tests.cc | 42 +++++++++++ webrtc/voice_engine/channel.cc | 4 ++ webrtc/voice_engine/channel.h | 2 + webrtc/voice_engine/channel_proxy.cc | 5 ++ webrtc/voice_engine/channel_proxy.h | 2 + 32 files changed, 268 insertions(+), 14 deletions(-) diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc index 7e8e426ed9..fef5b1d8ef 100644 --- a/webrtc/audio/audio_send_stream.cc +++ b/webrtc/audio/audio_send_stream.cc @@ -268,6 +268,11 @@ const webrtc::AudioSendStream::Config& AudioSendStream::config() const { 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(audio_state_.get()); diff --git a/webrtc/audio/audio_send_stream.h b/webrtc/audio/audio_send_stream.h index 5a2864b77f..bb619cf2b5 100644 --- a/webrtc/audio/audio_send_stream.h +++ b/webrtc/audio/audio_send_stream.h @@ -57,6 +57,7 @@ class AudioSendStream final : public webrtc::AudioSendStream, 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 0ea4229834..26f8c82bd9 100644 --- a/webrtc/call.h +++ b/webrtc/call.h @@ -147,6 +147,10 @@ class Call { 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 d727217084..ebc1aeb866 100644 --- a/webrtc/call/call.cc +++ b/webrtc/call/call.cc @@ -111,6 +111,9 @@ class Call : public webrtc::Call, 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::SignalChannelNetworkState(MediaType media, NetworkState state) { } } +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 6470624061..57062b382a 100644 --- a/webrtc/media/base/fakemediaengine.h +++ b/webrtc/media/base/fakemediaengine.h @@ -210,6 +210,10 @@ template class RtpHelper : public Base { 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 @@ template class RtpHelper : public Base { 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 @@ template class RtpHelper : public Base { 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 b21919c94a..ecb09f033a 100644 --- a/webrtc/media/base/mediachannel.h +++ b/webrtc/media/base/mediachannel.h @@ -405,6 +405,9 @@ class MediaChannel : public sigslot::has_slots<> { 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 98f90be332..37a84da16f 100644 --- a/webrtc/media/base/rtpdataengine.h +++ b/webrtc/media/base/rtpdataengine.h @@ -83,6 +83,7 @@ class RtpDataMediaChannel : public DataMediaChannel { 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 43e083fefb..d2aa7bc1b4 100644 --- a/webrtc/media/engine/fakewebrtccall.cc +++ b/webrtc/media/engine/fakewebrtccall.cc @@ -528,6 +528,22 @@ void FakeCall::SignalChannelNetworkState(webrtc::MediaType media, } } +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 59084fc4c8..7ff80ce0cc 100644 --- a/webrtc/media/engine/fakewebrtccall.h +++ b/webrtc/media/engine/fakewebrtccall.h @@ -262,6 +262,8 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver { 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 @@ class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver { 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 14564071da..3cacc7da82 100644 --- a/webrtc/media/engine/webrtcvideoengine2.cc +++ b/webrtc/media/engine/webrtcvideoengine2.cc @@ -1482,6 +1482,12 @@ void WebRtcVideoChannel2::OnNetworkRouteChanged( 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 ff62fafa8e..ef893d2e98 100644 --- a/webrtc/media/engine/webrtcvideoengine2.h +++ b/webrtc/media/engine/webrtcvideoengine2.h @@ -172,6 +172,7 @@ class WebRtcVideoChannel2 : public VideoMediaChannel, public webrtc::Transport { 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 6f24ef8b27..a4768db49f 100644 --- a/webrtc/media/engine/webrtcvoiceengine.cc +++ b/webrtc/media/engine/webrtcvoiceengine.cc @@ -2463,6 +2463,13 @@ void WebRtcVoiceMediaChannel::OnReadyToSend(bool ready) { 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 df2f64d53e..a0cae71478 100644 --- a/webrtc/media/engine/webrtcvoiceengine.h +++ b/webrtc/media/engine/webrtcvoiceengine.h @@ -192,6 +192,7 @@ class WebRtcVoiceMediaChannel final : public VoiceMediaChannel, 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 6591383916..90011c4f46 100644 --- a/webrtc/media/sctp/sctpdataengine.h +++ b/webrtc/media/sctp/sctpdataengine.h @@ -163,6 +163,7 @@ class SctpDataMediaChannel : public DataMediaChannel, 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 fe88b1b674..1e4da64220 100644 --- a/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/include/rtp_rtcp.h @@ -116,10 +116,14 @@ class RtpRtcp : public Module { // |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 d39fce8ec1..04603efcea 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 @@ class MockRtpRtcp : public RtpRtcp { 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 664bf3acd1..72a1f11f42 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 @@ int32_t ModuleRtpRtcpImpl::SetTransportOverhead( 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 8cd47ed280..3bda93b929 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 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp { 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 d1e520de8f..576557f32e 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 @@ TEST_F(RtpRtcpAPITest, MTU) { 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 d9eb9b6fac..7b483292fc 100644 --- a/webrtc/pc/channel.cc +++ b/webrtc/pc/channel.cc @@ -172,7 +172,8 @@ BaseChannel::BaseChannel(rtc::Thread* worker_thread, 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::ConnectToTransportChannel(TransportChannel* tc) { 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 @@ void BaseChannel::OnSelectedCandidatePairChanged( 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 @@ void BaseChannel::OnSelectedCandidatePairChanged( ready_to_send, selected_candidate_pair->local_candidate().network_id(), selected_candidate_pair->remote_candidate().network_id(), last_sent_packet_id); + + UpdateTransportOverhead(); } invoker_.AsyncInvoke( RTC_FROM_HERE, worker_thread_, @@ -905,16 +910,12 @@ void BaseChannel::ChannelWritable_n() { LOG(LS_INFO) << "Channel writable (" << content_name_ << ")" << (was_ever_writable_ ? "" : " for the first time"); - std::vector infos; - transport_channel_->GetStats(&infos); - for (std::vector::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 @@ bool BaseChannel::SetupDtlsSrtp_n(bool rtcp_channel) { static_cast(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 @@ void BaseChannel::UpdateMediaSendRecvState() { 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( + 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 45918ffca0..e69609e46b 100644 --- a/webrtc/pc/channel.h +++ b/webrtc/pc/channel.h @@ -366,6 +366,8 @@ class BaseChannel 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 @@ class BaseChannel std::vector 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 0bea6dcad2..16b5be71e1 100644 --- a/webrtc/pc/channel_unittest.cc +++ b/webrtc/pc/channel_unittest.cc @@ -962,6 +962,9 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> { 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 5e2dbb0eb6..7000ed9f6b 100644 --- a/webrtc/pc/srtpfilter.cc +++ b/webrtc/pc/srtpfilter.cc @@ -215,6 +215,17 @@ bool SrtpFilter::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { 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 @@ bool SrtpSession::GetRtpAuthParams(uint8_t** key, int* key_len, int* tag_len) { #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 ec91805e30..06edddf80d 100644 --- a/webrtc/pc/srtpfilter.h +++ b/webrtc/pc/srtpfilter.h @@ -111,6 +111,9 @@ class SrtpFilter { // 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 @@ class SrtpSession { // 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 2383519a85..1f4b14f968 100644 --- a/webrtc/test/mock_voe_channel_proxy.h +++ b/webrtc/test/mock_voe_channel_proxy.h @@ -57,6 +57,7 @@ class MockVoEChannelProxy : public voe::ChannelProxy { const rtc::scoped_refptr&()); 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 827b54b83f..26082abf36 100644 --- a/webrtc/video/video_send_stream.cc +++ b/webrtc/video/video_send_stream.cc @@ -274,6 +274,8 @@ class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver, void EnableEncodedFrameRecording(const std::vector& files, size_t byte_limit); + void SetTransportOverhead(int transport_overhead_per_packet); + private: class CheckEncoderActivityTask; class EncoderReconfiguredTask; @@ -617,6 +619,14 @@ VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() { 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 @@ int VideoSendStreamImpl::ProtectionRequest( 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 e2c3616d7d..2845aedd0e 100644 --- a/webrtc/video/video_send_stream.h +++ b/webrtc/video/video_send_stream.h @@ -90,6 +90,8 @@ class VideoSendStream : public webrtc::VideoSendStream { 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 2b28f4fad4..2b5c6e6909 100644 --- a/webrtc/video/video_send_stream_tests.cc +++ b/webrtc/video/video_send_stream_tests.cc @@ -1321,6 +1321,48 @@ TEST_F(VideoSendStreamTest, ChangingNetworkRoute) { 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(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 3d195eb141..66f14bd463 100644 --- a/webrtc/voice_engine/channel.cc +++ b/webrtc/voice_engine/channel.cc @@ -2828,6 +2828,10 @@ void Channel::SetRtcEventLog(RtcEventLog* event_log) { 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 c86820f2a5..4bfcd74dbf 100644 --- a/webrtc/voice_engine/channel.h +++ b/webrtc/voice_engine/channel.h @@ -417,6 +417,8 @@ class Channel // 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 6aef29cf0c..1f9d7f3467 100644 --- a/webrtc/voice_engine/channel_proxy.cc +++ b/webrtc/voice_engine/channel_proxy.cc @@ -231,6 +231,11 @@ int ChannelProxy::NeededFrequency() const { return static_cast(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 ea0446e5b5..44b25fd067 100644 --- a/webrtc/voice_engine/channel_proxy.h +++ b/webrtc/voice_engine/channel_proxy.h @@ -94,6 +94,8 @@ class ChannelProxy { virtual int NeededFrequency() const; + virtual void SetTransportOverhead(int transport_overhead_per_packet); + private: Channel* channel() const;