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
19using webrtc::RTCPUtility::kBtDlrr;
20using webrtc::RTCPUtility::kBtReceiverReferenceTime;
21using webrtc::RTCPUtility::kBtVoipMetric;
22
23using webrtc::RTCPUtility::PT_APP;
24using webrtc::RTCPUtility::PT_IJ;
25using webrtc::RTCPUtility::PT_PSFB;
26using webrtc::RTCPUtility::PT_RTPFB;
27using webrtc::RTCPUtility::PT_SDES;
28using webrtc::RTCPUtility::PT_SR;
29using webrtc::RTCPUtility::PT_XR;
30
31using webrtc::RTCPUtility::RTCPPacketAPP;
32using webrtc::RTCPUtility::RTCPPacketPSFBAPP;
33using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
34using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
35using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
36using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
37using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
38using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
39using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
40using webrtc::RTCPUtility::RTCPPacketSR;
41using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
42using webrtc::RTCPUtility::RTCPPacketXR;
43
44namespace webrtc {
45namespace rtcp {
46namespace {
47// Unused SSRC of media source, set to 0.
48const uint32_t kUnusedMediaSourceSsrc0 = 0;
49
50void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
51  buffer[(*offset)++] = value;
52}
53void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
54  ByteWriter<uint16_t>::WriteBigEndian(buffer + *offset, value);
55  *offset += 2;
56}
57void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
58  ByteWriter<uint32_t, 3>::WriteBigEndian(buffer + *offset, value);
59  *offset += 3;
60}
61void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
62  ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value);
63  *offset += 4;
64}
65
66void 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
103void 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
131void 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
166void 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
194void 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
222void 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
252void 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
289void CreateXrHeader(const RTCPPacketXR& header,
290                    uint8_t* buffer,
291                    size_t* pos) {
292  AssignUWord32(buffer, pos, header.OriginatorSSRC);
293}
294
295}  // namespace
296
297void RtcpPacket::Append(RtcpPacket* packet) {
298  assert(packet);
299  appended_packets_.push_back(packet);
300}
301
302rtc::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
327bool RtcpPacket::Build(PacketReadyCallback* callback) const {
328  uint8_t buffer[IP_PACKET_SIZE];
329  return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback);
330}
331
332bool 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
341bool 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
354bool 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
364size_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
380void 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
393bool 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
407bool 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
417bool 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
431bool 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
449size_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
460bool 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
475void 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
502bool 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
516bool 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
530void 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
538bool 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
563bool 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
573bool 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
583bool 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
593size_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
601RawPacket::RawPacket(size_t buffer_length)
602    : buffer_length_(buffer_length), length_(0) {
603  buffer_.reset(new uint8_t[buffer_length]);
604}
605
606RawPacket::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
612const uint8_t* RawPacket::Buffer() const {
613  return buffer_.get();
614}
615
616uint8_t* RawPacket::MutableBuffer() {
617  return buffer_.get();
618}
619
620size_t RawPacket::BufferLength() const {
621  return buffer_length_;
622}
623
624size_t RawPacket::Length() const {
625  return length_;
626}
627
628void RawPacket::SetLength(size_t length) {
629  assert(length <= buffer_length_);
630  length_ = length;
631}
632
633}  // namespace rtcp
634}  // namespace webrtc
635