diff --git a/modules/rtp_rtcp/include/flexfec_sender.h b/modules/rtp_rtcp/include/flexfec_sender.h index 5b939d534b..ac07b8da9e 100644 --- a/modules/rtp_rtcp/include/flexfec_sender.h +++ b/modules/rtp_rtcp/include/flexfec_sender.h @@ -12,6 +12,7 @@ #define MODULES_RTP_RTCP_INCLUDE_FLEXFEC_SENDER_H_ #include +#include #include #include "api/array_view.h" @@ -38,6 +39,7 @@ class FlexfecSender { FlexfecSender(int payload_type, uint32_t ssrc, uint32_t protected_media_ssrc, + const std::string& mid, const std::vector& rtp_header_extensions, rtc::ArrayView extension_sizes, const RtpState* rtp_state, @@ -79,6 +81,8 @@ class FlexfecSender { const uint32_t timestamp_offset_; const uint32_t ssrc_; const uint32_t protected_media_ssrc_; + // MID value to send in the MID header extension. + const std::string mid_; // Sequence number of next packet to generate. uint16_t seq_num_; diff --git a/modules/rtp_rtcp/source/flexfec_sender.cc b/modules/rtp_rtcp/source/flexfec_sender.cc index 28945ed96b..9704096ff7 100644 --- a/modules/rtp_rtcp/source/flexfec_sender.cc +++ b/modules/rtp_rtcp/source/flexfec_sender.cc @@ -38,7 +38,7 @@ const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000; // How often to log the generated FEC packets to the text log. constexpr int64_t kPacketLogIntervalMs = 10000; -RtpHeaderExtensionMap RegisterBweExtensions( +RtpHeaderExtensionMap RegisterSupportedExtensions( const std::vector& rtp_header_extensions) { RtpHeaderExtensionMap map; for (const auto& extension : rtp_header_extensions) { @@ -48,10 +48,12 @@ RtpHeaderExtensionMap RegisterBweExtensions( map.Register(extension.id); } else if (extension.uri == TransmissionOffset::kUri) { map.Register(extension.id); + } else if (extension.uri == RtpMid::kUri) { + map.Register(extension.id); } else { RTC_LOG(LS_INFO) << "FlexfecSender only supports RTP header extensions for " - << "BWE, so the extension " << extension.ToString() + << "BWE and MID, so the extension " << extension.ToString() << " will not be used."; } } @@ -64,6 +66,7 @@ FlexfecSender::FlexfecSender( int payload_type, uint32_t ssrc, uint32_t protected_media_ssrc, + const std::string& mid, const std::vector& rtp_header_extensions, rtc::ArrayView extension_sizes, const RtpState* rtp_state, @@ -79,11 +82,13 @@ FlexfecSender::FlexfecSender( : random_.Rand()), ssrc_(ssrc), protected_media_ssrc_(protected_media_ssrc), + mid_(mid), seq_num_(rtp_state ? rtp_state->sequence_number : random_.Rand(1, kMaxInitRtpSeqNumber)), ulpfec_generator_( ForwardErrorCorrection::CreateFlexfec(ssrc, protected_media_ssrc)), - rtp_header_extension_map_(RegisterBweExtensions(rtp_header_extensions)), + rtp_header_extension_map_( + RegisterSupportedExtensions(rtp_header_extensions)), header_extensions_size_( rtp_header_extension_map_.GetTotalLengthInBytes(extension_sizes)) { // This object should not have been instantiated if FlexFEC is disabled. @@ -134,6 +139,11 @@ std::vector> FlexfecSender::GetFecPackets() { fec_packet_to_send->ReserveExtension(); fec_packet_to_send->ReserveExtension(); fec_packet_to_send->ReserveExtension(); + // Possibly include the MID header extension. + if (!mid_.empty()) { + // This is a no-op if the MID header extension is not registered. + fec_packet_to_send->SetExtension(mid_); + } // RTP payload. uint8_t* payload = fec_packet_to_send->AllocatePayload(fec_packet->length); diff --git a/modules/rtp_rtcp/source/flexfec_sender_unittest.cc b/modules/rtp_rtcp/source/flexfec_sender_unittest.cc index aa729ed0b8..4c2a48d222 100644 --- a/modules/rtp_rtcp/source/flexfec_sender_unittest.cc +++ b/modules/rtp_rtcp/source/flexfec_sender_unittest.cc @@ -32,6 +32,7 @@ using test::fec::AugmentedPacketGenerator; constexpr int kFlexfecPayloadType = 123; constexpr uint32_t kMediaSsrc = 1234; constexpr uint32_t kFlexfecSsrc = 5678; +const char kNoMid[] = ""; const std::vector kNoRtpHeaderExtensions; const std::vector kNoRtpHeaderExtensionSizes; // Assume a single protected media SSRC. @@ -76,7 +77,7 @@ std::unique_ptr GenerateSingleFlexfecPacket( TEST(FlexfecSenderTest, Ssrc) { SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); @@ -85,7 +86,7 @@ TEST(FlexfecSenderTest, Ssrc) { TEST(FlexfecSenderTest, NoFecAvailableBeforeMediaAdded) { SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); @@ -96,7 +97,7 @@ TEST(FlexfecSenderTest, NoFecAvailableBeforeMediaAdded) { TEST(FlexfecSenderTest, ProtectOneFrameWithOneFecPacket) { SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); auto fec_packet = GenerateSingleFlexfecPacket(&sender); @@ -119,7 +120,7 @@ TEST(FlexfecSenderTest, ProtectTwoFramesWithOneFecPacket) { constexpr size_t kNumFrames = 2; constexpr size_t kNumPacketsPerFrame = 2; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); sender.SetFecParameters(params); @@ -159,7 +160,7 @@ TEST(FlexfecSenderTest, ProtectTwoFramesWithTwoFecPackets) { constexpr size_t kNumFrames = 2; constexpr size_t kNumPacketsPerFrame = 2; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); sender.SetFecParameters(params); @@ -195,7 +196,7 @@ TEST(FlexfecSenderTest, ProtectTwoFramesWithTwoFecPackets) { TEST(FlexfecSenderTest, NoRtpHeaderExtensionsForBweByDefault) { const std::vector kRtpHeaderExtensions{}; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); auto fec_packet = GenerateSingleFlexfecPacket(&sender); @@ -209,7 +210,7 @@ TEST(FlexfecSenderTest, RegisterAbsoluteSendTimeRtpHeaderExtension) { const std::vector kRtpHeaderExtensions{ {RtpExtension::kAbsSendTimeUri, 1}}; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); auto fec_packet = GenerateSingleFlexfecPacket(&sender); @@ -223,7 +224,7 @@ TEST(FlexfecSenderTest, RegisterTransmissionOffsetRtpHeaderExtension) { const std::vector kRtpHeaderExtensions{ {RtpExtension::kTimestampOffsetUri, 1}}; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); auto fec_packet = GenerateSingleFlexfecPacket(&sender); @@ -237,7 +238,7 @@ TEST(FlexfecSenderTest, RegisterTransportSequenceNumberRtpHeaderExtension) { const std::vector kRtpHeaderExtensions{ {RtpExtension::kTransportSequenceNumberUri, 1}}; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); auto fec_packet = GenerateSingleFlexfecPacket(&sender); @@ -253,7 +254,7 @@ TEST(FlexfecSenderTest, RegisterAllRtpHeaderExtensionsForBwe) { {RtpExtension::kTimestampOffsetUri, 2}, {RtpExtension::kTransportSequenceNumberUri, 3}}; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); auto fec_packet = GenerateSingleFlexfecPacket(&sender); @@ -265,7 +266,7 @@ TEST(FlexfecSenderTest, RegisterAllRtpHeaderExtensionsForBwe) { TEST(FlexfecSenderTest, MaxPacketOverhead) { SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); @@ -285,7 +286,7 @@ TEST(FlexfecSenderTest, MaxPacketOverheadWithExtensions) { kExtensionHeaderLength + AbsoluteSendTime::kValueSizeBytes + kExtensionHeaderLength + TransmissionOffset::kValueSizeBytes + kExtensionHeaderLength + TransportSequenceNumber::kValueSizeBytes); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kRtpHeaderExtensions, RTPSender::FecExtensionSizes(), nullptr /* rtp_state */, &clock); @@ -293,12 +294,28 @@ TEST(FlexfecSenderTest, MaxPacketOverheadWithExtensions) { sender.MaxPacketOverhead()); } +TEST(FlexfecSenderTest, MidIncludedInPacketsWhenSet) { + const std::vector kRtpHeaderExtensions{ + {RtpExtension::kMidUri, 1}}; + const char kMid[] = "mid"; + SimulatedClock clock(kInitialSimulatedClockTime); + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kMid, + kRtpHeaderExtensions, RTPSender::FecExtensionSizes(), + nullptr /* rtp_state */, &clock); + + auto fec_packet = GenerateSingleFlexfecPacket(&sender); + + std::string mid; + ASSERT_TRUE(fec_packet->GetExtension(&mid)); + EXPECT_EQ(kMid, mid); +} + TEST(FlexfecSenderTest, SetsAndGetsRtpState) { RtpState initial_rtp_state; initial_rtp_state.sequence_number = 100; initial_rtp_state.start_timestamp = 200; SimulatedClock clock(kInitialSimulatedClockTime); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, &initial_rtp_state, &clock); diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.h b/modules/rtp_rtcp/source/rtp_header_extensions.h index 6ef5040db5..8526f13d6f 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -150,6 +150,10 @@ class VideoTimingExtension { // Subclasses must defined kId and kUri static constexpr members. class BaseRtpStringExtension { public: + // String RTP header extensions are limited to 16 bytes because it is the + // maximum length that can be encoded with one-byte header extensions. + static constexpr uint8_t kMaxValueSizeBytes = 16; + static bool Parse(rtc::ArrayView data, StringRtpHeaderExtension* str); static size_t ValueSize(const StringRtpHeaderExtension& str) { diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index 8db6791522..11e96b54a8 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -60,6 +60,7 @@ constexpr RtpExtensionSize kFecOrPaddingExtensionSizes[] = { CreateExtensionSize(), CreateExtensionSize(), CreateExtensionSize(), + {RtpMid::kId, RtpMid::kMaxValueSizeBytes}, }; // Size info for header extensions that might be used in video packets. @@ -71,6 +72,7 @@ constexpr RtpExtensionSize kVideoExtensionSizes[] = { CreateExtensionSize(), CreateExtensionSize(), CreateExtensionSize(), + {RtpMid::kId, RtpMid::kMaxValueSizeBytes}, }; const char* FrameTypeToString(FrameType frame_type) { diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc index d769ec31cd..282e44aece 100644 --- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -980,10 +980,11 @@ TEST_P(RtpSenderTest, SendFlexfecPackets) { constexpr int kFlexfecPayloadType = 118; constexpr uint32_t kMediaSsrc = 1234; constexpr uint32_t kFlexfecSsrc = 5678; + const char kNoMid[] = ""; const std::vector kNoRtpExtensions; const std::vector kNoRtpExtensionSizes; FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, - kNoRtpExtensions, kNoRtpExtensionSizes, + kNoMid, kNoRtpExtensions, kNoRtpExtensionSizes, nullptr /* rtp_state */, &fake_clock_); // Reset |rtp_sender_| to use FlexFEC. @@ -1038,11 +1039,12 @@ TEST_P(RtpSenderTest, NoFlexfecForTimingFrames) { constexpr int kFlexfecPayloadType = 118; constexpr uint32_t kMediaSsrc = 1234; constexpr uint32_t kFlexfecSsrc = 5678; + const char kNoMid[] = ""; const std::vector kNoRtpExtensions; const std::vector kNoRtpExtensionSizes; FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, - kNoRtpExtensions, kNoRtpExtensionSizes, + kNoMid, kNoRtpExtensions, kNoRtpExtensionSizes, nullptr /* rtp_state */, &fake_clock_); // Reset |rtp_sender_| to use FlexFEC. @@ -1138,10 +1140,11 @@ TEST_P(RtpSenderTestWithoutPacer, SendFlexfecPackets) { constexpr int kFlexfecPayloadType = 118; constexpr uint32_t kMediaSsrc = 1234; constexpr uint32_t kFlexfecSsrc = 5678; + const char kNoMid[] = ""; const std::vector kNoRtpExtensions; const std::vector kNoRtpExtensionSizes; FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, - kNoRtpExtensions, kNoRtpExtensionSizes, + kNoMid, kNoRtpExtensions, kNoRtpExtensionSizes, nullptr /* rtp_state */, &fake_clock_); // Reset |rtp_sender_| to use FlexFEC. @@ -1201,10 +1204,11 @@ TEST_P(RtpSenderTest, FecOverheadRate) { constexpr int kFlexfecPayloadType = 118; constexpr uint32_t kMediaSsrc = 1234; constexpr uint32_t kFlexfecSsrc = 5678; + const char kNoMid[] = ""; const std::vector kNoRtpExtensions; const std::vector kNoRtpExtensionSizes; FlexfecSender flexfec_sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, - kNoRtpExtensions, kNoRtpExtensionSizes, + kNoMid, kNoRtpExtensions, kNoRtpExtensionSizes, nullptr /* rtp_state */, &fake_clock_); // Reset |rtp_sender_| to use FlexFEC. diff --git a/test/fuzzers/flexfec_sender_fuzzer.cc b/test/fuzzers/flexfec_sender_fuzzer.cc index 64bc3ed247..ab08850847 100644 --- a/test/fuzzers/flexfec_sender_fuzzer.cc +++ b/test/fuzzers/flexfec_sender_fuzzer.cc @@ -23,6 +23,7 @@ namespace { constexpr int kFlexfecPayloadType = 123; constexpr uint32_t kMediaSsrc = 1234; constexpr uint32_t kFlexfecSsrc = 5678; +const char kNoMid[] = ""; const std::vector kNoRtpHeaderExtensions; const std::vector kNoRtpHeaderExtensionSizes; @@ -35,7 +36,7 @@ void FuzzOneInput(const uint8_t* data, size_t size) { } SimulatedClock clock(1 + data[i++]); - FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, + FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc, kNoMid, kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes, nullptr /* rtp_state */, &clock); FecProtectionParams params = { diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc index a7a41e03ee..4152efdf8b 100644 --- a/video/video_send_stream.cc +++ b/video/video_send_stream.cc @@ -150,8 +150,9 @@ std::unique_ptr MaybeCreateFlexfecSender( RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size()); return rtc::MakeUnique( config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc, - config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions, - RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock()); + config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.mid, + config.rtp.extensions, RTPSender::FecExtensionSizes(), rtp_state, + Clock::GetRealTimeClock()); } bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {