Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / rtp_fec_unittest.cc
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 <list>
12
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
15 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
16
17 using webrtc::ForwardErrorCorrection;
18
19 // Minimum RTP header size in bytes.
20 const uint8_t kRtpHeaderSize = 12;
21
22 // Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum.
23 const uint8_t kTransportOverhead = 28;
24
25 // Maximum number of media packets used in the FEC (RFC 5109).
26 const uint8_t kMaxNumberMediaPackets = ForwardErrorCorrection::kMaxMediaPackets;
27
28 typedef std::list<ForwardErrorCorrection::Packet*> PacketList;
29 typedef std::list<ForwardErrorCorrection::ReceivedPacket*> ReceivedPacketList;
30 typedef std::list<ForwardErrorCorrection::RecoveredPacket*> RecoveredPacketList;
31
32 template <typename T> void ClearList(std::list<T*>* my_list) {
33   T* packet = NULL;
34   while (!my_list->empty()) {
35     packet = my_list->front();
36     delete packet;
37     my_list->pop_front();
38   }
39 }
40
41 class RtpFecTest : public ::testing::Test {
42  protected:
43   RtpFecTest()
44       : fec_(new ForwardErrorCorrection()), ssrc_(rand()), fec_seq_num_(0) {}
45
46   ForwardErrorCorrection* fec_;
47   int ssrc_;
48   uint16_t fec_seq_num_;
49
50   PacketList media_packet_list_;
51   PacketList fec_packet_list_;
52   ReceivedPacketList received_packet_list_;
53   RecoveredPacketList recovered_packet_list_;
54
55   // Media packet "i" is lost if media_loss_mask_[i] = 1,
56   // received if media_loss_mask_[i] = 0.
57   int media_loss_mask_[kMaxNumberMediaPackets];
58
59   // FEC packet "i" is lost if fec_loss_mask_[i] = 1,
60   // received if fec_loss_mask_[i] = 0.
61   int fec_loss_mask_[kMaxNumberMediaPackets];
62
63   // Construct the media packet list, up to |num_media_packets| packets.
64   // Returns the next sequence number after the last media packet.
65   // (this will be the sequence of the first FEC packet)
66   int ConstructMediaPacketsSeqNum(int num_media_packets, int start_seq_num);
67   int ConstructMediaPackets(int num_media_packets);
68
69   // Construct the received packet list: a subset of the media and FEC packets.
70   void NetworkReceivedPackets();
71
72   // Add packet from |packet_list| to list of received packets, using the
73   // |loss_mask|.
74   // The |packet_list| may be a media packet list (is_fec = false), or a
75   // FEC packet list (is_fec = true).
76   void ReceivedPackets(const PacketList& packet_list, int* loss_mask,
77                        bool is_fec);
78
79   // Check for complete recovery after FEC decoding.
80   bool IsRecoveryComplete();
81
82   // Delete the received packets.
83   void FreeRecoveredPacketList();
84
85   // Delete the media and FEC packets.
86   void TearDown();
87 };
88
89 TEST_F(RtpFecTest, FecRecoveryNoLoss) {
90   const int kNumImportantPackets = 0;
91   const bool kUseUnequalProtection = false;
92   const int kNumMediaPackets = 4;
93   uint8_t kProtectionFactor = 60;
94
95   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
96
97   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
98                                  kNumImportantPackets, kUseUnequalProtection,
99                                  webrtc::kFecMaskBursty, &fec_packet_list_));
100
101   // Expect 1 FEC packet.
102   EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
103
104   // No packets lost.
105   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
106   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
107   NetworkReceivedPackets();
108
109   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
110                                &recovered_packet_list_));
111
112   // No packets lost, expect complete recovery.
113   EXPECT_TRUE(IsRecoveryComplete());
114 }
115
116 TEST_F(RtpFecTest, FecRecoveryWithLoss) {
117   const int kNumImportantPackets = 0;
118   const bool kUseUnequalProtection = false;
119   const int kNumMediaPackets = 4;
120   uint8_t kProtectionFactor = 60;
121
122   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
123
124   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
125                                  kNumImportantPackets, kUseUnequalProtection,
126                                  webrtc::kFecMaskBursty, &fec_packet_list_));
127
128   // Expect 1 FEC packet.
129   EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
130
131   // 1 media packet lost
132   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
133   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
134   media_loss_mask_[3] = 1;
135   NetworkReceivedPackets();
136
137   EXPECT_EQ(0,
138             fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
139
140   // One packet lost, one FEC packet, expect complete recovery.
141   EXPECT_TRUE(IsRecoveryComplete());
142   FreeRecoveredPacketList();
143
144   // 2 media packets lost.
145   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
146   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
147   media_loss_mask_[1] = 1;
148   media_loss_mask_[3] = 1;
149   NetworkReceivedPackets();
150
151   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
152                                &recovered_packet_list_));
153
154   // 2 packets lost, one FEC packet, cannot get complete recovery.
155   EXPECT_FALSE(IsRecoveryComplete());
156 }
157
158 // Test 50% protection with random mask type: Two cases are considered:
159 // a 50% non-consecutive loss which can be fully recovered, and a 50%
160 // consecutive loss which cannot be fully recovered.
161 TEST_F(RtpFecTest, FecRecoveryWithLoss50percRandomMask) {
162   const int kNumImportantPackets = 0;
163   const bool kUseUnequalProtection = false;
164   const int kNumMediaPackets = 4;
165   const uint8_t kProtectionFactor = 255;
166
167   // Packet Mask for (4,4,0) code, from random mask table.
168   // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0)
169
170   //         media#0   media#1  media#2    media#3
171   // fec#0:    1          1        0          0
172   // fec#1:    1          0        1          0
173   // fec#2:    0          0        1          1
174   // fec#3:    0          1        0          1
175   //
176
177   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
178
179   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
180                                  kNumImportantPackets, kUseUnequalProtection,
181                                  webrtc::kFecMaskRandom, &fec_packet_list_));
182
183   // Expect 4 FEC packets.
184   EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size()));
185
186   // 4 packets lost: 3 media packets (0, 2, 3), and one FEC packet (0) lost.
187   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
188   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
189   fec_loss_mask_[0] = 1;
190   media_loss_mask_[0] = 1;
191   media_loss_mask_[2] = 1;
192   media_loss_mask_[3] = 1;
193   NetworkReceivedPackets();
194
195   EXPECT_EQ(0,
196             fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
197
198   // With media packet#1 and FEC packets #1, #2, #3, expect complete recovery.
199   EXPECT_TRUE(IsRecoveryComplete());
200   FreeRecoveredPacketList();
201
202   // 4 consecutive packets lost: media packets 0, 1, 2, 3.
203   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
204   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
205   media_loss_mask_[0] = 1;
206   media_loss_mask_[1] = 1;
207   media_loss_mask_[2] = 1;
208   media_loss_mask_[3] = 1;
209   NetworkReceivedPackets();
210
211   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
212                                &recovered_packet_list_));
213
214   // Cannot get complete recovery for this loss configuration with random mask.
215   EXPECT_FALSE(IsRecoveryComplete());
216 }
217
218 // Test 50% protection with bursty type: Three cases are considered:
219 // two 50% consecutive losses which can be fully recovered, and one
220 // non-consecutive which cannot be fully recovered.
221 TEST_F(RtpFecTest, FecRecoveryWithLoss50percBurstyMask) {
222   const int kNumImportantPackets = 0;
223   const bool kUseUnequalProtection = false;
224   const int kNumMediaPackets = 4;
225   const uint8_t kProtectionFactor = 255;
226
227   // Packet Mask for (4,4,0) code, from bursty mask table.
228   // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0)
229
230   //         media#0   media#1  media#2    media#3
231   // fec#0:    1          0        0          0
232   // fec#1:    1          1        0          0
233   // fec#2:    0          1        1          0
234   // fec#3:    0          0        1          1
235   //
236
237   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
238
239   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
240                                  kNumImportantPackets, kUseUnequalProtection,
241                                  webrtc::kFecMaskBursty, &fec_packet_list_));
242
243   // Expect 4 FEC packets.
244   EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size()));
245
246   // 4 consecutive packets lost: media packets 0,1,2,3.
247   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
248   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
249   media_loss_mask_[0] = 1;
250   media_loss_mask_[1] = 1;
251   media_loss_mask_[2] = 1;
252   media_loss_mask_[3] = 1;
253   NetworkReceivedPackets();
254
255   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
256                                &recovered_packet_list_));
257
258   // Expect complete recovery for consecutive packet loss <= 50%.
259   EXPECT_TRUE(IsRecoveryComplete());
260   FreeRecoveredPacketList();
261
262   // 4 consecutive packets lost: media packets 1,2, 3, and FEC packet 0.
263   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
264   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
265   fec_loss_mask_[0] = 1;
266   media_loss_mask_[1] = 1;
267   media_loss_mask_[2] = 1;
268   media_loss_mask_[3] = 1;
269   NetworkReceivedPackets();
270
271   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
272                                &recovered_packet_list_));
273
274   // Expect complete recovery for consecutive packet loss <= 50%.
275   EXPECT_TRUE(IsRecoveryComplete());
276   FreeRecoveredPacketList();
277
278   // 4 packets lost (non-consecutive loss): media packets 0, 3, and FEC# 0, 3.
279   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
280   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
281   fec_loss_mask_[0] = 1;
282   fec_loss_mask_[3] = 1;
283   media_loss_mask_[0] = 1;
284   media_loss_mask_[3] = 1;
285   NetworkReceivedPackets();
286
287   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
288                                &recovered_packet_list_));
289
290   // Cannot get complete recovery for this loss configuration.
291   EXPECT_FALSE(IsRecoveryComplete());
292 }
293
294 TEST_F(RtpFecTest, FecRecoveryNoLossUep) {
295   const int kNumImportantPackets = 2;
296   const bool kUseUnequalProtection = true;
297   const int kNumMediaPackets = 4;
298   const uint8_t kProtectionFactor = 60;
299
300   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
301
302   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
303                                  kNumImportantPackets, kUseUnequalProtection,
304                                  webrtc::kFecMaskBursty, &fec_packet_list_));
305
306   // Expect 1 FEC packet.
307   EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
308
309   // No packets lost.
310   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
311   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
312   NetworkReceivedPackets();
313
314   EXPECT_EQ(0,
315             fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
316
317   // No packets lost, expect complete recovery.
318   EXPECT_TRUE(IsRecoveryComplete());
319 }
320
321 TEST_F(RtpFecTest, FecRecoveryWithLossUep) {
322   const int kNumImportantPackets = 2;
323   const bool kUseUnequalProtection = true;
324   const int kNumMediaPackets = 4;
325   const uint8_t kProtectionFactor = 60;
326
327   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
328
329   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
330                                  kNumImportantPackets, kUseUnequalProtection,
331                                  webrtc::kFecMaskBursty, &fec_packet_list_));
332
333   // Expect 1 FEC packet.
334   EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
335
336   // 1 media packet lost.
337   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
338   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
339   media_loss_mask_[3] = 1;
340   NetworkReceivedPackets();
341
342   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
343                                &recovered_packet_list_));
344
345   // One packet lost, one FEC packet, expect complete recovery.
346   EXPECT_TRUE(IsRecoveryComplete());
347   FreeRecoveredPacketList();
348
349   // 2 media packets lost.
350   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
351   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
352   media_loss_mask_[1] = 1;
353   media_loss_mask_[3] = 1;
354   NetworkReceivedPackets();
355
356   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
357                                &recovered_packet_list_));
358
359   // 2 packets lost, one FEC packet, cannot get complete recovery.
360   EXPECT_FALSE(IsRecoveryComplete());
361 }
362
363 // Test 50% protection with random mask type for UEP on.
364 TEST_F(RtpFecTest, FecRecoveryWithLoss50percUepRandomMask) {
365   const int kNumImportantPackets = 1;
366   const bool kUseUnequalProtection = true;
367   const int kNumMediaPackets = 4;
368   const uint8_t kProtectionFactor = 255;
369
370   // Packet Mask for (4,4,1) code, from random mask table.
371   // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 1)
372
373   //         media#0   media#1  media#2    media#3
374   // fec#0:    1          0        0          0
375   // fec#1:    1          1        0          0
376   // fec#2:    1          0        1          1
377   // fec#3:    0          1        1          0
378   //
379
380   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
381
382   EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
383                                  kNumImportantPackets, kUseUnequalProtection,
384                                  webrtc::kFecMaskRandom, &fec_packet_list_));
385
386   // Expect 4 FEC packets.
387   EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size()));
388
389   // 4 packets lost: 3 media packets and FEC packet#1 lost.
390   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
391   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
392   fec_loss_mask_[1] = 1;
393   media_loss_mask_[0] = 1;
394   media_loss_mask_[2] = 1;
395   media_loss_mask_[3] = 1;
396   NetworkReceivedPackets();
397
398   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
399                                &recovered_packet_list_));
400
401   // With media packet#3 and FEC packets #0, #1, #3, expect complete recovery.
402   EXPECT_TRUE(IsRecoveryComplete());
403   FreeRecoveredPacketList();
404
405   // 5 packets lost: 4 media packets and one FEC packet#2 lost.
406   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
407   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
408   fec_loss_mask_[2] = 1;
409   media_loss_mask_[0] = 1;
410   media_loss_mask_[1] = 1;
411   media_loss_mask_[2] = 1;
412   media_loss_mask_[3] = 1;
413   NetworkReceivedPackets();
414
415   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
416                                &recovered_packet_list_));
417
418   // Cannot get complete recovery for this loss configuration.
419   EXPECT_FALSE(IsRecoveryComplete());
420 }
421
422 TEST_F(RtpFecTest, FecRecoveryNonConsecutivePackets) {
423   const int kNumImportantPackets = 0;
424   const bool kUseUnequalProtection = false;
425   const int kNumMediaPackets = 5;
426   uint8_t kProtectionFactor = 60;
427
428   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
429
430   // Create a new temporary packet list for generating FEC packets.
431   // This list should have every other packet removed.
432   PacketList protected_media_packets;
433   int i = 0;
434   for (PacketList::iterator it = media_packet_list_.begin();
435        it != media_packet_list_.end(); ++it, ++i) {
436     if (i % 2 == 0) protected_media_packets.push_back(*it);
437   }
438
439   EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor,
440                                  kNumImportantPackets, kUseUnequalProtection,
441                                  webrtc::kFecMaskBursty, &fec_packet_list_));
442
443   // Expect 1 FEC packet.
444   EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
445
446   // 1 protected media packet lost
447   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
448   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
449   media_loss_mask_[2] = 1;
450   NetworkReceivedPackets();
451
452   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
453                                &recovered_packet_list_));
454
455   // One packet lost, one FEC packet, expect complete recovery.
456   EXPECT_TRUE(IsRecoveryComplete());
457   FreeRecoveredPacketList();
458
459   // Unprotected packet lost.
460   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
461   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
462   media_loss_mask_[1] = 1;
463   NetworkReceivedPackets();
464
465   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
466                                &recovered_packet_list_));
467
468   // Unprotected packet lost. Recovery not possible.
469   EXPECT_FALSE(IsRecoveryComplete());
470   FreeRecoveredPacketList();
471
472   // 2 media packets lost.
473   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
474   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
475   media_loss_mask_[0] = 1;
476   media_loss_mask_[2] = 1;
477   NetworkReceivedPackets();
478
479   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
480                                &recovered_packet_list_));
481
482   // 2 protected packets lost, one FEC packet, cannot get complete recovery.
483   EXPECT_FALSE(IsRecoveryComplete());
484 }
485
486 TEST_F(RtpFecTest, FecRecoveryNonConsecutivePacketsExtension) {
487   const int kNumImportantPackets = 0;
488   const bool kUseUnequalProtection = false;
489   const int kNumMediaPackets = 21;
490   uint8_t kProtectionFactor = 127;
491
492   fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
493
494   // Create a new temporary packet list for generating FEC packets.
495   // This list should have every other packet removed.
496   PacketList protected_media_packets;
497   int i = 0;
498   for (PacketList::iterator it = media_packet_list_.begin();
499        it != media_packet_list_.end(); ++it, ++i) {
500     if (i % 2 == 0) protected_media_packets.push_back(*it);
501   }
502
503   // Zero column insertion will have to extend the size of the packet
504   // mask since the number of actual packets are 21, while the number
505   // of protected packets are 11.
506   EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor,
507                                  kNumImportantPackets, kUseUnequalProtection,
508                                  webrtc::kFecMaskBursty, &fec_packet_list_));
509
510   // Expect 5 FEC packet.
511   EXPECT_EQ(5, static_cast<int>(fec_packet_list_.size()));
512
513   // Last protected media packet lost
514   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
515   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
516   media_loss_mask_[kNumMediaPackets - 1] = 1;
517   NetworkReceivedPackets();
518
519   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
520                                &recovered_packet_list_));
521
522   // One packet lost, one FEC packet, expect complete recovery.
523   EXPECT_TRUE(IsRecoveryComplete());
524   FreeRecoveredPacketList();
525
526   // Last unprotected packet lost.
527   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
528   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
529   media_loss_mask_[kNumMediaPackets - 2] = 1;
530   NetworkReceivedPackets();
531
532   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
533                                &recovered_packet_list_));
534
535   // Unprotected packet lost. Recovery not possible.
536   EXPECT_FALSE(IsRecoveryComplete());
537   FreeRecoveredPacketList();
538
539   // 6 media packets lost.
540   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
541   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
542   media_loss_mask_[kNumMediaPackets - 11] = 1;
543   media_loss_mask_[kNumMediaPackets - 9] = 1;
544   media_loss_mask_[kNumMediaPackets - 7] = 1;
545   media_loss_mask_[kNumMediaPackets - 5] = 1;
546   media_loss_mask_[kNumMediaPackets - 3] = 1;
547   media_loss_mask_[kNumMediaPackets - 1] = 1;
548   NetworkReceivedPackets();
549
550   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
551                                &recovered_packet_list_));
552
553   // 5 protected packets lost, one FEC packet, cannot get complete recovery.
554   EXPECT_FALSE(IsRecoveryComplete());
555 }
556
557 TEST_F(RtpFecTest, FecRecoveryNonConsecutivePacketsWrap) {
558   const int kNumImportantPackets = 0;
559   const bool kUseUnequalProtection = false;
560   const int kNumMediaPackets = 21;
561   uint8_t kProtectionFactor = 127;
562
563   fec_seq_num_ = ConstructMediaPacketsSeqNum(kNumMediaPackets, 0xFFFF - 5);
564
565   // Create a new temporary packet list for generating FEC packets.
566   // This list should have every other packet removed.
567   PacketList protected_media_packets;
568   int i = 0;
569   for (PacketList::iterator it = media_packet_list_.begin();
570        it != media_packet_list_.end(); ++it, ++i) {
571     if (i % 2 == 0) protected_media_packets.push_back(*it);
572   }
573
574   // Zero column insertion will have to extend the size of the packet
575   // mask since the number of actual packets are 21, while the number
576   // of protected packets are 11.
577   EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor,
578                                  kNumImportantPackets, kUseUnequalProtection,
579                                  webrtc::kFecMaskBursty, &fec_packet_list_));
580
581   // Expect 5 FEC packet.
582   EXPECT_EQ(5, static_cast<int>(fec_packet_list_.size()));
583
584   // Last protected media packet lost
585   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
586   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
587   media_loss_mask_[kNumMediaPackets - 1] = 1;
588   NetworkReceivedPackets();
589
590   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
591                                &recovered_packet_list_));
592
593   // One packet lost, one FEC packet, expect complete recovery.
594   EXPECT_TRUE(IsRecoveryComplete());
595   FreeRecoveredPacketList();
596
597   // Last unprotected packet lost.
598   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
599   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
600   media_loss_mask_[kNumMediaPackets - 2] = 1;
601   NetworkReceivedPackets();
602
603   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
604                                &recovered_packet_list_));
605
606   // Unprotected packet lost. Recovery not possible.
607   EXPECT_FALSE(IsRecoveryComplete());
608   FreeRecoveredPacketList();
609
610   // 6 media packets lost.
611   memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
612   memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
613   media_loss_mask_[kNumMediaPackets - 11] = 1;
614   media_loss_mask_[kNumMediaPackets - 9] = 1;
615   media_loss_mask_[kNumMediaPackets - 7] = 1;
616   media_loss_mask_[kNumMediaPackets - 5] = 1;
617   media_loss_mask_[kNumMediaPackets - 3] = 1;
618   media_loss_mask_[kNumMediaPackets - 1] = 1;
619   NetworkReceivedPackets();
620
621   EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
622                                &recovered_packet_list_));
623
624   // 5 protected packets lost, one FEC packet, cannot get complete recovery.
625   EXPECT_FALSE(IsRecoveryComplete());
626 }
627
628 // TODO(marpan): Add more test cases.
629
630 void RtpFecTest::TearDown() {
631   fec_->ResetState(&recovered_packet_list_);
632   delete fec_;
633   FreeRecoveredPacketList();
634   ClearList(&media_packet_list_);
635   EXPECT_TRUE(media_packet_list_.empty());
636 }
637
638 void RtpFecTest::FreeRecoveredPacketList() {
639   ClearList(&recovered_packet_list_);
640 }
641
642 bool RtpFecTest::IsRecoveryComplete() {
643   // Check that the number of media and recovered packets are equal.
644   if (media_packet_list_.size() != recovered_packet_list_.size()) {
645     return false;
646   }
647
648   ForwardErrorCorrection::Packet* media_packet;
649   ForwardErrorCorrection::RecoveredPacket* recovered_packet;
650
651   bool recovery = true;
652
653   PacketList::iterator media_packet_list_item = media_packet_list_.begin();
654   RecoveredPacketList::iterator recovered_packet_list_item =
655       recovered_packet_list_.begin();
656   while (media_packet_list_item != media_packet_list_.end()) {
657     if (recovered_packet_list_item == recovered_packet_list_.end()) {
658       return false;
659     }
660     media_packet = *media_packet_list_item;
661     recovered_packet = *recovered_packet_list_item;
662     if (recovered_packet->pkt->length != media_packet->length) {
663       return false;
664     }
665     if (memcmp(recovered_packet->pkt->data, media_packet->data,
666                media_packet->length) != 0) {
667       return false;
668     }
669     media_packet_list_item++;
670     recovered_packet_list_item++;
671   }
672   return recovery;
673 }
674
675 void RtpFecTest::NetworkReceivedPackets() {
676   const bool kFecPacket = true;
677   ReceivedPackets(media_packet_list_, media_loss_mask_, !kFecPacket);
678   ReceivedPackets(fec_packet_list_, fec_loss_mask_, kFecPacket);
679 }
680
681 void RtpFecTest::ReceivedPackets(const PacketList& packet_list, int* loss_mask,
682                                  bool is_fec) {
683   ForwardErrorCorrection::Packet* packet;
684   ForwardErrorCorrection::ReceivedPacket* received_packet;
685   int seq_num = fec_seq_num_;
686   int packet_idx = 0;
687
688   PacketList::const_iterator packet_list_item = packet_list.begin();
689
690   while (packet_list_item != packet_list.end()) {
691     packet = *packet_list_item;
692     if (loss_mask[packet_idx] == 0) {
693       received_packet = new ForwardErrorCorrection::ReceivedPacket;
694       received_packet->pkt = new ForwardErrorCorrection::Packet;
695       received_packet_list_.push_back(received_packet);
696       received_packet->pkt->length = packet->length;
697       memcpy(received_packet->pkt->data, packet->data, packet->length);
698       received_packet->is_fec = is_fec;
699       if (!is_fec) {
700         // For media packets, the sequence number and marker bit is
701         // obtained from RTP header. These were set in ConstructMediaPackets().
702         received_packet->seq_num =
703             webrtc::ModuleRTPUtility::BufferToUWord16(&packet->data[2]);
704       } else {
705         // The sequence number, marker bit, and ssrc number are defined in the
706         // RTP header of the FEC packet, which is not constructed in this test.
707         // So we set these values below based on the values generated in
708         // ConstructMediaPackets().
709         received_packet->seq_num = seq_num;
710         // The ssrc value for FEC packets is set to the one used for the
711         // media packets in ConstructMediaPackets().
712         received_packet->ssrc = ssrc_;
713       }
714     }
715     packet_idx++;
716     packet_list_item++;
717     // Sequence number of FEC packets are defined as increment by 1 from
718     // last media packet in frame.
719     if (is_fec) seq_num++;
720   }
721 }
722
723 int RtpFecTest::ConstructMediaPacketsSeqNum(int num_media_packets,
724                                             int start_seq_num) {
725   assert(num_media_packets > 0);
726   ForwardErrorCorrection::Packet* media_packet = NULL;
727   int sequence_number = start_seq_num;
728   int time_stamp = rand();
729
730   for (int i = 0; i < num_media_packets; ++i) {
731     media_packet = new ForwardErrorCorrection::Packet;
732     media_packet_list_.push_back(media_packet);
733     media_packet->length = static_cast<uint16_t>(
734         (static_cast<float>(rand()) / RAND_MAX) *
735         (IP_PACKET_SIZE - kRtpHeaderSize - kTransportOverhead -
736          ForwardErrorCorrection::PacketOverhead()));
737
738     if (media_packet->length < kRtpHeaderSize) {
739       media_packet->length = kRtpHeaderSize;
740     }
741     // Generate random values for the first 2 bytes
742     media_packet->data[0] = static_cast<uint8_t>(rand() % 256);
743     media_packet->data[1] = static_cast<uint8_t>(rand() % 256);
744
745     // The first two bits are assumed to be 10 by the FEC encoder.
746     // In fact the FEC decoder will set the two first bits to 10 regardless of
747     // what they actually were. Set the first two bits to 10 so that a memcmp
748     // can be performed for the whole restored packet.
749     media_packet->data[0] |= 0x80;
750     media_packet->data[0] &= 0xbf;
751
752     // FEC is applied to a whole frame.
753     // A frame is signaled by multiple packets without the marker bit set
754     // followed by the last packet of the frame for which the marker bit is set.
755     // Only push one (fake) frame to the FEC.
756     media_packet->data[1] &= 0x7f;
757
758     webrtc::ModuleRTPUtility::AssignUWord16ToBuffer(&media_packet->data[2],
759                                                     sequence_number);
760     webrtc::ModuleRTPUtility::AssignUWord32ToBuffer(&media_packet->data[4],
761                                                     time_stamp);
762     webrtc::ModuleRTPUtility::AssignUWord32ToBuffer(&media_packet->data[8],
763                                                     ssrc_);
764
765     // Generate random values for payload.
766     for (int j = 12; j < media_packet->length; ++j) {
767       media_packet->data[j] = static_cast<uint8_t>(rand() % 256);
768     }
769     sequence_number++;
770   }
771   // Last packet, set marker bit.
772   assert(media_packet != NULL);
773   media_packet->data[1] |= 0x80;
774   return sequence_number;
775 }
776
777 int RtpFecTest::ConstructMediaPackets(int num_media_packets) {
778   return ConstructMediaPacketsSeqNum(num_media_packets, rand());
779 }