diff --git a/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc b/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc index 516306cc18..49db1474f9 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc @@ -33,9 +33,9 @@ using ::testing::Args; using ::testing::ElementsAreArray; using ::testing::Return; -using ::webrtc::test::fec::FrameGenerator; using Packet = ::webrtc::ForwardErrorCorrection::Packet; using ::webrtc::test::fec::RawRtpPacket; +using ::webrtc::test::fec::UlpfecPacketGenerator; class ReceiverFecTest : public ::testing::Test { protected: @@ -99,7 +99,7 @@ class ReceiverFecTest : public ::testing::Test { MockRtpData rtp_data_callback_; std::unique_ptr fec_; std::unique_ptr receiver_fec_; - FrameGenerator generator_; + UlpfecPacketGenerator generator_; }; TEST_F(ReceiverFecTest, TwoMediaOneFec) { diff --git a/webrtc/modules/rtp_rtcp/source/fec_test_helper.cc b/webrtc/modules/rtp_rtcp/source/fec_test_helper.cc index 235720d819..3799c7f0c2 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_test_helper.cc +++ b/webrtc/modules/rtp_rtcp/source/fec_test_helper.cc @@ -26,85 +26,6 @@ constexpr uint8_t kRedPayloadType = 97; constexpr uint8_t kVp8PayloadType = 120; } // namespace -FrameGenerator::FrameGenerator() - : num_packets_(0), seq_num_(0), timestamp_(0) {} - -void FrameGenerator::NewFrame(int num_packets) { - num_packets_ = num_packets; - timestamp_ += 3000; -} - -uint16_t FrameGenerator::NextSeqNum() { return ++seq_num_; } - -RawRtpPacket* FrameGenerator::NextPacket(int offset, size_t length) { - RawRtpPacket* rtp_packet = new RawRtpPacket; - for (size_t i = 0; i < length; ++i) - rtp_packet->data[i + kRtpHeaderSize] = offset + i; - rtp_packet->length = length + kRtpHeaderSize; - memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader)); - rtp_packet->header.frameType = kVideoFrameDelta; - rtp_packet->header.header.headerLength = kRtpHeaderSize; - rtp_packet->header.header.markerBit = (num_packets_ == 1); - rtp_packet->header.header.sequenceNumber = seq_num_; - rtp_packet->header.header.timestamp = timestamp_; - rtp_packet->header.header.payloadType = kVp8PayloadType; - BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header); - ++seq_num_; - --num_packets_; - return rtp_packet; -} - -// Creates a new RtpPacket with the RED header added to the packet. -RawRtpPacket* FrameGenerator::BuildMediaRedPacket(const RawRtpPacket* packet) { - const size_t kHeaderLength = packet->header.header.headerLength; - RawRtpPacket* red_packet = new RawRtpPacket; - red_packet->header = packet->header; - red_packet->length = packet->length + 1; // 1 byte RED header. - memset(red_packet->data, 0, red_packet->length); - // Copy RTP header. - memcpy(red_packet->data, packet->data, kHeaderLength); - SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength); - memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength, - packet->length - kHeaderLength); - return red_packet; -} - -// Creates a new RtpPacket with FEC payload and RED header. Does this by -// creating a new fake media RtpPacket, clears the marker bit and adds a RED -// header. Finally replaces the payload with the content of |packet->data|. -RawRtpPacket* FrameGenerator::BuildFecRedPacket( - const ForwardErrorCorrection::Packet* packet) { - // Create a fake media packet to get a correct header. 1 byte RED header. - ++num_packets_; - RawRtpPacket* red_packet = NextPacket(0, packet->length + 1); - red_packet->data[1] &= ~0x80; // Clear marker bit. - const size_t kHeaderLength = red_packet->header.header.headerLength; - SetRedHeader(red_packet, kFecPayloadType, kHeaderLength); - memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length); - red_packet->length = kHeaderLength + 1 + packet->length; - return red_packet; -} - -void FrameGenerator::SetRedHeader(ForwardErrorCorrection::Packet* red_packet, - uint8_t payload_type, - size_t header_length) const { - // Replace pltype. - red_packet->data[1] &= 0x80; // Reset. - red_packet->data[1] += kRedPayloadType; // Replace. - - // Add RED header, f-bit always 0. - red_packet->data[header_length] = payload_type; -} - -void FrameGenerator::BuildRtpHeader(uint8_t* data, const RTPHeader* header) { - data[0] = 0x80; // Version 2. - data[1] = header->payloadType; - data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0); - ByteWriter::WriteBigEndian(data + 2, header->sequenceNumber); - ByteWriter::WriteBigEndian(data + 4, header->timestamp); - ByteWriter::WriteBigEndian(data + 8, header->ssrc); -} - ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( int num_media_packets, uint16_t start_seq_num) { @@ -168,6 +89,90 @@ uint16_t MediaPacketGenerator::GetFecSeqNum() { return fec_seq_num_; } +UlpfecPacketGenerator::UlpfecPacketGenerator() + : num_packets_(0), seq_num_(0), timestamp_(0) {} + +void UlpfecPacketGenerator::NewFrame(int num_packets) { + num_packets_ = num_packets; + timestamp_ += 3000; +} + +uint16_t UlpfecPacketGenerator::NextSeqNum() { + return ++seq_num_; +} + +RawRtpPacket* UlpfecPacketGenerator::NextPacket(int offset, size_t length) { + RawRtpPacket* rtp_packet = new RawRtpPacket; + for (size_t i = 0; i < length; ++i) + rtp_packet->data[i + kRtpHeaderSize] = offset + i; + rtp_packet->length = length + kRtpHeaderSize; + memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader)); + rtp_packet->header.frameType = kVideoFrameDelta; + rtp_packet->header.header.headerLength = kRtpHeaderSize; + rtp_packet->header.header.markerBit = (num_packets_ == 1); + rtp_packet->header.header.sequenceNumber = seq_num_; + rtp_packet->header.header.timestamp = timestamp_; + rtp_packet->header.header.payloadType = kVp8PayloadType; + BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header); + ++seq_num_; + --num_packets_; + return rtp_packet; +} + +// Creates a new RtpPacket with the RED header added to the packet. +RawRtpPacket* UlpfecPacketGenerator::BuildMediaRedPacket( + const RawRtpPacket* packet) { + const size_t kHeaderLength = packet->header.header.headerLength; + RawRtpPacket* red_packet = new RawRtpPacket; + red_packet->header = packet->header; + red_packet->length = packet->length + 1; // 1 byte RED header. + memset(red_packet->data, 0, red_packet->length); + // Copy RTP header. + memcpy(red_packet->data, packet->data, kHeaderLength); + SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength); + memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength, + packet->length - kHeaderLength); + return red_packet; +} + +// Creates a new RtpPacket with FEC payload and RED header. Does this by +// creating a new fake media RtpPacket, clears the marker bit and adds a RED +// header. Finally replaces the payload with the content of |packet->data|. +RawRtpPacket* UlpfecPacketGenerator::BuildFecRedPacket( + const ForwardErrorCorrection::Packet* packet) { + // Create a fake media packet to get a correct header. 1 byte RED header. + ++num_packets_; + RawRtpPacket* red_packet = NextPacket(0, packet->length + 1); + red_packet->data[1] &= ~0x80; // Clear marker bit. + const size_t kHeaderLength = red_packet->header.header.headerLength; + SetRedHeader(red_packet, kFecPayloadType, kHeaderLength); + memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length); + red_packet->length = kHeaderLength + 1 + packet->length; + return red_packet; +} + +void UlpfecPacketGenerator::SetRedHeader( + ForwardErrorCorrection::Packet* red_packet, + uint8_t payload_type, + size_t header_length) const { + // Replace pltype. + red_packet->data[1] &= 0x80; // Reset. + red_packet->data[1] += kRedPayloadType; // Replace. + + // Add RED header, f-bit always 0. + red_packet->data[header_length] = payload_type; +} + +void UlpfecPacketGenerator::BuildRtpHeader(uint8_t* data, + const RTPHeader* header) { + data[0] = 0x80; // Version 2. + data[1] = header->payloadType; + data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0); + ByteWriter::WriteBigEndian(data + 2, header->sequenceNumber); + ByteWriter::WriteBigEndian(data + 4, header->timestamp); + ByteWriter::WriteBigEndian(data + 8, header->ssrc); +} + } // namespace fec } // namespace test } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/fec_test_helper.h b/webrtc/modules/rtp_rtcp/source/fec_test_helper.h index 9c0a323056..594d38ddff 100644 --- a/webrtc/modules/rtp_rtcp/source/fec_test_helper.h +++ b/webrtc/modules/rtp_rtcp/source/fec_test_helper.h @@ -18,44 +18,13 @@ namespace webrtc { namespace test { - -// Needed to not clash with another webrtc::FrameGenerator. namespace fec { struct RawRtpPacket : public ForwardErrorCorrection::Packet { WebRtcRTPHeader header; }; -class FrameGenerator { - public: - FrameGenerator(); - - void NewFrame(int num_packets); - - uint16_t NextSeqNum(); - - RawRtpPacket* NextPacket(int offset, size_t length); - - // Creates a new RtpPacket with the RED header added to the packet. - RawRtpPacket* BuildMediaRedPacket(const RawRtpPacket* packet); - - // Creates a new RtpPacket with FEC payload and red header. Does this by - // creating a new fake media RtpPacket, clears the marker bit and adds a RED - // header. Finally replaces the payload with the content of |packet->data|. - RawRtpPacket* BuildFecRedPacket(const ForwardErrorCorrection::Packet* packet); - - void SetRedHeader(ForwardErrorCorrection::Packet* red_packet, - uint8_t payload_type, - size_t header_length) const; - - private: - static void BuildRtpHeader(uint8_t* data, const RTPHeader* header); - - int num_packets_; - uint16_t seq_num_; - uint32_t timestamp_; -}; - +// This class generates media packets corresponding to a single frame. class MediaPacketGenerator { public: MediaPacketGenerator(uint32_t min_packet_size, @@ -86,6 +55,38 @@ class MediaPacketGenerator { uint16_t fec_seq_num_; }; +// This class generates media and ULPFEC packets (both encapsulated in RED) +// for a single frame. +class UlpfecPacketGenerator { + public: + UlpfecPacketGenerator(); + + void NewFrame(int num_packets); + + uint16_t NextSeqNum(); + + RawRtpPacket* NextPacket(int offset, size_t length); + + // Creates a new RtpPacket with the RED header added to the packet. + RawRtpPacket* BuildMediaRedPacket(const RawRtpPacket* packet); + + // Creates a new RtpPacket with FEC payload and red header. Does this by + // creating a new fake media RtpPacket, clears the marker bit and adds a RED + // header. Finally replaces the payload with the content of |packet->data|. + RawRtpPacket* BuildFecRedPacket(const ForwardErrorCorrection::Packet* packet); + + void SetRedHeader(ForwardErrorCorrection::Packet* red_packet, + uint8_t payload_type, + size_t header_length) const; + + private: + static void BuildRtpHeader(uint8_t* data, const RTPHeader* header); + + int num_packets_; + uint16_t seq_num_; + uint32_t timestamp_; +}; + } // namespace fec } // namespace test } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc b/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc index 14d80eb7cb..4fc87f73bf 100644 --- a/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/producer_fec_unittest.cc @@ -25,8 +25,8 @@ constexpr uint8_t kFecPayloadType = 96; constexpr uint8_t kRedPayloadType = 97; } // namespace -using ::webrtc::test::fec::FrameGenerator; using ::webrtc::test::fec::RawRtpPacket; +using ::webrtc::test::fec::UlpfecPacketGenerator; void VerifyHeader(uint16_t seq_num, uint32_t timestamp, @@ -50,7 +50,7 @@ void VerifyHeader(uint16_t seq_num, class ProducerFecTest : public ::testing::Test { protected: ProducerFec producer_; - FrameGenerator generator_; + UlpfecPacketGenerator generator_; }; // Verifies bug found via fuzzing, where a gap in the packet sequence caused us