Bug 1632489 - Use repaired-rtp-stream-id in rtx packets; r=ng
authorDan Minor <dminor@mozilla.com>
Tue, 12 May 2020 21:35:10 +0000
changeset 529683 cc52615f768271de6a6e7c921252c88b2a72d687
parent 529682 45ad6b848a8ffaece932fd949ba0a670f12510fa
child 529684 8e0260c418540d1c07090d4398d5b41d394df83d
push id37414
push usernbeleuzu@mozilla.com
push dateThu, 14 May 2020 02:40:10 +0000
treeherdermozilla-central@045d696faa87 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersng
bugs1632489
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1632489 - Use repaired-rtp-stream-id in rtx packets; r=ng This imports a few fixes from tip of libwebrtc, which now supports mid, rid and rrid. The rtx packet is now allocated as max_packet_size_, which is necessary to have enough capacity for the rrid. It takes the CopyHeaderAndExtensionsToRtxPacket function from upstream, which omits copying extensions that should not be copied over, such as rid. It is necessary to make AllocateExtension and FindExtension public in order for this function to work. It then copies the rid from the source packet over to rrid in the rtx packet. Upstream has code for this as well, but taking it would require more extensive changes to our copy of libwebrtc. We can drop these local modifications with the next update. Depends on D74839 Differential Revision: https://phabricator.services.mozilla.com/D74840
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_packet.h
@@ -113,16 +113,24 @@ class RtpPacket {
 
   // Allocates and store header extension. Returns true on success.
   bool SetRawExtension(int id, rtc::ArrayView<const uint8_t> data);
 
   // Allocates and returns place to store rtp header extension.
   // Returns empty arrayview on failure.
   rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
 
+  // Find an extension |type|.
+  // Returns view of the raw extension or empty view on failure.
+  rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
+
+  // Find or allocate an extension |type|. Returns view of size |length|
+  // to write raw extension to or an empty view on failure.
+  rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
+
   // Reserve size_bytes for payload. Returns nullptr on failure.
   uint8_t* SetPayloadSize(size_t size_bytes);
   // Same as SetPayloadSize but doesn't guarantee to keep current payload.
   uint8_t* AllocatePayload(size_t size_bytes);
   bool SetPadding(uint8_t size_bytes, Random* random);
 
  private:
   struct ExtensionInfo {
@@ -130,24 +138,16 @@ class RtpPacket {
     uint16_t offset;
     uint8_t length;
   };
 
   // Helper function for Parse. Fill header fields using data in given buffer,
   // but does not touch packet own buffer, leaving packet in invalid state.
   bool ParseBuffer(const uint8_t* buffer, size_t size);
 
-  // Find an extension |type|.
-  // Returns view of the raw extension or empty view on failure.
-  rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
-
-  // Find or allocate an extension |type|. Returns view of size |length|
-  // to write raw extension to or an empty view on failure.
-  rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
-
   uint8_t* WriteAt(size_t offset);
   void WriteAt(size_t offset, uint8_t byte);
 
   // Header.
   bool marker_;
   uint8_t payload_type_;
   uint8_t padding_size_;
   uint16_t sequence_number_;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -1188,24 +1188,73 @@ bool RTPSender::SetFecParameters(const F
                                  const FecProtectionParams& key_params) {
   if (audio_configured_) {
     return false;
   }
   video_->SetFecParameters(delta_params, key_params);
   return true;
 }
 
+static void CopyHeaderAndExtensionsToRtxPacket(const RtpPacketToSend& packet,
+                                               RtpPacketToSend* rtx_packet) {
+  // Set the relevant fixed packet headers. The following are not set:
+  // * Payload type - it is replaced in rtx packets.
+  // * Sequence number - RTX has a separate sequence numbering.
+  // * SSRC - RTX stream has its own SSRC.
+  rtx_packet->SetMarker(packet.Marker());
+  rtx_packet->SetTimestamp(packet.Timestamp());
+
+  // Set the variable fields in the packet header:
+  // * CSRCs - must be set before header extensions.
+  // * Header extensions - replace Rid header with RepairedRid header.
+  const std::vector<uint32_t> csrcs = packet.Csrcs();
+  rtx_packet->SetCsrcs(csrcs);
+  for (int extension_num = kRtpExtensionNone + 1;
+       extension_num < kRtpExtensionNumberOfExtensions; ++extension_num) {
+    auto extension = static_cast<RTPExtensionType>(extension_num);
+
+    // Stream ID header extensions (MID, RSID) are sent per-SSRC. Since RTX
+    // operates on a different SSRC, the presence and values of these header
+    // extensions should be determined separately and not blindly copied.
+    if (extension == kRtpExtensionMid ||
+        extension == kRtpExtensionRtpStreamId) {
+      continue;
+    }
+
+    rtc::ArrayView<const uint8_t> source = packet.FindExtension(extension);
+
+    // Empty extensions should be supported, so not checking |source.empty()|.
+    // TODO: But this does not work in Mozilla's version of libwebrtc. Remove
+    // this check with the next update from tip of libwebrtc.
+    if (source.empty()) {
+      continue;
+    }
+
+    rtc::ArrayView<uint8_t> destination =
+        rtx_packet->AllocateExtension(extension, source.size());
+
+    // Could happen if any:
+    // 1. Extension has 0 length.
+    // 2. Extension is not registered in destination.
+    // 3. Allocating extension in destination failed.
+    if (destination.empty() || source.size() != destination.size()) {
+      continue;
+    }
+
+    std::memcpy(destination.begin(), source.begin(), destination.size());
+  }
+}
+
 std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket(
     const RtpPacketToSend& packet) {
   // TODO(danilchap): Create rtx packet with extra capacity for SRTP
   // when transport interface would be updated to take buffer class.
   std::unique_ptr<RtpPacketToSend> rtx_packet(new RtpPacketToSend(
-      &rtp_header_extension_map_, packet.size() + kRtxHeaderSize));
+      &rtp_header_extension_map_, max_packet_size_));
   // Add original RTP header.
-  rtx_packet->CopyHeaderFrom(packet);
   {
     rtc::CritScope lock(&send_critsect_);
     if (!sending_media_)
       return nullptr;
 
     RTC_DCHECK(ssrc_rtx_);
 
     // Replace payload type.
@@ -1214,18 +1263,28 @@ std::unique_ptr<RtpPacketToSend> RTPSend
       return nullptr;
     rtx_packet->SetPayloadType(kv->second);
 
     // Replace sequence number.
     rtx_packet->SetSequenceNumber(sequence_number_rtx_++);
 
     // Replace SSRC.
     rtx_packet->SetSsrc(*ssrc_rtx_);
+
+    CopyHeaderAndExtensionsToRtxPacket(packet, rtx_packet.get());
+
+    // Copy rtp-stream-id from packet to repaired-rtp-stream-id
+    if (rtp_header_extension_map_.IsRegistered(kRtpExtensionRtpStreamId) &&
+        rtp_header_extension_map_.IsRegistered(kRtpExtensionRepairedRtpStreamId)) {
+      std::string rid;
+      if (packet.GetExtension<RtpStreamId>(&rid)) {
+        rtx_packet->SetExtension<RepairedRtpStreamId>(rid);
+      }
+    }
   }
-
   uint8_t* rtx_payload =
       rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize);
   RTC_DCHECK(rtx_payload);
   // Add OSN (original sequence number).
   ByteWriter<uint16_t>::WriteBigEndian(rtx_payload, packet.SequenceNumber());
 
   // Add original payload data.
   auto payload = packet.payload();