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/source/fec_test_helper.h"
19 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
22 using ::testing::Args;
23 using ::testing::ElementsAreArray;
24 using ::testing::Return;
28 class MockRtpData : public RtpData {
30 MOCK_METHOD3(OnReceivedPayloadData,
31 int32_t(const uint8_t* payloadData,
32 const uint16_t payloadSize,
33 const WebRtcRTPHeader* rtpHeader));
35 MOCK_METHOD2(OnRecoveredPacket,
36 bool(const uint8_t* packet, int packet_length));
39 class ReceiverFecTest : public ::testing::Test {
41 virtual void SetUp() {
42 fec_ = new ForwardErrorCorrection();
43 receiver_fec_ = FecReceiver::Create(&rtp_data_callback_);
44 generator_ = new FrameGenerator();
47 virtual void TearDown() {
53 void GenerateFEC(std::list<Packet*>* media_packets,
54 std::list<Packet*>* fec_packets,
55 unsigned int num_fec_packets) {
56 uint8_t protection_factor = num_fec_packets * 255 / media_packets->size();
57 EXPECT_EQ(0, fec_->GenerateFEC(*media_packets, protection_factor,
58 0, false, kFecMaskBursty, fec_packets));
59 ASSERT_EQ(num_fec_packets, fec_packets->size());
62 void GenerateFrame(int num_media_packets, int frame_offset,
63 std::list<RtpPacket*>* media_rtp_packets,
64 std::list<Packet*>* media_packets) {
65 generator_->NewFrame(num_media_packets);
66 for (int i = 0; i < num_media_packets; ++i) {
67 media_rtp_packets->push_back(
68 generator_->NextPacket(frame_offset + i, kRtpHeaderSize + 10));
69 media_packets->push_back(media_rtp_packets->back());
73 void VerifyReconstructedMediaPacket(const RtpPacket* packet, int times) {
74 // Verify that the content of the reconstructed packet is equal to the
75 // content of |packet|, and that the same content is received |times| number
77 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet->length))
78 .With(Args<0, 1>(ElementsAreArray(packet->data,
80 .Times(times).WillRepeatedly(Return(true));
83 void BuildAndAddRedMediaPacket(RtpPacket* packet) {
84 RtpPacket* red_packet = generator_->BuildMediaRedPacket(packet);
85 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
86 red_packet->header.header, red_packet->data,
87 red_packet->length, kFecPayloadType));
91 void BuildAndAddRedFecPacket(Packet* packet) {
92 RtpPacket* red_packet = generator_->BuildFecRedPacket(packet);
93 EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
94 red_packet->header.header, red_packet->data,
95 red_packet->length, kFecPayloadType));
99 ForwardErrorCorrection* fec_;
100 MockRtpData rtp_data_callback_;
101 FecReceiver* receiver_fec_;
102 FrameGenerator* generator_;
105 void DeletePackets(std::list<Packet*>* packets) {
106 while (!packets->empty()) {
107 delete packets->front();
108 packets->pop_front();
112 TEST_F(ReceiverFecTest, TwoMediaOneFec) {
113 const unsigned int kNumFecPackets = 1u;
114 std::list<RtpPacket*> media_rtp_packets;
115 std::list<Packet*> media_packets;
116 GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
117 std::list<Packet*> fec_packets;
118 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
121 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
122 std::list<RtpPacket*>::iterator media_it = media_rtp_packets.begin();
123 BuildAndAddRedMediaPacket(*media_it);
124 VerifyReconstructedMediaPacket(*it, 1);
125 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
126 // Drop one media packet.
127 std::list<Packet*>::iterator fec_it = fec_packets.begin();
128 BuildAndAddRedFecPacket(*fec_it);
130 VerifyReconstructedMediaPacket(*it, 1);
131 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
133 DeletePackets(&media_packets);
136 TEST_F(ReceiverFecTest, TwoMediaTwoFec) {
137 const unsigned int kNumFecPackets = 2u;
138 std::list<RtpPacket*> media_rtp_packets;
139 std::list<Packet*> media_packets;
140 GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
141 std::list<Packet*> fec_packets;
142 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
145 // Drop both media packets.
146 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
147 std::list<Packet*>::iterator fec_it = fec_packets.begin();
148 BuildAndAddRedFecPacket(*fec_it);
149 VerifyReconstructedMediaPacket(*it, 1);
150 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
152 BuildAndAddRedFecPacket(*fec_it);
154 VerifyReconstructedMediaPacket(*it, 1);
155 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
157 DeletePackets(&media_packets);
160 TEST_F(ReceiverFecTest, TwoFramesOneFec) {
161 const unsigned int kNumFecPackets = 1u;
162 std::list<RtpPacket*> media_rtp_packets;
163 std::list<Packet*> media_packets;
164 GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
165 GenerateFrame(1, 1, &media_rtp_packets, &media_packets);
166 std::list<Packet*> fec_packets;
167 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
170 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
171 BuildAndAddRedMediaPacket(media_rtp_packets.front());
172 VerifyReconstructedMediaPacket(*it, 1);
173 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
174 // Drop one media packet.
175 BuildAndAddRedFecPacket(fec_packets.front());
177 VerifyReconstructedMediaPacket(*it, 1);
178 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
180 DeletePackets(&media_packets);
183 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) {
184 const unsigned int kNumFecPackets = 1u;
185 std::list<RtpPacket*> media_rtp_packets;
186 std::list<Packet*> media_packets;
187 GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
188 GenerateFrame(2, 1, &media_rtp_packets, &media_packets);
190 std::list<Packet*> fec_packets;
191 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
194 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
195 BuildAndAddRedMediaPacket(*it); // First frame: one packet.
196 VerifyReconstructedMediaPacket(*it, 1);
197 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
199 BuildAndAddRedMediaPacket(*it); // First packet of second frame.
200 VerifyReconstructedMediaPacket(*it, 1);
201 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
203 DeletePackets(&media_packets);
206 TEST_F(ReceiverFecTest, MaxFramesOneFec) {
207 const unsigned int kNumFecPackets = 1u;
208 const unsigned int kNumMediaPackets = 48u;
209 std::list<RtpPacket*> media_rtp_packets;
210 std::list<Packet*> media_packets;
211 for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
212 GenerateFrame(1, i, &media_rtp_packets, &media_packets);
214 std::list<Packet*> fec_packets;
215 GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
218 std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
219 ++it; // Drop first packet.
220 for (; it != media_rtp_packets.end(); ++it) {
221 BuildAndAddRedMediaPacket(*it);
222 VerifyReconstructedMediaPacket(*it, 1);
223 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
225 BuildAndAddRedFecPacket(fec_packets.front());
226 it = media_rtp_packets.begin();
227 VerifyReconstructedMediaPacket(*it, 1);
228 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
230 DeletePackets(&media_packets);
233 TEST_F(ReceiverFecTest, TooManyFrames) {
234 const unsigned int kNumFecPackets = 1u;
235 const unsigned int kNumMediaPackets = 49u;
236 std::list<RtpPacket*> media_rtp_packets;
237 std::list<Packet*> media_packets;
238 for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
239 GenerateFrame(1, i, &media_rtp_packets, &media_packets);
241 std::list<Packet*> fec_packets;
242 EXPECT_EQ(-1, fec_->GenerateFEC(media_packets,
243 kNumFecPackets * 255 / kNumMediaPackets, 0,
244 false, kFecMaskBursty, &fec_packets));
246 DeletePackets(&media_packets);
249 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) {
250 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
251 // Delay the FEC packet.
252 Packet* delayed_fec = NULL;
253 const unsigned int kNumFecPacketsBatch1 = 1u;
254 const unsigned int kNumMediaPacketsBatch1 = 2u;
255 std::list<RtpPacket*> media_rtp_packets_batch1;
256 std::list<Packet*> media_packets_batch1;
257 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
258 &media_packets_batch1);
259 std::list<Packet*> fec_packets;
260 GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
262 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
263 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
264 .Times(1).WillRepeatedly(Return(true));
265 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
266 delayed_fec = fec_packets.front();
268 // Fill the FEC decoder. No packets should be dropped.
269 const unsigned int kNumMediaPacketsBatch2 = 46u;
270 std::list<RtpPacket*> media_rtp_packets_batch2;
271 std::list<Packet*> media_packets_batch2;
272 for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
273 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
275 for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
276 it != media_rtp_packets_batch2.end(); ++it) {
277 BuildAndAddRedMediaPacket(*it);
278 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
279 .Times(1).WillRepeatedly(Return(true));
280 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
283 // Add the delayed FEC packet. One packet should be reconstructed.
284 BuildAndAddRedFecPacket(delayed_fec);
285 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
286 .Times(1).WillRepeatedly(Return(true));
287 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
289 DeletePackets(&media_packets_batch1);
290 DeletePackets(&media_packets_batch2);
293 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) {
294 // 1 frame with 2 media packets and one FEC packet. One media packet missing.
295 // Delay the FEC packet.
296 Packet* delayed_fec = NULL;
297 const unsigned int kNumFecPacketsBatch1 = 1u;
298 const unsigned int kNumMediaPacketsBatch1 = 2u;
299 std::list<RtpPacket*> media_rtp_packets_batch1;
300 std::list<Packet*> media_packets_batch1;
301 GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
302 &media_packets_batch1);
303 std::list<Packet*> fec_packets;
304 GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
306 BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
307 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
308 .Times(1).WillRepeatedly(Return(true));
309 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
310 delayed_fec = fec_packets.front();
312 // Fill the FEC decoder and force the last packet to be dropped.
313 const unsigned int kNumMediaPacketsBatch2 = 48u;
314 std::list<RtpPacket*> media_rtp_packets_batch2;
315 std::list<Packet*> media_packets_batch2;
316 for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
317 GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
319 for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
320 it != media_rtp_packets_batch2.end(); ++it) {
321 BuildAndAddRedMediaPacket(*it);
322 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
323 .Times(1).WillRepeatedly(Return(true));
324 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
327 // Add the delayed FEC packet. No packet should be reconstructed since the
328 // first media packet of that frame has been dropped due to being too old.
329 BuildAndAddRedFecPacket(delayed_fec);
330 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
332 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
334 DeletePackets(&media_packets_batch1);
335 DeletePackets(&media_packets_batch2);
338 TEST_F(ReceiverFecTest, OldFecPacketDropped) {
339 // 49 frames with 2 media packets and one FEC packet. All media packets
341 const unsigned int kNumMediaPackets = 49 * 2;
342 std::list<RtpPacket*> media_rtp_packets;
343 std::list<Packet*> media_packets;
344 for (unsigned int i = 0; i < kNumMediaPackets / 2; ++i) {
345 std::list<RtpPacket*> frame_media_rtp_packets;
346 std::list<Packet*> frame_media_packets;
347 std::list<Packet*> fec_packets;
348 GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets);
349 GenerateFEC(&frame_media_packets, &fec_packets, 1);
350 for (std::list<Packet*>::iterator it = fec_packets.begin();
351 it != fec_packets.end(); ++it) {
352 // Only FEC packets inserted. No packets recoverable at this time.
353 BuildAndAddRedFecPacket(*it);
354 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
356 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
358 media_packets.insert(media_packets.end(), frame_media_packets.begin(),
359 frame_media_packets.end());
360 media_rtp_packets.insert(media_rtp_packets.end(),
361 frame_media_rtp_packets.begin(),
362 frame_media_rtp_packets.end());
364 // Insert the oldest media packet. The corresponding FEC packet is too old
365 // and should've been dropped. Only the media packet we inserted will be
367 BuildAndAddRedMediaPacket(media_rtp_packets.front());
368 EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
369 .Times(1).WillRepeatedly(Return(true));
370 EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
372 DeletePackets(&media_packets);
375 } // namespace webrtc