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 "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
14 #include "webrtc/system_wrappers/interface/logging.h"
15
16 using webrtc::RTCPUtility::kBtDlrr;
17 using webrtc::RTCPUtility::kBtReceiverReferenceTime;
18 using webrtc::RTCPUtility::kBtVoipMetric;
19
20 using webrtc::RTCPUtility::PT_APP;
21 using webrtc::RTCPUtility::PT_BYE;
22 using webrtc::RTCPUtility::PT_IJ;
23 using webrtc::RTCPUtility::PT_PSFB;
24 using webrtc::RTCPUtility::PT_RR;
25 using webrtc::RTCPUtility::PT_RTPFB;
26 using webrtc::RTCPUtility::PT_SDES;
27 using webrtc::RTCPUtility::PT_SR;
28 using webrtc::RTCPUtility::PT_XR;
29
30 using webrtc::RTCPUtility::RTCPPacketAPP;
31 using webrtc::RTCPUtility::RTCPPacketBYE;
32 using webrtc::RTCPUtility::RTCPPacketPSFBAPP;
33 using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
34 using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
35 using webrtc::RTCPUtility::RTCPPacketPSFBPLI;
36 using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
37 using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
38 using webrtc::RTCPUtility::RTCPPacketPSFBSLI;
39 using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem;
40 using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
41 using webrtc::RTCPUtility::RTCPPacketRR;
42 using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
43 using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
44 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN;
45 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem;
46 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR;
47 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem;
48 using webrtc::RTCPUtility::RTCPPacketSR;
49 using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
50 using webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem;
51 using webrtc::RTCPUtility::RTCPPacketXR;
52 using webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem;
53
54 namespace webrtc {
55 namespace rtcp {
56 namespace {
57 // Unused SSRC of media source, set to 0.
58 const uint32_t kUnusedMediaSourceSsrc0 = 0;
59
AssignUWord8(uint8_t * buffer,size_t * offset,uint8_t value)60 void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
61 buffer[(*offset)++] = value;
62 }
AssignUWord16(uint8_t * buffer,size_t * offset,uint16_t value)63 void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
64 RtpUtility::AssignUWord16ToBuffer(buffer + *offset, value);
65 *offset += 2;
66 }
AssignUWord24(uint8_t * buffer,size_t * offset,uint32_t value)67 void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
68 RtpUtility::AssignUWord24ToBuffer(buffer + *offset, value);
69 *offset += 3;
70 }
AssignUWord32(uint8_t * buffer,size_t * offset,uint32_t value)71 void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
72 RtpUtility::AssignUWord32ToBuffer(buffer + *offset, value);
73 *offset += 4;
74 }
75
ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,uint8_t bits_mantissa,uint32_t * mantissa,uint8_t * exp)76 void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,
77 uint8_t bits_mantissa,
78 uint32_t* mantissa,
79 uint8_t* exp) {
80 // input_base10 = mantissa * 2^exp
81 assert(bits_mantissa <= 32);
82 uint32_t mantissa_max = (1 << bits_mantissa) - 1;
83 uint8_t exponent = 0;
84 for (uint32_t i = 0; i < 64; ++i) {
85 if (input_base10 <= (mantissa_max << i)) {
86 exponent = i;
87 break;
88 }
89 }
90 *exp = exponent;
91 *mantissa = (input_base10 >> exponent);
92 }
93
BlockToHeaderLength(size_t length_in_bytes)94 size_t BlockToHeaderLength(size_t length_in_bytes) {
95 // Length in 32-bit words minus 1.
96 assert(length_in_bytes > 0);
97 assert(length_in_bytes % 4 == 0);
98 return (length_in_bytes / 4) - 1;
99 }
100
101 // From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
102 //
103 // RTP header format.
104 // 0 1 2 3
105 // 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
106 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 // |V=2|P| RC/FMT | PT | length |
108 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109
CreateHeader(uint8_t count_or_format,uint8_t packet_type,size_t length,uint8_t * buffer,size_t * pos)110 void CreateHeader(uint8_t count_or_format, // Depends on packet type.
111 uint8_t packet_type,
112 size_t length,
113 uint8_t* buffer,
114 size_t* pos) {
115 assert(length <= 0xffff);
116 const uint8_t kVersion = 2;
117 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
118 AssignUWord8(buffer, pos, packet_type);
119 AssignUWord16(buffer, pos, length);
120 }
121
122 // Sender report (SR) (RFC 3550).
123 // 0 1 2 3
124 // 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
125 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126 // |V=2|P| RC | PT=SR=200 | length |
127 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 // | SSRC of sender |
129 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
130 // | NTP timestamp, most significant word |
131 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132 // | NTP timestamp, least significant word |
133 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134 // | RTP timestamp |
135 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 // | sender's packet count |
137 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 // | sender's octet count |
139 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
140
CreateSenderReport(const RTCPPacketSR & sr,size_t length,uint8_t * buffer,size_t * pos)141 void CreateSenderReport(const RTCPPacketSR& sr,
142 size_t length,
143 uint8_t* buffer,
144 size_t* pos) {
145 CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
146 AssignUWord32(buffer, pos, sr.SenderSSRC);
147 AssignUWord32(buffer, pos, sr.NTPMostSignificant);
148 AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
149 AssignUWord32(buffer, pos, sr.RTPTimestamp);
150 AssignUWord32(buffer, pos, sr.SenderPacketCount);
151 AssignUWord32(buffer, pos, sr.SenderOctetCount);
152 }
153
154 // Receiver report (RR), header (RFC 3550).
155 //
156 // 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
157 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 // |V=2|P| RC | PT=RR=201 | length |
159 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160 // | SSRC of packet sender |
161 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
162
CreateReceiverReport(const RTCPPacketRR & rr,size_t length,uint8_t * buffer,size_t * pos)163 void CreateReceiverReport(const RTCPPacketRR& rr,
164 size_t length,
165 uint8_t* buffer,
166 size_t* pos) {
167 CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
168 AssignUWord32(buffer, pos, rr.SenderSSRC);
169 }
170
171 // Report block (RFC 3550).
172 //
173 // 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
174 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
175 // | SSRC_1 (SSRC of first source) |
176 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177 // | fraction lost | cumulative number of packets lost |
178 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179 // | extended highest sequence number received |
180 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
181 // | interarrival jitter |
182 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
183 // | last SR (LSR) |
184 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
185 // | delay since last SR (DLSR) |
186 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
187
CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem> & blocks,uint8_t * buffer,size_t * pos)188 void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
189 uint8_t* buffer,
190 size_t* pos) {
191 for (std::vector<RTCPPacketReportBlockItem>::const_iterator
192 it = blocks.begin(); it != blocks.end(); ++it) {
193 AssignUWord32(buffer, pos, (*it).SSRC);
194 AssignUWord8(buffer, pos, (*it).FractionLost);
195 AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost);
196 AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber);
197 AssignUWord32(buffer, pos, (*it).Jitter);
198 AssignUWord32(buffer, pos, (*it).LastSR);
199 AssignUWord32(buffer, pos, (*it).DelayLastSR);
200 }
201 }
202
203 // Transmission Time Offsets in RTP Streams (RFC 5450).
204 //
205 // 0 1 2 3
206 // 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
207 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208 // hdr |V=2|P| RC | PT=IJ=195 | length |
209 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210 // | inter-arrival jitter |
211 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212 // . .
213 // . .
214 // . .
215 // | inter-arrival jitter |
216 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217
CreateIj(const std::vector<uint32_t> & ij_items,uint8_t * buffer,size_t * pos)218 void CreateIj(const std::vector<uint32_t>& ij_items,
219 uint8_t* buffer,
220 size_t* pos) {
221 size_t length = ij_items.size();
222 CreateHeader(length, PT_IJ, length, buffer, pos);
223 for (std::vector<uint32_t>::const_iterator it = ij_items.begin();
224 it != ij_items.end(); ++it) {
225 AssignUWord32(buffer, pos, *it);
226 }
227 }
228
229 // Source Description (SDES) (RFC 3550).
230 //
231 // 0 1 2 3
232 // 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
233 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
234 // header |V=2|P| SC | PT=SDES=202 | length |
235 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
236 // chunk | SSRC/CSRC_1 |
237 // 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
238 // | SDES items |
239 // | ... |
240 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
241 // chunk | SSRC/CSRC_2 |
242 // 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
243 // | SDES items |
244 // | ... |
245 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
246 //
247 // Canonical End-Point Identifier SDES Item (CNAME)
248 //
249 // 0 1 2 3
250 // 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
251 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
252 // | CNAME=1 | length | user and domain name ...
253 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
254
CreateSdes(const std::vector<Sdes::Chunk> & chunks,size_t length,uint8_t * buffer,size_t * pos)255 void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
256 size_t length,
257 uint8_t* buffer,
258 size_t* pos) {
259 CreateHeader(chunks.size(), PT_SDES, length, buffer, pos);
260 const uint8_t kSdesItemType = 1;
261 for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
262 it != chunks.end(); ++it) {
263 AssignUWord32(buffer, pos, (*it).ssrc);
264 AssignUWord8(buffer, pos, kSdesItemType);
265 AssignUWord8(buffer, pos, (*it).name.length());
266 memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
267 *pos += (*it).name.length();
268 memset(buffer + *pos, 0, (*it).null_octets);
269 *pos += (*it).null_octets;
270 }
271 }
272
273 // Bye packet (BYE) (RFC 3550).
274 //
275 // 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
276 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
277 // |V=2|P| SC | PT=BYE=203 | length |
278 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
279 // | SSRC/CSRC |
280 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281 // : ... :
282 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
283 // (opt) | length | reason for leaving ...
284 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
285
CreateBye(const RTCPPacketBYE & bye,const std::vector<uint32_t> & csrcs,size_t length,uint8_t * buffer,size_t * pos)286 void CreateBye(const RTCPPacketBYE& bye,
287 const std::vector<uint32_t>& csrcs,
288 size_t length,
289 uint8_t* buffer,
290 size_t* pos) {
291 CreateHeader(length, PT_BYE, length, buffer, pos);
292 AssignUWord32(buffer, pos, bye.SenderSSRC);
293 for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
294 it != csrcs.end(); ++it) {
295 AssignUWord32(buffer, pos, *it);
296 }
297 }
298
299 // Application-Defined packet (APP) (RFC 3550).
300 //
301 // 0 1 2 3
302 // 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
303 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
304 // |V=2|P| subtype | PT=APP=204 | length |
305 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
306 // | SSRC/CSRC |
307 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
308 // | name (ASCII) |
309 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
310 // | application-dependent data ...
311 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
312
CreateApp(const RTCPPacketAPP & app,uint32_t ssrc,size_t length,uint8_t * buffer,size_t * pos)313 void CreateApp(const RTCPPacketAPP& app,
314 uint32_t ssrc,
315 size_t length,
316 uint8_t* buffer,
317 size_t* pos) {
318 CreateHeader(app.SubType, PT_APP, length, buffer, pos);
319 AssignUWord32(buffer, pos, ssrc);
320 AssignUWord32(buffer, pos, app.Name);
321 memcpy(buffer + *pos, app.Data, app.Size);
322 *pos += app.Size;
323 }
324
325 // RFC 4585: Feedback format.
326 //
327 // Common packet format:
328 //
329 // 0 1 2 3
330 // 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
331 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
332 // |V=2|P| FMT | PT | length |
333 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
334 // | SSRC of packet sender |
335 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336 // | SSRC of media source |
337 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
338 // : Feedback Control Information (FCI) :
339 // :
340 //
341
342 // Picture loss indication (PLI) (RFC 4585).
343 //
344 // FCI: no feedback control information.
345
CreatePli(const RTCPPacketPSFBPLI & pli,size_t length,uint8_t * buffer,size_t * pos)346 void CreatePli(const RTCPPacketPSFBPLI& pli,
347 size_t length,
348 uint8_t* buffer,
349 size_t* pos) {
350 const uint8_t kFmt = 1;
351 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
352 AssignUWord32(buffer, pos, pli.SenderSSRC);
353 AssignUWord32(buffer, pos, pli.MediaSSRC);
354 }
355
356 // Slice loss indication (SLI) (RFC 4585).
357 //
358 // FCI:
359 //
360 // 0 1 2 3
361 // 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
362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363 // | First | Number | PictureID |
364 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365
CreateSli(const RTCPPacketPSFBSLI & sli,const RTCPPacketPSFBSLIItem & sli_item,size_t length,uint8_t * buffer,size_t * pos)366 void CreateSli(const RTCPPacketPSFBSLI& sli,
367 const RTCPPacketPSFBSLIItem& sli_item,
368 size_t length,
369 uint8_t* buffer,
370 size_t* pos) {
371 const uint8_t kFmt = 2;
372 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
373 AssignUWord32(buffer, pos, sli.SenderSSRC);
374 AssignUWord32(buffer, pos, sli.MediaSSRC);
375
376 AssignUWord8(buffer, pos, sli_item.FirstMB >> 5);
377 AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) +
378 ((sli_item.NumberOfMB >> 10) & 0x07));
379 AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2);
380 AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId);
381 }
382
383 // Generic NACK (RFC 4585).
384 //
385 // FCI:
386 //
387 // 0 1 2 3
388 // 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
389 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390 // | PID | BLP |
391 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
392
CreateNack(const RTCPPacketRTPFBNACK & nack,const std::vector<RTCPPacketRTPFBNACKItem> & nack_fields,size_t length,uint8_t * buffer,size_t * pos)393 void CreateNack(const RTCPPacketRTPFBNACK& nack,
394 const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
395 size_t length,
396 uint8_t* buffer,
397 size_t* pos) {
398 const uint8_t kFmt = 1;
399 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
400 AssignUWord32(buffer, pos, nack.SenderSSRC);
401 AssignUWord32(buffer, pos, nack.MediaSSRC);
402 for (std::vector<RTCPPacketRTPFBNACKItem>::const_iterator
403 it = nack_fields.begin(); it != nack_fields.end(); ++it) {
404 AssignUWord16(buffer, pos, (*it).PacketID);
405 AssignUWord16(buffer, pos, (*it).BitMask);
406 }
407 }
408
409 // Reference picture selection indication (RPSI) (RFC 4585).
410 //
411 // FCI:
412 //
413 // 0 1 2 3
414 // 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
415 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416 // | PB |0| Payload Type| Native RPSI bit string |
417 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
418 // | defined per codec ... | Padding (0) |
419 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420
CreateRpsi(const RTCPPacketPSFBRPSI & rpsi,uint8_t padding_bytes,size_t length,uint8_t * buffer,size_t * pos)421 void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
422 uint8_t padding_bytes,
423 size_t length,
424 uint8_t* buffer,
425 size_t* pos) {
426 // Native bit string should be a multiple of 8 bits.
427 assert(rpsi.NumberOfValidBits % 8 == 0);
428 const uint8_t kFmt = 3;
429 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
430 AssignUWord32(buffer, pos, rpsi.SenderSSRC);
431 AssignUWord32(buffer, pos, rpsi.MediaSSRC);
432 AssignUWord8(buffer, pos, padding_bytes * 8);
433 AssignUWord8(buffer, pos, rpsi.PayloadType);
434 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
435 *pos += rpsi.NumberOfValidBits / 8;
436 memset(buffer + *pos, 0, padding_bytes);
437 *pos += padding_bytes;
438 }
439
440 // Full intra request (FIR) (RFC 5104).
441 //
442 // FCI:
443 //
444 // 0 1 2 3
445 // 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
446 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
447 // | SSRC |
448 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
449 // | Seq nr. | Reserved |
450 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
451
CreateFir(const RTCPPacketPSFBFIR & fir,const RTCPPacketPSFBFIRItem & fir_item,size_t length,uint8_t * buffer,size_t * pos)452 void CreateFir(const RTCPPacketPSFBFIR& fir,
453 const RTCPPacketPSFBFIRItem& fir_item,
454 size_t length,
455 uint8_t* buffer,
456 size_t* pos) {
457 const uint8_t kFmt = 4;
458 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
459 AssignUWord32(buffer, pos, fir.SenderSSRC);
460 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
461 AssignUWord32(buffer, pos, fir_item.SSRC);
462 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
463 AssignUWord24(buffer, pos, 0);
464 }
465
CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem & tmmbr_item,uint8_t * buffer,size_t * pos)466 void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
467 uint8_t* buffer,
468 size_t* pos) {
469 uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000;
470 uint32_t mantissa = 0;
471 uint8_t exp = 0;
472 ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp);
473
474 AssignUWord32(buffer, pos, tmmbr_item.SSRC);
475 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03));
476 AssignUWord8(buffer, pos, mantissa >> 7);
477 AssignUWord8(buffer, pos, (mantissa << 1) +
478 ((tmmbr_item.MeasuredOverhead >> 8) & 0x01));
479 AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead);
480 }
481
482 // Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
483 //
484 // FCI:
485 //
486 // 0 1 2 3
487 // 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
488 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
489 // | SSRC |
490 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
491 // | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
492 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
493
CreateTmmbr(const RTCPPacketRTPFBTMMBR & tmmbr,const RTCPPacketRTPFBTMMBRItem & tmmbr_item,size_t length,uint8_t * buffer,size_t * pos)494 void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr,
495 const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
496 size_t length,
497 uint8_t* buffer,
498 size_t* pos) {
499 const uint8_t kFmt = 3;
500 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
501 AssignUWord32(buffer, pos, tmmbr.SenderSSRC);
502 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
503 CreateTmmbrItem(tmmbr_item, buffer, pos);
504 }
505
506 // Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
507 //
508 // FCI:
509 //
510 // 0 1 2 3
511 // 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
512 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513 // | SSRC |
514 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
515 // | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
516 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
517
CreateTmmbn(const RTCPPacketRTPFBTMMBN & tmmbn,const std::vector<RTCPPacketRTPFBTMMBRItem> & tmmbn_items,size_t length,uint8_t * buffer,size_t * pos)518 void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn,
519 const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items,
520 size_t length,
521 uint8_t* buffer,
522 size_t* pos) {
523 const uint8_t kFmt = 4;
524 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
525 AssignUWord32(buffer, pos, tmmbn.SenderSSRC);
526 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
527 for (uint8_t i = 0; i < tmmbn_items.size(); ++i) {
528 CreateTmmbrItem(tmmbn_items[i], buffer, pos);
529 }
530 }
531
532 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
533 //
534 // 0 1 2 3
535 // 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
536 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
537 // |V=2|P| FMT=15 | PT=206 | length |
538 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539 // | SSRC of packet sender |
540 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541 // | SSRC of media source |
542 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543 // | Unique identifier 'R' 'E' 'M' 'B' |
544 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
545 // | Num SSRC | BR Exp | BR Mantissa |
546 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
547 // | SSRC feedback |
548 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
549 // | ... |
550
CreateRemb(const RTCPPacketPSFBAPP & remb,const RTCPPacketPSFBREMBItem & remb_item,size_t length,uint8_t * buffer,size_t * pos)551 void CreateRemb(const RTCPPacketPSFBAPP& remb,
552 const RTCPPacketPSFBREMBItem& remb_item,
553 size_t length,
554 uint8_t* buffer,
555 size_t* pos) {
556 uint32_t mantissa = 0;
557 uint8_t exp = 0;
558 ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp);
559
560 const uint8_t kFmt = 15;
561 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
562 AssignUWord32(buffer, pos, remb.SenderSSRC);
563 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
564 AssignUWord8(buffer, pos, 'R');
565 AssignUWord8(buffer, pos, 'E');
566 AssignUWord8(buffer, pos, 'M');
567 AssignUWord8(buffer, pos, 'B');
568 AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs);
569 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03));
570 AssignUWord8(buffer, pos, mantissa >> 8);
571 AssignUWord8(buffer, pos, mantissa);
572 for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) {
573 AssignUWord32(buffer, pos, remb_item.SSRCs[i]);
574 }
575 }
576
577 // From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
578 //
579 // Format for XR packets:
580 //
581 // 0 1 2 3
582 // 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
583 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
584 // |V=2|P|reserved | PT=XR=207 | length |
585 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
586 // | SSRC |
587 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
588 // : report blocks :
589 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
590
CreateXrHeader(const RTCPPacketXR & header,size_t length,uint8_t * buffer,size_t * pos)591 void CreateXrHeader(const RTCPPacketXR& header,
592 size_t length,
593 uint8_t* buffer,
594 size_t* pos) {
595 CreateHeader(0U, PT_XR, length, buffer, pos);
596 AssignUWord32(buffer, pos, header.OriginatorSSRC);
597 }
598
CreateXrBlockHeader(uint8_t block_type,uint16_t block_length,uint8_t * buffer,size_t * pos)599 void CreateXrBlockHeader(uint8_t block_type,
600 uint16_t block_length,
601 uint8_t* buffer,
602 size_t* pos) {
603 AssignUWord8(buffer, pos, block_type);
604 AssignUWord8(buffer, pos, 0);
605 AssignUWord16(buffer, pos, block_length);
606 }
607
608 // Receiver Reference Time Report Block (RFC 3611).
609 //
610 // 0 1 2 3
611 // 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
612 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613 // | BT=4 | reserved | block length = 2 |
614 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615 // | NTP timestamp, most significant word |
616 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
617 // | NTP timestamp, least significant word |
618 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
619
CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem> & rrtrs,uint8_t * buffer,size_t * pos)620 void CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem>& rrtrs,
621 uint8_t* buffer,
622 size_t* pos) {
623 const uint16_t kBlockLength = 2;
624 for (std::vector<RTCPPacketXRReceiverReferenceTimeItem>::const_iterator it =
625 rrtrs.begin(); it != rrtrs.end(); ++it) {
626 CreateXrBlockHeader(kBtReceiverReferenceTime, kBlockLength, buffer, pos);
627 AssignUWord32(buffer, pos, (*it).NTPMostSignificant);
628 AssignUWord32(buffer, pos, (*it).NTPLeastSignificant);
629 }
630 }
631
632 // DLRR Report Block (RFC 3611).
633 //
634 // 0 1 2 3
635 // 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
636 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
637 // | BT=5 | reserved | block length |
638 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
639 // | SSRC_1 (SSRC of first receiver) | sub-
640 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
641 // | last RR (LRR) | 1
642 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
643 // | delay since last RR (DLRR) |
644 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
645 // | SSRC_2 (SSRC of second receiver) | sub-
646 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
647 // : ... : 2
648
CreateDlrr(const std::vector<Xr::DlrrBlock> & dlrrs,uint8_t * buffer,size_t * pos)649 void CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs,
650 uint8_t* buffer,
651 size_t* pos) {
652 for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin();
653 it != dlrrs.end(); ++it) {
654 if ((*it).empty()) {
655 continue;
656 }
657 uint16_t block_length = 3 * (*it).size();
658 CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos);
659 for (Xr::DlrrBlock::const_iterator it_block = (*it).begin();
660 it_block != (*it).end(); ++it_block) {
661 AssignUWord32(buffer, pos, (*it_block).SSRC);
662 AssignUWord32(buffer, pos, (*it_block).LastRR);
663 AssignUWord32(buffer, pos, (*it_block).DelayLastRR);
664 }
665 }
666 }
667
668 // VoIP Metrics Report Block (RFC 3611).
669 //
670 // 0 1 2 3
671 // 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
672 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
673 // | BT=7 | reserved | block length = 8 |
674 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675 // | SSRC of source |
676 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
677 // | loss rate | discard rate | burst density | gap density |
678 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
679 // | burst duration | gap duration |
680 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681 // | round trip delay | end system delay |
682 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
683 // | signal level | noise level | RERL | Gmin |
684 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
685 // | R factor | ext. R factor | MOS-LQ | MOS-CQ |
686 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
687 // | RX config | reserved | JB nominal |
688 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
689 // | JB maximum | JB abs max |
690 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
691
CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem> & metrics,uint8_t * buffer,size_t * pos)692 void CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem>& metrics,
693 uint8_t* buffer,
694 size_t* pos) {
695 const uint16_t kBlockLength = 8;
696 for (std::vector<RTCPPacketXRVOIPMetricItem>::const_iterator it =
697 metrics.begin(); it != metrics.end(); ++it) {
698 CreateXrBlockHeader(kBtVoipMetric, kBlockLength, buffer, pos);
699 AssignUWord32(buffer, pos, (*it).SSRC);
700 AssignUWord8(buffer, pos, (*it).lossRate);
701 AssignUWord8(buffer, pos, (*it).discardRate);
702 AssignUWord8(buffer, pos, (*it).burstDensity);
703 AssignUWord8(buffer, pos, (*it).gapDensity);
704 AssignUWord16(buffer, pos, (*it).burstDuration);
705 AssignUWord16(buffer, pos, (*it).gapDuration);
706 AssignUWord16(buffer, pos, (*it).roundTripDelay);
707 AssignUWord16(buffer, pos, (*it).endSystemDelay);
708 AssignUWord8(buffer, pos, (*it).signalLevel);
709 AssignUWord8(buffer, pos, (*it).noiseLevel);
710 AssignUWord8(buffer, pos, (*it).RERL);
711 AssignUWord8(buffer, pos, (*it).Gmin);
712 AssignUWord8(buffer, pos, (*it).Rfactor);
713 AssignUWord8(buffer, pos, (*it).extRfactor);
714 AssignUWord8(buffer, pos, (*it).MOSLQ);
715 AssignUWord8(buffer, pos, (*it).MOSCQ);
716 AssignUWord8(buffer, pos, (*it).RXconfig);
717 AssignUWord8(buffer, pos, 0);
718 AssignUWord16(buffer, pos, (*it).JBnominal);
719 AssignUWord16(buffer, pos, (*it).JBmax);
720 AssignUWord16(buffer, pos, (*it).JBabsMax);
721 }
722 }
723 } // namespace
724
Append(RtcpPacket * packet)725 void RtcpPacket::Append(RtcpPacket* packet) {
726 assert(packet);
727 appended_packets_.push_back(packet);
728 }
729
Build() const730 RawPacket RtcpPacket::Build() const {
731 size_t length = 0;
732 uint8_t packet[IP_PACKET_SIZE];
733 CreateAndAddAppended(packet, &length, IP_PACKET_SIZE);
734 return RawPacket(packet, length);
735 }
736
Build(uint8_t * packet,size_t * length,size_t max_length) const737 void RtcpPacket::Build(uint8_t* packet,
738 size_t* length,
739 size_t max_length) const {
740 *length = 0;
741 CreateAndAddAppended(packet, length, max_length);
742 }
743
CreateAndAddAppended(uint8_t * packet,size_t * length,size_t max_length) const744 void RtcpPacket::CreateAndAddAppended(uint8_t* packet,
745 size_t* length,
746 size_t max_length) const {
747 Create(packet, length, max_length);
748 for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
749 it != appended_packets_.end(); ++it) {
750 (*it)->CreateAndAddAppended(packet, length, max_length);
751 }
752 }
753
Create(uint8_t * packet,size_t * length,size_t max_length) const754 void Empty::Create(uint8_t* packet, size_t* length, size_t max_length) const {
755 }
756
Create(uint8_t * packet,size_t * length,size_t max_length) const757 void SenderReport::Create(uint8_t* packet,
758 size_t* length,
759 size_t max_length) const {
760 if (*length + BlockLength() > max_length) {
761 LOG(LS_WARNING) << "Max packet size reached.";
762 return;
763 }
764 CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, length);
765 CreateReportBlocks(report_blocks_, packet, length);
766 }
767
WithReportBlock(ReportBlock * block)768 void SenderReport::WithReportBlock(ReportBlock* block) {
769 assert(block);
770 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
771 LOG(LS_WARNING) << "Max report blocks reached.";
772 return;
773 }
774 report_blocks_.push_back(block->report_block_);
775 sr_.NumberOfReportBlocks = report_blocks_.size();
776 }
777
Create(uint8_t * packet,size_t * length,size_t max_length) const778 void ReceiverReport::Create(uint8_t* packet,
779 size_t* length,
780 size_t max_length) const {
781 if (*length + BlockLength() > max_length) {
782 LOG(LS_WARNING) << "Max packet size reached.";
783 return;
784 }
785 CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, length);
786 CreateReportBlocks(report_blocks_, packet, length);
787 }
788
WithReportBlock(ReportBlock * block)789 void ReceiverReport::WithReportBlock(ReportBlock* block) {
790 assert(block);
791 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
792 LOG(LS_WARNING) << "Max report blocks reached.";
793 return;
794 }
795 report_blocks_.push_back(block->report_block_);
796 rr_.NumberOfReportBlocks = report_blocks_.size();
797 }
798
Create(uint8_t * packet,size_t * length,size_t max_length) const799 void Ij::Create(uint8_t* packet, size_t* length, size_t max_length) const {
800 if (*length + BlockLength() > max_length) {
801 LOG(LS_WARNING) << "Max packet size reached.";
802 return;
803 }
804 CreateIj(ij_items_, packet, length);
805 }
806
WithJitterItem(uint32_t jitter)807 void Ij::WithJitterItem(uint32_t jitter) {
808 if (ij_items_.size() >= kMaxNumberOfIjItems) {
809 LOG(LS_WARNING) << "Max inter-arrival jitter items reached.";
810 return;
811 }
812 ij_items_.push_back(jitter);
813 }
814
Create(uint8_t * packet,size_t * length,size_t max_length) const815 void Sdes::Create(uint8_t* packet, size_t* length, size_t max_length) const {
816 assert(!chunks_.empty());
817 if (*length + BlockLength() > max_length) {
818 LOG(LS_WARNING) << "Max packet size reached.";
819 return;
820 }
821 CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, length);
822 }
823
WithCName(uint32_t ssrc,std::string cname)824 void Sdes::WithCName(uint32_t ssrc, std::string cname) {
825 assert(cname.length() <= 0xff);
826 if (chunks_.size() >= kMaxNumberOfChunks) {
827 LOG(LS_WARNING) << "Max SDES chunks reached.";
828 return;
829 }
830 // In each chunk, the list of items must be terminated by one or more null
831 // octets. The next chunk must start on a 32-bit boundary.
832 // CNAME (1 byte) | length (1 byte) | name | padding.
833 int null_octets = 4 - ((2 + cname.length()) % 4);
834 Chunk chunk;
835 chunk.ssrc = ssrc;
836 chunk.name = cname;
837 chunk.null_octets = null_octets;
838 chunks_.push_back(chunk);
839 }
840
BlockLength() const841 size_t Sdes::BlockLength() const {
842 // Header (4 bytes).
843 // Chunk:
844 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
845 size_t length = kHeaderLength;
846 for (std::vector<Chunk>::const_iterator it = chunks_.begin();
847 it != chunks_.end(); ++it) {
848 length += 6 + (*it).name.length() + (*it).null_octets;
849 }
850 assert(length % 4 == 0);
851 return length;
852 }
853
Create(uint8_t * packet,size_t * length,size_t max_length) const854 void Bye::Create(uint8_t* packet, size_t* length, size_t max_length) const {
855 if (*length + BlockLength() > max_length) {
856 LOG(LS_WARNING) << "Max packet size reached.";
857 return;
858 }
859 CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, length);
860 }
861
WithCsrc(uint32_t csrc)862 void Bye::WithCsrc(uint32_t csrc) {
863 if (csrcs_.size() >= kMaxNumberOfCsrcs) {
864 LOG(LS_WARNING) << "Max CSRC size reached.";
865 return;
866 }
867 csrcs_.push_back(csrc);
868 }
869
Create(uint8_t * packet,size_t * length,size_t max_length) const870 void App::Create(uint8_t* packet, size_t* length, size_t max_length) const {
871 if (*length + BlockLength() > max_length) {
872 LOG(LS_WARNING) << "Max packet size reached.";
873 return;
874 }
875 CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, length);
876 }
877
Create(uint8_t * packet,size_t * length,size_t max_length) const878 void Pli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
879 if (*length + BlockLength() > max_length) {
880 LOG(LS_WARNING) << "Max packet size reached.";
881 return;
882 }
883 CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, length);
884 }
885
Create(uint8_t * packet,size_t * length,size_t max_length) const886 void Sli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
887 if (*length + BlockLength() > max_length) {
888 LOG(LS_WARNING) << "Max packet size reached.";
889 return;
890 }
891 CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet,
892 length);
893 }
894
Create(uint8_t * packet,size_t * length,size_t max_length) const895 void Nack::Create(uint8_t* packet, size_t* length, size_t max_length) const {
896 assert(!nack_fields_.empty());
897 if (*length + BlockLength() > max_length) {
898 LOG(LS_WARNING) << "Max packet size reached.";
899 return;
900 }
901 CreateNack(nack_, nack_fields_, BlockToHeaderLength(BlockLength()), packet,
902 length);
903 }
904
WithList(const uint16_t * nack_list,int length)905 void Nack::WithList(const uint16_t* nack_list, int length) {
906 assert(nack_list);
907 assert(nack_fields_.empty());
908 int i = 0;
909 while (i < length) {
910 uint16_t pid = nack_list[i++];
911 // Bitmask specifies losses in any of the 16 packets following the pid.
912 uint16_t bitmask = 0;
913 while (i < length) {
914 int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1;
915 if (shift >= 0 && shift <= 15) {
916 bitmask |= (1 << shift);
917 ++i;
918 } else {
919 break;
920 }
921 }
922 RTCPUtility::RTCPPacketRTPFBNACKItem item;
923 item.PacketID = pid;
924 item.BitMask = bitmask;
925 nack_fields_.push_back(item);
926 }
927 }
928
Create(uint8_t * packet,size_t * length,size_t max_length) const929 void Rpsi::Create(uint8_t* packet, size_t* length, size_t max_length) const {
930 assert(rpsi_.NumberOfValidBits > 0);
931 if (*length + BlockLength() > max_length) {
932 LOG(LS_WARNING) << "Max packet size reached.";
933 return;
934 }
935 CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet,
936 length);
937 }
938
WithPictureId(uint64_t picture_id)939 void Rpsi::WithPictureId(uint64_t picture_id) {
940 const uint32_t kPidBits = 7;
941 const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL;
942 uint8_t required_bytes = 0;
943 uint64_t shifted_pid = picture_id;
944 do {
945 ++required_bytes;
946 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
947 } while (shifted_pid > 0);
948
949 // Convert picture id to native bit string (natively defined by the video
950 // codec).
951 int pos = 0;
952 for (int i = required_bytes - 1; i > 0; i--) {
953 rpsi_.NativeBitString[pos++] =
954 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
955 }
956 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
957 rpsi_.NumberOfValidBits = pos * 8;
958
959 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
960 padding_bytes_ = 4 - ((2 + required_bytes) % 4);
961 if (padding_bytes_ == 4) {
962 padding_bytes_ = 0;
963 }
964 }
965
Create(uint8_t * packet,size_t * length,size_t max_length) const966 void Fir::Create(uint8_t* packet, size_t* length, size_t max_length) const {
967 if (*length + BlockLength() > max_length) {
968 LOG(LS_WARNING) << "Max packet size reached.";
969 return;
970 }
971 CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet,
972 length);
973 }
974
Create(uint8_t * packet,size_t * length,size_t max_length) const975 void Remb::Create(uint8_t* packet, size_t* length, size_t max_length) const {
976 if (*length + BlockLength() > max_length) {
977 LOG(LS_WARNING) << "Max packet size reached.";
978 return;
979 }
980 CreateRemb(remb_, remb_item_, BlockToHeaderLength(BlockLength()), packet,
981 length);
982 }
983
AppliesTo(uint32_t ssrc)984 void Remb::AppliesTo(uint32_t ssrc) {
985 if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) {
986 LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached.";
987 return;
988 }
989 remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc;
990 }
991
Create(uint8_t * packet,size_t * length,size_t max_length) const992 void Tmmbr::Create(uint8_t* packet, size_t* length, size_t max_length) const {
993 if (*length + BlockLength() > max_length) {
994 LOG(LS_WARNING) << "Max packet size reached.";
995 return;
996 }
997 CreateTmmbr(tmmbr_, tmmbr_item_, BlockToHeaderLength(BlockLength()), packet,
998 length);
999 }
1000
WithTmmbr(uint32_t ssrc,uint32_t bitrate_kbps,uint16_t overhead)1001 void Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) {
1002 assert(overhead <= 0x1ff);
1003 if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) {
1004 LOG(LS_WARNING) << "Max TMMBN size reached.";
1005 return;
1006 }
1007 RTCPPacketRTPFBTMMBRItem tmmbn_item;
1008 tmmbn_item.SSRC = ssrc;
1009 tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps;
1010 tmmbn_item.MeasuredOverhead = overhead;
1011 tmmbn_items_.push_back(tmmbn_item);
1012 }
1013
Create(uint8_t * packet,size_t * length,size_t max_length) const1014 void Tmmbn::Create(uint8_t* packet, size_t* length, size_t max_length) const {
1015 if (*length + BlockLength() > max_length) {
1016 LOG(LS_WARNING) << "Max packet size reached.";
1017 return;
1018 }
1019 CreateTmmbn(tmmbn_, tmmbn_items_, BlockToHeaderLength(BlockLength()), packet,
1020 length);
1021 }
1022
Create(uint8_t * packet,size_t * length,size_t max_length) const1023 void Xr::Create(uint8_t* packet, size_t* length, size_t max_length) const {
1024 if (*length + BlockLength() > max_length) {
1025 LOG(LS_WARNING) << "Max packet size reached.";
1026 return;
1027 }
1028 CreateXrHeader(xr_header_, BlockToHeaderLength(BlockLength()), packet,
1029 length);
1030 CreateRrtr(rrtr_blocks_, packet, length);
1031 CreateDlrr(dlrr_blocks_, packet, length);
1032 CreateVoipMetric(voip_metric_blocks_, packet, length);
1033 }
1034
WithRrtr(Rrtr * rrtr)1035 void Xr::WithRrtr(Rrtr* rrtr) {
1036 assert(rrtr);
1037 if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) {
1038 LOG(LS_WARNING) << "Max RRTR blocks reached.";
1039 return;
1040 }
1041 rrtr_blocks_.push_back(rrtr->rrtr_block_);
1042 }
1043
WithDlrr(Dlrr * dlrr)1044 void Xr::WithDlrr(Dlrr* dlrr) {
1045 assert(dlrr);
1046 if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) {
1047 LOG(LS_WARNING) << "Max DLRR blocks reached.";
1048 return;
1049 }
1050 dlrr_blocks_.push_back(dlrr->dlrr_block_);
1051 }
1052
WithVoipMetric(VoipMetric * voip_metric)1053 void Xr::WithVoipMetric(VoipMetric* voip_metric) {
1054 assert(voip_metric);
1055 if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) {
1056 LOG(LS_WARNING) << "Max Voip Metric blocks reached.";
1057 return;
1058 }
1059 voip_metric_blocks_.push_back(voip_metric->metric_);
1060 }
1061
DlrrLength() const1062 size_t Xr::DlrrLength() const {
1063 const size_t kBlockHeaderLen = 4;
1064 const size_t kSubBlockLen = 12;
1065 size_t length = 0;
1066 for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin();
1067 it != dlrr_blocks_.end(); ++it) {
1068 if (!(*it).empty()) {
1069 length += kBlockHeaderLen + kSubBlockLen * (*it).size();
1070 }
1071 }
1072 return length;
1073 }
1074
WithDlrrItem(uint32_t ssrc,uint32_t last_rr,uint32_t delay_last_rr)1075 void Dlrr::WithDlrrItem(uint32_t ssrc,
1076 uint32_t last_rr,
1077 uint32_t delay_last_rr) {
1078 if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) {
1079 LOG(LS_WARNING) << "Max DLRR items reached.";
1080 return;
1081 }
1082 RTCPPacketXRDLRRReportBlockItem dlrr;
1083 dlrr.SSRC = ssrc;
1084 dlrr.LastRR = last_rr;
1085 dlrr.DelayLastRR = delay_last_rr;
1086 dlrr_block_.push_back(dlrr);
1087 }
1088
1089 } // namespace rtcp
1090 } // namespace webrtc
1091