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() | |
30 : num_packets_(0), seq_num_(0), timestamp_(0) {} | |
31 | |
32 void FrameGenerator::NewFrame(int num_packets) { | |
33 num_packets_ = num_packets; | |
34 timestamp_ += 3000; | |
35 } | |
36 | |
37 uint16_t FrameGenerator::NextSeqNum() { return ++seq_num_; } | |
38 | |
39 RawRtpPacket* FrameGenerator::NextPacket(int offset, size_t length) { | |
40 RawRtpPacket* rtp_packet = new RawRtpPacket; | |
41 for (size_t i = 0; i < length; ++i) | |
42 rtp_packet->data[i + kRtpHeaderSize] = offset + i; | |
43 rtp_packet->length = length + kRtpHeaderSize; | |
44 memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader)); | |
45 rtp_packet->header.frameType = kVideoFrameDelta; | |
46 rtp_packet->header.header.headerLength = kRtpHeaderSize; | |
47 rtp_packet->header.header.markerBit = (num_packets_ == 1); | |
48 rtp_packet->header.header.sequenceNumber = seq_num_; | |
49 rtp_packet->header.header.timestamp = timestamp_; | |
50 rtp_packet->header.header.payloadType = kVp8PayloadType; | |
51 BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header); | |
52 ++seq_num_; | |
53 --num_packets_; | |
54 return rtp_packet; | |
55 } | |
56 | |
57 // Creates a new RtpPacket with the RED header added to the packet. | |
58 RawRtpPacket* FrameGenerator::BuildMediaRedPacket(const RawRtpPacket* packet) { | |
59 const size_t kHeaderLength = packet->header.header.headerLength; | |
60 RawRtpPacket* red_packet = new RawRtpPacket; | |
61 red_packet->header = packet->header; | |
62 red_packet->length = packet->length + 1; // 1 byte RED header. | |
63 memset(red_packet->data, 0, red_packet->length); | |
64 // Copy RTP header. | |
65 memcpy(red_packet->data, packet->data, kHeaderLength); | |
66 SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength); | |
67 memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength, | |
68 packet->length - kHeaderLength); | |
69 return red_packet; | |
70 } | |
71 | |
72 // 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 | |
74 // header. Finally replaces the payload with the content of |packet->data|. | |
75 RawRtpPacket* FrameGenerator::BuildFecRedPacket( | |
76 const ForwardErrorCorrection::Packet* packet) { | |
77 // Create a fake media packet to get a correct header. 1 byte RED header. | |
78 ++num_packets_; | |
79 RawRtpPacket* red_packet = NextPacket(0, packet->length + 1); | |
80 red_packet->data[1] &= ~0x80; // Clear marker bit. | |
81 const size_t kHeaderLength = red_packet->header.header.headerLength; | |
82 SetRedHeader(red_packet, kFecPayloadType, kHeaderLength); | |
83 memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length); | |
84 red_packet->length = kHeaderLength + 1 + packet->length; | |
85 return red_packet; | |
86 } | |
87 | |
88 void FrameGenerator::SetRedHeader(ForwardErrorCorrection::Packet* red_packet, | |
89 uint8_t payload_type, | |
90 size_t header_length) const { | |
91 // Replace pltype. | |
92 red_packet->data[1] &= 0x80; // Reset. | |
93 red_packet->data[1] += kRedPayloadType; // Replace. | |
94 | |
95 // Add RED header, f-bit always 0. | |
96 red_packet->data[header_length] = payload_type; | |
97 } | |
98 | |
99 void FrameGenerator::BuildRtpHeader(uint8_t* data, const RTPHeader* header) { | |
100 data[0] = 0x80; // Version 2. | |
101 data[1] = header->payloadType; | |
102 data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0); | |
103 ByteWriter<uint16_t>::WriteBigEndian(data + 2, header->sequenceNumber); | |
104 ByteWriter<uint32_t>::WriteBigEndian(data + 4, header->timestamp); | |
105 ByteWriter<uint32_t>::WriteBigEndian(data + 8, header->ssrc); | |
106 } | |
107 | |
108 void MediaPacketGenerator::ConstructMediaPacketsSeqNum(int num_media_packets, | 29 void MediaPacketGenerator::ConstructMediaPacketsSeqNum(int num_media_packets, |
109 uint16_t start_seq_num) { | 30 uint16_t start_seq_num) { |
110 RTC_DCHECK_GT(num_media_packets, 0); | 31 RTC_DCHECK_GT(num_media_packets, 0); |
111 uint16_t seq_num = start_seq_num; | 32 uint16_t seq_num = start_seq_num; |
112 int time_stamp = random_->Rand<int>(); | 33 int time_stamp = random_->Rand<int>(); |
113 uint32_t ssrc = random_->Rand<uint32_t>(); | 34 uint32_t ssrc = random_->Rand<uint32_t>(); |
114 | 35 |
115 media_packets_.clear(); | 36 media_packets_.clear(); |
116 | 37 |
117 for (int i = 0; i < num_media_packets; ++i) { | 38 for (int i = 0; i < num_media_packets; ++i) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 } | 88 } |
168 | 89 |
169 uint32_t MediaPacketGenerator::GetSsrc() { | 90 uint32_t MediaPacketGenerator::GetSsrc() { |
170 return ssrc_; | 91 return ssrc_; |
171 } | 92 } |
172 | 93 |
173 uint16_t MediaPacketGenerator::GetFecSeqNum() { | 94 uint16_t MediaPacketGenerator::GetFecSeqNum() { |
174 return fec_seq_num_; | 95 return fec_seq_num_; |
175 } | 96 } |
176 | 97 |
| 98 UlpfecPacketGenerator::UlpfecPacketGenerator() |
| 99 : num_packets_(0), seq_num_(0), timestamp_(0) {} |
| 100 |
| 101 void UlpfecPacketGenerator::NewFrame(int num_packets) { |
| 102 num_packets_ = num_packets; |
| 103 timestamp_ += 3000; |
| 104 } |
| 105 |
| 106 uint16_t UlpfecPacketGenerator::NextSeqNum() { |
| 107 return ++seq_num_; |
| 108 } |
| 109 |
| 110 RawRtpPacket* UlpfecPacketGenerator::NextPacket(int offset, size_t length) { |
| 111 RawRtpPacket* rtp_packet = new RawRtpPacket; |
| 112 for (size_t i = 0; i < length; ++i) |
| 113 rtp_packet->data[i + kRtpHeaderSize] = offset + i; |
| 114 rtp_packet->length = length + kRtpHeaderSize; |
| 115 memset(&rtp_packet->header, 0, sizeof(WebRtcRTPHeader)); |
| 116 rtp_packet->header.frameType = kVideoFrameDelta; |
| 117 rtp_packet->header.header.headerLength = kRtpHeaderSize; |
| 118 rtp_packet->header.header.markerBit = (num_packets_ == 1); |
| 119 rtp_packet->header.header.sequenceNumber = seq_num_; |
| 120 rtp_packet->header.header.timestamp = timestamp_; |
| 121 rtp_packet->header.header.payloadType = kVp8PayloadType; |
| 122 BuildRtpHeader(rtp_packet->data, &rtp_packet->header.header); |
| 123 ++seq_num_; |
| 124 --num_packets_; |
| 125 return rtp_packet; |
| 126 } |
| 127 |
| 128 RawRtpPacket* UlpfecPacketGenerator::BuildMediaRedPacket( |
| 129 const RawRtpPacket* packet) { |
| 130 const size_t kHeaderLength = packet->header.header.headerLength; |
| 131 RawRtpPacket* red_packet = new RawRtpPacket; |
| 132 red_packet->header = packet->header; |
| 133 red_packet->length = packet->length + 1; // 1 byte RED header. |
| 134 memset(red_packet->data, 0, red_packet->length); |
| 135 // Copy RTP header. |
| 136 memcpy(red_packet->data, packet->data, kHeaderLength); |
| 137 SetRedHeader(red_packet, red_packet->data[1] & 0x7f, kHeaderLength); |
| 138 memcpy(red_packet->data + kHeaderLength + 1, packet->data + kHeaderLength, |
| 139 packet->length - kHeaderLength); |
| 140 return red_packet; |
| 141 } |
| 142 |
| 143 RawRtpPacket* UlpfecPacketGenerator::BuildFecRedPacket( |
| 144 const ForwardErrorCorrection::Packet* packet) { |
| 145 // Create a fake media packet to get a correct header. 1 byte RED header. |
| 146 ++num_packets_; |
| 147 RawRtpPacket* red_packet = NextPacket(0, packet->length + 1); |
| 148 red_packet->data[1] &= ~0x80; // Clear marker bit. |
| 149 const size_t kHeaderLength = red_packet->header.header.headerLength; |
| 150 SetRedHeader(red_packet, kFecPayloadType, kHeaderLength); |
| 151 memcpy(red_packet->data + kHeaderLength + 1, packet->data, packet->length); |
| 152 red_packet->length = kHeaderLength + 1 + packet->length; |
| 153 return red_packet; |
| 154 } |
| 155 |
| 156 void UlpfecPacketGenerator::SetRedHeader( |
| 157 ForwardErrorCorrection::Packet* red_packet, |
| 158 uint8_t payload_type, |
| 159 size_t header_length) const { |
| 160 // Replace pltype. |
| 161 red_packet->data[1] &= 0x80; // Reset. |
| 162 red_packet->data[1] += kRedPayloadType; // Replace. |
| 163 |
| 164 // Add RED header, f-bit always 0. |
| 165 red_packet->data[header_length] = payload_type; |
| 166 } |
| 167 |
| 168 void UlpfecPacketGenerator::BuildRtpHeader(uint8_t* data, |
| 169 const RTPHeader* header) { |
| 170 data[0] = 0x80; // Version 2. |
| 171 data[1] = header->payloadType; |
| 172 data[1] |= (header->markerBit ? kRtpMarkerBitMask : 0); |
| 173 ByteWriter<uint16_t>::WriteBigEndian(data + 2, header->sequenceNumber); |
| 174 ByteWriter<uint32_t>::WriteBigEndian(data + 4, header->timestamp); |
| 175 ByteWriter<uint32_t>::WriteBigEndian(data + 8, header->ssrc); |
| 176 } |
| 177 |
177 } // namespace fec | 178 } // namespace fec |
178 } // namespace test | 179 } // namespace test |
179 } // namespace webrtc | 180 } // namespace webrtc |
OLD | NEW |