Add MID sending to FlexfecSender

Bug: webrtc:4050
Change-Id: I1eefd99cca1c02751d3f5a2d3b57625ccb45323f
Reviewed-on: https://webrtc-review.googlesource.com/64321
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22811}
diff --git a/modules/rtp_rtcp/include/flexfec_sender.h b/modules/rtp_rtcp/include/flexfec_sender.h
index 5b939d5..ac07b8d 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 <memory>
+#include <string>
 #include <vector>
 
 #include "api/array_view.h"
@@ -38,6 +39,7 @@
   FlexfecSender(int payload_type,
                 uint32_t ssrc,
                 uint32_t protected_media_ssrc,
+                const std::string& mid,
                 const std::vector<RtpExtension>& rtp_header_extensions,
                 rtc::ArrayView<const RtpExtensionSize> extension_sizes,
                 const RtpState* rtp_state,
@@ -79,6 +81,8 @@
   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 28945ed..9704096 100644
--- a/modules/rtp_rtcp/source/flexfec_sender.cc
+++ b/modules/rtp_rtcp/source/flexfec_sender.cc
@@ -38,7 +38,7 @@
 // How often to log the generated FEC packets to the text log.
 constexpr int64_t kPacketLogIntervalMs = 10000;
 
-RtpHeaderExtensionMap RegisterBweExtensions(
+RtpHeaderExtensionMap RegisterSupportedExtensions(
     const std::vector<RtpExtension>& rtp_header_extensions) {
   RtpHeaderExtensionMap map;
   for (const auto& extension : rtp_header_extensions) {
@@ -48,10 +48,12 @@
       map.Register<AbsoluteSendTime>(extension.id);
     } else if (extension.uri == TransmissionOffset::kUri) {
       map.Register<TransmissionOffset>(extension.id);
+    } else if (extension.uri == RtpMid::kUri) {
+      map.Register<RtpMid>(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 @@
     int payload_type,
     uint32_t ssrc,
     uint32_t protected_media_ssrc,
+    const std::string& mid,
     const std::vector<RtpExtension>& rtp_header_extensions,
     rtc::ArrayView<const RtpExtensionSize> extension_sizes,
     const RtpState* rtp_state,
@@ -79,11 +82,13 @@
                                   : random_.Rand<uint32_t>()),
       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 @@
     fec_packet_to_send->ReserveExtension<AbsoluteSendTime>();
     fec_packet_to_send->ReserveExtension<TransmissionOffset>();
     fec_packet_to_send->ReserveExtension<TransportSequenceNumber>();
+    // 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<RtpMid>(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 aa729ed..4c2a48d 100644
--- a/modules/rtp_rtcp/source/flexfec_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/flexfec_sender_unittest.cc
@@ -32,6 +32,7 @@
 constexpr int kFlexfecPayloadType = 123;
 constexpr uint32_t kMediaSsrc = 1234;
 constexpr uint32_t kFlexfecSsrc = 5678;
+const char kNoMid[] = "";
 const std::vector<RtpExtension> kNoRtpHeaderExtensions;
 const std::vector<RtpExtensionSize> kNoRtpHeaderExtensionSizes;
 // Assume a single protected media SSRC.
@@ -76,7 +77,7 @@
 
 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, 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, 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 @@
   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 @@
   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, NoRtpHeaderExtensionsForBweByDefault) {
   const std::vector<RtpExtension> 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 @@
   const std::vector<RtpExtension> 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 @@
   const std::vector<RtpExtension> 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 @@
   const std::vector<RtpExtension> 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 @@
       {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, 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 @@
       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 @@
             sender.MaxPacketOverhead());
 }
 
+TEST(FlexfecSenderTest, MidIncludedInPacketsWhenSet) {
+  const std::vector<RtpExtension> 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<RtpMid>(&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 6ef5040..8526f13 100644
--- a/modules/rtp_rtcp/source/rtp_header_extensions.h
+++ b/modules/rtp_rtcp/source/rtp_header_extensions.h
@@ -150,6 +150,10 @@
 // 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<const uint8_t> 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 8db6791..11e96b5 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -60,6 +60,7 @@
     CreateExtensionSize<TransmissionOffset>(),
     CreateExtensionSize<TransportSequenceNumber>(),
     CreateExtensionSize<PlayoutDelayLimits>(),
+    {RtpMid::kId, RtpMid::kMaxValueSizeBytes},
 };
 
 // Size info for header extensions that might be used in video packets.
@@ -71,6 +72,7 @@
     CreateExtensionSize<VideoOrientation>(),
     CreateExtensionSize<VideoContentTypeExtension>(),
     CreateExtensionSize<VideoTimingExtension>(),
+    {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 d769ec3..282e44a 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -980,10 +980,11 @@
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
+  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> 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 @@
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
+  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> 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 @@
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
+  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> 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 @@
   constexpr int kFlexfecPayloadType = 118;
   constexpr uint32_t kMediaSsrc = 1234;
   constexpr uint32_t kFlexfecSsrc = 5678;
+  const char kNoMid[] = "";
   const std::vector<RtpExtension> kNoRtpExtensions;
   const std::vector<RtpExtensionSize> 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 64bc3ed..ab08850 100644
--- a/test/fuzzers/flexfec_sender_fuzzer.cc
+++ b/test/fuzzers/flexfec_sender_fuzzer.cc
@@ -23,6 +23,7 @@
 constexpr int kFlexfecPayloadType = 123;
 constexpr uint32_t kMediaSsrc = 1234;
 constexpr uint32_t kFlexfecSsrc = 5678;
+const char kNoMid[] = "";
 const std::vector<RtpExtension> kNoRtpHeaderExtensions;
 const std::vector<RtpExtensionSize> kNoRtpHeaderExtensionSizes;
 
@@ -35,7 +36,7 @@
   }
 
   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 a7a41e0..4152efd 100644
--- a/video/video_send_stream.cc
+++ b/video/video_send_stream.cc
@@ -150,8 +150,9 @@
   RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
   return rtc::MakeUnique<FlexfecSender>(
       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) {