stefan@webrtc.org | e0d6fa4 | 2012-03-20 22:10:56 +0000 | [diff] [blame] | 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 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #include "modules/rtp_rtcp/source/fec_test_helper.h" |
stefan@webrtc.org | e0d6fa4 | 2012-03-20 22:10:56 +0000 | [diff] [blame] | 12 | |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 13 | #include <memory> |
| 14 | #include <utility> |
| 15 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 16 | #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| 17 | #include "modules/rtp_rtcp/source/byte_io.h" |
| 18 | #include "modules/rtp_rtcp/source/rtp_utility.h" |
| 19 | #include "rtc_base/checks.h" |
stefan@webrtc.org | e0d6fa4 | 2012-03-20 22:10:56 +0000 | [diff] [blame] | 20 | |
| 21 | namespace webrtc { |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 22 | namespace test { |
| 23 | namespace fec { |
| 24 | |
| 25 | namespace { |
| 26 | constexpr uint8_t kFecPayloadType = 96; |
| 27 | constexpr uint8_t kRedPayloadType = 97; |
| 28 | constexpr uint8_t kVp8PayloadType = 120; |
brandtr | 8d02ea7 | 2016-10-03 23:47:05 -0700 | [diff] [blame] | 29 | |
| 30 | constexpr int kPacketTimestampIncrement = 3000; |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 31 | } // namespace |
stefan@webrtc.org | e0d6fa4 | 2012-03-20 22:10:56 +0000 | [diff] [blame] | 32 | |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 33 | ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( |
| 34 | int num_media_packets, |
| 35 | uint16_t start_seq_num) { |
| 36 | RTC_DCHECK_GT(num_media_packets, 0); |
| 37 | uint16_t seq_num = start_seq_num; |
| 38 | int time_stamp = random_->Rand<int>(); |
| 39 | |
| 40 | ForwardErrorCorrection::PacketList media_packets; |
| 41 | |
| 42 | for (int i = 0; i < num_media_packets; ++i) { |
| 43 | std::unique_ptr<ForwardErrorCorrection::Packet> media_packet( |
| 44 | new ForwardErrorCorrection::Packet()); |
| 45 | media_packet->length = random_->Rand(min_packet_size_, max_packet_size_); |
| 46 | |
| 47 | // Generate random values for the first 2 bytes |
| 48 | media_packet->data[0] = random_->Rand<uint8_t>(); |
| 49 | media_packet->data[1] = random_->Rand<uint8_t>(); |
| 50 | |
| 51 | // The first two bits are assumed to be 10 by the FEC encoder. |
| 52 | // In fact the FEC decoder will set the two first bits to 10 regardless of |
| 53 | // what they actually were. Set the first two bits to 10 so that a memcmp |
| 54 | // can be performed for the whole restored packet. |
| 55 | media_packet->data[0] |= 0x80; |
| 56 | media_packet->data[0] &= 0xbf; |
| 57 | |
| 58 | // FEC is applied to a whole frame. |
| 59 | // A frame is signaled by multiple packets without the marker bit set |
| 60 | // followed by the last packet of the frame for which the marker bit is set. |
| 61 | // Only push one (fake) frame to the FEC. |
| 62 | media_packet->data[1] &= 0x7f; |
| 63 | |
| 64 | webrtc::ByteWriter<uint16_t>::WriteBigEndian(&media_packet->data[2], |
| 65 | seq_num); |
| 66 | webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[4], |
| 67 | time_stamp); |
| 68 | webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[8], ssrc_); |
| 69 | |
| 70 | // Generate random values for payload. |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 71 | for (size_t j = 12; j < media_packet->length; ++j) |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 72 | media_packet->data[j] = random_->Rand<uint8_t>(); |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 73 | seq_num++; |
| 74 | media_packets.push_back(std::move(media_packet)); |
| 75 | } |
| 76 | // Last packet, set marker bit. |
| 77 | ForwardErrorCorrection::Packet* media_packet = media_packets.back().get(); |
| 78 | RTC_DCHECK(media_packet); |
| 79 | media_packet->data[1] |= 0x80; |
| 80 | |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 81 | next_seq_num_ = seq_num; |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 82 | |
| 83 | return media_packets; |
| 84 | } |
| 85 | |
| 86 | ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( |
| 87 | int num_media_packets) { |
| 88 | return ConstructMediaPackets(num_media_packets, random_->Rand<uint16_t>()); |
| 89 | } |
| 90 | |
brandtr | d726a3f | 2017-06-29 02:45:35 -0700 | [diff] [blame] | 91 | uint16_t MediaPacketGenerator::GetNextSeqNum() { |
| 92 | return next_seq_num_; |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 93 | } |
| 94 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 95 | AugmentedPacketGenerator::AugmentedPacketGenerator(uint32_t ssrc) |
| 96 | : num_packets_(0), ssrc_(ssrc), seq_num_(0), timestamp_(0) {} |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 97 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 98 | void AugmentedPacketGenerator::NewFrame(size_t num_packets) { |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 99 | num_packets_ = num_packets; |
brandtr | 8d02ea7 | 2016-10-03 23:47:05 -0700 | [diff] [blame] | 100 | timestamp_ += kPacketTimestampIncrement; |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 101 | } |
| 102 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 103 | uint16_t AugmentedPacketGenerator::NextPacketSeqNum() { |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 104 | return ++seq_num_; |
| 105 | } |
| 106 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 107 | std::unique_ptr<AugmentedPacket> AugmentedPacketGenerator::NextPacket( |
| 108 | size_t offset, |
| 109 | size_t length) { |
| 110 | std::unique_ptr<AugmentedPacket> packet(new AugmentedPacket()); |
| 111 | |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 112 | for (size_t i = 0; i < length; ++i) |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 113 | packet->data[i + kRtpHeaderSize] = offset + i; |
| 114 | packet->length = length + kRtpHeaderSize; |
| 115 | memset(&packet->header, 0, sizeof(WebRtcRTPHeader)); |
| 116 | packet->header.frameType = kVideoFrameDelta; |
| 117 | packet->header.header.headerLength = kRtpHeaderSize; |
| 118 | packet->header.header.markerBit = (num_packets_ == 1); |
| 119 | packet->header.header.payloadType = kVp8PayloadType; |
| 120 | packet->header.header.sequenceNumber = seq_num_; |
| 121 | packet->header.header.timestamp = timestamp_; |
| 122 | packet->header.header.ssrc = ssrc_; |
| 123 | WriteRtpHeader(packet->header.header, packet->data); |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 124 | ++seq_num_; |
| 125 | --num_packets_; |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 126 | |
| 127 | return packet; |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 128 | } |
| 129 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 130 | void AugmentedPacketGenerator::WriteRtpHeader(const RTPHeader& header, |
| 131 | uint8_t* data) { |
| 132 | data[0] = 0x80; // Version 2. |
| 133 | data[1] = header.payloadType; |
| 134 | data[1] |= (header.markerBit ? kRtpMarkerBitMask : 0); |
| 135 | ByteWriter<uint16_t>::WriteBigEndian(data + 2, header.sequenceNumber); |
| 136 | ByteWriter<uint32_t>::WriteBigEndian(data + 4, header.timestamp); |
| 137 | ByteWriter<uint32_t>::WriteBigEndian(data + 8, header.ssrc); |
| 138 | } |
| 139 | |
brandtr | 8d02ea7 | 2016-10-03 23:47:05 -0700 | [diff] [blame] | 140 | FlexfecPacketGenerator::FlexfecPacketGenerator(uint32_t media_ssrc, |
| 141 | uint32_t flexfec_ssrc) |
| 142 | : AugmentedPacketGenerator(media_ssrc), |
| 143 | flexfec_ssrc_(flexfec_ssrc), |
| 144 | flexfec_seq_num_(0), |
| 145 | flexfec_timestamp_(0) {} |
| 146 | |
| 147 | std::unique_ptr<AugmentedPacket> FlexfecPacketGenerator::BuildFlexfecPacket( |
| 148 | const ForwardErrorCorrection::Packet& packet) { |
| 149 | RTC_DCHECK_LE(packet.length, |
| 150 | static_cast<size_t>(IP_PACKET_SIZE - kRtpHeaderSize)); |
| 151 | |
| 152 | RTPHeader header; |
| 153 | header.sequenceNumber = flexfec_seq_num_; |
| 154 | ++flexfec_seq_num_; |
| 155 | header.timestamp = flexfec_timestamp_; |
| 156 | flexfec_timestamp_ += kPacketTimestampIncrement; |
| 157 | header.ssrc = flexfec_ssrc_; |
| 158 | |
| 159 | std::unique_ptr<AugmentedPacket> packet_with_rtp_header( |
| 160 | new AugmentedPacket()); |
| 161 | WriteRtpHeader(header, packet_with_rtp_header->data); |
| 162 | memcpy(packet_with_rtp_header->data + kRtpHeaderSize, packet.data, |
| 163 | packet.length); |
| 164 | packet_with_rtp_header->length = kRtpHeaderSize + packet.length; |
| 165 | |
| 166 | return packet_with_rtp_header; |
| 167 | } |
| 168 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 169 | UlpfecPacketGenerator::UlpfecPacketGenerator(uint32_t ssrc) |
| 170 | : AugmentedPacketGenerator(ssrc) {} |
| 171 | |
| 172 | std::unique_ptr<AugmentedPacket> UlpfecPacketGenerator::BuildMediaRedPacket( |
| 173 | const AugmentedPacket& packet) { |
| 174 | std::unique_ptr<AugmentedPacket> red_packet(new AugmentedPacket()); |
| 175 | |
| 176 | const size_t kHeaderLength = packet.header.header.headerLength; |
| 177 | red_packet->header = packet.header; |
| 178 | red_packet->length = packet.length + 1; // 1 byte RED header. |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 179 | // Copy RTP header. |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 180 | memcpy(red_packet->data, packet.data, kHeaderLength); |
| 181 | SetRedHeader(red_packet->data[1] & 0x7f, kHeaderLength, red_packet.get()); |
| 182 | memcpy(red_packet->data + kHeaderLength + 1, packet.data + kHeaderLength, |
| 183 | packet.length - kHeaderLength); |
| 184 | |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 185 | return red_packet; |
| 186 | } |
| 187 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 188 | std::unique_ptr<AugmentedPacket> UlpfecPacketGenerator::BuildUlpfecRedPacket( |
| 189 | const ForwardErrorCorrection::Packet& packet) { |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 190 | // Create a fake media packet to get a correct header. 1 byte RED header. |
| 191 | ++num_packets_; |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 192 | std::unique_ptr<AugmentedPacket> red_packet = |
| 193 | NextPacket(0, packet.length + 1); |
| 194 | |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 195 | red_packet->data[1] &= ~0x80; // Clear marker bit. |
| 196 | const size_t kHeaderLength = red_packet->header.header.headerLength; |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 197 | SetRedHeader(kFecPayloadType, kHeaderLength, red_packet.get()); |
| 198 | memcpy(red_packet->data + kHeaderLength + 1, packet.data, packet.length); |
| 199 | red_packet->length = kHeaderLength + 1 + packet.length; |
| 200 | |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 201 | return red_packet; |
| 202 | } |
| 203 | |
brandtr | 0aabdac | 2016-10-03 06:36:43 -0700 | [diff] [blame] | 204 | void UlpfecPacketGenerator::SetRedHeader(uint8_t payload_type, |
| 205 | size_t header_length, |
| 206 | AugmentedPacket* red_packet) { |
| 207 | // Replace payload type. |
brandtr | a4545ee | 2016-10-03 02:58:45 -0700 | [diff] [blame] | 208 | red_packet->data[1] &= 0x80; // Reset. |
| 209 | red_packet->data[1] += kRedPayloadType; // Replace. |
| 210 | |
| 211 | // Add RED header, f-bit always 0. |
| 212 | red_packet->data[header_length] = payload_type; |
| 213 | } |
| 214 | |
brandtr | ece4aba | 2016-09-20 23:16:28 -0700 | [diff] [blame] | 215 | } // namespace fec |
| 216 | } // namespace test |
stefan@webrtc.org | e0d6fa4 | 2012-03-20 22:10:56 +0000 | [diff] [blame] | 217 | } // namespace webrtc |