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/fec_test_helper.h" 15 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h" 16 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h" 17 18 namespace webrtc { 19 20 void VerifyHeader(uint16_t seq_num, 21 uint32_t timestamp, 22 int red_pltype, 23 int fec_pltype, 24 RedPacket* packet, 25 bool marker_bit) { 26 EXPECT_GT(packet->length(), static_cast<int>(kRtpHeaderSize)); 27 EXPECT_TRUE(packet->data() != NULL); 28 uint8_t* data = packet->data(); 29 // Marker bit not set. 30 EXPECT_EQ(marker_bit ? 0x80 : 0, data[1] & 0x80); 31 EXPECT_EQ(red_pltype, data[1] & 0x7F); 32 EXPECT_EQ(seq_num, (data[2] << 8) + data[3]); 33 uint32_t parsed_timestamp = (data[4] << 24) + (data[5] << 16) + 34 (data[6] << 8) + data[7]; 35 EXPECT_EQ(timestamp, parsed_timestamp); 36 EXPECT_EQ(fec_pltype, data[kRtpHeaderSize]); 37 } 38 39 class ProducerFecTest : public ::testing::Test { 40 protected: 41 virtual void SetUp() { 42 fec_ = new ForwardErrorCorrection(); 43 producer_ = new ProducerFec(fec_); 44 generator_ = new FrameGenerator; 45 } 46 47 virtual void TearDown() { 48 delete producer_; 49 delete fec_; 50 delete generator_; 51 } 52 ForwardErrorCorrection* fec_; 53 ProducerFec* producer_; 54 FrameGenerator* generator_; 55 }; 56 57 TEST_F(ProducerFecTest, OneFrameFec) { 58 // The number of media packets (|kNumPackets|), number of frames (one for 59 // this test), and the protection factor (|params->fec_rate|) are set to make 60 // sure the conditions for generating FEC are satisfied. This means: 61 // (1) protection factor is high enough so that actual overhead over 1 frame 62 // of packets is within |kMaxExcessOverhead|, and (2) the total number of 63 // media packets for 1 frame is at least |minimum_media_packets_fec_|. 64 const int kNumPackets = 4; 65 FecProtectionParams params = {15, false, 3}; 66 std::list<RtpPacket*> rtp_packets; 67 generator_->NewFrame(kNumPackets); 68 producer_->SetFecParameters(¶ms, 0); // Expecting one FEC packet. 69 uint32_t last_timestamp = 0; 70 for (int i = 0; i < kNumPackets; ++i) { 71 RtpPacket* rtp_packet = generator_->NextPacket(i, 10); 72 rtp_packets.push_back(rtp_packet); 73 EXPECT_EQ(0, producer_->AddRtpPacketAndGenerateFec(rtp_packet->data, 74 rtp_packet->length, 75 kRtpHeaderSize)); 76 last_timestamp = rtp_packet->header.header.timestamp; 77 } 78 EXPECT_TRUE(producer_->FecAvailable()); 79 uint16_t seq_num = generator_->NextSeqNum(); 80 RedPacket* packet = producer_->GetFecPacket(kRedPayloadType, 81 kFecPayloadType, 82 seq_num, 83 kRtpHeaderSize); 84 EXPECT_FALSE(producer_->FecAvailable()); 85 ASSERT_TRUE(packet != NULL); 86 VerifyHeader(seq_num, last_timestamp, 87 kRedPayloadType, kFecPayloadType, packet, false); 88 while (!rtp_packets.empty()) { 89 delete rtp_packets.front(); 90 rtp_packets.pop_front(); 91 } 92 delete packet; 93 } 94 95 TEST_F(ProducerFecTest, TwoFrameFec) { 96 // The number of media packets/frame (|kNumPackets|), the number of frames 97 // (|kNumFrames|), and the protection factor (|params->fec_rate|) are set to 98 // make sure the conditions for generating FEC are satisfied. This means: 99 // (1) protection factor is high enough so that actual overhead over 100 // |kNumFrames| is within |kMaxExcessOverhead|, and (2) the total number of 101 // media packets for |kNumFrames| frames is at least 102 // |minimum_media_packets_fec_|. 103 const int kNumPackets = 2; 104 const int kNumFrames = 2; 105 106 FecProtectionParams params = {15, 0, 3}; 107 std::list<RtpPacket*> rtp_packets; 108 producer_->SetFecParameters(¶ms, 0); // Expecting one FEC packet. 109 uint32_t last_timestamp = 0; 110 for (int i = 0; i < kNumFrames; ++i) { 111 generator_->NewFrame(kNumPackets); 112 for (int j = 0; j < kNumPackets; ++j) { 113 RtpPacket* rtp_packet = generator_->NextPacket(i * kNumPackets + j, 10); 114 rtp_packets.push_back(rtp_packet); 115 EXPECT_EQ(0, producer_->AddRtpPacketAndGenerateFec(rtp_packet->data, 116 rtp_packet->length, 117 kRtpHeaderSize)); 118 last_timestamp = rtp_packet->header.header.timestamp; 119 } 120 } 121 EXPECT_TRUE(producer_->FecAvailable()); 122 uint16_t seq_num = generator_->NextSeqNum(); 123 RedPacket* packet = producer_->GetFecPacket(kRedPayloadType, 124 kFecPayloadType, 125 seq_num, 126 kRtpHeaderSize); 127 EXPECT_FALSE(producer_->FecAvailable()); 128 EXPECT_TRUE(packet != NULL); 129 VerifyHeader(seq_num, last_timestamp, 130 kRedPayloadType, kFecPayloadType, packet, false); 131 while (!rtp_packets.empty()) { 132 delete rtp_packets.front(); 133 rtp_packets.pop_front(); 134 } 135 delete packet; 136 } 137 138 TEST_F(ProducerFecTest, BuildRedPacket) { 139 generator_->NewFrame(1); 140 RtpPacket* packet = generator_->NextPacket(0, 10); 141 RedPacket* red_packet = producer_->BuildRedPacket(packet->data, 142 packet->length - 143 kRtpHeaderSize, 144 kRtpHeaderSize, 145 kRedPayloadType); 146 EXPECT_EQ(packet->length + 1, red_packet->length()); 147 VerifyHeader(packet->header.header.sequenceNumber, 148 packet->header.header.timestamp, 149 kRedPayloadType, 150 packet->header.header.payloadType, 151 red_packet, 152 true); // Marker bit set. 153 for (int i = 0; i < 10; ++i) 154 EXPECT_EQ(i, red_packet->data()[kRtpHeaderSize + 1 + i]); 155 delete red_packet; 156 delete packet; 157 } 158 159 } // namespace webrtc 160