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