Propagate ECN to RtpPacketReceived

Bug: webrtc:15368
Change-Id: Ie2d982a9172759a65f7f7225eeddd64cfa82490d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/341560
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41903}
This commit is contained in:
Per K 2024-03-12 13:00:50 +01:00 committed by WebRTC LUCI CQ
parent a0672c5f32
commit 776c1a1a86
10 changed files with 64 additions and 13 deletions

View file

@ -133,6 +133,7 @@ rtc_library("rtp_rtcp_format") {
"../../rtc_base:macromagic", "../../rtc_base:macromagic",
"../../rtc_base:safe_conversions", "../../rtc_base:safe_conversions",
"../../rtc_base:stringutils", "../../rtc_base:stringutils",
"../../rtc_base/network:ecn_marking",
"../../system_wrappers", "../../system_wrappers",
"../video_coding:codec_globals_headers", "../video_coding:codec_globals_headers",
] ]

View file

@ -20,6 +20,7 @@
#include "api/scoped_refptr.h" #include "api/scoped_refptr.h"
#include "api/units/timestamp.h" #include "api/units/timestamp.h"
#include "modules/rtp_rtcp/source/rtp_packet.h" #include "modules/rtp_rtcp/source/rtp_packet.h"
#include "rtc_base/network/ecn_marking.h"
namespace webrtc { namespace webrtc {
// Class to hold rtp packet with metadata for receiver side. // Class to hold rtp packet with metadata for receiver side.
@ -48,6 +49,11 @@ class RtpPacketReceived : public RtpPacket {
webrtc::Timestamp arrival_time() const { return arrival_time_; } webrtc::Timestamp arrival_time() const { return arrival_time_; }
void set_arrival_time(webrtc::Timestamp time) { arrival_time_ = time; } void set_arrival_time(webrtc::Timestamp time) { arrival_time_ = time; }
// Explicit Congestion Notification (ECN), RFC-3168, Section 5.
// Used by L4S: https://www.rfc-editor.org/rfc/rfc9331.html
rtc::EcnMarking ecn() const { return ecn_; }
void set_ecn(rtc::EcnMarking ecn) { ecn_ = ecn; }
// Flag if packet was recovered via RTX or FEC. // Flag if packet was recovered via RTX or FEC.
bool recovered() const { return recovered_; } bool recovered() const { return recovered_; }
void set_recovered(bool value) { recovered_ = value; } void set_recovered(bool value) { recovered_ = value; }
@ -68,6 +74,7 @@ class RtpPacketReceived : public RtpPacket {
private: private:
webrtc::Timestamp arrival_time_ = Timestamp::MinusInfinity(); webrtc::Timestamp arrival_time_ = Timestamp::MinusInfinity();
rtc::EcnMarking ecn_ = rtc::EcnMarking::kNotEct;
int payload_type_frequency_ = 0; int payload_type_frequency_ = 0;
bool recovered_ = false; bool recovered_ = false;
rtc::scoped_refptr<rtc::RefCountedBase> additional_data_; rtc::scoped_refptr<rtc::RefCountedBase> additional_data_;

View file

@ -1100,6 +1100,7 @@ if (rtc_include_tests) {
"../rtc_base:socket_server", "../rtc_base:socket_server",
"../rtc_base:ssl", "../rtc_base:ssl",
"../rtc_base:threading", "../rtc_base:threading",
"../rtc_base:timeutils",
"../rtc_base/network:received_packet", "../rtc_base/network:received_packet",
"../rtc_base/third_party/sigslot", "../rtc_base/third_party/sigslot",
"../test:test_support", "../test:test_support",

View file

@ -16,6 +16,7 @@
#include "p2p/base/packet_transport_internal.h" #include "p2p/base/packet_transport_internal.h"
#include "rtc_base/copy_on_write_buffer.h" #include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/time_utils.h"
namespace rtc { namespace rtc {
@ -64,7 +65,7 @@ class FakePacketTransport : public PacketTransportInternal {
return -1; return -1;
} }
CopyOnWriteBuffer packet(data, len); CopyOnWriteBuffer packet(data, len);
SendPacketInternal(packet); SendPacketInternal(packet, options);
SentPacket sent_packet(options.packet_id, TimeMillis()); SentPacket sent_packet(options.packet_id, TimeMillis());
SignalSentPacket(this, sent_packet); SignalSentPacket(this, sent_packet);
@ -120,11 +121,13 @@ class FakePacketTransport : public PacketTransportInternal {
SignalReceivingState(this); SignalReceivingState(this);
} }
void SendPacketInternal(const CopyOnWriteBuffer& packet) { void SendPacketInternal(const CopyOnWriteBuffer& packet,
const rtc::PacketOptions& options) {
last_sent_packet_ = packet; last_sent_packet_ = packet;
if (dest_) { if (dest_) {
dest_->NotifyPacketReceived(rtc::ReceivedPacket::CreateFromLegacy( dest_->NotifyPacketReceived(rtc::ReceivedPacket(
packet.data(), packet.size(), rtc::TimeMicros())); packet, SocketAddress(), webrtc::Timestamp::Micros(rtc::TimeMicros()),
options.ecn_1 ? EcnMarking::kEct1 : EcnMarking::kNotEct));
} }
} }

View file

@ -191,8 +191,11 @@ flat_set<uint32_t> RtpTransport::GetSsrcsForSink(RtpPacketSinkInterface* sink) {
} }
void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer packet, void RtpTransport::DemuxPacket(rtc::CopyOnWriteBuffer packet,
webrtc::Timestamp arrival_time) { webrtc::Timestamp arrival_time,
RtpPacketReceived parsed_packet(&header_extension_map_, arrival_time); rtc::EcnMarking ecn) {
RtpPacketReceived parsed_packet(&header_extension_map_);
parsed_packet.set_arrival_time(arrival_time);
parsed_packet.set_ecn(ecn);
if (!parsed_packet.Parse(std::move(packet))) { if (!parsed_packet.Parse(std::move(packet))) {
RTC_LOG(LS_ERROR) RTC_LOG(LS_ERROR)
@ -247,8 +250,10 @@ void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport,
void RtpTransport::OnRtpPacketReceived( void RtpTransport::OnRtpPacketReceived(
const rtc::ReceivedPacket& received_packet) { const rtc::ReceivedPacket& received_packet) {
rtc::CopyOnWriteBuffer payload(received_packet.payload()); rtc::CopyOnWriteBuffer payload(received_packet.payload());
DemuxPacket(payload, received_packet.arrival_time().value_or( DemuxPacket(
Timestamp::MinusInfinity())); payload,
received_packet.arrival_time().value_or(Timestamp::MinusInfinity()),
received_packet.ecn());
} }
void RtpTransport::OnRtcpPacketReceived( void RtpTransport::OnRtcpPacketReceived(

View file

@ -92,7 +92,9 @@ class RtpTransport : public RtpTransportInternal {
protected: protected:
// These methods will be used in the subclasses. // These methods will be used in the subclasses.
void DemuxPacket(rtc::CopyOnWriteBuffer packet, Timestamp arrival_time); void DemuxPacket(rtc::CopyOnWriteBuffer packet,
Timestamp arrival_time,
rtc::EcnMarking ecn);
bool SendPacket(bool rtcp, bool SendPacket(bool rtcp,
rtc::CopyOnWriteBuffer* packet, rtc::CopyOnWriteBuffer* packet,

View file

@ -301,6 +301,29 @@ TEST(RtpTransportTest, SignalHandledRtpPayloadType) {
transport.UnregisterRtpDemuxerSink(&observer); transport.UnregisterRtpDemuxerSink(&observer);
} }
TEST(RtpTransportTest, ReceivedPacketEcnMarkingPropagatedToDemuxedPacket) {
RtpTransport transport(kMuxDisabled);
// Setup FakePacketTransport to send packets to itself.
rtc::FakePacketTransport fake_rtp("fake_rtp");
fake_rtp.SetDestination(&fake_rtp, true);
transport.SetRtpPacketTransport(&fake_rtp);
TransportObserver observer(&transport);
RtpDemuxerCriteria demuxer_criteria;
// Add a payload type of kRtpData.
demuxer_criteria.payload_types().insert(0x11);
transport.RegisterRtpDemuxerSink(demuxer_criteria, &observer);
rtc::PacketOptions options;
options.ecn_1 = true;
const int flags = 0;
rtc::Buffer rtp_data(kRtpData, kRtpLen);
fake_rtp.SendPacket(rtp_data.data<char>(), kRtpLen, options, flags);
ASSERT_EQ(observer.rtp_count(), 1);
EXPECT_EQ(observer.last_recv_rtp_packet().ecn(), rtc::EcnMarking::kEct1);
transport.UnregisterRtpDemuxerSink(&observer);
}
// Test that SignalPacketReceived does not fire when a RTP packet with an // Test that SignalPacketReceived does not fire when a RTP packet with an
// unhandled payload type is received. // unhandled payload type is received.
TEST(RtpTransportTest, DontSignalUnhandledRtpPayloadType) { TEST(RtpTransportTest, DontSignalUnhandledRtpPayloadType) {

View file

@ -145,7 +145,8 @@ void SrtpTransport::OnRtpPacketReceived(const rtc::ReceivedPacket& packet) {
} }
payload.SetSize(len); payload.SetSize(len);
DemuxPacket(std::move(payload), DemuxPacket(std::move(payload),
packet.arrival_time().value_or(Timestamp::MinusInfinity())); packet.arrival_time().value_or(Timestamp::MinusInfinity()),
packet.ecn());
} }
void SrtpTransport::OnRtcpPacketReceived(const rtc::ReceivedPacket& packet) { void SrtpTransport::OnRtcpPacketReceived(const rtc::ReceivedPacket& packet) {

View file

@ -46,7 +46,7 @@ class TransportObserver : public RtpPacketSinkInterface {
// RtpPacketInterface override. // RtpPacketInterface override.
void OnRtpPacket(const RtpPacketReceived& packet) override { void OnRtpPacket(const RtpPacketReceived& packet) override {
rtp_count_++; rtp_count_++;
last_recv_rtp_packet_ = packet.Buffer(); last_recv_rtp_packet_ = packet;
} }
void OnUndemuxableRtpPacket(const RtpPacketReceived& packet) { void OnUndemuxableRtpPacket(const RtpPacketReceived& packet) {
@ -64,7 +64,7 @@ class TransportObserver : public RtpPacketSinkInterface {
int rtcp_count() const { return rtcp_count_; } int rtcp_count() const { return rtcp_count_; }
int sent_packet_count() const { return sent_packet_count_; } int sent_packet_count() const { return sent_packet_count_; }
rtc::CopyOnWriteBuffer last_recv_rtp_packet() { const RtpPacketReceived& last_recv_rtp_packet() {
return last_recv_rtp_packet_; return last_recv_rtp_packet_;
} }
@ -98,7 +98,7 @@ class TransportObserver : public RtpPacketSinkInterface {
int rtcp_count_ = 0; int rtcp_count_ = 0;
int sent_packet_count_ = 0; int sent_packet_count_ = 0;
int ready_to_send_signal_count_ = 0; int ready_to_send_signal_count_ = 0;
rtc::CopyOnWriteBuffer last_recv_rtp_packet_; RtpPacketReceived last_recv_rtp_packet_;
rtc::CopyOnWriteBuffer last_recv_rtcp_packet_; rtc::CopyOnWriteBuffer last_recv_rtcp_packet_;
absl::AnyInvocable<void(bool)> action_on_ready_to_send_; absl::AnyInvocable<void(bool)> action_on_ready_to_send_;
absl::AnyInvocable<void()> action_on_sent_packet_; absl::AnyInvocable<void()> action_on_sent_packet_;

View file

@ -50,6 +50,14 @@ struct RTC_EXPORT PacketOptions {
~PacketOptions(); ~PacketOptions();
DiffServCodePoint dscp = DSCP_NO_CHANGE; DiffServCodePoint dscp = DSCP_NO_CHANGE;
// Packet will be sent with ECN(1), RFC-3168, Section 5.
// Intended to be used with L4S
// https://www.rfc-editor.org/rfc/rfc9331.html
// TODO(https://bugs.webrtc.org/15368): Actually implement support for sending
// packets with different marking.
bool ecn_1 = false;
// When used with RTP packets (for example, webrtc::PacketOptions), the value // When used with RTP packets (for example, webrtc::PacketOptions), the value
// should be 16 bits. A value of -1 represents "not set". // should be 16 bits. A value of -1 represents "not set".
int64_t packet_id = -1; int64_t packet_id = -1;