Home | History | Annotate | Download | only in source
      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 
     50 void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
     51   buffer[(*offset)++] = value;
     52 }
     53 void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
     54   ByteWriter<uint16_t>::WriteBigEndian(buffer + *offset, value);
     55   *offset += 2;
     56 }
     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 }
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    297 void RtcpPacket::Append(RtcpPacket* packet) {
    298   assert(packet);
    299   appended_packets_.push_back(packet);
    300 }
    301 
    302 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 
    327 bool RtcpPacket::Build(PacketReadyCallback* callback) const {
    328   uint8_t buffer[IP_PACKET_SIZE];
    329   return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback);
    330 }
    331 
    332 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 
    341 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 
    354 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 
    364 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 
    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 
    393 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 
    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 
    417 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 
    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 
    449 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 
    460 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 
    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 
    502 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 
    516 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 
    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 
    538 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 
    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 
    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 
    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 
    593 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 
    601 RawPacket::RawPacket(size_t buffer_length)
    602     : buffer_length_(buffer_length), length_(0) {
    603   buffer_.reset(new uint8_t[buffer_length]);
    604 }
    605 
    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 
    612 const uint8_t* RawPacket::Buffer() const {
    613   return buffer_.get();
    614 }
    615 
    616 uint8_t* RawPacket::MutableBuffer() {
    617   return buffer_.get();
    618 }
    619 
    620 size_t RawPacket::BufferLength() const {
    621   return buffer_length_;
    622 }
    623 
    624 size_t RawPacket::Length() const {
    625   return length_;
    626 }
    627 
    628 void RawPacket::SetLength(size_t length) {
    629   assert(length <= buffer_length_);
    630   length_ = length;
    631 }
    632 
    633 }  // namespace rtcp
    634 }  // namespace webrtc
    635