Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / fec_receiver_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 <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/modules/rtp_rtcp/interface/fec_receiver.h"
18 #include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
19 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h"
20 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
21
22 using ::testing::_;
23 using ::testing::Args;
24 using ::testing::ElementsAreArray;
25 using ::testing::Return;
26
27 namespace webrtc {
28
29 class ReceiverFecTest : public ::testing::Test {
30  protected:
31   virtual void SetUp() {
32     fec_ = new ForwardErrorCorrection();
33     receiver_fec_ = FecReceiver::Create(&rtp_data_callback_);
34     generator_ = new FrameGenerator();
35   }
36
37   virtual void TearDown() {
38     delete fec_;
39     delete receiver_fec_;
40     delete generator_;
41   }
42
43   void GenerateFEC(std::list<Packet*>* media_packets,
44                    std::list<Packet*>* fec_packets,
45                    unsigned int num_fec_packets) {
46     uint8_t protection_factor = num_fec_packets * 255 / media_packets->size();
47     EXPECT_EQ(0, fec_->GenerateFEC(*media_packets, protection_factor,
48                                    0, false, kFecMaskBursty, fec_packets));
49     ASSERT_EQ(num_fec_packets, fec_packets->size());
50   }
51
52   void GenerateFrame(int num_media_packets, int frame_offset,
53                      std::list<RtpPacket*>* media_rtp_packets,
54                      std::list<Packet*>* media_packets) {
55     generator_->NewFrame(num_media_packets);
56     for (int i = 0; i < num_media_packets; ++i) {
57       media_rtp_packets->push_back(
58           generator_->NextPacket(frame_offset + i, kRtpHeaderSize + 10));
59       media_packets->push_back(media_rtp_packets->back());
60     }
61   }
62
63   void VerifyReconstructedMediaPacket(const RtpPacket* packet, int times) {
64     // Verify that the content of the reconstructed packet is equal to the
65     // content of |packet|, and that the same content is received |times| number
66     // of times in a row.
67     EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, packet->length))
68         .With(Args<0, 1>(ElementsAreArray(packet->data,
69                                           packet->length)))
70         .Times(times).WillRepeatedly(Return(true));
71   }
72
73   void BuildAndAddRedMediaPacket(RtpPacket* packet) {
74     RtpPacket* red_packet = generator_->BuildMediaRedPacket(packet);
75     EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
76                      red_packet->header.header, red_packet->data,
77                      red_packet->length, kFecPayloadType));
78     delete red_packet;
79   }
80
81   void BuildAndAddRedFecPacket(Packet* packet) {
82     RtpPacket* red_packet = generator_->BuildFecRedPacket(packet);
83     EXPECT_EQ(0, receiver_fec_->AddReceivedRedPacket(
84                      red_packet->header.header, red_packet->data,
85                      red_packet->length, kFecPayloadType));
86     delete red_packet;
87   }
88
89   ForwardErrorCorrection* fec_;
90   MockRtpData rtp_data_callback_;
91   FecReceiver* receiver_fec_;
92   FrameGenerator* generator_;
93 };
94
95 void DeletePackets(std::list<Packet*>* packets) {
96   while (!packets->empty()) {
97     delete packets->front();
98     packets->pop_front();
99   }
100 }
101
102 TEST_F(ReceiverFecTest, TwoMediaOneFec) {
103   const unsigned int kNumFecPackets = 1u;
104   std::list<RtpPacket*> media_rtp_packets;
105   std::list<Packet*> media_packets;
106   GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
107   std::list<Packet*> fec_packets;
108   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
109
110   // Recovery
111   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
112   std::list<RtpPacket*>::iterator media_it = media_rtp_packets.begin();
113   BuildAndAddRedMediaPacket(*media_it);
114   VerifyReconstructedMediaPacket(*it, 1);
115   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
116   // Drop one media packet.
117   std::list<Packet*>::iterator fec_it = fec_packets.begin();
118   BuildAndAddRedFecPacket(*fec_it);
119   ++it;
120   VerifyReconstructedMediaPacket(*it, 1);
121   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
122
123   DeletePackets(&media_packets);
124 }
125
126 TEST_F(ReceiverFecTest, TwoMediaTwoFec) {
127   const unsigned int kNumFecPackets = 2u;
128   std::list<RtpPacket*> media_rtp_packets;
129   std::list<Packet*> media_packets;
130   GenerateFrame(2, 0, &media_rtp_packets, &media_packets);
131   std::list<Packet*> fec_packets;
132   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
133
134   // Recovery
135   // Drop both media packets.
136   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
137   std::list<Packet*>::iterator fec_it = fec_packets.begin();
138   BuildAndAddRedFecPacket(*fec_it);
139   VerifyReconstructedMediaPacket(*it, 1);
140   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
141   ++fec_it;
142   BuildAndAddRedFecPacket(*fec_it);
143   ++it;
144   VerifyReconstructedMediaPacket(*it, 1);
145   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
146
147   DeletePackets(&media_packets);
148 }
149
150 TEST_F(ReceiverFecTest, TwoFramesOneFec) {
151   const unsigned int kNumFecPackets = 1u;
152   std::list<RtpPacket*> media_rtp_packets;
153   std::list<Packet*> media_packets;
154   GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
155   GenerateFrame(1, 1, &media_rtp_packets, &media_packets);
156   std::list<Packet*> fec_packets;
157   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
158
159   // Recovery
160   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
161   BuildAndAddRedMediaPacket(media_rtp_packets.front());
162   VerifyReconstructedMediaPacket(*it, 1);
163   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
164   // Drop one media packet.
165   BuildAndAddRedFecPacket(fec_packets.front());
166   ++it;
167   VerifyReconstructedMediaPacket(*it, 1);
168   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
169
170   DeletePackets(&media_packets);
171 }
172
173 TEST_F(ReceiverFecTest, OneCompleteOneUnrecoverableFrame) {
174   const unsigned int kNumFecPackets = 1u;
175   std::list<RtpPacket*> media_rtp_packets;
176   std::list<Packet*> media_packets;
177   GenerateFrame(1, 0, &media_rtp_packets, &media_packets);
178   GenerateFrame(2, 1, &media_rtp_packets, &media_packets);
179
180   std::list<Packet*> fec_packets;
181   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
182
183   // Recovery
184   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
185   BuildAndAddRedMediaPacket(*it);  // First frame: one packet.
186   VerifyReconstructedMediaPacket(*it, 1);
187   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
188   ++it;
189   BuildAndAddRedMediaPacket(*it);  // First packet of second frame.
190   VerifyReconstructedMediaPacket(*it, 1);
191   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
192
193   DeletePackets(&media_packets);
194 }
195
196 TEST_F(ReceiverFecTest, MaxFramesOneFec) {
197   const unsigned int kNumFecPackets = 1u;
198   const unsigned int kNumMediaPackets = 48u;
199   std::list<RtpPacket*> media_rtp_packets;
200   std::list<Packet*> media_packets;
201   for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
202     GenerateFrame(1, i, &media_rtp_packets, &media_packets);
203   }
204   std::list<Packet*> fec_packets;
205   GenerateFEC(&media_packets, &fec_packets, kNumFecPackets);
206
207   // Recovery
208   std::list<RtpPacket*>::iterator it = media_rtp_packets.begin();
209   ++it;  // Drop first packet.
210   for (; it != media_rtp_packets.end(); ++it) {
211     BuildAndAddRedMediaPacket(*it);
212     VerifyReconstructedMediaPacket(*it, 1);
213     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
214   }
215   BuildAndAddRedFecPacket(fec_packets.front());
216   it = media_rtp_packets.begin();
217   VerifyReconstructedMediaPacket(*it, 1);
218   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
219
220   DeletePackets(&media_packets);
221 }
222
223 TEST_F(ReceiverFecTest, TooManyFrames) {
224   const unsigned int kNumFecPackets = 1u;
225   const unsigned int kNumMediaPackets = 49u;
226   std::list<RtpPacket*> media_rtp_packets;
227   std::list<Packet*> media_packets;
228   for (unsigned int i = 0; i < kNumMediaPackets; ++i) {
229     GenerateFrame(1, i, &media_rtp_packets, &media_packets);
230   }
231   std::list<Packet*> fec_packets;
232   EXPECT_EQ(-1, fec_->GenerateFEC(media_packets,
233                                   kNumFecPackets * 255 / kNumMediaPackets, 0,
234                                   false, kFecMaskBursty, &fec_packets));
235
236   DeletePackets(&media_packets);
237 }
238
239 TEST_F(ReceiverFecTest, PacketNotDroppedTooEarly) {
240   // 1 frame with 2 media packets and one FEC packet. One media packet missing.
241   // Delay the FEC packet.
242   Packet* delayed_fec = NULL;
243   const unsigned int kNumFecPacketsBatch1 = 1u;
244   const unsigned int kNumMediaPacketsBatch1 = 2u;
245   std::list<RtpPacket*> media_rtp_packets_batch1;
246   std::list<Packet*> media_packets_batch1;
247   GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
248                 &media_packets_batch1);
249   std::list<Packet*> fec_packets;
250   GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
251
252   BuildAndAddRedMediaPacket(media_rtp_packets_batch1.front());
253   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
254       .Times(1).WillRepeatedly(Return(true));
255   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
256   delayed_fec = fec_packets.front();
257
258   // Fill the FEC decoder. No packets should be dropped.
259   const unsigned int kNumMediaPacketsBatch2 = 46u;
260   std::list<RtpPacket*> media_rtp_packets_batch2;
261   std::list<Packet*> media_packets_batch2;
262   for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
263     GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
264   }
265   for (std::list<RtpPacket*>::iterator it = media_rtp_packets_batch2.begin();
266        it != media_rtp_packets_batch2.end(); ++it) {
267     BuildAndAddRedMediaPacket(*it);
268     EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
269         .Times(1).WillRepeatedly(Return(true));
270     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
271   }
272
273   // Add the delayed FEC packet. One packet should be reconstructed.
274   BuildAndAddRedFecPacket(delayed_fec);
275   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
276       .Times(1).WillRepeatedly(Return(true));
277   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
278
279   DeletePackets(&media_packets_batch1);
280   DeletePackets(&media_packets_batch2);
281 }
282
283 TEST_F(ReceiverFecTest, PacketDroppedWhenTooOld) {
284   // 1 frame with 2 media packets and one FEC packet. One media packet missing.
285   // Delay the FEC packet.
286   Packet* delayed_fec = NULL;
287   const unsigned int kNumFecPacketsBatch1 = 1u;
288   const unsigned int kNumMediaPacketsBatch1 = 2u;
289   std::list<RtpPacket*> media_rtp_packets_batch1;
290   std::list<Packet*> media_packets_batch1;
291   GenerateFrame(kNumMediaPacketsBatch1, 0, &media_rtp_packets_batch1,
292                 &media_packets_batch1);
293   std::list<Packet*> fec_packets;
294   GenerateFEC(&media_packets_batch1, &fec_packets, kNumFecPacketsBatch1);
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 and force the last packet to be dropped.
303   const unsigned int kNumMediaPacketsBatch2 = 48u;
304   std::list<RtpPacket*> media_rtp_packets_batch2;
305   std::list<Packet*> media_packets_batch2;
306   for (unsigned int i = 0; i < kNumMediaPacketsBatch2; ++i) {
307     GenerateFrame(1, i, &media_rtp_packets_batch2, &media_packets_batch2);
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. No packet should be reconstructed since the
318   // first media packet of that frame has been dropped due to being too old.
319   BuildAndAddRedFecPacket(delayed_fec);
320   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
321       .Times(0);
322   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
323
324   DeletePackets(&media_packets_batch1);
325   DeletePackets(&media_packets_batch2);
326 }
327
328 TEST_F(ReceiverFecTest, OldFecPacketDropped) {
329   // 49 frames with 2 media packets and one FEC packet. All media packets
330   // missing.
331   const unsigned int kNumMediaPackets = 49 * 2;
332   std::list<RtpPacket*> media_rtp_packets;
333   std::list<Packet*> media_packets;
334   for (unsigned int i = 0; i < kNumMediaPackets / 2; ++i) {
335     std::list<RtpPacket*> frame_media_rtp_packets;
336     std::list<Packet*> frame_media_packets;
337     std::list<Packet*> fec_packets;
338     GenerateFrame(2, 0, &frame_media_rtp_packets, &frame_media_packets);
339     GenerateFEC(&frame_media_packets, &fec_packets, 1);
340     for (std::list<Packet*>::iterator it = fec_packets.begin();
341          it != fec_packets.end(); ++it) {
342       // Only FEC packets inserted. No packets recoverable at this time.
343       BuildAndAddRedFecPacket(*it);
344       EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
345           .Times(0);
346       EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
347     }
348     media_packets.insert(media_packets.end(), frame_media_packets.begin(),
349                          frame_media_packets.end());
350     media_rtp_packets.insert(media_rtp_packets.end(),
351                              frame_media_rtp_packets.begin(),
352                              frame_media_rtp_packets.end());
353   }
354   // Insert the oldest media packet. The corresponding FEC packet is too old
355   // and should've been dropped. Only the media packet we inserted will be
356   // returned.
357   BuildAndAddRedMediaPacket(media_rtp_packets.front());
358   EXPECT_CALL(rtp_data_callback_, OnRecoveredPacket(_, _))
359       .Times(1).WillRepeatedly(Return(true));
360   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
361
362   DeletePackets(&media_packets);
363 }
364
365 }  // namespace webrtc