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 <string.h>
12
13#include <list>
14
15#include "testing/gmock/include/gmock/gmock.h"
16#include "testing/gtest/include/gtest/gtest.h"
17#include "webrtc/base/scoped_ptr.h"
18#include "webrtc/modules/rtp_rtcp/include/fec_receiver.h"
19#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
20#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
21#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
22#include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h"
23#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
24
25using ::testing::_;
26using ::testing::Args;
27using ::testing::ElementsAreArray;
28using ::testing::Return;
29
30namespace webrtc {
31
32class ReceiverFecTest : public ::testing::Test {
33 protected:
34  virtual void SetUp() {
35    fec_.reset(new ForwardErrorCorrection());
36    receiver_fec_.reset(FecReceiver::Create(&rtp_data_callback_));
37    generator_.reset(new FrameGenerator());
38  }
39
40  void GenerateFEC(std::list<Packet*>* media_packets,
41                   std::list<Packet*>* fec_packets,
42                   unsigned int num_fec_packets) {
43    uint8_t protection_factor = num_fec_packets * 255 / media_packets->size();
44    EXPECT_EQ(0, fec_->GenerateFEC(*media_packets, protection_factor,
45                                   0, false, kFecMaskBursty, fec_packets));
46    ASSERT_EQ(num_fec_packets, fec_packets->size());
47  }
48
49  void GenerateFrame(int num_media_packets, int frame_offset,
50                     std::list<RtpPacket*>* media_rtp_packets,
51                     std::list<Packet*>* media_packets) {
52    generator_->NewFrame(num_media_packets);
53    for (int i = 0; i < num_media_packets; ++i) {
54      media_rtp_packets->push_back(
55          generator_->NextPacket(frame_offset + i, kRtpHeaderSize + 10));
56      media_packets->push_back(media_rtp_packets->back());
57    }
58  }
59
60  void VerifyReconstructedMediaPacket(const RtpPacket* packet, int times) {
61    // Verify that the content of the reconstructed packet is equal to the
62    // content of |packet|, and that the same content is received |times| number
63    // of times in a row.
64    EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet->length))
65        .With(Args<0, 1>(ElementsAreArray(packet->data,
66                                          packet->length)))
67        .Times(times).WillRepeatedly(Return(true));
68  }
69
70  void BuildAndAddRedMediaPacket(RtpPacket* packet) {
71    RtpPacket* red_packet = generator_->BuildMediaRedPacket(packet);
72    EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
73                     red_packet->header.header, red_packet->data,
74                     red_packet->length, kFecPayloadType));
75    delete red_packet;
76  }
77
78  void BuildAndAddRedFecPacket(Packet* packet) {
79    RtpPacket* red_packet = generator_->BuildFecRedPacket(packet);
80    EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
81                     red_packet->header.header, red_packet->data,
82                     red_packet->length, kFecPayloadType));
83    delete red_packet;
84  }
85
86  void InjectGarbagePacketLength(size_t fec_garbage_offset);
87  static void SurvivesMaliciousPacket(const uint8_t* data,
88                                      size_t length,
89                                      uint8_t ulpfec_payload_type);
90
91  MockRtpData rtp_data_callback_;
92  rtc::scoped_ptr<ForwardErrorCorrection> fec_;
93  rtc::scoped_ptr<FecReceiver> receiver_fec_;
94  rtc::scoped_ptr<FrameGenerator> generator_;
95};
96
97void DeletePackets(std::list<Packet*>* packets) {
98  while (!packets->empty()) {
99    delete packets->front();
100    packets->pop_front();
101  }
102}
103
104TEST_F(ReceiverFecTest, TwoMediaOneFec) {
105  const unsigned int kNumFecPackets = 1u;
106  std::list<RtpPacket*> media_rtp_packets;
107  std::list<Packet*> media_packets;
108  GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
109  std::list<Packet*> fec_packets;
110  GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
111
112  // Recovery
113  std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
114  BuildAndAddRedMediaPacket(*it);
115  VerifyReconstructedMediaPacket(*it, 1);
116  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
117  // Drop one media packet.
118  std::list<Packet*>::iterator fec_it = fec_packets.begin();
119  BuildAndAddRedFecPacket(*fec_it);
120  ++it;
121  VerifyReconstructedMediaPacket(*it, 1);
122  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
123
124  FecPacketCounter counter = receiver_fec_->GetPacketCounter();
125  EXPECT_EQ(2U, counter.num_packets);
126  EXPECT_EQ(1U, counter.num_fec_packets);
127  EXPECT_EQ(1U, counter.num_recovered_packets);
128
129  DeletePackets(&media_packets);
130}
131
132void ReceiverFecTest::InjectGarbagePacketLength(size_t fec_garbage_offset) {
133  EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
134      .WillRepeatedly(Return(true));
135
136  const unsigned int kNumFecPackets = 1u;
137  std::list<RtpPacket*> media_rtp_packets;
138  std::list<Packet*> media_packets;
139  GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
140  std::list<Packet*> fec_packets;
141  GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
142  ByteWriter<uint16_t>::WriteBigEndian(
143      &fec_packets.front()->data[fec_garbage_offset], 0x4711);
144
145  // Inject first media packet, then first FEC packet, skipping the second media
146  // packet to cause a recovery from the FEC packet.
147  BuildAndAddRedMediaPacket(media_rtp_packets.front());
148  BuildAndAddRedFecPacket(fec_packets.front());
149  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
150
151  FecPacketCounter counter = receiver_fec_->GetPacketCounter();
152  EXPECT_EQ(2u, counter.num_packets);
153  EXPECT_EQ(1u, counter.num_fec_packets);
154  EXPECT_EQ(0u, counter.num_recovered_packets);
155
156  DeletePackets(&media_packets);
157}
158
159TEST_F(ReceiverFecTest, InjectGarbageFecHeaderLengthRecovery) {
160  // Byte offset 8 is the 'length recovery' field of the FEC header.
161  InjectGarbagePacketLength(8);
162}
163
164TEST_F(ReceiverFecTest, InjectGarbageFecLevelHeaderProtectionLength) {
165  // Byte offset 10 is the 'protection length' field in the first FEC level
166  // header.
167  InjectGarbagePacketLength(10);
168}
169
170TEST_F(ReceiverFecTest, TwoMediaTwoFec) {
171  const unsigned int kNumFecPackets = 2u;
172  std::list<RtpPacket*> media_rtp_packets;
173  std::list<Packet*> media_packets;
174  GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
175  std::list<Packet*> fec_packets;
176  GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
177
178  // Recovery
179  // Drop both media packets.
180  std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
181  std::list<Packet*>::iterator fec_it = fec_packets.begin();
182  BuildAndAddRedFecPacket(*fec_it);
183  VerifyReconstructedMediaPacket(*it, 1);
184  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
185  ++fec_it;
186  BuildAndAddRedFecPacket(*fec_it);
187  ++it;
188  VerifyReconstructedMediaPacket(*it, 1);
189  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
190
191  DeletePackets(&media_packets);
192}
193
194TEST_F(ReceiverFecTest, TwoFramesOneFec) {
195  const unsigned int kNumFecPackets = 1u;
196  std::list<RtpPacket*> media_rtp_packets;
197  std::list<Packet*> media_packets;
198  GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
199  GenerateFrame(1, 1, &media_rtp_packets, &media_packets);
200  std::list<Packet*> fec_packets;
201  GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
202
203  // Recovery
204  std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
205  BuildAndAddRedMediaPacket(media_rtp_packets.front());
206  VerifyReconstructedMediaPacket(*it, 1);
207  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
208  // Drop one media packet.
209  BuildAndAddRedFecPacket(fec_packets.front());
210  ++it;
211  VerifyReconstructedMediaPacket(*it, 1);
212  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
213
214  DeletePackets(&media_packets);
215}
216
217TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) {
218  const unsigned int kNumFecPackets = 1u;
219  std::list<RtpPacket*> media_rtp_packets;
220  std::list<Packet*> media_packets;
221  GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
222  GenerateFrame(2, 1, &media_rtp_packets, &media_packets);
223
224  std::list<Packet*> fec_packets;
225  GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
226
227  // Recovery
228  std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
229  BuildAndAddRedMediaPacket(*it);  // First frame: one packet.
230  VerifyReconstructedMediaPacket(*it, 1);
231  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
232  ++it;
233  BuildAndAddRedMediaPacket(*it);  // First packet of second frame.
234  VerifyReconstructedMediaPacket(*it, 1);
235  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
236
237  DeletePackets(&media_packets);
238}
239
240TEST_F(ReceiverFecTest, MaxFramesOneFec) {
241  const unsigned int kNumFecPackets = 1u;
242  const unsigned int kNumMediaPackets = 48u;
243  std::list<RtpPacket*> media_rtp_packets;
244  std::list<Packet*> media_packets;
245  for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
246    GenerateFrame(1, i, &media_rtp_packets, &media_packets);
247  }
248  std::list<Packet*> fec_packets;
249  GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
250
251  // Recovery
252  std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
253  ++it;  // Drop first packet.
254  for (; it != media_rtp_packets.end(); ++it) {
255    BuildAndAddRedMediaPacket(*it);
256    VerifyReconstructedMediaPacket(*it, 1);
257    EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
258  }
259  BuildAndAddRedFecPacket(fec_packets.front());
260  it = media_rtp_packets.begin();
261  VerifyReconstructedMediaPacket(*it, 1);
262  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
263
264  DeletePackets(&media_packets);
265}
266
267TEST_F(ReceiverFecTest, TooManyFrames) {
268  const unsigned int kNumFecPackets = 1u;
269  const unsigned int kNumMediaPackets = 49u;
270  std::list<RtpPacket*> media_rtp_packets;
271  std::list<Packet*> media_packets;
272  for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
273    GenerateFrame(1, i, &media_rtp_packets, &media_packets);
274  }
275  std::list<Packet*> fec_packets;
276  EXPECT_EQ(-1, fec_->GenerateFEC(media_packets,
277                                  kNumFecPackets * 255 / kNumMediaPackets, 0,
278                                  false, kFecMaskBursty, &fec_packets));
279
280  DeletePackets(&media_packets);
281}
282
283TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) {
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);
295
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();
301
302  // Fill the FEC decoder. No packets should be dropped.
303  const unsigned int kNumMediaPacketsBatch2 = 46u;
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);
308  }
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());
315  }
316
317  // Add the delayed FEC packet. One packet should be reconstructed.
318  BuildAndAddRedFecPacket(delayed_fec);
319  EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
320      .Times(1).WillRepeatedly(Return(true));
321  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
322
323  DeletePackets(&media_packets_batch1);
324  DeletePackets(&media_packets_batch2);
325}
326
327TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) {
328  // 1 frame with 2 media packets and one FEC packet. One media packet missing.
329  // Delay the FEC packet.
330  Packet* delayed_fec = NULL;
331  const unsigned int kNumFecPacketsBatch1 = 1u;
332  const unsigned int kNumMediaPacketsBatch1 = 2u;
333  std::list<RtpPacket*> media_rtp_packets_batch1;
334  std::list<Packet*> media_packets_batch1;
335  GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
336                &media_packets_batch1);
337  std::list<Packet*> fec_packets;
338  GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
339
340  BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
341  EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
342      .Times(1).WillRepeatedly(Return(true));
343  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
344  delayed_fec = fec_packets.front();
345
346  // Fill the FEC decoder and force the last packet to be dropped.
347  const unsigned int kNumMediaPacketsBatch2 = 48u;
348  std::list<RtpPacket*> media_rtp_packets_batch2;
349  std::list<Packet*> media_packets_batch2;
350  for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
351    GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
352  }
353  for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
354       it != media_rtp_packets_batch2.end(); ++it) {
355    BuildAndAddRedMediaPacket(*it);
356    EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
357        .Times(1).WillRepeatedly(Return(true));
358    EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
359  }
360
361  // Add the delayed FEC packet. No packet should be reconstructed since the
362  // first media packet of that frame has been dropped due to being too old.
363  BuildAndAddRedFecPacket(delayed_fec);
364  EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
365      .Times(0);
366  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
367
368  DeletePackets(&media_packets_batch1);
369  DeletePackets(&media_packets_batch2);
370}
371
372TEST_F(ReceiverFecTest, OldFecPacketDropped) {
373  // 49 frames with 2 media packets and one FEC packet. All media packets
374  // missing.
375  const unsigned int kNumMediaPackets = 49 * 2;
376  std::list<RtpPacket*> media_rtp_packets;
377  std::list<Packet*> media_packets;
378  for (unsigned int i = 0; i < kNumMediaPackets / 2; ++i) {
379    std::list<RtpPacket*> frame_media_rtp_packets;
380    std::list<Packet*> frame_media_packets;
381    std::list<Packet*> fec_packets;
382    GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets);
383    GenerateFEC(&frame_media_packets, &fec_packets, 1);
384    for (std::list<Packet*>::iterator it = fec_packets.begin();
385         it != fec_packets.end(); ++it) {
386      // Only FEC packets inserted. No packets recoverable at this time.
387      BuildAndAddRedFecPacket(*it);
388      EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
389          .Times(0);
390      EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
391    }
392    media_packets.insert(media_packets.end(), frame_media_packets.begin(),
393                         frame_media_packets.end());
394    media_rtp_packets.insert(media_rtp_packets.end(),
395                             frame_media_rtp_packets.begin(),
396                             frame_media_rtp_packets.end());
397  }
398  // Insert the oldest media packet. The corresponding FEC packet is too old
399  // and should've been dropped. Only the media packet we inserted will be
400  // returned.
401  BuildAndAddRedMediaPacket(media_rtp_packets.front());
402  EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
403      .Times(1).WillRepeatedly(Return(true));
404  EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
405
406  DeletePackets(&media_packets);
407}
408
409void ReceiverFecTest::SurvivesMaliciousPacket(const uint8_t* data,
410                                              size_t length,
411                                              uint8_t ulpfec_payload_type) {
412  webrtc::RTPHeader header;
413  rtc::scoped_ptr<webrtc::RtpHeaderParser> parser(
414      webrtc::RtpHeaderParser::Create());
415  ASSERT_TRUE(parser->Parse(data, length, &header));
416
417  webrtc::NullRtpData null_callback;
418  rtc::scoped_ptr<webrtc::FecReceiver> receiver_fec(
419      webrtc::FecReceiver::Create(&null_callback));
420
421  receiver_fec->AddReceivedRedPacket(header, data, length, ulpfec_payload_type);
422}
423
424TEST_F(ReceiverFecTest, TruncatedPacketWithFBitSet) {
425  const uint8_t kTruncatedPacket[] = {0x80,
426                                      0x2a,
427                                      0x68,
428                                      0x71,
429                                      0x29,
430                                      0xa1,
431                                      0x27,
432                                      0x3a,
433                                      0x29,
434                                      0x12,
435                                      0x2a,
436                                      0x98,
437                                      0xe0,
438                                      0x29};
439
440  SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
441}
442
443TEST_F(ReceiverFecTest, TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
444  const uint8_t kPacket[] = {0x89,
445                             0x27,
446                             0x3a,
447                             0x83,
448                             0x27,
449                             0x3a,
450                             0x3a,
451                             0xf3,
452                             0x67,
453                             0xbe,
454                             0x2a,
455                             0xa9,
456                             0x27,
457                             0x54,
458                             0x3a,
459                             0x3a,
460                             0x2a,
461                             0x67,
462                             0x3a,
463                             0xf3,
464                             0x67,
465                             0xbe,
466                             0x2a,
467                             0x27,
468                             0xe6,
469                             0xf6,
470                             0x03,
471                             0x3e,
472                             0x29,
473                             0x27,
474                             0x21,
475                             0x27,
476                             0x2a,
477                             0x29,
478                             0x21,
479                             0x4b,
480                             0x29,
481                             0x3a,
482                             0x28,
483                             0x29,
484                             0xbf,
485                             0x29,
486                             0x2a,
487                             0x26,
488                             0x29,
489                             0xae,
490                             0x27,
491                             0xa6,
492                             0xf6,
493                             0x00,
494                             0x03,
495                             0x3e};
496  SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
497}
498
499TEST_F(ReceiverFecTest, TruncatedPacketWithoutDataPastFirstBlock) {
500  const uint8_t kPacket[] = {0x82,
501                             0x38,
502                             0x92,
503                             0x38,
504                             0x92,
505                             0x38,
506                             0xde,
507                             0x2a,
508                             0x11,
509                             0xc8,
510                             0xa3,
511                             0xc4,
512                             0x82,
513                             0x38,
514                             0x2a,
515                             0x21,
516                             0x2a,
517                             0x28,
518                             0x92,
519                             0x38,
520                             0x92,
521                             0x00,
522                             0x00,
523                             0x0a,
524                             0x3a,
525                             0xc8,
526                             0xa3,
527                             0x3a,
528                             0x27,
529                             0xc4,
530                             0x2a,
531                             0x21,
532                             0x2a,
533                             0x28};
534  SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
535}
536
537}  // namespace webrtc
538