OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" | 11 #include "webrtc/modules/rtp_rtcp/source/fec_test_helper.h" |
12 | 12 |
13 #include <memory> | 13 #include <memory> |
14 #include <utility> | 14 #include <utility> |
15 | 15 |
16 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 16 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
17 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 17 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
18 | 18 |
19 namespace webrtc { | 19 namespace webrtc { |
20 namespace test { | 20 namespace test { |
21 namespace fec { | 21 namespace fec { |
22 | 22 |
23 namespace { | 23 namespace { |
24 constexpr uint8_t kFecPayloadType = 96; | 24 constexpr uint8_t kFecPayloadType = 96; |
25 constexpr uint8_t kRedPayloadType = 97; | 25 constexpr uint8_t kRedPayloadType = 97; |
26 constexpr uint8_t kVp8PayloadType = 120; | 26 constexpr uint8_t kVp8PayloadType = 120; |
27 } // namespace | 27 } // namespace |
28 | 28 |
29 FrameGenerator::FrameGenerator() | 29 ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( |
| 30 int num_media_packets, |
| 31 uint16_t start_seq_num) { |
| 32 RTC_DCHECK_GT(num_media_packets, 0); |
| 33 uint16_t seq_num = start_seq_num; |
| 34 int time_stamp = random_->Rand<int>(); |
| 35 |
| 36 ForwardErrorCorrection::PacketList media_packets; |
| 37 |
| 38 for (int i = 0; i < num_media_packets; ++i) { |
| 39 std::unique_ptr<ForwardErrorCorrection::Packet> media_packet( |
| 40 new ForwardErrorCorrection::Packet()); |
| 41 media_packet->length = random_->Rand(min_packet_size_, max_packet_size_); |
| 42 |
| 43 // Generate random values for the first 2 bytes |
| 44 media_packet->data[0] = random_->Rand<uint8_t>(); |
| 45 media_packet->data[1] = random_->Rand<uint8_t>(); |
| 46 |
| 47 // The first two bits are assumed to be 10 by the FEC encoder. |
| 48 // In fact the FEC decoder will set the two first bits to 10 regardless of |
| 49 // what they actually were. Set the first two bits to 10 so that a memcmp |
| 50 // can be performed for the whole restored packet. |
| 51 media_packet->data[0] |= 0x80; |
| 52 media_packet->data[0] &= 0xbf; |
| 53 |
| 54 // FEC is applied to a whole frame. |
| 55 // A frame is signaled by multiple packets without the marker bit set |
| 56 // followed by the last packet of the frame for which the marker bit is set. |
| 57 // Only push one (fake) frame to the FEC. |
| 58 media_packet->data[1] &= 0x7f; |
| 59 |
| 60 webrtc::ByteWriter<uint16_t>::WriteBigEndian(&media_packet->data[2], |
| 61 seq_num); |
| 62 webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[4], |
| 63 time_stamp); |
| 64 webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[8], ssrc_); |
| 65 |
| 66 // Generate random values for payload. |
| 67 for (size_t j = 12; j < media_packet->length; ++j) { |
| 68 media_packet->data[j] = random_->Rand<uint8_t>(); |
| 69 } |
| 70 seq_num++; |
| 71 media_packets.push_back(std::move(media_packet)); |
| 72 } |
| 73 // Last packet, set marker bit. |
| 74 ForwardErrorCorrection::Packet* media_packet = media_packets.back().get(); |
| 75 RTC_DCHECK(media_packet); |
| 76 media_packet->data[1] |= 0x80; |
| 77 |
| 78 fec_seq_num_ = seq_num; |
| 79 |
| 80 return media_packets; |
| 81 } |
| 82 |
| 83 ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( |
| 84 int num_media_packets) { |
| 85 return ConstructMediaPackets(num_media_packets, random_->Rand<uint16_t>()); |
| 86 } |
| 87 |
| 88 uint16_t MediaPacketGenerator::GetFecSeqNum() { |
| 89 return fec_seq_num_; |
| 90 } |
| 91 |
| 92 UlpfecPacketGenerator::UlpfecPacketGenerator() |
30 : num_packets_(0), seq_num_(0), timestamp_(0) {} | 93 : num_packets_(0), seq_num_(0), timestamp_(0) {} |
31 | 94 |
32 void FrameGenerator::NewFrame(int num_packets) { | 95 void UlpfecPacketGenerator::NewFrame(int num_packets) { |
33 num_packets_ = num_packets; | 96 num_packets_ = num_packets; |
34 timestamp_ += 3000; | 97 timestamp_ += 3000; |
35 } | 98 } |
36 | 99 |
37 uint16_t FrameGenerator::NextSeqNum() { return ++seq_num_; } | 100 uint16_t UlpfecPacketGenerator::NextSeqNum() { |
| 101 return ++seq_num_; |
| 102 } |
38 | 103 |
39 RawRtpPacket* FrameGenerator::NextPacket(int offset, size_t length) { | 104 RawRtpPacket* UlpfecPacketGenerator::NextPacket(int offset, size_t length) { |
40 RawRtpPacket* rtp_packet = new RawRtpPacket; | 105 RawRtpPacket* rtp_packet = new RawRtpPacket; |
41 for (size_t i = 0; i < length; ++i) | 106 for (size_t i = 0; i < length; ++i) |
42 rtp_packet->data[i + kRtpHeaderSize] = offset + i; | 107 rtp_packet->data[i + kRtpHeaderSize] = offset + i; |
43 rtp_packet->length = length + kRtpHeaderSize; | 108 rtp_packet->length = length + kRtpHeaderSize; |
44 memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader)); | 109 memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader)); |
45 rtp_packet->header.frameType = kVideoFrameDelta; | 110 rtp_packet->header.frameType = kVideoFrameDelta; |
46 rtp_packet->header.header.headerLength = kRtpHeaderSize; | 111 rtp_packet->header.header.headerLength = kRtpHeaderSize; |
47 rtp_packet->header.header.markerBit = (num_packets_ == 1); | 112 rtp_packet->header.header.markerBit = (num_packets_ == 1); |
48 rtp_packet->header.header.sequenceNumber = seq_num_; | 113 rtp_packet->header.header.sequenceNumber = seq_num_; |
49 rtp_packet->header.header.timestamp = timestamp_; | 114 rtp_packet->header.header.timestamp = timestamp_; |
50 rtp_packet->header.header.payloadType = kVp8PayloadType; | 115 rtp_packet->header.header.payloadType = kVp8PayloadType; |
51 BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header); | 116 BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header); |
52 ++seq_num_; | 117 ++seq_num_; |
53 --num_packets_; | 118 --num_packets_; |
54 return rtp_packet; | 119 return rtp_packet; |
55 } | 120 } |
56 | 121 |
57 // Creates a new RtpPacket with the RED header added to the packet. | 122 // Creates a new RtpPacket with the RED header added to the packet. |
58 RawRtpPacket* FrameGenerator::BuildMediaRedPacket(const RawRtpPacket* packet) { | 123 RawRtpPacket* UlpfecPacketGenerator::BuildMediaRedPacket( |
| 124 const RawRtpPacket* packet) { |
59 const size_t kHeaderLength = packet->header.header.headerLength; | 125 const size_t kHeaderLength = packet->header.header.headerLength; |
60 RawRtpPacket* red_packet = new RawRtpPacket; | 126 RawRtpPacket* red_packet = new RawRtpPacket; |
61 red_packet->header = packet->header; | 127 red_packet->header = packet->header; |
62 red_packet->length = packet->length + 1; // 1 byte RED header. | 128 red_packet->length = packet->length + 1; // 1 byte RED header. |
63 memset(red_packet->data, 0, red_packet->length); | 129 memset(red_packet->data, 0, red_packet->length); |
64 // Copy RTP header. | 130 // Copy RTP header. |
65 memcpy(red_packet->data, packet->data, kHeaderLength); | 131 memcpy(red_packet->data, packet->data, kHeaderLength); |
66 SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength); | 132 SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength); |
67 memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength, | 133 memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength, |
68 packet->length - kHeaderLength); | 134 packet->length - kHeaderLength); |
69 return red_packet; | 135 return red_packet; |
70 } | 136 } |
71 | 137 |
72 // Creates a new RtpPacket with FEC payload and RED header. Does this by | 138 // Creates a new RtpPacket with FEC payload and RED header. Does this by |
73 // creating a new fake media RtpPacket, clears the marker bit and adds a RED | 139 // creating a new fake media RtpPacket, clears the marker bit and adds a RED |
74 // header. Finally replaces the payload with the content of |packet->data|. | 140 // header. Finally replaces the payload with the content of |packet->data|. |
75 RawRtpPacket* FrameGenerator::BuildFecRedPacket( | 141 RawRtpPacket* UlpfecPacketGenerator::BuildFecRedPacket( |
76 const ForwardErrorCorrection::Packet* packet) { | 142 const ForwardErrorCorrection::Packet* packet) { |
77 // Create a fake media packet to get a correct header. 1 byte RED header. | 143 // Create a fake media packet to get a correct header. 1 byte RED header. |
78 ++num_packets_; | 144 ++num_packets_; |
79 RawRtpPacket* red_packet = NextPacket(0, packet->length + 1); | 145 RawRtpPacket* red_packet = NextPacket(0, packet->length + 1); |
80 red_packet->data[1] &= ~0x80; // Clear marker bit. | 146 red_packet->data[1] &= ~0x80; // Clear marker bit. |
81 const size_t kHeaderLength = red_packet->header.header.headerLength; | 147 const size_t kHeaderLength = red_packet->header.header.headerLength; |
82 SetRedHeader(red_packet, kFecPayloadType, kHeaderLength); | 148 SetRedHeader(red_packet, kFecPayloadType, kHeaderLength); |
83 memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length); | 149 memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length); |
84 red_packet->length = kHeaderLength + 1 + packet->length; | 150 red_packet->length = kHeaderLength + 1 + packet->length; |
85 return red_packet; | 151 return red_packet; |
86 } | 152 } |
87 | 153 |
88 void FrameGenerator::SetRedHeader(ForwardErrorCorrection::Packet* red_packet, | 154 void UlpfecPacketGenerator::SetRedHeader( |
89 uint8_t payload_type, | 155 ForwardErrorCorrection::Packet* red_packet, |
90 size_t header_length) const { | 156 uint8_t payload_type, |
| 157 size_t header_length) const { |
91 // Replace pltype. | 158 // Replace pltype. |
92 red_packet->data[1] &= 0x80; // Reset. | 159 red_packet->data[1] &= 0x80; // Reset. |
93 red_packet->data[1] += kRedPayloadType; // Replace. | 160 red_packet->data[1] += kRedPayloadType; // Replace. |
94 | 161 |
95 // Add RED header, f-bit always 0. | 162 // Add RED header, f-bit always 0. |
96 red_packet->data[header_length] = payload_type; | 163 red_packet->data[header_length] = payload_type; |
97 } | 164 } |
98 | 165 |
99 void FrameGenerator::BuildRtpHeader(uint8_t* data, const RTPHeader* header) { | 166 void UlpfecPacketGenerator::BuildRtpHeader(uint8_t* data, |
| 167 const RTPHeader* header) { |
100 data[0] = 0x80; // Version 2. | 168 data[0] = 0x80; // Version 2. |
101 data[1] = header->payloadType; | 169 data[1] = header->payloadType; |
102 data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0); | 170 data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0); |
103 ByteWriter<uint16_t>::WriteBigEndian(data + 2, header->sequenceNumber); | 171 ByteWriter<uint16_t>::WriteBigEndian(data + 2, header->sequenceNumber); |
104 ByteWriter<uint32_t>::WriteBigEndian(data + 4, header->timestamp); | 172 ByteWriter<uint32_t>::WriteBigEndian(data + 4, header->timestamp); |
105 ByteWriter<uint32_t>::WriteBigEndian(data + 8, header->ssrc); | 173 ByteWriter<uint32_t>::WriteBigEndian(data + 8, header->ssrc); |
106 } | 174 } |
107 | 175 |
108 ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( | |
109 int num_media_packets, | |
110 uint16_t start_seq_num) { | |
111 RTC_DCHECK_GT(num_media_packets, 0); | |
112 uint16_t seq_num = start_seq_num; | |
113 int time_stamp = random_->Rand<int>(); | |
114 | |
115 ForwardErrorCorrection::PacketList media_packets; | |
116 | |
117 for (int i = 0; i < num_media_packets; ++i) { | |
118 std::unique_ptr<ForwardErrorCorrection::Packet> media_packet( | |
119 new ForwardErrorCorrection::Packet()); | |
120 media_packet->length = random_->Rand(min_packet_size_, max_packet_size_); | |
121 | |
122 // Generate random values for the first 2 bytes | |
123 media_packet->data[0] = random_->Rand<uint8_t>(); | |
124 media_packet->data[1] = random_->Rand<uint8_t>(); | |
125 | |
126 // The first two bits are assumed to be 10 by the FEC encoder. | |
127 // In fact the FEC decoder will set the two first bits to 10 regardless of | |
128 // what they actually were. Set the first two bits to 10 so that a memcmp | |
129 // can be performed for the whole restored packet. | |
130 media_packet->data[0] |= 0x80; | |
131 media_packet->data[0] &= 0xbf; | |
132 | |
133 // FEC is applied to a whole frame. | |
134 // A frame is signaled by multiple packets without the marker bit set | |
135 // followed by the last packet of the frame for which the marker bit is set. | |
136 // Only push one (fake) frame to the FEC. | |
137 media_packet->data[1] &= 0x7f; | |
138 | |
139 webrtc::ByteWriter<uint16_t>::WriteBigEndian(&media_packet->data[2], | |
140 seq_num); | |
141 webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[4], | |
142 time_stamp); | |
143 webrtc::ByteWriter<uint32_t>::WriteBigEndian(&media_packet->data[8], ssrc_); | |
144 | |
145 // Generate random values for payload. | |
146 for (size_t j = 12; j < media_packet->length; ++j) { | |
147 media_packet->data[j] = random_->Rand<uint8_t>(); | |
148 } | |
149 seq_num++; | |
150 media_packets.push_back(std::move(media_packet)); | |
151 } | |
152 // Last packet, set marker bit. | |
153 ForwardErrorCorrection::Packet* media_packet = media_packets.back().get(); | |
154 RTC_DCHECK(media_packet); | |
155 media_packet->data[1] |= 0x80; | |
156 | |
157 fec_seq_num_ = seq_num; | |
158 | |
159 return media_packets; | |
160 } | |
161 | |
162 ForwardErrorCorrection::PacketList MediaPacketGenerator::ConstructMediaPackets( | |
163 int num_media_packets) { | |
164 return ConstructMediaPackets(num_media_packets, random_->Rand<uint16_t>()); | |
165 } | |
166 | |
167 uint16_t MediaPacketGenerator::GetFecSeqNum() { | |
168 return fec_seq_num_; | |
169 } | |
170 | |
171 } // namespace fec | 176 } // namespace fec |
172 } // namespace test | 177 } // namespace test |
173 } // namespace webrtc | 178 } // namespace webrtc |
OLD | NEW |