diff --git a/modules/rtp_rtcp/source/fec_test_helper.cc b/modules/rtp_rtcp/source/fec_test_helper.cc index ff736fd5f2..b9ac25e4a8 100644 --- a/modules/rtp_rtcp/source/fec_test_helper.cc +++ b/modules/rtp_rtcp/source/fec_test_helper.cc @@ -184,19 +184,21 @@ UlpfecPacketGenerator::UlpfecPacketGenerator(uint32_t ssrc) RtpPacketReceived UlpfecPacketGenerator::BuildMediaRedPacket( const AugmentedPacket& packet, bool is_recovered) { - RtpPacketReceived red_packet; - // Copy RTP header. + // Create a temporary buffer used to wrap the media packet in RED. + rtc::CopyOnWriteBuffer red_buffer; const size_t kHeaderLength = packet.header.headerLength; - red_packet.Parse(packet.data.cdata(), kHeaderLength); - RTC_DCHECK_EQ(red_packet.headers_size(), kHeaderLength); - uint8_t* rtp_payload = - red_packet.AllocatePayload(packet.data.size() + 1 - kHeaderLength); - // Move payload type into rtp payload. - rtp_payload[0] = red_packet.PayloadType(); + // Append header. + red_buffer.SetData(packet.data.data(), kHeaderLength); + // Find payload type and add it as RED header. + uint8_t media_payload_type = red_buffer[1] & 0x7F; + red_buffer.AppendData({media_payload_type}); + // Append rest of payload/padding. + red_buffer.AppendData( + packet.data.Slice(kHeaderLength, packet.data.size() - kHeaderLength)); + + RtpPacketReceived red_packet; + RTC_CHECK(red_packet.Parse(std::move(red_buffer))); red_packet.SetPayloadType(kRedPayloadType); - // Copy the payload. - memcpy(rtp_payload + 1, packet.data.cdata() + kHeaderLength, - packet.data.size() - kHeaderLength); red_packet.set_recovered(is_recovered); return red_packet; diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc index 16b87ba727..fdfa475186 100644 --- a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc +++ b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc @@ -132,9 +132,8 @@ bool UlpfecReceiverImpl::AddReceivedRedPacket( rtp_packet.Buffer().Slice(rtp_packet.headers_size() + kRedHeaderLength, rtp_packet.payload_size() - kRedHeaderLength); } else { - auto red_payload = rtp_packet.payload().subview(kRedHeaderLength); - received_packet->pkt->data.EnsureCapacity(rtp_packet.headers_size() + - red_payload.size()); + received_packet->pkt->data.EnsureCapacity(rtp_packet.size() - + kRedHeaderLength); // Copy RTP header. received_packet->pkt->data.SetData(rtp_packet.data(), rtp_packet.headers_size()); @@ -142,9 +141,10 @@ bool UlpfecReceiverImpl::AddReceivedRedPacket( uint8_t& payload_type_byte = received_packet->pkt->data.MutableData()[1]; payload_type_byte &= 0x80; // Reset RED payload type. payload_type_byte += payload_type; // Set media payload type. - // Copy payload data. - received_packet->pkt->data.AppendData(red_payload.data(), - red_payload.size()); + // Copy payload and padding data, after the RED header. + received_packet->pkt->data.AppendData( + rtp_packet.data() + rtp_packet.headers_size() + kRedHeaderLength, + rtp_packet.size() - rtp_packet.headers_size() - kRedHeaderLength); } if (received_packet->pkt->data.size() > 0) { diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc b/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc index 9dbaeb81f3..016df6e834 100644 --- a/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc +++ b/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc @@ -512,4 +512,31 @@ TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) { SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100); } +TEST_F(UlpfecReceiverTest, MediaWithPadding) { + const size_t kNumFecPackets = 1; + std::list augmented_media_packets; + ForwardErrorCorrection::PacketList media_packets; + PacketizeFrame(2, 0, &augmented_media_packets, &media_packets); + + // Append four bytes of padding to the first media packet. + const uint8_t kPadding[] = {0, 0, 0, 4}; + augmented_media_packets.front()->data.AppendData(kPadding); + augmented_media_packets.front()->data.MutableData()[0] |= 1 << 5; // P bit. + augmented_media_packets.front()->header.paddingLength = 4; + + std::list fec_packets; + EncodeFec(media_packets, kNumFecPackets, &fec_packets); + + auto it = augmented_media_packets.begin(); + BuildAndAddRedMediaPacket(augmented_media_packets.front()); + + VerifyReconstructedMediaPacket(**it, 1); + EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); + + BuildAndAddRedFecPacket(fec_packets.front()); + ++it; + VerifyReconstructedMediaPacket(**it, 1); + EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec()); +} + } // namespace webrtc