1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/rtp_rtcp/source/ulpfec_generator.h"
12 
13 #include <list>
14 #include <memory>
15 #include <utility>
16 #include <vector>
17 
18 #include "modules/rtp_rtcp/source/byte_io.h"
19 #include "modules/rtp_rtcp/source/fec_test_helper.h"
20 #include "modules/rtp_rtcp/source/forward_error_correction.h"
21 #include "test/gtest.h"
22 
23 namespace webrtc {
24 
25 namespace {
26 using test::fec::AugmentedPacket;
27 using test::fec::AugmentedPacketGenerator;
28 
29 constexpr int kFecPayloadType = 96;
30 constexpr int kRedPayloadType = 97;
31 constexpr uint32_t kMediaSsrc = 835424;
32 }  // namespace
33 
VerifyHeader(uint16_t seq_num,uint32_t timestamp,int red_payload_type,int fec_payload_type,bool marker_bit,const rtc::CopyOnWriteBuffer & data)34 void VerifyHeader(uint16_t seq_num,
35                   uint32_t timestamp,
36                   int red_payload_type,
37                   int fec_payload_type,
38                   bool marker_bit,
39                   const rtc::CopyOnWriteBuffer& data) {
40   // Marker bit not set.
41   EXPECT_EQ(marker_bit ? 0x80 : 0, data[1] & 0x80);
42   EXPECT_EQ(red_payload_type, data[1] & 0x7F);
43   EXPECT_EQ(seq_num, (data[2] << 8) + data[3]);
44   uint32_t parsed_timestamp =
45       (data[4] << 24) + (data[5] << 16) + (data[6] << 8) + data[7];
46   EXPECT_EQ(timestamp, parsed_timestamp);
47   EXPECT_EQ(static_cast<uint8_t>(fec_payload_type), data[kRtpHeaderSize]);
48 }
49 
50 class UlpfecGeneratorTest : public ::testing::Test {
51  protected:
UlpfecGeneratorTest()52   UlpfecGeneratorTest()
53       : fake_clock_(1),
54         ulpfec_generator_(kRedPayloadType, kFecPayloadType, &fake_clock_),
55         packet_generator_(kMediaSsrc) {}
56 
57   SimulatedClock fake_clock_;
58   UlpfecGenerator ulpfec_generator_;
59   AugmentedPacketGenerator packet_generator_;
60 };
61 
62 // Verifies bug found via fuzzing, where a gap in the packet sequence caused us
63 // to move past the end of the current FEC packet mask byte without moving to
64 // the next byte. That likely caused us to repeatedly read from the same byte,
65 // and if that byte didn't protect packets we would generate empty FEC.
TEST_F(UlpfecGeneratorTest,NoEmptyFecWithSeqNumGaps)66 TEST_F(UlpfecGeneratorTest, NoEmptyFecWithSeqNumGaps) {
67   struct Packet {
68     size_t header_size;
69     size_t payload_size;
70     uint16_t seq_num;
71     bool marker_bit;
72   };
73   std::vector<Packet> protected_packets;
74   protected_packets.push_back({15, 3, 41, 0});
75   protected_packets.push_back({14, 1, 43, 0});
76   protected_packets.push_back({19, 0, 48, 0});
77   protected_packets.push_back({19, 0, 50, 0});
78   protected_packets.push_back({14, 3, 51, 0});
79   protected_packets.push_back({13, 8, 52, 0});
80   protected_packets.push_back({19, 2, 53, 0});
81   protected_packets.push_back({12, 3, 54, 0});
82   protected_packets.push_back({21, 0, 55, 0});
83   protected_packets.push_back({13, 3, 57, 1});
84   FecProtectionParams params = {117, 3, kFecMaskBursty};
85   ulpfec_generator_.SetProtectionParameters(params, params);
86   for (Packet p : protected_packets) {
87     RtpPacketToSend packet(nullptr);
88     packet.SetMarker(p.marker_bit);
89     packet.AllocateExtension(RTPExtensionType::kRtpExtensionMid,
90                              p.header_size - packet.headers_size());
91     packet.SetSequenceNumber(p.seq_num);
92     packet.AllocatePayload(p.payload_size);
93     ulpfec_generator_.AddPacketAndGenerateFec(packet);
94 
95     std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
96         ulpfec_generator_.GetFecPackets();
97     if (!p.marker_bit) {
98       EXPECT_TRUE(fec_packets.empty());
99     } else {
100       EXPECT_FALSE(fec_packets.empty());
101     }
102   }
103 }
104 
TEST_F(UlpfecGeneratorTest,OneFrameFec)105 TEST_F(UlpfecGeneratorTest, OneFrameFec) {
106   // The number of media packets (|kNumPackets|), number of frames (one for
107   // this test), and the protection factor (|params->fec_rate|) are set to make
108   // sure the conditions for generating FEC are satisfied. This means:
109   // (1) protection factor is high enough so that actual overhead over 1 frame
110   // of packets is within |kMaxExcessOverhead|, and (2) the total number of
111   // media packets for 1 frame is at least |minimum_media_packets_fec_|.
112   constexpr size_t kNumPackets = 4;
113   FecProtectionParams params = {15, 3, kFecMaskRandom};
114   packet_generator_.NewFrame(kNumPackets);
115   // Expecting one FEC packet.
116   ulpfec_generator_.SetProtectionParameters(params, params);
117   uint32_t last_timestamp = 0;
118   for (size_t i = 0; i < kNumPackets; ++i) {
119     std::unique_ptr<AugmentedPacket> packet =
120         packet_generator_.NextPacket(i, 10);
121     RtpPacketToSend rtp_packet(nullptr);
122     EXPECT_TRUE(rtp_packet.Parse(packet->data.data(), packet->data.size()));
123     ulpfec_generator_.AddPacketAndGenerateFec(rtp_packet);
124     last_timestamp = packet->header.timestamp;
125   }
126   std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
127       ulpfec_generator_.GetFecPackets();
128   EXPECT_EQ(fec_packets.size(), 1u);
129   uint16_t seq_num = packet_generator_.NextPacketSeqNum();
130   fec_packets[0]->SetSequenceNumber(seq_num);
131   EXPECT_TRUE(ulpfec_generator_.GetFecPackets().empty());
132 
133   EXPECT_EQ(fec_packets[0]->headers_size(), kRtpHeaderSize);
134 
135   VerifyHeader(seq_num, last_timestamp, kRedPayloadType, kFecPayloadType, false,
136                fec_packets[0]->Buffer());
137 }
138 
TEST_F(UlpfecGeneratorTest,TwoFrameFec)139 TEST_F(UlpfecGeneratorTest, TwoFrameFec) {
140   // The number of media packets/frame (|kNumPackets|), the number of frames
141   // (|kNumFrames|), and the protection factor (|params->fec_rate|) are set to
142   // make sure the conditions for generating FEC are satisfied. This means:
143   // (1) protection factor is high enough so that actual overhead over
144   // |kNumFrames| is within |kMaxExcessOverhead|, and (2) the total number of
145   // media packets for |kNumFrames| frames is at least
146   // |minimum_media_packets_fec_|.
147   constexpr size_t kNumPackets = 2;
148   constexpr size_t kNumFrames = 2;
149 
150   FecProtectionParams params = {15, 3, kFecMaskRandom};
151   // Expecting one FEC packet.
152   ulpfec_generator_.SetProtectionParameters(params, params);
153   uint32_t last_timestamp = 0;
154   for (size_t i = 0; i < kNumFrames; ++i) {
155     packet_generator_.NewFrame(kNumPackets);
156     for (size_t j = 0; j < kNumPackets; ++j) {
157       std::unique_ptr<AugmentedPacket> packet =
158           packet_generator_.NextPacket(i * kNumPackets + j, 10);
159       RtpPacketToSend rtp_packet(nullptr);
160       EXPECT_TRUE(rtp_packet.Parse(packet->data.data(), packet->data.size()));
161       ulpfec_generator_.AddPacketAndGenerateFec(rtp_packet);
162       last_timestamp = packet->header.timestamp;
163     }
164   }
165   std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
166       ulpfec_generator_.GetFecPackets();
167   EXPECT_EQ(fec_packets.size(), 1u);
168   const uint16_t seq_num = packet_generator_.NextPacketSeqNum();
169   fec_packets[0]->SetSequenceNumber(seq_num);
170   VerifyHeader(seq_num, last_timestamp, kRedPayloadType, kFecPayloadType, false,
171                fec_packets[0]->Buffer());
172 }
173 
TEST_F(UlpfecGeneratorTest,MixedMediaRtpHeaderLengths)174 TEST_F(UlpfecGeneratorTest, MixedMediaRtpHeaderLengths) {
175   constexpr size_t kShortRtpHeaderLength = 12;
176   constexpr size_t kLongRtpHeaderLength = 16;
177 
178   // Only one frame required to generate FEC.
179   FecProtectionParams params = {127, 1, kFecMaskRandom};
180   ulpfec_generator_.SetProtectionParameters(params, params);
181 
182   // Fill up internal buffer with media packets with short RTP header length.
183   packet_generator_.NewFrame(kUlpfecMaxMediaPackets + 1);
184   for (size_t i = 0; i < kUlpfecMaxMediaPackets; ++i) {
185     std::unique_ptr<AugmentedPacket> packet =
186         packet_generator_.NextPacket(i, 10);
187     RtpPacketToSend rtp_packet(nullptr);
188     EXPECT_TRUE(rtp_packet.Parse(packet->data.data(), packet->data.size()));
189     EXPECT_EQ(rtp_packet.headers_size(), kShortRtpHeaderLength);
190     ulpfec_generator_.AddPacketAndGenerateFec(rtp_packet);
191     EXPECT_TRUE(ulpfec_generator_.GetFecPackets().empty());
192   }
193 
194   // Kick off FEC generation with media packet with long RTP header length.
195   // Since the internal buffer is full, this packet will not be protected.
196   std::unique_ptr<AugmentedPacket> packet =
197       packet_generator_.NextPacket(kUlpfecMaxMediaPackets, 10);
198   RtpPacketToSend rtp_packet(nullptr);
199   EXPECT_TRUE(rtp_packet.Parse(packet->data.data(), packet->data.size()));
200   EXPECT_TRUE(rtp_packet.SetPayloadSize(0) != nullptr);
201   const uint32_t csrcs[]{1};
202   rtp_packet.SetCsrcs(csrcs);
203 
204   EXPECT_EQ(rtp_packet.headers_size(), kLongRtpHeaderLength);
205 
206   ulpfec_generator_.AddPacketAndGenerateFec(rtp_packet);
207   std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
208       ulpfec_generator_.GetFecPackets();
209   EXPECT_FALSE(fec_packets.empty());
210 
211   // Ensure that the RED header is placed correctly, i.e. the correct
212   // RTP header length was used in the RED packet creation.
213   uint16_t seq_num = packet_generator_.NextPacketSeqNum();
214   for (const auto& fec_packet : fec_packets) {
215     fec_packet->SetSequenceNumber(seq_num++);
216     EXPECT_EQ(kFecPayloadType, fec_packet->data()[kShortRtpHeaderLength]);
217   }
218 }
219 
220 }  // namespace webrtc
221