1 /*
2 * Copyright (c) 2014 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 "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
12
13 #include <algorithm>
14
15 #include "webrtc/base/checks.h"
16 #include "webrtc/base/logging.h"
17 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
18
19 using webrtc::RTCPUtility::kBtDlrr;
20 using webrtc::RTCPUtility::kBtReceiverReferenceTime;
21 using webrtc::RTCPUtility::kBtVoipMetric;
22
23 using webrtc::RTCPUtility::PT_APP;
24 using webrtc::RTCPUtility::PT_IJ;
25 using webrtc::RTCPUtility::PT_PSFB;
26 using webrtc::RTCPUtility::PT_RTPFB;
27 using webrtc::RTCPUtility::PT_SDES;
28 using webrtc::RTCPUtility::PT_SR;
29 using webrtc::RTCPUtility::PT_XR;
30
31 using webrtc::RTCPUtility::RTCPPacketAPP;
32 using webrtc::RTCPUtility::RTCPPacketPSFBAPP;
33 using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
34 using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
35 using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
36 using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
37 using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
38 using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
39 using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
40 using webrtc::RTCPUtility::RTCPPacketSR;
41 using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
42 using webrtc::RTCPUtility::RTCPPacketXR;
43
44 namespace webrtc {
45 namespace rtcp {
46 namespace {
47 // Unused SSRC of media source, set to 0.
48 const uint32_t kUnusedMediaSourceSsrc0 = 0;
49
AssignUWord8(uint8_t * buffer,size_t * offset,uint8_t value)50 void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
51 buffer[(*offset)++] = value;
52 }
AssignUWord16(uint8_t * buffer,size_t * offset,uint16_t value)53 void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
54 ByteWriter<uint16_t>::WriteBigEndian(buffer + *offset, value);
55 *offset += 2;
56 }
AssignUWord24(uint8_t * buffer,size_t * offset,uint32_t value)57 void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
58 ByteWriter<uint32_t, 3>::WriteBigEndian(buffer + *offset, value);
59 *offset += 3;
60 }
AssignUWord32(uint8_t * buffer,size_t * offset,uint32_t value)61 void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
62 ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value);
63 *offset += 4;
64 }
65
ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,uint8_t bits_mantissa,uint32_t * mantissa,uint8_t * exp)66 void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,
67 uint8_t bits_mantissa,
68 uint32_t* mantissa,
69 uint8_t* exp) {
70 // input_base10 = mantissa * 2^exp
71 assert(bits_mantissa <= 32);
72 uint32_t mantissa_max = (1 << bits_mantissa) - 1;
73 uint8_t exponent = 0;
74 for (uint32_t i = 0; i < 64; ++i) {
75 if (input_base10 <= (mantissa_max << i)) {
76 exponent = i;
77 break;
78 }
79 }
80 *exp = exponent;
81 *mantissa = (input_base10 >> exponent);
82 }
83
84 // Sender report (SR) (RFC 3550).
85 // 0 1 2 3
86 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
87 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88 // |V=2|P| RC | PT=SR=200 | length |
89 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 // | SSRC of sender |
91 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
92 // | NTP timestamp, most significant word |
93 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 // | NTP timestamp, least significant word |
95 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 // | RTP timestamp |
97 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 // | sender's packet count |
99 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 // | sender's octet count |
101 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
102
CreateSenderReport(const RTCPPacketSR & sr,uint8_t * buffer,size_t * pos)103 void CreateSenderReport(const RTCPPacketSR& sr,
104 uint8_t* buffer,
105 size_t* pos) {
106 AssignUWord32(buffer, pos, sr.SenderSSRC);
107 AssignUWord32(buffer, pos, sr.NTPMostSignificant);
108 AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
109 AssignUWord32(buffer, pos, sr.RTPTimestamp);
110 AssignUWord32(buffer, pos, sr.SenderPacketCount);
111 AssignUWord32(buffer, pos, sr.SenderOctetCount);
112 }
113
114 // Report block (RFC 3550).
115 //
116 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
117 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
118 // | SSRC_1 (SSRC of first source) |
119 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 // | fraction lost | cumulative number of packets lost |
121 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 // | extended highest sequence number received |
123 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 // | interarrival jitter |
125 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126 // | last SR (LSR) |
127 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 // | delay since last SR (DLSR) |
129 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
130
CreateReportBlocks(const std::vector<ReportBlock> & blocks,uint8_t * buffer,size_t * pos)131 void CreateReportBlocks(const std::vector<ReportBlock>& blocks,
132 uint8_t* buffer,
133 size_t* pos) {
134 for (const ReportBlock& block : blocks) {
135 block.Create(buffer + *pos);
136 *pos += ReportBlock::kLength;
137 }
138 }
139
140 // Source Description (SDES) (RFC 3550).
141 //
142 // 0 1 2 3
143 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
144 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145 // header |V=2|P| SC | PT=SDES=202 | length |
146 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
147 // chunk | SSRC/CSRC_1 |
148 // 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 // | SDES items |
150 // | ... |
151 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
152 // chunk | SSRC/CSRC_2 |
153 // 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 // | SDES items |
155 // | ... |
156 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
157 //
158 // Canonical End-Point Identifier SDES Item (CNAME)
159 //
160 // 0 1 2 3
161 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
162 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163 // | CNAME=1 | length | user and domain name ...
164 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165
CreateSdes(const std::vector<Sdes::Chunk> & chunks,uint8_t * buffer,size_t * pos)166 void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
167 uint8_t* buffer,
168 size_t* pos) {
169 const uint8_t kSdesItemType = 1;
170 for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
171 it != chunks.end(); ++it) {
172 AssignUWord32(buffer, pos, (*it).ssrc);
173 AssignUWord8(buffer, pos, kSdesItemType);
174 AssignUWord8(buffer, pos, (*it).name.length());
175 memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
176 *pos += (*it).name.length();
177 memset(buffer + *pos, 0, (*it).null_octets);
178 *pos += (*it).null_octets;
179 }
180 }
181
182 // Reference picture selection indication (RPSI) (RFC 4585).
183 //
184 // FCI:
185 //
186 // 0 1 2 3
187 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
188 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
189 // | PB |0| Payload Type| Native RPSI bit string |
190 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
191 // | defined per codec ... | Padding (0) |
192 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
193
CreateRpsi(const RTCPPacketPSFBRPSI & rpsi,uint8_t padding_bytes,uint8_t * buffer,size_t * pos)194 void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
195 uint8_t padding_bytes,
196 uint8_t* buffer,
197 size_t* pos) {
198 // Native bit string should be a multiple of 8 bits.
199 assert(rpsi.NumberOfValidBits % 8 == 0);
200 AssignUWord32(buffer, pos, rpsi.SenderSSRC);
201 AssignUWord32(buffer, pos, rpsi.MediaSSRC);
202 AssignUWord8(buffer, pos, padding_bytes * 8);
203 AssignUWord8(buffer, pos, rpsi.PayloadType);
204 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
205 *pos += rpsi.NumberOfValidBits / 8;
206 memset(buffer + *pos, 0, padding_bytes);
207 *pos += padding_bytes;
208 }
209
210 // Full intra request (FIR) (RFC 5104).
211 //
212 // FCI:
213 //
214 // 0 1 2 3
215 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
216 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217 // | SSRC |
218 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219 // | Seq nr. | Reserved |
220 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
221
CreateFir(const RTCPPacketPSFBFIR & fir,const RTCPPacketPSFBFIRItem & fir_item,uint8_t * buffer,size_t * pos)222 void CreateFir(const RTCPPacketPSFBFIR& fir,
223 const RTCPPacketPSFBFIRItem& fir_item,
224 uint8_t* buffer,
225 size_t* pos) {
226 AssignUWord32(buffer, pos, fir.SenderSSRC);
227 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
228 AssignUWord32(buffer, pos, fir_item.SSRC);
229 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
230 AssignUWord24(buffer, pos, 0);
231 }
232
233 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
234 //
235 // 0 1 2 3
236 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
237 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
238 // |V=2|P| FMT=15 | PT=206 | length |
239 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
240 // | SSRC of packet sender |
241 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242 // | SSRC of media source |
243 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244 // | Unique identifier 'R' 'E' 'M' 'B' |
245 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
246 // | Num SSRC | BR Exp | BR Mantissa |
247 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248 // | SSRC feedback |
249 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
250 // | ... |
251
CreateRemb(const RTCPPacketPSFBAPP & remb,const RTCPPacketPSFBREMBItem & remb_item,uint8_t * buffer,size_t * pos)252 void CreateRemb(const RTCPPacketPSFBAPP& remb,
253 const RTCPPacketPSFBREMBItem& remb_item,
254 uint8_t* buffer,
255 size_t* pos) {
256 uint32_t mantissa = 0;
257 uint8_t exp = 0;
258 ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp);
259
260 AssignUWord32(buffer, pos, remb.SenderSSRC);
261 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
262 AssignUWord8(buffer, pos, 'R');
263 AssignUWord8(buffer, pos, 'E');
264 AssignUWord8(buffer, pos, 'M');
265 AssignUWord8(buffer, pos, 'B');
266 AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs);
267 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03));
268 AssignUWord8(buffer, pos, mantissa >> 8);
269 AssignUWord8(buffer, pos, mantissa);
270 for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) {
271 AssignUWord32(buffer, pos, remb_item.SSRCs[i]);
272 }
273 }
274
275 // From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
276 //
277 // Format for XR packets:
278 //
279 // 0 1 2 3
280 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
281 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
282 // |V=2|P|reserved | PT=XR=207 | length |
283 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
284 // | SSRC |
285 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
286 // : report blocks :
287 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
288
CreateXrHeader(const RTCPPacketXR & header,uint8_t * buffer,size_t * pos)289 void CreateXrHeader(const RTCPPacketXR& header,
290 uint8_t* buffer,
291 size_t* pos) {
292 AssignUWord32(buffer, pos, header.OriginatorSSRC);
293 }
294
295 } // namespace
296
Append(RtcpPacket * packet)297 void RtcpPacket::Append(RtcpPacket* packet) {
298 assert(packet);
299 appended_packets_.push_back(packet);
300 }
301
Build() const302 rtc::scoped_ptr<RawPacket> RtcpPacket::Build() const {
303 size_t length = 0;
304 rtc::scoped_ptr<RawPacket> packet(new RawPacket(IP_PACKET_SIZE));
305
306 class PacketVerifier : public PacketReadyCallback {
307 public:
308 explicit PacketVerifier(RawPacket* packet)
309 : called_(false), packet_(packet) {}
310 virtual ~PacketVerifier() {}
311 void OnPacketReady(uint8_t* data, size_t length) override {
312 RTC_CHECK(!called_) << "Fragmentation not supported.";
313 called_ = true;
314 packet_->SetLength(length);
315 }
316
317 private:
318 bool called_;
319 RawPacket* const packet_;
320 } verifier(packet.get());
321 CreateAndAddAppended(packet->MutableBuffer(), &length, packet->BufferLength(),
322 &verifier);
323 OnBufferFull(packet->MutableBuffer(), &length, &verifier);
324 return packet;
325 }
326
Build(PacketReadyCallback * callback) const327 bool RtcpPacket::Build(PacketReadyCallback* callback) const {
328 uint8_t buffer[IP_PACKET_SIZE];
329 return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback);
330 }
331
BuildExternalBuffer(uint8_t * buffer,size_t max_length,PacketReadyCallback * callback) const332 bool RtcpPacket::BuildExternalBuffer(uint8_t* buffer,
333 size_t max_length,
334 PacketReadyCallback* callback) const {
335 size_t index = 0;
336 if (!CreateAndAddAppended(buffer, &index, max_length, callback))
337 return false;
338 return OnBufferFull(buffer, &index, callback);
339 }
340
CreateAndAddAppended(uint8_t * packet,size_t * index,size_t max_length,PacketReadyCallback * callback) const341 bool RtcpPacket::CreateAndAddAppended(uint8_t* packet,
342 size_t* index,
343 size_t max_length,
344 PacketReadyCallback* callback) const {
345 if (!Create(packet, index, max_length, callback))
346 return false;
347 for (RtcpPacket* appended : appended_packets_) {
348 if (!appended->CreateAndAddAppended(packet, index, max_length, callback))
349 return false;
350 }
351 return true;
352 }
353
OnBufferFull(uint8_t * packet,size_t * index,RtcpPacket::PacketReadyCallback * callback) const354 bool RtcpPacket::OnBufferFull(uint8_t* packet,
355 size_t* index,
356 RtcpPacket::PacketReadyCallback* callback) const {
357 if (*index == 0)
358 return false;
359 callback->OnPacketReady(packet, *index);
360 *index = 0;
361 return true;
362 }
363
HeaderLength() const364 size_t RtcpPacket::HeaderLength() const {
365 size_t length_in_bytes = BlockLength();
366 // Length in 32-bit words minus 1.
367 assert(length_in_bytes > 0);
368 return ((length_in_bytes + 3) / 4) - 1;
369 }
370
371 // From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
372 //
373 // RTP header format.
374 // 0 1 2 3
375 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
376 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
377 // |V=2|P| RC/FMT | PT | length |
378 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379
CreateHeader(uint8_t count_or_format,uint8_t packet_type,size_t length,uint8_t * buffer,size_t * pos)380 void RtcpPacket::CreateHeader(
381 uint8_t count_or_format, // Depends on packet type.
382 uint8_t packet_type,
383 size_t length,
384 uint8_t* buffer,
385 size_t* pos) {
386 assert(length <= 0xffff);
387 const uint8_t kVersion = 2;
388 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
389 AssignUWord8(buffer, pos, packet_type);
390 AssignUWord16(buffer, pos, length);
391 }
392
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const393 bool SenderReport::Create(uint8_t* packet,
394 size_t* index,
395 size_t max_length,
396 RtcpPacket::PacketReadyCallback* callback) const {
397 while (*index + BlockLength() > max_length) {
398 if (!OnBufferFull(packet, index, callback))
399 return false;
400 }
401 CreateHeader(sr_.NumberOfReportBlocks, PT_SR, HeaderLength(), packet, index);
402 CreateSenderReport(sr_, packet, index);
403 CreateReportBlocks(report_blocks_, packet, index);
404 return true;
405 }
406
WithReportBlock(const ReportBlock & block)407 bool SenderReport::WithReportBlock(const ReportBlock& block) {
408 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
409 LOG(LS_WARNING) << "Max report blocks reached.";
410 return false;
411 }
412 report_blocks_.push_back(block);
413 sr_.NumberOfReportBlocks = report_blocks_.size();
414 return true;
415 }
416
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const417 bool Sdes::Create(uint8_t* packet,
418 size_t* index,
419 size_t max_length,
420 RtcpPacket::PacketReadyCallback* callback) const {
421 assert(!chunks_.empty());
422 while (*index + BlockLength() > max_length) {
423 if (!OnBufferFull(packet, index, callback))
424 return false;
425 }
426 CreateHeader(chunks_.size(), PT_SDES, HeaderLength(), packet, index);
427 CreateSdes(chunks_, packet, index);
428 return true;
429 }
430
WithCName(uint32_t ssrc,const std::string & cname)431 bool Sdes::WithCName(uint32_t ssrc, const std::string& cname) {
432 assert(cname.length() <= 0xff);
433 if (chunks_.size() >= kMaxNumberOfChunks) {
434 LOG(LS_WARNING) << "Max SDES chunks reached.";
435 return false;
436 }
437 // In each chunk, the list of items must be terminated by one or more null
438 // octets. The next chunk must start on a 32-bit boundary.
439 // CNAME (1 byte) | length (1 byte) | name | padding.
440 int null_octets = 4 - ((2 + cname.length()) % 4);
441 Chunk chunk;
442 chunk.ssrc = ssrc;
443 chunk.name = cname;
444 chunk.null_octets = null_octets;
445 chunks_.push_back(chunk);
446 return true;
447 }
448
BlockLength() const449 size_t Sdes::BlockLength() const {
450 // Header (4 bytes).
451 // Chunk:
452 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
453 size_t length = kHeaderLength;
454 for (const Chunk& chunk : chunks_)
455 length += 6 + chunk.name.length() + chunk.null_octets;
456 assert(length % 4 == 0);
457 return length;
458 }
459
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const460 bool Rpsi::Create(uint8_t* packet,
461 size_t* index,
462 size_t max_length,
463 RtcpPacket::PacketReadyCallback* callback) const {
464 assert(rpsi_.NumberOfValidBits > 0);
465 while (*index + BlockLength() > max_length) {
466 if (!OnBufferFull(packet, index, callback))
467 return false;
468 }
469 const uint8_t kFmt = 3;
470 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
471 CreateRpsi(rpsi_, padding_bytes_, packet, index);
472 return true;
473 }
474
WithPictureId(uint64_t picture_id)475 void Rpsi::WithPictureId(uint64_t picture_id) {
476 const uint32_t kPidBits = 7;
477 const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL;
478 uint8_t required_bytes = 0;
479 uint64_t shifted_pid = picture_id;
480 do {
481 ++required_bytes;
482 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
483 } while (shifted_pid > 0);
484
485 // Convert picture id to native bit string (natively defined by the video
486 // codec).
487 int pos = 0;
488 for (int i = required_bytes - 1; i > 0; i--) {
489 rpsi_.NativeBitString[pos++] =
490 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
491 }
492 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
493 rpsi_.NumberOfValidBits = pos * 8;
494
495 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
496 padding_bytes_ = 4 - ((2 + required_bytes) % 4);
497 if (padding_bytes_ == 4) {
498 padding_bytes_ = 0;
499 }
500 }
501
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const502 bool Fir::Create(uint8_t* packet,
503 size_t* index,
504 size_t max_length,
505 RtcpPacket::PacketReadyCallback* callback) const {
506 while (*index + BlockLength() > max_length) {
507 if (!OnBufferFull(packet, index, callback))
508 return false;
509 }
510 const uint8_t kFmt = 4;
511 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
512 CreateFir(fir_, fir_item_, packet, index);
513 return true;
514 }
515
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const516 bool Remb::Create(uint8_t* packet,
517 size_t* index,
518 size_t max_length,
519 RtcpPacket::PacketReadyCallback* callback) const {
520 while (*index + BlockLength() > max_length) {
521 if (!OnBufferFull(packet, index, callback))
522 return false;
523 }
524 const uint8_t kFmt = 15;
525 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
526 CreateRemb(remb_, remb_item_, packet, index);
527 return true;
528 }
529
AppliesTo(uint32_t ssrc)530 void Remb::AppliesTo(uint32_t ssrc) {
531 if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) {
532 LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached.";
533 return;
534 }
535 remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc;
536 }
537
Create(uint8_t * packet,size_t * index,size_t max_length,RtcpPacket::PacketReadyCallback * callback) const538 bool Xr::Create(uint8_t* packet,
539 size_t* index,
540 size_t max_length,
541 RtcpPacket::PacketReadyCallback* callback) const {
542 while (*index + BlockLength() > max_length) {
543 if (!OnBufferFull(packet, index, callback))
544 return false;
545 }
546 CreateHeader(0U, PT_XR, HeaderLength(), packet, index);
547 CreateXrHeader(xr_header_, packet, index);
548 for (const Rrtr& block : rrtr_blocks_) {
549 block.Create(packet + *index);
550 *index += Rrtr::kLength;
551 }
552 for (const Dlrr& block : dlrr_blocks_) {
553 block.Create(packet + *index);
554 *index += block.BlockLength();
555 }
556 for (const VoipMetric& block : voip_metric_blocks_) {
557 block.Create(packet + *index);
558 *index += VoipMetric::kLength;
559 }
560 return true;
561 }
562
WithRrtr(Rrtr * rrtr)563 bool Xr::WithRrtr(Rrtr* rrtr) {
564 RTC_DCHECK(rrtr);
565 if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) {
566 LOG(LS_WARNING) << "Max RRTR blocks reached.";
567 return false;
568 }
569 rrtr_blocks_.push_back(*rrtr);
570 return true;
571 }
572
WithDlrr(Dlrr * dlrr)573 bool Xr::WithDlrr(Dlrr* dlrr) {
574 RTC_DCHECK(dlrr);
575 if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) {
576 LOG(LS_WARNING) << "Max DLRR blocks reached.";
577 return false;
578 }
579 dlrr_blocks_.push_back(*dlrr);
580 return true;
581 }
582
WithVoipMetric(VoipMetric * voip_metric)583 bool Xr::WithVoipMetric(VoipMetric* voip_metric) {
584 assert(voip_metric);
585 if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) {
586 LOG(LS_WARNING) << "Max Voip Metric blocks reached.";
587 return false;
588 }
589 voip_metric_blocks_.push_back(*voip_metric);
590 return true;
591 }
592
DlrrLength() const593 size_t Xr::DlrrLength() const {
594 size_t length = 0;
595 for (const Dlrr& block : dlrr_blocks_) {
596 length += block.BlockLength();
597 }
598 return length;
599 }
600
RawPacket(size_t buffer_length)601 RawPacket::RawPacket(size_t buffer_length)
602 : buffer_length_(buffer_length), length_(0) {
603 buffer_.reset(new uint8_t[buffer_length]);
604 }
605
RawPacket(const uint8_t * packet,size_t packet_length)606 RawPacket::RawPacket(const uint8_t* packet, size_t packet_length)
607 : buffer_length_(packet_length), length_(packet_length) {
608 buffer_.reset(new uint8_t[packet_length]);
609 memcpy(buffer_.get(), packet, packet_length);
610 }
611
Buffer() const612 const uint8_t* RawPacket::Buffer() const {
613 return buffer_.get();
614 }
615
MutableBuffer()616 uint8_t* RawPacket::MutableBuffer() {
617 return buffer_.get();
618 }
619
BufferLength() const620 size_t RawPacket::BufferLength() const {
621 return buffer_length_;
622 }
623
Length() const624 size_t RawPacket::Length() const {
625 return length_;
626 }
627
SetLength(size_t length)628 void RawPacket::SetLength(size_t length) {
629 assert(length <= buffer_length_);
630 length_ = length;
631 }
632
633 } // namespace rtcp
634 } // namespace webrtc
635