diff --git a/pc/BUILD.gn b/pc/BUILD.gn index ce6896a50a..410365e31a 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -309,6 +309,7 @@ rtc_source_set("jsep_transport_controller") { ] absl_deps = [ "//third_party/abseil-cpp/absl/algorithm:container", + "//third_party/abseil-cpp/absl/functional:any_invocable", "//third_party/abseil-cpp/absl/types:optional", ] } diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc index 3ea24d4503..4c351a69ef 100644 --- a/pc/jsep_transport_controller.cc +++ b/pc/jsep_transport_controller.cc @@ -53,7 +53,7 @@ JsepTransportController::JsepTransportController( RTC_DCHECK_RUN_ON(network_thread_); UpdateAggregateStates_n(); }), - config_(config), + config_(std::move(config)), active_reset_srtp_params_(config.active_reset_srtp_params), bundles_(config.bundle_policy) { // The `transport_observer` is assumed to be non-null. @@ -1090,6 +1090,8 @@ RTCError JsepTransportController::MaybeCreateJsepTransport( jsep_transport->rtp_transport()->SignalRtcpPacketReceived.connect( this, &JsepTransportController::OnRtcpPacketReceived_n); + jsep_transport->rtp_transport()->SignalUnDemuxableRtpPacketReceived.connect( + this, &JsepTransportController::OnUnDemuxableRtpPacketReceived_n); transports_.RegisterTransport(content_info.name, std::move(jsep_transport)); UpdateAggregateStates_n(); @@ -1410,6 +1412,12 @@ void JsepTransportController::OnRtcpPacketReceived_n( config_.rtcp_handler(*packet, packet_time_us); } +void JsepTransportController::OnUnDemuxableRtpPacketReceived_n( + const webrtc::RtpPacketReceived& packet) { + RTC_DCHECK(config_.un_demuxable_packet_handler); + config_.un_demuxable_packet_handler(packet); +} + void JsepTransportController::OnDtlsHandshakeError( rtc::SSLHandshakeError error) { config_.on_dtls_handshake_error_(error); diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h index 4779bf9227..5880e346cd 100644 --- a/pc/jsep_transport_controller.h +++ b/pc/jsep_transport_controller.h @@ -21,6 +21,7 @@ #include #include +#include "absl/functional/any_invocable.h" #include "absl/types/optional.h" #include "api/async_dns_resolver.h" #include "api/candidate.h" @@ -124,9 +125,11 @@ class JsepTransportController : public sigslot::has_slots<> { Observer* transport_observer = nullptr; // Must be provided and valid for the lifetime of the // JsepTransportController instance. - std::function + absl::AnyInvocable rtcp_handler; + absl::AnyInvocable + un_demuxable_packet_handler; // Initial value for whether DtlsTransport reset causes a reset // of SRTP parameters. bool active_reset_srtp_params = false; @@ -450,6 +453,8 @@ class JsepTransportController : public sigslot::has_slots<> { void OnRtcpPacketReceived_n(rtc::CopyOnWriteBuffer* packet, int64_t packet_time_us) RTC_RUN_ON(network_thread_); + void OnUnDemuxableRtpPacketReceived_n(const webrtc::RtpPacketReceived& packet) + RTC_RUN_ON(network_thread_); void OnDtlsHandshakeError(rtc::SSLHandshakeError error); diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc index c30f381971..3c3018dab1 100644 --- a/pc/jsep_transport_controller_unittest.cc +++ b/pc/jsep_transport_controller_unittest.cc @@ -103,7 +103,7 @@ class JsepTransportControllerTest : public JsepTransportController::Observer, config.field_trials = &field_trials_; transport_controller_ = std::make_unique( network_thread, port_allocator, nullptr /* async_resolver_factory */, - config); + std::move(config)); SendTask(network_thread, [&] { ConnectTransportControllerSignals(); }); } @@ -400,7 +400,7 @@ TEST_F(JsepTransportControllerTest, GetRtpTransport) { TEST_F(JsepTransportControllerTest, GetDtlsTransport) { JsepTransportController::Config config; config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyNegotiate; - CreateJsepTransportController(config); + CreateJsepTransportController(std::move(config)); auto description = CreateSessionDescriptionWithoutBundle(); EXPECT_TRUE(transport_controller_ ->SetLocalDescription(SdpType::kOffer, description.get()) @@ -435,7 +435,7 @@ TEST_F(JsepTransportControllerTest, GetDtlsTransport) { TEST_F(JsepTransportControllerTest, GetDtlsTransportWithRtcpMux) { JsepTransportController::Config config; config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - CreateJsepTransportController(config); + CreateJsepTransportController(std::move(config)); auto description = CreateSessionDescriptionWithoutBundle(); EXPECT_TRUE(transport_controller_ ->SetLocalDescription(SdpType::kOffer, description.get()) @@ -987,7 +987,7 @@ TEST_F(JsepTransportControllerTest, IceRoleNotRedetermined) { JsepTransportController::Config config; config.redetermine_role_on_ice_restart = false; - CreateJsepTransportController(config); + CreateJsepTransportController(std::move(config)); // Let the `transport_controller_` be the controlled side initially. auto remote_offer = std::make_unique(); AddAudioSection(remote_offer.get(), kAudioMid1, kIceUfrag1, kIcePwd1, @@ -2317,7 +2317,7 @@ TEST_F(JsepTransportControllerTest, RejectFirstContentInBundleGroup) { TEST_F(JsepTransportControllerTest, ApplyNonRtcpMuxOfferWhenMuxingRequired) { JsepTransportController::Config config; config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - CreateJsepTransportController(config); + CreateJsepTransportController(std::move(config)); auto local_offer = std::make_unique(); AddAudioSection(local_offer.get(), kAudioMid1, kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS, @@ -2335,7 +2335,7 @@ TEST_F(JsepTransportControllerTest, ApplyNonRtcpMuxOfferWhenMuxingRequired) { TEST_F(JsepTransportControllerTest, ApplyNonRtcpMuxAnswerWhenMuxingRequired) { JsepTransportController::Config config; config.rtcp_mux_policy = PeerConnectionInterface::kRtcpMuxPolicyRequire; - CreateJsepTransportController(config); + CreateJsepTransportController(std::move(config)); auto local_offer = std::make_unique(); AddAudioSection(local_offer.get(), kAudioMid1, kIceUfrag1, kIcePwd1, cricket::ICEMODE_FULL, cricket::CONNECTIONROLE_ACTPASS, diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 8de19b29cb..dc3e901806 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -24,6 +24,7 @@ #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "api/jsep_ice_candidate.h" +#include "api/media_types.h" #include "api/rtp_parameters.h" #include "api/rtp_transceiver_direction.h" #include "api/uma_metrics.h" @@ -699,6 +700,7 @@ JsepTransportController* PeerConnection::InitializeTransportController_n( : options_.crypto_options; config.transport_observer = this; config.rtcp_handler = InitializeRtcpCallback(); + config.un_demuxable_packet_handler = InitializeUnDemuxablePacketHandler(); config.event_log = event_log_ptr_; #if defined(ENABLE_EXTERNAL_AUTH) config.enable_external_auth = true; @@ -720,9 +722,9 @@ JsepTransportController* PeerConnection::InitializeTransportController_n( config.field_trials = trials_.get(); - transport_controller_.reset( - new JsepTransportController(network_thread(), port_allocator_.get(), - async_dns_resolver_factory_.get(), config)); + transport_controller_.reset(new JsepTransportController( + network_thread(), port_allocator_.get(), + async_dns_resolver_factory_.get(), std::move(config))); transport_controller_->SubscribeIceConnectionState( [this](cricket::IceConnectionState s) { @@ -2991,4 +2993,21 @@ PeerConnection::InitializeRtcpCallback() { }; } +std::function +PeerConnection::InitializeUnDemuxablePacketHandler() { + RTC_DCHECK_RUN_ON(network_thread()); + return [this](const RtpPacketReceived& parsed_packet) { + worker_thread()->PostTask( + SafeTask(worker_thread_safety_, [this, parsed_packet]() { + // Deliver the packet anyway to Call to allow Call to do BWE. + // Even if there is no media receiver, the packet has still + // been received on the network and has been correcly parsed. + call_ptr_->Receiver()->DeliverRtpPacket( + MediaType::ANY, parsed_packet, + /*undemuxable_packet_handler=*/ + [](const RtpPacketReceived& packet) { return false; }); + })); + }; +} + } // namespace webrtc diff --git a/pc/peer_connection.h b/pc/peer_connection.h index 51747114f5..950758be07 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -51,6 +51,7 @@ #include "api/transport/enums.h" #include "api/turn_customizer.h" #include "call/call.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "p2p/base/ice_transport_internal.h" #include "p2p/base/port.h" #include "p2p/base/port_allocator.h" @@ -600,6 +601,9 @@ class PeerConnection : public PeerConnectionInternal, int64_t packet_time_us)> InitializeRtcpCallback(); + std::function + InitializeUnDemuxablePacketHandler(); + const rtc::scoped_refptr context_; // Field trials active for this PeerConnection is the first of: // a) Specified in PeerConnectionDependencies (owned). diff --git a/pc/rtp_transport.cc b/pc/rtp_transport.cc index 1aa8660467..8ef597f58f 100644 --- a/pc/rtp_transport.cc +++ b/pc/rtp_transport.cc @@ -193,8 +193,9 @@ void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer packet, } if (!rtp_demuxer_.OnRtpPacket(parsed_packet)) { - RTC_LOG(LS_WARNING) << "Failed to demux RTP packet: " + RTC_LOG(LS_VERBOSE) << "Failed to demux RTP packet: " << RtpDemuxer::DescribePacket(parsed_packet); + SignalUnDemuxableRtpPacketReceived(parsed_packet); } } diff --git a/pc/rtp_transport_internal.h b/pc/rtp_transport_internal.h index 9e816113f1..264be134a4 100644 --- a/pc/rtp_transport_internal.h +++ b/pc/rtp_transport_internal.h @@ -53,10 +53,15 @@ class RtpTransportInternal : public sigslot::has_slots<> { sigslot::signal1 SignalReadyToSend; // Called whenever an RTCP packet is received. There is no equivalent signal - // for RTP packets because they would be forwarded to the BaseChannel through - // the RtpDemuxer callback. + // for demuxable RTP packets because they would be forwarded to the + // BaseChannel through the RtpDemuxer callback. sigslot::signal2 SignalRtcpPacketReceived; + // Called whenever a RTP packet that can not be demuxed by the transport is + // received. + sigslot::signal + SignalUnDemuxableRtpPacketReceived; + // Called whenever the network route of the P2P layer transport changes. // The argument is an optional network route. sigslot::signal1> SignalNetworkRouteChanged; diff --git a/pc/rtp_transport_unittest.cc b/pc/rtp_transport_unittest.cc index 0e6af734f3..e3d4101037 100644 --- a/pc/rtp_transport_unittest.cc +++ b/pc/rtp_transport_unittest.cc @@ -288,6 +288,7 @@ TEST(RtpTransportTest, SignalHandledRtpPayloadType) { rtc::Buffer rtp_data(kRtpData, kRtpLen); fake_rtp.SendPacket(rtp_data.data(), kRtpLen, options, flags); EXPECT_EQ(1, observer.rtp_count()); + EXPECT_EQ(0, observer.un_demuxable_rtp_count()); EXPECT_EQ(0, observer.rtcp_count()); // Remove the sink before destroying the transport. transport.UnregisterRtpDemuxerSink(&observer); @@ -311,6 +312,7 @@ TEST(RtpTransportTest, DontSignalUnhandledRtpPayloadType) { rtc::Buffer rtp_data(kRtpData, kRtpLen); fake_rtp.SendPacket(rtp_data.data(), kRtpLen, options, flags); EXPECT_EQ(0, observer.rtp_count()); + EXPECT_EQ(1, observer.un_demuxable_rtp_count()); EXPECT_EQ(0, observer.rtcp_count()); // Remove the sink before destroying the transport. transport.UnregisterRtpDemuxerSink(&observer); diff --git a/pc/test/rtp_transport_test_util.h b/pc/test/rtp_transport_test_util.h index 0353b74754..e93dbdb3c2 100644 --- a/pc/test/rtp_transport_test_util.h +++ b/pc/test/rtp_transport_test_util.h @@ -30,6 +30,8 @@ class TransportObserver : public RtpPacketSinkInterface, this, &TransportObserver::OnRtcpPacketReceived); rtp_transport->SignalReadyToSend.connect(this, &TransportObserver::OnReadyToSend); + rtp_transport->SignalUnDemuxableRtpPacketReceived.connect( + this, &TransportObserver::OnUndemuxableRtpPacket); } // RtpPacketInterface override. @@ -38,6 +40,10 @@ class TransportObserver : public RtpPacketSinkInterface, last_recv_rtp_packet_ = packet.Buffer(); } + void OnUndemuxableRtpPacket(const RtpPacketReceived& packet) { + un_demuxable_rtp_count_++; + } + void OnRtcpPacketReceived(rtc::CopyOnWriteBuffer* packet, int64_t packet_time_us) { rtcp_count_++; @@ -45,6 +51,7 @@ class TransportObserver : public RtpPacketSinkInterface, } int rtp_count() const { return rtp_count_; } + int un_demuxable_rtp_count() const { return un_demuxable_rtp_count_; } int rtcp_count() const { return rtcp_count_; } rtc::CopyOnWriteBuffer last_recv_rtp_packet() { @@ -67,6 +74,7 @@ class TransportObserver : public RtpPacketSinkInterface, private: bool ready_to_send_ = false; int rtp_count_ = 0; + int un_demuxable_rtp_count_ = 0; int rtcp_count_ = 0; int ready_to_send_signal_count_ = 0; rtc::CopyOnWriteBuffer last_recv_rtp_packet_;