2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/modules/rtp_rtcp/interface/fec_receiver.h"
18 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
19 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h"
20 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
23 using ::testing::Args;
24 using ::testing::ElementsAreArray;
25 using ::testing::Return;
29 class ReceiverFecTest : public ::testing::Test {
31 virtual void SetUp() {
32 fec_ = new ForwardErrorCorrection();
33 receiver_fec_ = FecReceiver::Create(&rtp_data_callback_);
34 generator_ = new FrameGenerator();
37 virtual void TearDown() {
43 void GenerateFEC(std::list<Packet*>* media_packets,
44 std::list<Packet*>* fec_packets,
45 unsigned int num_fec_packets) {
46 uint8_t protection_factor = num_fec_packets * 255 / media_packets->size();
47 EXPECT_EQ(0, fec_->GenerateFEC(*media_packets, protection_factor,
48 0, false, kFecMaskBursty, fec_packets));
49 ASSERT_EQ(num_fec_packets, fec_packets->size());
52 void GenerateFrame(int num_media_packets, int frame_offset,
53 std::list<RtpPacket*>* media_rtp_packets,
54 std::list<Packet*>* media_packets) {
55 generator_->NewFrame(num_media_packets);
56 for (int i = 0; i < num_media_packets; ++i) {
57 media_rtp_packets->push_back(
58 generator_->NextPacket(frame_offset + i, kRtpHeaderSize + 10));
59 media_packets->push_back(media_rtp_packets->back());
63 void VerifyReconstructedMediaPacket(const RtpPacket* packet, int times) {
64 // Verify that the content of the reconstructed packet is equal to the
65 // content of |packet|, and that the same content is received |times| number
67 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet->length))
68 .With(Args<0, 1>(ElementsAreArray(packet->data,
70 .Times(times).WillRepeatedly(Return(true));
73 void BuildAndAddRedMediaPacket(RtpPacket* packet) {
74 RtpPacket* red_packet = generator_->BuildMediaRedPacket(packet);
75 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
76 red_packet->header.header, red_packet->data,
77 red_packet->length, kFecPayloadType));
81 void BuildAndAddRedFecPacket(Packet* packet) {
82 RtpPacket* red_packet = generator_->BuildFecRedPacket(packet);
83 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
84 red_packet->header.header, red_packet->data,
85 red_packet->length, kFecPayloadType));
89 ForwardErrorCorrection* fec_;
90 MockRtpData rtp_data_callback_;
91 FecReceiver* receiver_fec_;
92 FrameGenerator* generator_;
95 void DeletePackets(std::list<Packet*>* packets) {
96 while (!packets->empty()) {
97 delete packets->front();
102 TEST_F(ReceiverFecTest, TwoMediaOneFec) {
103 const unsigned int kNumFecPackets = 1u;
104 std::list<RtpPacket*> media_rtp_packets;
105 std::list<Packet*> media_packets;
106 GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
107 std::list<Packet*> fec_packets;
108 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
111 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
112 std::list<RtpPacket*>::iterator media_it = media_rtp_packets.begin();
113 BuildAndAddRedMediaPacket(*media_it);
114 VerifyReconstructedMediaPacket(*it, 1);
115 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
116 // Drop one media packet.
117 std::list<Packet*>::iterator fec_it = fec_packets.begin();
118 BuildAndAddRedFecPacket(*fec_it);
120 VerifyReconstructedMediaPacket(*it, 1);
121 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
123 DeletePackets(&media_packets);
126 TEST_F(ReceiverFecTest, TwoMediaTwoFec) {
127 const unsigned int kNumFecPackets = 2u;
128 std::list<RtpPacket*> media_rtp_packets;
129 std::list<Packet*> media_packets;
130 GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
131 std::list<Packet*> fec_packets;
132 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
135 // Drop both media packets.
136 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
137 std::list<Packet*>::iterator fec_it = fec_packets.begin();
138 BuildAndAddRedFecPacket(*fec_it);
139 VerifyReconstructedMediaPacket(*it, 1);
140 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
142 BuildAndAddRedFecPacket(*fec_it);
144 VerifyReconstructedMediaPacket(*it, 1);
145 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
147 DeletePackets(&media_packets);
150 TEST_F(ReceiverFecTest, TwoFramesOneFec) {
151 const unsigned int kNumFecPackets = 1u;
152 std::list<RtpPacket*> media_rtp_packets;
153 std::list<Packet*> media_packets;
154 GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
155 GenerateFrame(1, 1, &media_rtp_packets, &media_packets);
156 std::list<Packet*> fec_packets;
157 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
160 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
161 BuildAndAddRedMediaPacket(media_rtp_packets.front());
162 VerifyReconstructedMediaPacket(*it, 1);
163 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
164 // Drop one media packet.
165 BuildAndAddRedFecPacket(fec_packets.front());
167 VerifyReconstructedMediaPacket(*it, 1);
168 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
170 DeletePackets(&media_packets);
173 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) {
174 const unsigned int kNumFecPackets = 1u;
175 std::list<RtpPacket*> media_rtp_packets;
176 std::list<Packet*> media_packets;
177 GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
178 GenerateFrame(2, 1, &media_rtp_packets, &media_packets);
180 std::list<Packet*> fec_packets;
181 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
184 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
185 BuildAndAddRedMediaPacket(*it); // First frame: one packet.
186 VerifyReconstructedMediaPacket(*it, 1);
187 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
189 BuildAndAddRedMediaPacket(*it); // First packet of second frame.
190 VerifyReconstructedMediaPacket(*it, 1);
191 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
193 DeletePackets(&media_packets);
196 TEST_F(ReceiverFecTest, MaxFramesOneFec) {
197 const unsigned int kNumFecPackets = 1u;
198 const unsigned int kNumMediaPackets = 48u;
199 std::list<RtpPacket*> media_rtp_packets;
200 std::list<Packet*> media_packets;
201 for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
202 GenerateFrame(1, i, &media_rtp_packets, &media_packets);
204 std::list<Packet*> fec_packets;
205 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
208 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
209 ++it; // Drop first packet.
210 for (; it != media_rtp_packets.end(); ++it) {
211 BuildAndAddRedMediaPacket(*it);
212 VerifyReconstructedMediaPacket(*it, 1);
213 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
215 BuildAndAddRedFecPacket(fec_packets.front());
216 it = media_rtp_packets.begin();
217 VerifyReconstructedMediaPacket(*it, 1);
218 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
220 DeletePackets(&media_packets);
223 TEST_F(ReceiverFecTest, TooManyFrames) {
224 const unsigned int kNumFecPackets = 1u;
225 const unsigned int kNumMediaPackets = 49u;
226 std::list<RtpPacket*> media_rtp_packets;
227 std::list<Packet*> media_packets;
228 for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
229 GenerateFrame(1, i, &media_rtp_packets, &media_packets);
231 std::list<Packet*> fec_packets;
232 EXPECT_EQ(-1, fec_->GenerateFEC(media_packets,
233 kNumFecPackets * 255 / kNumMediaPackets, 0,
234 false, kFecMaskBursty, &fec_packets));
236 DeletePackets(&media_packets);
239 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) {
240 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
241 // Delay the FEC packet.
242 Packet* delayed_fec = NULL;
243 const unsigned int kNumFecPacketsBatch1 = 1u;
244 const unsigned int kNumMediaPacketsBatch1 = 2u;
245 std::list<RtpPacket*> media_rtp_packets_batch1;
246 std::list<Packet*> media_packets_batch1;
247 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
248 &media_packets_batch1);
249 std::list<Packet*> fec_packets;
250 GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
252 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
253 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
254 .Times(1).WillRepeatedly(Return(true));
255 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
256 delayed_fec = fec_packets.front();
258 // Fill the FEC decoder. No packets should be dropped.
259 const unsigned int kNumMediaPacketsBatch2 = 46u;
260 std::list<RtpPacket*> media_rtp_packets_batch2;
261 std::list<Packet*> media_packets_batch2;
262 for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
263 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
265 for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
266 it != media_rtp_packets_batch2.end(); ++it) {
267 BuildAndAddRedMediaPacket(*it);
268 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
269 .Times(1).WillRepeatedly(Return(true));
270 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
273 // Add the delayed FEC packet. One packet should be reconstructed.
274 BuildAndAddRedFecPacket(delayed_fec);
275 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
276 .Times(1).WillRepeatedly(Return(true));
277 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
279 DeletePackets(&media_packets_batch1);
280 DeletePackets(&media_packets_batch2);
283 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) {
284 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
285 // Delay the FEC packet.
286 Packet* delayed_fec = NULL;
287 const unsigned int kNumFecPacketsBatch1 = 1u;
288 const unsigned int kNumMediaPacketsBatch1 = 2u;
289 std::list<RtpPacket*> media_rtp_packets_batch1;
290 std::list<Packet*> media_packets_batch1;
291 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
292 &media_packets_batch1);
293 std::list<Packet*> fec_packets;
294 GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
296 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
297 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
298 .Times(1).WillRepeatedly(Return(true));
299 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
300 delayed_fec = fec_packets.front();
302 // Fill the FEC decoder and force the last packet to be dropped.
303 const unsigned int kNumMediaPacketsBatch2 = 48u;
304 std::list<RtpPacket*> media_rtp_packets_batch2;
305 std::list<Packet*> media_packets_batch2;
306 for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
307 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
309 for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
310 it != media_rtp_packets_batch2.end(); ++it) {
311 BuildAndAddRedMediaPacket(*it);
312 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
313 .Times(1).WillRepeatedly(Return(true));
314 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
317 // Add the delayed FEC packet. No packet should be reconstructed since the
318 // first media packet of that frame has been dropped due to being too old.
319 BuildAndAddRedFecPacket(delayed_fec);
320 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
322 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
324 DeletePackets(&media_packets_batch1);
325 DeletePackets(&media_packets_batch2);
328 TEST_F(ReceiverFecTest, OldFecPacketDropped) {
329 // 49 frames with 2 media packets and one FEC packet. All media packets
331 const unsigned int kNumMediaPackets = 49 * 2;
332 std::list<RtpPacket*> media_rtp_packets;
333 std::list<Packet*> media_packets;
334 for (unsigned int i = 0; i < kNumMediaPackets / 2; ++i) {
335 std::list<RtpPacket*> frame_media_rtp_packets;
336 std::list<Packet*> frame_media_packets;
337 std::list<Packet*> fec_packets;
338 GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets);
339 GenerateFEC(&frame_media_packets, &fec_packets, 1);
340 for (std::list<Packet*>::iterator it = fec_packets.begin();
341 it != fec_packets.end(); ++it) {
342 // Only FEC packets inserted. No packets recoverable at this time.
343 BuildAndAddRedFecPacket(*it);
344 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
346 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
348 media_packets.insert(media_packets.end(), frame_media_packets.begin(),
349 frame_media_packets.end());
350 media_rtp_packets.insert(media_rtp_packets.end(),
351 frame_media_rtp_packets.begin(),
352 frame_media_rtp_packets.end());
354 // Insert the oldest media packet. The corresponding FEC packet is too old
355 // and should've been dropped. Only the media packet we inserted will be
357 BuildAndAddRedMediaPacket(media_rtp_packets.front());
358 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
359 .Times(1).WillRepeatedly(Return(true));
360 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
362 DeletePackets(&media_packets);
365 } // namespace webrtc