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
17using webrtc::ForwardErrorCorrection;
18
19// Minimum RTP header size in bytes.
20const uint8_t kRtpHeaderSize = 12;
21
22// Transport header size in bytes. Assume UDP/IPv4 as a reasonable minimum.
23const uint8_t kTransportOverhead = 28;
24
25// Maximum number of media packets used in the FEC (RFC 5109).
26const uint8_t kMaxNumberMediaPackets = ForwardErrorCorrection::kMaxMediaPackets;
27
28typedef std::list<ForwardErrorCorrection::Packet*> PacketList;
29typedef std::list<ForwardErrorCorrection::ReceivedPacket*> ReceivedPacketList;
30typedef std::list<ForwardErrorCorrection::RecoveredPacket*> RecoveredPacketList;
31
32template <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
41class 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
89TEST_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
116TEST_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// Verify that we don't use an old FEC packet for FEC decoding.
159TEST_F(RtpFecTest, FecRecoveryWithSeqNumGapTwoFrames) {
160  const int kNumImportantPackets = 0;
161  const bool kUseUnequalProtection = false;
162  uint8_t kProtectionFactor = 20;
163
164  // Two frames: first frame (old) with two media packets and 1 FEC packet.
165  // Second frame (new) with 3 media packets, and no FEC packets.
166  //       ---Frame 1----                     ----Frame 2------
167  //  #0(media) #1(media) #2(FEC)     #65535(media) #0(media) #1(media).
168  // If we lose either packet 0 or 1 of second frame, FEC decoding should not
169  // try to decode using "old" FEC packet #2.
170
171  // Construct media packets for first frame, starting at sequence number 0.
172  fec_seq_num_ = ConstructMediaPacketsSeqNum(2, 0);
173
174  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
175                                 kNumImportantPackets, kUseUnequalProtection,
176                                 webrtc::kFecMaskBursty, &fec_packet_list_));
177  // Expect 1 FEC packet.
178  EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
179  // Add FEC packet (seq#2) of this first frame to received list (i.e., assume
180  // the two media packet were lost).
181  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
182  ReceivedPackets(fec_packet_list_, fec_loss_mask_, true);
183
184  // Construct media packets for second frame, with sequence number wrap.
185  ClearList(&media_packet_list_);
186  fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 65535);
187
188  // Expect 3 media packets for this frame.
189  EXPECT_EQ(3, static_cast<int>(media_packet_list_.size()));
190
191  // Second media packet lost (seq#0).
192  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
193  media_loss_mask_[1] = 1;
194  // Add packets #65535, and #1 to received list.
195  ReceivedPackets(media_packet_list_, media_loss_mask_, false);
196
197  EXPECT_EQ(0,
198            fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
199
200  // Expect that no decoding is done to get missing packet (seq#0) of second
201  // frame, using old FEC packet (seq#2) from first (old) frame. So number of
202  // recovered packets is 2, and not equal to number of media packets (=3).
203  EXPECT_EQ(2, static_cast<int>(recovered_packet_list_.size()));
204  EXPECT_TRUE(recovered_packet_list_.size() != media_packet_list_.size());
205  FreeRecoveredPacketList();
206}
207
208// Verify we can still recovery frame if sequence number wrap occurs within
209// the frame and FEC packet following wrap is received after media packets.
210TEST_F(RtpFecTest, FecRecoveryWithSeqNumGapOneFrameRecovery) {
211  const int kNumImportantPackets = 0;
212  const bool kUseUnequalProtection = false;
213  uint8_t kProtectionFactor = 20;
214
215  // One frame, with sequence number wrap in media packets.
216  //         -----Frame 1----
217  //  #65534(media) #65535(media) #0(media) #1(FEC).
218  fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 65534);
219
220  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
221                                 kNumImportantPackets, kUseUnequalProtection,
222                                 webrtc::kFecMaskBursty, &fec_packet_list_));
223
224  // Expect 1 FEC packet.
225  EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
226
227  // Lose one media packet (seq# 65535).
228  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
229  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
230  media_loss_mask_[1] = 1;
231  ReceivedPackets(media_packet_list_, media_loss_mask_, false);
232  // Add FEC packet to received list following the media packets.
233  ReceivedPackets(fec_packet_list_, fec_loss_mask_, true);
234
235  EXPECT_EQ(0,
236            fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
237
238  // Expect 3 media packets in recovered list, and complete recovery.
239  // Wrap-around won't remove FEC packet, as it follows the wrap.
240  EXPECT_EQ(3, static_cast<int>(recovered_packet_list_.size()));
241  EXPECT_TRUE(IsRecoveryComplete());
242  FreeRecoveredPacketList();
243}
244
245// Sequence number wrap occurs within the FEC packets for the frame.
246// In this case we will discard FEC packet and full recovery is not expected.
247// Same problem will occur if wrap is within media packets but FEC packet is
248// received before the media packets. This may be improved if timing information
249// is used to detect old FEC packets.
250// TODO(marpan): Update test if wrap-around handling changes in FEC decoding.
251TEST_F(RtpFecTest, FecRecoveryWithSeqNumGapOneFrameNoRecovery) {
252  const int kNumImportantPackets = 0;
253  const bool kUseUnequalProtection = false;
254  uint8_t kProtectionFactor = 200;
255
256  // 1 frame: 3 media packets and 2 FEC packets.
257  // Sequence number wrap in FEC packets.
258  //           -----Frame 1----
259  // #65532(media) #65533(media) #65534(media) #65535(FEC) #0(FEC).
260  fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 65532);
261
262  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
263                                 kNumImportantPackets, kUseUnequalProtection,
264                                 webrtc::kFecMaskBursty, &fec_packet_list_));
265
266  // Expect 2 FEC packets.
267  EXPECT_EQ(2, static_cast<int>(fec_packet_list_.size()));
268
269  // Lose the last two media packets (seq# 65533, 65534).
270  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
271  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
272  media_loss_mask_[1] = 1;
273  media_loss_mask_[2] = 1;
274  ReceivedPackets(media_packet_list_, media_loss_mask_, false);
275  ReceivedPackets(fec_packet_list_, fec_loss_mask_, true);
276
277  EXPECT_EQ(0,
278            fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
279
280  // The two FEC packets are received and should allow for complete recovery,
281  // but because of the wrap the second FEC packet will be discarded, and only
282  // one media packet is recoverable. So exepct 2 media packets on recovered
283  // list and no complete recovery.
284  EXPECT_EQ(2, static_cast<int>(recovered_packet_list_.size()));
285  EXPECT_TRUE(recovered_packet_list_.size() != media_packet_list_.size());
286  EXPECT_FALSE(IsRecoveryComplete());
287  FreeRecoveredPacketList();
288}
289
290// Verify we can still recovery frame if FEC is received before media packets.
291TEST_F(RtpFecTest, FecRecoveryWithFecOutOfOrder) {
292  const int kNumImportantPackets = 0;
293  const bool kUseUnequalProtection = false;
294  uint8_t kProtectionFactor = 20;
295
296  // One frame: 3 media packets, 1 FEC packet.
297  //         -----Frame 1----
298  //  #0(media) #1(media) #2(media) #3(FEC).
299  fec_seq_num_ = ConstructMediaPacketsSeqNum(3, 0);
300
301  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
302                                 kNumImportantPackets, kUseUnequalProtection,
303                                 webrtc::kFecMaskBursty, &fec_packet_list_));
304
305  // Expect 1 FEC packet.
306  EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
307
308  // Lose one media packet (seq# 1).
309  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
310  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
311  media_loss_mask_[1] = 1;
312  // Add FEC packet to received list before the media packets.
313  ReceivedPackets(fec_packet_list_, fec_loss_mask_, true);
314  // Add media packets to received list.
315  ReceivedPackets(media_packet_list_, media_loss_mask_, false);
316
317  EXPECT_EQ(0,
318            fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
319
320  // Expect 3 media packets in recovered list, and complete recovery.
321  EXPECT_EQ(3, static_cast<int>(recovered_packet_list_.size()));
322  EXPECT_TRUE(IsRecoveryComplete());
323  FreeRecoveredPacketList();
324}
325
326// Test 50% protection with random mask type: Two cases are considered:
327// a 50% non-consecutive loss which can be fully recovered, and a 50%
328// consecutive loss which cannot be fully recovered.
329TEST_F(RtpFecTest, FecRecoveryWithLoss50percRandomMask) {
330  const int kNumImportantPackets = 0;
331  const bool kUseUnequalProtection = false;
332  const int kNumMediaPackets = 4;
333  const uint8_t kProtectionFactor = 255;
334
335  // Packet Mask for (4,4,0) code, from random mask table.
336  // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0)
337
338  //         media#0   media#1  media#2    media#3
339  // fec#0:    1          1        0          0
340  // fec#1:    1          0        1          0
341  // fec#2:    0          0        1          1
342  // fec#3:    0          1        0          1
343  //
344
345  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
346
347  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
348                                 kNumImportantPackets, kUseUnequalProtection,
349                                 webrtc::kFecMaskRandom, &fec_packet_list_));
350
351  // Expect 4 FEC packets.
352  EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size()));
353
354  // 4 packets lost: 3 media packets (0, 2, 3), and one FEC packet (0) lost.
355  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
356  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
357  fec_loss_mask_[0] = 1;
358  media_loss_mask_[0] = 1;
359  media_loss_mask_[2] = 1;
360  media_loss_mask_[3] = 1;
361  NetworkReceivedPackets();
362
363  EXPECT_EQ(0,
364            fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
365
366  // With media packet#1 and FEC packets #1, #2, #3, expect complete recovery.
367  EXPECT_TRUE(IsRecoveryComplete());
368  FreeRecoveredPacketList();
369
370  // 4 consecutive packets lost: media packets 0, 1, 2, 3.
371  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
372  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
373  media_loss_mask_[0] = 1;
374  media_loss_mask_[1] = 1;
375  media_loss_mask_[2] = 1;
376  media_loss_mask_[3] = 1;
377  NetworkReceivedPackets();
378
379  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
380                               &recovered_packet_list_));
381
382  // Cannot get complete recovery for this loss configuration with random mask.
383  EXPECT_FALSE(IsRecoveryComplete());
384}
385
386// Test 50% protection with bursty type: Three cases are considered:
387// two 50% consecutive losses which can be fully recovered, and one
388// non-consecutive which cannot be fully recovered.
389TEST_F(RtpFecTest, FecRecoveryWithLoss50percBurstyMask) {
390  const int kNumImportantPackets = 0;
391  const bool kUseUnequalProtection = false;
392  const int kNumMediaPackets = 4;
393  const uint8_t kProtectionFactor = 255;
394
395  // Packet Mask for (4,4,0) code, from bursty mask table.
396  // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 0)
397
398  //         media#0   media#1  media#2    media#3
399  // fec#0:    1          0        0          0
400  // fec#1:    1          1        0          0
401  // fec#2:    0          1        1          0
402  // fec#3:    0          0        1          1
403  //
404
405  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
406
407  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
408                                 kNumImportantPackets, kUseUnequalProtection,
409                                 webrtc::kFecMaskBursty, &fec_packet_list_));
410
411  // Expect 4 FEC packets.
412  EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size()));
413
414  // 4 consecutive packets lost: media packets 0,1,2,3.
415  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
416  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
417  media_loss_mask_[0] = 1;
418  media_loss_mask_[1] = 1;
419  media_loss_mask_[2] = 1;
420  media_loss_mask_[3] = 1;
421  NetworkReceivedPackets();
422
423  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
424                               &recovered_packet_list_));
425
426  // Expect complete recovery for consecutive packet loss <= 50%.
427  EXPECT_TRUE(IsRecoveryComplete());
428  FreeRecoveredPacketList();
429
430  // 4 consecutive packets lost: media packets 1,2, 3, and FEC packet 0.
431  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
432  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
433  fec_loss_mask_[0] = 1;
434  media_loss_mask_[1] = 1;
435  media_loss_mask_[2] = 1;
436  media_loss_mask_[3] = 1;
437  NetworkReceivedPackets();
438
439  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
440                               &recovered_packet_list_));
441
442  // Expect complete recovery for consecutive packet loss <= 50%.
443  EXPECT_TRUE(IsRecoveryComplete());
444  FreeRecoveredPacketList();
445
446  // 4 packets lost (non-consecutive loss): media packets 0, 3, and FEC# 0, 3.
447  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
448  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
449  fec_loss_mask_[0] = 1;
450  fec_loss_mask_[3] = 1;
451  media_loss_mask_[0] = 1;
452  media_loss_mask_[3] = 1;
453  NetworkReceivedPackets();
454
455  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
456                               &recovered_packet_list_));
457
458  // Cannot get complete recovery for this loss configuration.
459  EXPECT_FALSE(IsRecoveryComplete());
460}
461
462TEST_F(RtpFecTest, FecRecoveryNoLossUep) {
463  const int kNumImportantPackets = 2;
464  const bool kUseUnequalProtection = true;
465  const int kNumMediaPackets = 4;
466  const uint8_t kProtectionFactor = 60;
467
468  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
469
470  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
471                                 kNumImportantPackets, kUseUnequalProtection,
472                                 webrtc::kFecMaskBursty, &fec_packet_list_));
473
474  // Expect 1 FEC packet.
475  EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
476
477  // No packets lost.
478  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
479  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
480  NetworkReceivedPackets();
481
482  EXPECT_EQ(0,
483            fec_->DecodeFEC(&received_packet_list_, &recovered_packet_list_));
484
485  // No packets lost, expect complete recovery.
486  EXPECT_TRUE(IsRecoveryComplete());
487}
488
489TEST_F(RtpFecTest, FecRecoveryWithLossUep) {
490  const int kNumImportantPackets = 2;
491  const bool kUseUnequalProtection = true;
492  const int kNumMediaPackets = 4;
493  const uint8_t kProtectionFactor = 60;
494
495  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
496
497  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
498                                 kNumImportantPackets, kUseUnequalProtection,
499                                 webrtc::kFecMaskBursty, &fec_packet_list_));
500
501  // Expect 1 FEC packet.
502  EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
503
504  // 1 media packet lost.
505  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
506  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
507  media_loss_mask_[3] = 1;
508  NetworkReceivedPackets();
509
510  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
511                               &recovered_packet_list_));
512
513  // One packet lost, one FEC packet, expect complete recovery.
514  EXPECT_TRUE(IsRecoveryComplete());
515  FreeRecoveredPacketList();
516
517  // 2 media packets lost.
518  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
519  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
520  media_loss_mask_[1] = 1;
521  media_loss_mask_[3] = 1;
522  NetworkReceivedPackets();
523
524  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
525                               &recovered_packet_list_));
526
527  // 2 packets lost, one FEC packet, cannot get complete recovery.
528  EXPECT_FALSE(IsRecoveryComplete());
529}
530
531// Test 50% protection with random mask type for UEP on.
532TEST_F(RtpFecTest, FecRecoveryWithLoss50percUepRandomMask) {
533  const int kNumImportantPackets = 1;
534  const bool kUseUnequalProtection = true;
535  const int kNumMediaPackets = 4;
536  const uint8_t kProtectionFactor = 255;
537
538  // Packet Mask for (4,4,1) code, from random mask table.
539  // (kNumMediaPackets = 4; num_fec_packets = 4, kNumImportantPackets = 1)
540
541  //         media#0   media#1  media#2    media#3
542  // fec#0:    1          0        0          0
543  // fec#1:    1          1        0          0
544  // fec#2:    1          0        1          1
545  // fec#3:    0          1        1          0
546  //
547
548  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
549
550  EXPECT_EQ(0, fec_->GenerateFEC(media_packet_list_, kProtectionFactor,
551                                 kNumImportantPackets, kUseUnequalProtection,
552                                 webrtc::kFecMaskRandom, &fec_packet_list_));
553
554  // Expect 4 FEC packets.
555  EXPECT_EQ(4, static_cast<int>(fec_packet_list_.size()));
556
557  // 4 packets lost: 3 media packets and FEC packet#1 lost.
558  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
559  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
560  fec_loss_mask_[1] = 1;
561  media_loss_mask_[0] = 1;
562  media_loss_mask_[2] = 1;
563  media_loss_mask_[3] = 1;
564  NetworkReceivedPackets();
565
566  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
567                               &recovered_packet_list_));
568
569  // With media packet#3 and FEC packets #0, #1, #3, expect complete recovery.
570  EXPECT_TRUE(IsRecoveryComplete());
571  FreeRecoveredPacketList();
572
573  // 5 packets lost: 4 media packets and one FEC packet#2 lost.
574  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
575  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
576  fec_loss_mask_[2] = 1;
577  media_loss_mask_[0] = 1;
578  media_loss_mask_[1] = 1;
579  media_loss_mask_[2] = 1;
580  media_loss_mask_[3] = 1;
581  NetworkReceivedPackets();
582
583  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
584                               &recovered_packet_list_));
585
586  // Cannot get complete recovery for this loss configuration.
587  EXPECT_FALSE(IsRecoveryComplete());
588}
589
590TEST_F(RtpFecTest, FecRecoveryNonConsecutivePackets) {
591  const int kNumImportantPackets = 0;
592  const bool kUseUnequalProtection = false;
593  const int kNumMediaPackets = 5;
594  uint8_t kProtectionFactor = 60;
595
596  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
597
598  // Create a new temporary packet list for generating FEC packets.
599  // This list should have every other packet removed.
600  PacketList protected_media_packets;
601  int i = 0;
602  for (PacketList::iterator it = media_packet_list_.begin();
603       it != media_packet_list_.end(); ++it, ++i) {
604    if (i % 2 == 0) protected_media_packets.push_back(*it);
605  }
606
607  EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor,
608                                 kNumImportantPackets, kUseUnequalProtection,
609                                 webrtc::kFecMaskBursty, &fec_packet_list_));
610
611  // Expect 1 FEC packet.
612  EXPECT_EQ(1, static_cast<int>(fec_packet_list_.size()));
613
614  // 1 protected media packet lost
615  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
616  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
617  media_loss_mask_[2] = 1;
618  NetworkReceivedPackets();
619
620  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
621                               &recovered_packet_list_));
622
623  // One packet lost, one FEC packet, expect complete recovery.
624  EXPECT_TRUE(IsRecoveryComplete());
625  FreeRecoveredPacketList();
626
627  // Unprotected packet lost.
628  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
629  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
630  media_loss_mask_[1] = 1;
631  NetworkReceivedPackets();
632
633  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
634                               &recovered_packet_list_));
635
636  // Unprotected packet lost. Recovery not possible.
637  EXPECT_FALSE(IsRecoveryComplete());
638  FreeRecoveredPacketList();
639
640  // 2 media packets lost.
641  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
642  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
643  media_loss_mask_[0] = 1;
644  media_loss_mask_[2] = 1;
645  NetworkReceivedPackets();
646
647  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
648                               &recovered_packet_list_));
649
650  // 2 protected packets lost, one FEC packet, cannot get complete recovery.
651  EXPECT_FALSE(IsRecoveryComplete());
652}
653
654TEST_F(RtpFecTest, FecRecoveryNonConsecutivePacketsExtension) {
655  const int kNumImportantPackets = 0;
656  const bool kUseUnequalProtection = false;
657  const int kNumMediaPackets = 21;
658  uint8_t kProtectionFactor = 127;
659
660  fec_seq_num_ = ConstructMediaPackets(kNumMediaPackets);
661
662  // Create a new temporary packet list for generating FEC packets.
663  // This list should have every other packet removed.
664  PacketList protected_media_packets;
665  int i = 0;
666  for (PacketList::iterator it = media_packet_list_.begin();
667       it != media_packet_list_.end(); ++it, ++i) {
668    if (i % 2 == 0) protected_media_packets.push_back(*it);
669  }
670
671  // Zero column insertion will have to extend the size of the packet
672  // mask since the number of actual packets are 21, while the number
673  // of protected packets are 11.
674  EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor,
675                                 kNumImportantPackets, kUseUnequalProtection,
676                                 webrtc::kFecMaskBursty, &fec_packet_list_));
677
678  // Expect 5 FEC packet.
679  EXPECT_EQ(5, static_cast<int>(fec_packet_list_.size()));
680
681  // Last protected media packet lost
682  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
683  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
684  media_loss_mask_[kNumMediaPackets - 1] = 1;
685  NetworkReceivedPackets();
686
687  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
688                               &recovered_packet_list_));
689
690  // One packet lost, one FEC packet, expect complete recovery.
691  EXPECT_TRUE(IsRecoveryComplete());
692  FreeRecoveredPacketList();
693
694  // Last unprotected packet lost.
695  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
696  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
697  media_loss_mask_[kNumMediaPackets - 2] = 1;
698  NetworkReceivedPackets();
699
700  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
701                               &recovered_packet_list_));
702
703  // Unprotected packet lost. Recovery not possible.
704  EXPECT_FALSE(IsRecoveryComplete());
705  FreeRecoveredPacketList();
706
707  // 6 media packets lost.
708  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
709  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
710  media_loss_mask_[kNumMediaPackets - 11] = 1;
711  media_loss_mask_[kNumMediaPackets - 9] = 1;
712  media_loss_mask_[kNumMediaPackets - 7] = 1;
713  media_loss_mask_[kNumMediaPackets - 5] = 1;
714  media_loss_mask_[kNumMediaPackets - 3] = 1;
715  media_loss_mask_[kNumMediaPackets - 1] = 1;
716  NetworkReceivedPackets();
717
718  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
719                               &recovered_packet_list_));
720
721  // 5 protected packets lost, one FEC packet, cannot get complete recovery.
722  EXPECT_FALSE(IsRecoveryComplete());
723}
724
725TEST_F(RtpFecTest, FecRecoveryNonConsecutivePacketsWrap) {
726  const int kNumImportantPackets = 0;
727  const bool kUseUnequalProtection = false;
728  const int kNumMediaPackets = 21;
729  uint8_t kProtectionFactor = 127;
730
731  fec_seq_num_ = ConstructMediaPacketsSeqNum(kNumMediaPackets, 0xFFFF - 5);
732
733  // Create a new temporary packet list for generating FEC packets.
734  // This list should have every other packet removed.
735  PacketList protected_media_packets;
736  int i = 0;
737  for (PacketList::iterator it = media_packet_list_.begin();
738       it != media_packet_list_.end(); ++it, ++i) {
739    if (i % 2 == 0) protected_media_packets.push_back(*it);
740  }
741
742  // Zero column insertion will have to extend the size of the packet
743  // mask since the number of actual packets are 21, while the number
744  // of protected packets are 11.
745  EXPECT_EQ(0, fec_->GenerateFEC(protected_media_packets, kProtectionFactor,
746                                 kNumImportantPackets, kUseUnequalProtection,
747                                 webrtc::kFecMaskBursty, &fec_packet_list_));
748
749  // Expect 5 FEC packet.
750  EXPECT_EQ(5, static_cast<int>(fec_packet_list_.size()));
751
752  // Last protected media packet lost
753  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
754  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
755  media_loss_mask_[kNumMediaPackets - 1] = 1;
756  NetworkReceivedPackets();
757
758  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
759                               &recovered_packet_list_));
760
761  // One packet lost, one FEC packet, expect complete recovery.
762  EXPECT_TRUE(IsRecoveryComplete());
763  FreeRecoveredPacketList();
764
765  // Last unprotected packet lost.
766  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
767  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
768  media_loss_mask_[kNumMediaPackets - 2] = 1;
769  NetworkReceivedPackets();
770
771  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
772                               &recovered_packet_list_));
773
774  // Unprotected packet lost. Recovery not possible.
775  EXPECT_FALSE(IsRecoveryComplete());
776  FreeRecoveredPacketList();
777
778  // 6 media packets lost.
779  memset(media_loss_mask_, 0, sizeof(media_loss_mask_));
780  memset(fec_loss_mask_, 0, sizeof(fec_loss_mask_));
781  media_loss_mask_[kNumMediaPackets - 11] = 1;
782  media_loss_mask_[kNumMediaPackets - 9] = 1;
783  media_loss_mask_[kNumMediaPackets - 7] = 1;
784  media_loss_mask_[kNumMediaPackets - 5] = 1;
785  media_loss_mask_[kNumMediaPackets - 3] = 1;
786  media_loss_mask_[kNumMediaPackets - 1] = 1;
787  NetworkReceivedPackets();
788
789  EXPECT_EQ(0, fec_->DecodeFEC(&received_packet_list_,
790                               &recovered_packet_list_));
791
792  // 5 protected packets lost, one FEC packet, cannot get complete recovery.
793  EXPECT_FALSE(IsRecoveryComplete());
794}
795
796void RtpFecTest::TearDown() {
797  fec_->ResetState(&recovered_packet_list_);
798  delete fec_;
799  FreeRecoveredPacketList();
800  ClearList(&media_packet_list_);
801  EXPECT_TRUE(media_packet_list_.empty());
802}
803
804void RtpFecTest::FreeRecoveredPacketList() {
805  ClearList(&recovered_packet_list_);
806}
807
808bool RtpFecTest::IsRecoveryComplete() {
809  // Check that the number of media and recovered packets are equal.
810  if (media_packet_list_.size() != recovered_packet_list_.size()) {
811    return false;
812  }
813
814  ForwardErrorCorrection::Packet* media_packet;
815  ForwardErrorCorrection::RecoveredPacket* recovered_packet;
816
817  bool recovery = true;
818
819  PacketList::iterator media_packet_list_item = media_packet_list_.begin();
820  RecoveredPacketList::iterator recovered_packet_list_item =
821      recovered_packet_list_.begin();
822  while (media_packet_list_item != media_packet_list_.end()) {
823    if (recovered_packet_list_item == recovered_packet_list_.end()) {
824      return false;
825    }
826    media_packet = *media_packet_list_item;
827    recovered_packet = *recovered_packet_list_item;
828    if (recovered_packet->pkt->length != media_packet->length) {
829      return false;
830    }
831    if (memcmp(recovered_packet->pkt->data, media_packet->data,
832               media_packet->length) != 0) {
833      return false;
834    }
835    media_packet_list_item++;
836    recovered_packet_list_item++;
837  }
838  return recovery;
839}
840
841void RtpFecTest::NetworkReceivedPackets() {
842  const bool kFecPacket = true;
843  ReceivedPackets(media_packet_list_, media_loss_mask_, !kFecPacket);
844  ReceivedPackets(fec_packet_list_, fec_loss_mask_, kFecPacket);
845}
846
847void RtpFecTest::ReceivedPackets(const PacketList& packet_list, int* loss_mask,
848                                 bool is_fec) {
849  ForwardErrorCorrection::Packet* packet;
850  ForwardErrorCorrection::ReceivedPacket* received_packet;
851  int seq_num = fec_seq_num_;
852  int packet_idx = 0;
853
854  PacketList::const_iterator packet_list_item = packet_list.begin();
855
856  while (packet_list_item != packet_list.end()) {
857    packet = *packet_list_item;
858    if (loss_mask[packet_idx] == 0) {
859      received_packet = new ForwardErrorCorrection::ReceivedPacket;
860      received_packet->pkt = new ForwardErrorCorrection::Packet;
861      received_packet_list_.push_back(received_packet);
862      received_packet->pkt->length = packet->length;
863      memcpy(received_packet->pkt->data, packet->data, packet->length);
864      received_packet->is_fec = is_fec;
865      if (!is_fec) {
866        // For media packets, the sequence number and marker bit is
867        // obtained from RTP header. These were set in ConstructMediaPackets().
868        received_packet->seq_num =
869            webrtc::RtpUtility::BufferToUWord16(&packet->data[2]);
870      } else {
871        // The sequence number, marker bit, and ssrc number are defined in the
872        // RTP header of the FEC packet, which is not constructed in this test.
873        // So we set these values below based on the values generated in
874        // ConstructMediaPackets().
875        received_packet->seq_num = seq_num;
876        // The ssrc value for FEC packets is set to the one used for the
877        // media packets in ConstructMediaPackets().
878        received_packet->ssrc = ssrc_;
879      }
880    }
881    packet_idx++;
882    packet_list_item++;
883    // Sequence number of FEC packets are defined as increment by 1 from
884    // last media packet in frame.
885    if (is_fec) seq_num++;
886  }
887}
888
889int RtpFecTest::ConstructMediaPacketsSeqNum(int num_media_packets,
890                                            int start_seq_num) {
891  assert(num_media_packets > 0);
892  ForwardErrorCorrection::Packet* media_packet = NULL;
893  int sequence_number = start_seq_num;
894  int time_stamp = rand();
895
896  for (int i = 0; i < num_media_packets; ++i) {
897    media_packet = new ForwardErrorCorrection::Packet;
898    media_packet_list_.push_back(media_packet);
899    media_packet->length = static_cast<uint16_t>(
900        (static_cast<float>(rand()) / RAND_MAX) *
901        (IP_PACKET_SIZE - kRtpHeaderSize - kTransportOverhead -
902         ForwardErrorCorrection::PacketOverhead()));
903
904    if (media_packet->length < kRtpHeaderSize) {
905      media_packet->length = kRtpHeaderSize;
906    }
907    // Generate random values for the first 2 bytes
908    media_packet->data[0] = static_cast<uint8_t>(rand() % 256);
909    media_packet->data[1] = static_cast<uint8_t>(rand() % 256);
910
911    // The first two bits are assumed to be 10 by the FEC encoder.
912    // In fact the FEC decoder will set the two first bits to 10 regardless of
913    // what they actually were. Set the first two bits to 10 so that a memcmp
914    // can be performed for the whole restored packet.
915    media_packet->data[0] |= 0x80;
916    media_packet->data[0] &= 0xbf;
917
918    // FEC is applied to a whole frame.
919    // A frame is signaled by multiple packets without the marker bit set
920    // followed by the last packet of the frame for which the marker bit is set.
921    // Only push one (fake) frame to the FEC.
922    media_packet->data[1] &= 0x7f;
923
924    webrtc::RtpUtility::AssignUWord16ToBuffer(&media_packet->data[2],
925                                              sequence_number);
926    webrtc::RtpUtility::AssignUWord32ToBuffer(&media_packet->data[4],
927                                              time_stamp);
928    webrtc::RtpUtility::AssignUWord32ToBuffer(&media_packet->data[8], ssrc_);
929
930    // Generate random values for payload.
931    for (int j = 12; j < media_packet->length; ++j) {
932      media_packet->data[j] = static_cast<uint8_t>(rand() % 256);
933    }
934    sequence_number++;
935  }
936  // Last packet, set marker bit.
937  assert(media_packet != NULL);
938  media_packet->data[1] |= 0x80;
939  return sequence_number;
940}
941
942int RtpFecTest::ConstructMediaPackets(int num_media_packets) {
943  return ConstructMediaPacketsSeqNum(num_media_packets, rand());
944}
945