fec_test_helper.cc (6904B)
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 "modules/rtp_rtcp/source/fec_test_helper.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <cstring> 16 #include <memory> 17 #include <utility> 18 19 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 20 #include "modules/rtp_rtcp/source/byte_io.h" 21 #include "modules/rtp_rtcp/source/forward_error_correction.h" 22 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 23 #include "rtc_base/checks.h" 24 #include "rtc_base/copy_on_write_buffer.h" 25 #include "rtc_base/random.h" 26 27 namespace webrtc { 28 namespace test { 29 namespace fec { 30 31 namespace { 32 33 constexpr uint8_t kFecPayloadType = 96; 34 constexpr uint8_t kRedPayloadType = 97; 35 constexpr uint8_t kVp8PayloadType = 120; 36 37 constexpr int kPacketTimestampIncrement = 3000; 38 } // namespace 39 40 MediaPacketGenerator::MediaPacketGenerator(uint32_t min_packet_size, 41 uint32_t max_packet_size, 42 uint32_t ssrc, 43 Random* random) 44 : min_packet_size_(min_packet_size), 45 max_packet_size_(max_packet_size), 46 ssrc_(ssrc), 47 random_(random) {} 48 49 MediaPacketGenerator::~MediaPacketGenerator() = default; 50 51 ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( 52 int num_media_packets, 53 uint16_t start_seq_num) { 54 RTC_DCHECK_GT(num_media_packets, 0); 55 uint16_t seq_num = start_seq_num; 56 int time_stamp = random_->Rand<int>(); 57 58 ForwardErrorCorrection::PacketList media_packets; 59 60 for (int i = 0; i < num_media_packets; ++i) { 61 std::unique_ptr<ForwardErrorCorrection::Packet> media_packet( 62 new ForwardErrorCorrection::Packet()); 63 media_packet->data.SetSize( 64 random_->Rand(min_packet_size_, max_packet_size_)); 65 66 uint8_t* data = media_packet->data.MutableData(); 67 // Generate random values for the first 2 bytes 68 data[0] = random_->Rand<uint8_t>(); 69 data[1] = random_->Rand<uint8_t>(); 70 71 // The first two bits are assumed to be 10 by the FEC encoder. 72 // In fact the FEC decoder will set the two first bits to 10 regardless of 73 // what they actually were. Set the first two bits to 10 so that a memcmp 74 // can be performed for the whole restored packet. 75 data[0] |= 0x80; 76 data[0] &= 0xbf; 77 78 // FEC is applied to a whole frame. 79 // A frame is signaled by multiple packets without the marker bit set 80 // followed by the last packet of the frame for which the marker bit is set. 81 // Only push one (fake) frame to the FEC. 82 data[1] &= 0x7f; 83 84 ByteWriter<uint16_t>::WriteBigEndian(&data[2], seq_num); 85 ByteWriter<uint32_t>::WriteBigEndian(&data[4], time_stamp); 86 ByteWriter<uint32_t>::WriteBigEndian(&data[8], ssrc_); 87 88 // Generate random values for payload. 89 for (size_t j = 12; j < media_packet->data.size(); ++j) 90 data[j] = random_->Rand<uint8_t>(); 91 seq_num++; 92 media_packets.push_back(std::move(media_packet)); 93 } 94 // Last packet, set marker bit. 95 ForwardErrorCorrection::Packet* media_packet = media_packets.back().get(); 96 RTC_DCHECK(media_packet); 97 media_packet->data.MutableData()[1] |= 0x80; 98 99 next_seq_num_ = seq_num; 100 101 return media_packets; 102 } 103 104 ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( 105 int num_media_packets) { 106 return ConstructMediaPackets(num_media_packets, random_->Rand<uint16_t>()); 107 } 108 109 uint16_t MediaPacketGenerator::GetNextSeqNum() { 110 return next_seq_num_; 111 } 112 113 AugmentedPacketGenerator::AugmentedPacketGenerator(uint32_t ssrc) 114 : num_packets_(0), ssrc_(ssrc), seq_num_(0), timestamp_(0) {} 115 116 void AugmentedPacketGenerator::NewFrame(size_t num_packets) { 117 num_packets_ = num_packets; 118 timestamp_ += kPacketTimestampIncrement; 119 } 120 121 uint16_t AugmentedPacketGenerator::NextPacketSeqNum() { 122 return ++seq_num_; 123 } 124 125 void AugmentedPacketGenerator::NextPacket(size_t offset, 126 size_t length, 127 RtpPacket& packet) { 128 // Write Rtp Header 129 packet.SetMarker(num_packets_ == 1); 130 packet.SetPayloadType(kVp8PayloadType); 131 packet.SetSequenceNumber(seq_num_); 132 packet.SetTimestamp(timestamp_); 133 packet.SetSsrc(ssrc_); 134 135 // Generate RTP payload. 136 uint8_t* data = packet.AllocatePayload(length); 137 for (size_t i = 0; i < length; ++i) 138 data[i] = offset + i; 139 140 ++seq_num_; 141 --num_packets_; 142 } 143 144 FlexfecPacketGenerator::FlexfecPacketGenerator(uint32_t media_ssrc, 145 uint32_t flexfec_ssrc) 146 : AugmentedPacketGenerator(media_ssrc), 147 flexfec_ssrc_(flexfec_ssrc), 148 flexfec_seq_num_(0), 149 flexfec_timestamp_(0) {} 150 151 RtpPacketReceived FlexfecPacketGenerator::BuildFlexfecPacket( 152 const ForwardErrorCorrection::Packet& packet) { 153 RtpPacketReceived flexfec_packet; 154 155 flexfec_packet.SetSequenceNumber(flexfec_seq_num_); 156 ++flexfec_seq_num_; 157 flexfec_packet.SetTimestamp(flexfec_timestamp_); 158 flexfec_timestamp_ += kPacketTimestampIncrement; 159 flexfec_packet.SetSsrc(flexfec_ssrc_); 160 flexfec_packet.SetPayload(packet.data); 161 162 return flexfec_packet; 163 } 164 165 UlpfecPacketGenerator::UlpfecPacketGenerator(uint32_t ssrc) 166 : AugmentedPacketGenerator(ssrc) {} 167 168 RtpPacketReceived UlpfecPacketGenerator::BuildMediaRedPacket( 169 const RtpPacket& packet, 170 bool is_recovered) { 171 RtpPacketReceived red_packet; 172 // Append header. 173 red_packet.CopyHeaderFrom(packet); 174 // Find payload type and add it as RED header. 175 uint8_t* rtp_payload = red_packet.SetPayloadSize(1 + packet.payload_size()); 176 rtp_payload[0] = packet.PayloadType(); 177 // Append rest of payload/padding. 178 std::memcpy(rtp_payload + 1, packet.payload().data(), 179 packet.payload().size()); 180 red_packet.SetPadding(packet.padding_size()); 181 182 red_packet.SetPayloadType(kRedPayloadType); 183 red_packet.set_recovered(is_recovered); 184 185 return red_packet; 186 } 187 188 RtpPacketReceived UlpfecPacketGenerator::BuildUlpfecRedPacket( 189 const ForwardErrorCorrection::Packet& packet) { 190 // Create a fake media packet to get a correct header. 1 byte RED header. 191 ++num_packets_; 192 RtpPacketReceived red_packet = 193 NextPacket<RtpPacketReceived>(0, packet.data.size() + 1); 194 195 red_packet.SetMarker(false); 196 uint8_t* rtp_payload = red_packet.AllocatePayload(packet.data.size() + 1); 197 rtp_payload[0] = kFecPayloadType; 198 red_packet.SetPayloadType(kRedPayloadType); 199 memcpy(rtp_payload + 1, packet.data.cdata(), packet.data.size()); 200 red_packet.set_recovered(false); 201 202 return red_packet; 203 } 204 205 } // namespace fec 206 } // namespace test 207 } // namespace webrtc