• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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