Fix handling of large packets in RtxReceiveStream

Bug: webrtc:10999
Change-Id: If0c93d2b6c2ea957ac5dcc51dd69b71d2f5306a2
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156168
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29426}
diff --git a/call/rtx_receive_stream_unittest.cc b/call/rtx_receive_stream_unittest.cc
index 79dc2f1..90027bb 100644
--- a/call/rtx_receive_stream_unittest.cc
+++ b/call/rtx_receive_stream_unittest.cc
@@ -50,6 +50,26 @@
     0xee,
 };
 
+constexpr uint8_t kRtxPacketWithPadding[] = {
+    0xa0,  // Version 2, P set
+    98,    // Payload type.
+    0x12,
+    0x34,  // Seqno.
+    0x11,
+    0x11,
+    0x11,
+    0x11,  // Timestamp.
+    0x22,
+    0x22,
+    0x22,
+    0x22,  // SSRC.
+    // RTX header.
+    0x56,
+    0x57,  // Orig seqno.
+    // Padding
+    0x1,
+};
+
 constexpr uint8_t kRtxPacketWithCVO[] = {
     0x90,  // Version 2, X set.
     98,    // Payload type.
@@ -96,13 +116,13 @@
   RtpPacketReceived rtx_packet;
   EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
 
-  EXPECT_CALL(media_sink, OnRtpPacket(_))
-      .WillOnce(::testing::Invoke([](const RtpPacketReceived& packet) {
+  EXPECT_CALL(media_sink, OnRtpPacket)
+      .WillOnce([](const RtpPacketReceived& packet) {
         EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
         EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
         EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
         EXPECT_THAT(packet.payload(), ::testing::ElementsAre(0xee));
-      }));
+      });
 
   rtx_sink.OnRtpPacket(rtx_packet);
 }
@@ -113,10 +133,10 @@
   RtpPacketReceived rtx_packet;
   EXPECT_TRUE(rtx_packet.Parse(rtc::ArrayView<const uint8_t>(kRtxPacket)));
   EXPECT_FALSE(rtx_packet.recovered());
-  EXPECT_CALL(media_sink, OnRtpPacket(_))
-      .WillOnce(::testing::Invoke([](const RtpPacketReceived& packet) {
+  EXPECT_CALL(media_sink, OnRtpPacket)
+      .WillOnce([](const RtpPacketReceived& packet) {
         EXPECT_TRUE(packet.recovered());
-      }));
+      });
 
   rtx_sink.OnRtpPacket(rtx_packet);
 }
@@ -154,8 +174,8 @@
   EXPECT_TRUE(rtx_packet.GetExtension<VideoOrientation>(&rotation));
   EXPECT_EQ(kVideoRotation_90, rotation);
 
-  EXPECT_CALL(media_sink, OnRtpPacket(_))
-      .WillOnce(::testing::Invoke([](const RtpPacketReceived& packet) {
+  EXPECT_CALL(media_sink, OnRtpPacket)
+      .WillOnce([](const RtpPacketReceived& packet) {
         EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
         EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
         EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
@@ -163,7 +183,75 @@
         VideoRotation rotation = kVideoRotation_0;
         EXPECT_TRUE(packet.GetExtension<VideoOrientation>(&rotation));
         EXPECT_EQ(rotation, kVideoRotation_90);
-      }));
+      });
+
+  rtx_sink.OnRtpPacket(rtx_packet);
+}
+
+TEST(RtxReceiveStreamTest, SupportsLargePacket) {
+  StrictMock<MockRtpPacketSink> media_sink;
+  RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
+  RtpPacketReceived rtx_packet;
+  constexpr int kRtxPacketSize = 2000;
+  constexpr int kRtxPayloadOffset = 14;
+  uint8_t large_rtx_packet[kRtxPacketSize];
+  memcpy(large_rtx_packet, kRtxPacket, sizeof(kRtxPacket));
+  rtc::ArrayView<uint8_t> payload(large_rtx_packet + kRtxPayloadOffset,
+                                  kRtxPacketSize - kRtxPayloadOffset);
+
+  // Fill payload.
+  for (size_t i = 0; i < payload.size(); i++) {
+    payload[i] = i;
+  }
+  EXPECT_TRUE(
+      rtx_packet.Parse(rtc::ArrayView<const uint8_t>(large_rtx_packet)));
+
+  EXPECT_CALL(media_sink, OnRtpPacket)
+      .WillOnce([&](const RtpPacketReceived& packet) {
+        EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
+        EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
+        EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
+        EXPECT_THAT(packet.payload(), ::testing::ElementsAreArray(payload));
+      });
+
+  rtx_sink.OnRtpPacket(rtx_packet);
+}
+
+TEST(RtxReceiveStreamTest, SupportsLargePacketWithPadding) {
+  StrictMock<MockRtpPacketSink> media_sink;
+  RtxReceiveStream rtx_sink(&media_sink, PayloadTypeMapping(), kMediaSSRC);
+  RtpPacketReceived rtx_packet;
+  constexpr int kRtxPacketSize = 2000;
+  constexpr int kRtxPayloadOffset = 14;
+  constexpr int kRtxPaddingSize = 50;
+  uint8_t large_rtx_packet[kRtxPacketSize];
+  memcpy(large_rtx_packet, kRtxPacketWithPadding,
+         sizeof(kRtxPacketWithPadding));
+  rtc::ArrayView<uint8_t> payload(
+      large_rtx_packet + kRtxPayloadOffset,
+      kRtxPacketSize - kRtxPayloadOffset - kRtxPaddingSize);
+  rtc::ArrayView<uint8_t> padding(
+      large_rtx_packet + kRtxPacketSize - kRtxPaddingSize, kRtxPaddingSize);
+
+  // Fill payload.
+  for (size_t i = 0; i < payload.size(); i++) {
+    payload[i] = i;
+  }
+  // Fill padding. Only value of last padding byte matters.
+  for (size_t i = 0; i < padding.size(); i++) {
+    padding[i] = kRtxPaddingSize;
+  }
+
+  EXPECT_TRUE(
+      rtx_packet.Parse(rtc::ArrayView<const uint8_t>(large_rtx_packet)));
+
+  EXPECT_CALL(media_sink, OnRtpPacket)
+      .WillOnce([&](const RtpPacketReceived& packet) {
+        EXPECT_EQ(packet.SequenceNumber(), kMediaSeqno);
+        EXPECT_EQ(packet.Ssrc(), kMediaSSRC);
+        EXPECT_EQ(packet.PayloadType(), kMediaPayloadType);
+        EXPECT_THAT(packet.payload(), ::testing::ElementsAreArray(payload));
+      });
 
   rtx_sink.OnRtpPacket(rtx_packet);
 }
diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc
index b9c7e54..557edf0 100644
--- a/modules/rtp_rtcp/source/rtp_packet.cc
+++ b/modules/rtp_rtcp/source/rtp_packet.cc
@@ -121,7 +121,7 @@
   extensions_ = packet.extensions_;
   extension_entries_ = packet.extension_entries_;
   extensions_size_ = packet.extensions_size_;
-  buffer_.SetData(packet.data(), packet.headers_size());
+  buffer_ = packet.buffer_.Slice(0, packet.headers_size());
   // Reset payload and padding.
   payload_size_ = 0;
   padding_size_ = 0;