Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(387)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/fec_test_helper.cc

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

Powered by Google App Engine
This is Rietveld 408576698