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 "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
     14 #include "webrtc/system_wrappers/interface/logging.h"
     15 
     16 using webrtc::RTCPUtility::PT_APP;
     17 using webrtc::RTCPUtility::PT_BYE;
     18 using webrtc::RTCPUtility::PT_IJ;
     19 using webrtc::RTCPUtility::PT_PSFB;
     20 using webrtc::RTCPUtility::PT_RR;
     21 using webrtc::RTCPUtility::PT_RTPFB;
     22 using webrtc::RTCPUtility::PT_SDES;
     23 using webrtc::RTCPUtility::PT_SR;
     24 using webrtc::RTCPUtility::PT_XR;
     25 
     26 using webrtc::RTCPUtility::RTCPPacketAPP;
     27 using webrtc::RTCPUtility::RTCPPacketBYE;
     28 using webrtc::RTCPUtility::RTCPPacketPSFBAPP;
     29 using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
     30 using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
     31 using webrtc::RTCPUtility::RTCPPacketPSFBPLI;
     32 using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
     33 using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
     34 using webrtc::RTCPUtility::RTCPPacketPSFBSLI;
     35 using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem;
     36 using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
     37 using webrtc::RTCPUtility::RTCPPacketRR;
     38 using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
     39 using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
     40 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN;
     41 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem;
     42 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR;
     43 using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem;
     44 using webrtc::RTCPUtility::RTCPPacketSR;
     45 using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
     46 using webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem;
     47 using webrtc::RTCPUtility::RTCPPacketXR;
     48 using webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem;
     49 
     50 namespace webrtc {
     51 namespace rtcp {
     52 namespace {
     53 // Unused SSRC of media source, set to 0.
     54 const uint32_t kUnusedMediaSourceSsrc0 = 0;
     55 
     56 void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
     57   buffer[(*offset)++] = value;
     58 }
     59 void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
     60   ModuleRTPUtility::AssignUWord16ToBuffer(buffer + *offset, value);
     61   *offset += 2;
     62 }
     63 void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
     64   ModuleRTPUtility::AssignUWord24ToBuffer(buffer + *offset, value);
     65   *offset += 3;
     66 }
     67 void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
     68   ModuleRTPUtility::AssignUWord32ToBuffer(buffer + *offset, value);
     69   *offset += 4;
     70 }
     71 
     72 size_t BlockToHeaderLength(size_t length_in_bytes) {
     73   // Length in 32-bit words minus 1.
     74   assert(length_in_bytes > 0);
     75   assert(length_in_bytes % 4 == 0);
     76   return (length_in_bytes / 4) - 1;
     77 }
     78 
     79 // From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
     80 //
     81 // RTP header format.
     82 //   0                   1                   2                   3
     83 //   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
     84 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     85 //  |V=2|P| RC/FMT  |      PT       |             length            |
     86 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     87 
     88 void CreateHeader(uint8_t count_or_format,  // Depends on packet type.
     89                   uint8_t packet_type,
     90                   size_t length,
     91                   uint8_t* buffer,
     92                   size_t* pos) {
     93   assert(length <= 0xffff);
     94   const uint8_t kVersion = 2;
     95   AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
     96   AssignUWord8(buffer, pos, packet_type);
     97   AssignUWord16(buffer, pos, length);
     98 }
     99 
    100 //  Sender report (SR) (RFC 3550).
    101 //   0                   1                   2                   3
    102 //   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
    103 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    104 //  |V=2|P|    RC   |   PT=SR=200   |             length            |
    105 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    106 //  |                         SSRC of sender                        |
    107 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    108 //  |              NTP timestamp, most significant word             |
    109 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    110 //  |             NTP timestamp, least significant word             |
    111 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    112 //  |                         RTP timestamp                         |
    113 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    114 //  |                     sender's packet count                     |
    115 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    116 //  |                      sender's octet count                     |
    117 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    118 
    119 void CreateSenderReport(const RTCPPacketSR& sr,
    120                         size_t length,
    121                         uint8_t* buffer,
    122                         size_t* pos) {
    123   CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
    124   AssignUWord32(buffer, pos, sr.SenderSSRC);
    125   AssignUWord32(buffer, pos, sr.NTPMostSignificant);
    126   AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
    127   AssignUWord32(buffer, pos, sr.RTPTimestamp);
    128   AssignUWord32(buffer, pos, sr.SenderPacketCount);
    129   AssignUWord32(buffer, pos, sr.SenderOctetCount);
    130 }
    131 
    132 //  Receiver report (RR), header (RFC 3550).
    133 //
    134 //   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
    135 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    136 //  |V=2|P|    RC   |   PT=RR=201   |             length            |
    137 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    138 //  |                     SSRC of packet sender                     |
    139 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    140 
    141 void CreateReceiverReport(const RTCPPacketRR& rr,
    142                           size_t length,
    143                           uint8_t* buffer,
    144                           size_t* pos) {
    145   CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
    146   AssignUWord32(buffer, pos, rr.SenderSSRC);
    147 }
    148 
    149 //  Report block (RFC 3550).
    150 //
    151 //   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
    152 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    153 //  |                 SSRC_1 (SSRC of first source)                 |
    154 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    155 //  | fraction lost |       cumulative number of packets lost       |
    156 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    157 //  |           extended highest sequence number received           |
    158 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    159 //  |                      interarrival jitter                      |
    160 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    161 //  |                         last SR (LSR)                         |
    162 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    163 //  |                   delay since last SR (DLSR)                  |
    164 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    165 
    166 void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
    167                         uint8_t* buffer,
    168                         size_t* pos) {
    169   for (std::vector<RTCPPacketReportBlockItem>::const_iterator
    170        it = blocks.begin(); it != blocks.end(); ++it) {
    171     AssignUWord32(buffer, pos, (*it).SSRC);
    172     AssignUWord8(buffer, pos, (*it).FractionLost);
    173     AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost);
    174     AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber);
    175     AssignUWord32(buffer, pos, (*it).Jitter);
    176     AssignUWord32(buffer, pos, (*it).LastSR);
    177     AssignUWord32(buffer, pos, (*it).DelayLastSR);
    178   }
    179 }
    180 
    181 // Transmission Time Offsets in RTP Streams (RFC 5450).
    182 //
    183 //      0                   1                   2                   3
    184 //      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
    185 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    186 // hdr |V=2|P|    RC   |   PT=IJ=195   |             length            |
    187 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    188 //     |                      inter-arrival jitter                     |
    189 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    190 //     .                                                               .
    191 //     .                                                               .
    192 //     .                                                               .
    193 //     |                      inter-arrival jitter                     |
    194 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    195 
    196 void CreateIj(const std::vector<uint32_t>& ij_items,
    197               uint8_t* buffer,
    198               size_t* pos) {
    199   size_t length = ij_items.size();
    200   CreateHeader(length, PT_IJ, length, buffer, pos);
    201   for (std::vector<uint32_t>::const_iterator it = ij_items.begin();
    202        it != ij_items.end(); ++it) {
    203     AssignUWord32(buffer, pos, *it);
    204   }
    205 }
    206 
    207 // Source Description (SDES) (RFC 3550).
    208 //
    209 //         0                   1                   2                   3
    210 //         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
    211 //        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    212 // header |V=2|P|    SC   |  PT=SDES=202  |             length            |
    213 //        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    214 // chunk  |                          SSRC/CSRC_1                          |
    215 //   1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    216 //        |                           SDES items                          |
    217 //        |                              ...                              |
    218 //        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    219 // chunk  |                          SSRC/CSRC_2                          |
    220 //   2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    221 //        |                           SDES items                          |
    222 //        |                              ...                              |
    223 //        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    224 //
    225 // Canonical End-Point Identifier SDES Item (CNAME)
    226 //
    227 //    0                   1                   2                   3
    228 //    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
    229 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    230 //   |    CNAME=1    |     length    | user and domain name        ...
    231 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    232 
    233 void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
    234                 size_t length,
    235                 uint8_t* buffer,
    236                 size_t* pos) {
    237   CreateHeader(chunks.size(), PT_SDES, length, buffer, pos);
    238   const uint8_t kSdesItemType = 1;
    239   for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
    240        it != chunks.end(); ++it) {
    241     AssignUWord32(buffer, pos, (*it).ssrc);
    242     AssignUWord8(buffer, pos, kSdesItemType);
    243     AssignUWord8(buffer, pos, (*it).name.length());
    244     memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
    245     *pos += (*it).name.length();
    246     memset(buffer + *pos, 0, (*it).null_octets);
    247     *pos += (*it).null_octets;
    248   }
    249 }
    250 
    251 // Bye packet (BYE) (RFC 3550).
    252 //
    253 //        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
    254 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    255 //       |V=2|P|    SC   |   PT=BYE=203  |             length            |
    256 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    257 //       |                           SSRC/CSRC                           |
    258 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    259 //       :                              ...                              :
    260 //       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    261 // (opt) |     length    |               reason for leaving            ...
    262 //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    263 
    264 void CreateBye(const RTCPPacketBYE& bye,
    265                const std::vector<uint32_t>& csrcs,
    266                size_t length,
    267                uint8_t* buffer,
    268                size_t* pos) {
    269   CreateHeader(length, PT_BYE, length, buffer, pos);
    270   AssignUWord32(buffer, pos, bye.SenderSSRC);
    271   for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
    272        it != csrcs.end(); ++it) {
    273     AssignUWord32(buffer, pos, *it);
    274   }
    275 }
    276 
    277 // Application-Defined packet (APP) (RFC 3550).
    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| subtype |   PT=APP=204  |             length            |
    283 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    284 //  |                           SSRC/CSRC                           |
    285 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    286 //  |                          name (ASCII)                         |
    287 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    288 //  |                   application-dependent data                ...
    289 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    290 
    291 void CreateApp(const RTCPPacketAPP& app,
    292                uint32_t ssrc,
    293                size_t length,
    294                uint8_t* buffer,
    295                size_t* pos) {
    296   CreateHeader(app.SubType, PT_APP, length, buffer, pos);
    297   AssignUWord32(buffer, pos, ssrc);
    298   AssignUWord32(buffer, pos, app.Name);
    299   memcpy(buffer + *pos, app.Data, app.Size);
    300   *pos += app.Size;
    301 }
    302 
    303 // RFC 4585: Feedback format.
    304 //
    305 // Common packet format:
    306 //
    307 //    0                   1                   2                   3
    308 //    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
    309 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    310 //   |V=2|P|   FMT   |       PT      |          length               |
    311 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    312 //   |                  SSRC of packet sender                        |
    313 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    314 //   |                  SSRC of media source                         |
    315 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    316 //   :            Feedback Control Information (FCI)                 :
    317 //   :
    318 //
    319 
    320 // Picture loss indication (PLI) (RFC 4585).
    321 //
    322 // FCI: no feedback control information.
    323 
    324 void CreatePli(const RTCPPacketPSFBPLI& pli,
    325                size_t length,
    326                uint8_t* buffer,
    327                size_t* pos) {
    328   const uint8_t kFmt = 1;
    329   CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
    330   AssignUWord32(buffer, pos, pli.SenderSSRC);
    331   AssignUWord32(buffer, pos, pli.MediaSSRC);
    332 }
    333 
    334 // Slice loss indication (SLI) (RFC 4585).
    335 //
    336 // FCI:
    337 //
    338 //    0                   1                   2                   3
    339 //    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
    340 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    341 //   |            First        |        Number           | PictureID |
    342 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    343 
    344 void CreateSli(const RTCPPacketPSFBSLI& sli,
    345                const RTCPPacketPSFBSLIItem& sli_item,
    346                size_t length,
    347                uint8_t* buffer,
    348                size_t* pos) {
    349   const uint8_t kFmt = 2;
    350   CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
    351   AssignUWord32(buffer, pos, sli.SenderSSRC);
    352   AssignUWord32(buffer, pos, sli.MediaSSRC);
    353 
    354   AssignUWord8(buffer, pos, sli_item.FirstMB >> 5);
    355   AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) +
    356                             ((sli_item.NumberOfMB >> 10) & 0x07));
    357   AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2);
    358   AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId);
    359 }
    360 
    361 // Generic NACK (RFC 4585).
    362 //
    363 // FCI:
    364 //
    365 //    0                   1                   2                   3
    366 //    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
    367 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    368 //   |            PID                |             BLP               |
    369 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    370 
    371 void CreateNack(const RTCPPacketRTPFBNACK& nack,
    372                 const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
    373                 size_t length,
    374                 uint8_t* buffer,
    375                 size_t* pos) {
    376   const uint8_t kFmt = 1;
    377   CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
    378   AssignUWord32(buffer, pos, nack.SenderSSRC);
    379   AssignUWord32(buffer, pos, nack.MediaSSRC);
    380   for (std::vector<RTCPPacketRTPFBNACKItem>::const_iterator
    381       it = nack_fields.begin(); it != nack_fields.end(); ++it) {
    382     AssignUWord16(buffer, pos, (*it).PacketID);
    383     AssignUWord16(buffer, pos, (*it).BitMask);
    384   }
    385 }
    386 
    387 // Reference picture selection indication (RPSI) (RFC 4585).
    388 //
    389 // FCI:
    390 //
    391 //    0                   1                   2                   3
    392 //    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
    393 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    394 //   |      PB       |0| Payload Type|    Native RPSI bit string     |
    395 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    396 //   |   defined per codec          ...                | Padding (0) |
    397 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    398 
    399 void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
    400                 uint8_t padding_bytes,
    401                 size_t length,
    402                 uint8_t* buffer,
    403                 size_t* pos) {
    404   // Native bit string should be a multiple of 8 bits.
    405   assert(rpsi.NumberOfValidBits % 8 == 0);
    406   const uint8_t kFmt = 3;
    407   CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
    408   AssignUWord32(buffer, pos, rpsi.SenderSSRC);
    409   AssignUWord32(buffer, pos, rpsi.MediaSSRC);
    410   AssignUWord8(buffer, pos, padding_bytes * 8);
    411   AssignUWord8(buffer, pos, rpsi.PayloadType);
    412   memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
    413   *pos += rpsi.NumberOfValidBits / 8;
    414   memset(buffer + *pos, 0, padding_bytes);
    415   *pos += padding_bytes;
    416 }
    417 
    418 // Full intra request (FIR) (RFC 5104).
    419 //
    420 // FCI:
    421 //
    422 //    0                   1                   2                   3
    423 //    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
    424 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    425 //   |                              SSRC                             |
    426 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    427 //   | Seq nr.       |    Reserved                                   |
    428 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    429 
    430 void CreateFir(const RTCPPacketPSFBFIR& fir,
    431                const RTCPPacketPSFBFIRItem& fir_item,
    432                size_t length,
    433                uint8_t* buffer,
    434                size_t* pos) {
    435   const uint8_t kFmt = 4;
    436   CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
    437   AssignUWord32(buffer, pos, fir.SenderSSRC);
    438   AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
    439   AssignUWord32(buffer, pos, fir_item.SSRC);
    440   AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
    441   AssignUWord24(buffer, pos, 0);
    442 }
    443 }  // namespace
    444 
    445 void RtcpPacket::Append(RtcpPacket* packet) {
    446   assert(packet);
    447   appended_packets_.push_back(packet);
    448 }
    449 
    450 RawPacket RtcpPacket::Build() const {
    451   size_t length = 0;
    452   uint8_t packet[IP_PACKET_SIZE];
    453   CreateAndAddAppended(packet, &length, IP_PACKET_SIZE);
    454   return RawPacket(packet, length);
    455 }
    456 
    457 void RtcpPacket::Build(uint8_t* packet,
    458                        size_t* length,
    459                        size_t max_length) const {
    460   *length = 0;
    461   CreateAndAddAppended(packet, length, max_length);
    462 }
    463 
    464 void RtcpPacket::CreateAndAddAppended(uint8_t* packet,
    465                                       size_t* length,
    466                                       size_t max_length) const {
    467   Create(packet, length, max_length);
    468   for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
    469       it != appended_packets_.end(); ++it) {
    470     (*it)->CreateAndAddAppended(packet, length, max_length);
    471   }
    472 }
    473 
    474 void Empty::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    475 }
    476 
    477 void SenderReport::Create(uint8_t* packet,
    478                           size_t* length,
    479                           size_t max_length) const {
    480   if (*length + BlockLength() > max_length) {
    481     LOG(LS_WARNING) << "Max packet size reached.";
    482     return;
    483   }
    484   CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, length);
    485   CreateReportBlocks(report_blocks_, packet, length);
    486 }
    487 
    488 void SenderReport::WithReportBlock(ReportBlock* block) {
    489   assert(block);
    490   if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
    491     LOG(LS_WARNING) << "Max report blocks reached.";
    492     return;
    493   }
    494   report_blocks_.push_back(block->report_block_);
    495   sr_.NumberOfReportBlocks = report_blocks_.size();
    496 }
    497 
    498 void ReceiverReport::Create(uint8_t* packet,
    499                             size_t* length,
    500                             size_t max_length) const {
    501   if (*length + BlockLength() > max_length) {
    502     LOG(LS_WARNING) << "Max packet size reached.";
    503     return;
    504   }
    505   CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, length);
    506   CreateReportBlocks(report_blocks_, packet, length);
    507 }
    508 
    509 void ReceiverReport::WithReportBlock(ReportBlock* block) {
    510   assert(block);
    511   if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
    512     LOG(LS_WARNING) << "Max report blocks reached.";
    513     return;
    514   }
    515   report_blocks_.push_back(block->report_block_);
    516   rr_.NumberOfReportBlocks = report_blocks_.size();
    517 }
    518 
    519 void Ij::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    520   if (*length + BlockLength() > max_length) {
    521     LOG(LS_WARNING) << "Max packet size reached.";
    522     return;
    523   }
    524   CreateIj(ij_items_, packet, length);
    525 }
    526 
    527 void Ij::WithJitterItem(uint32_t jitter) {
    528   if (ij_items_.size() >= kMaxNumberOfIjItems) {
    529     LOG(LS_WARNING) << "Max inter-arrival jitter items reached.";
    530     return;
    531   }
    532   ij_items_.push_back(jitter);
    533 }
    534 
    535 void Sdes::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    536   assert(!chunks_.empty());
    537   if (*length + BlockLength() > max_length) {
    538     LOG(LS_WARNING) << "Max packet size reached.";
    539     return;
    540   }
    541   CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, length);
    542 }
    543 
    544 void Sdes::WithCName(uint32_t ssrc, std::string cname) {
    545   assert(cname.length() <= 0xff);
    546   if (chunks_.size() >= kMaxNumberOfChunks) {
    547     LOG(LS_WARNING) << "Max SDES chunks reached.";
    548     return;
    549   }
    550   // In each chunk, the list of items must be terminated by one or more null
    551   // octets. The next chunk must start on a 32-bit boundary.
    552   // CNAME (1 byte) | length (1 byte) | name | padding.
    553   int null_octets = 4 - ((2 + cname.length()) % 4);
    554   Chunk chunk;
    555   chunk.ssrc = ssrc;
    556   chunk.name = cname;
    557   chunk.null_octets = null_octets;
    558   chunks_.push_back(chunk);
    559 }
    560 
    561 size_t Sdes::BlockLength() const {
    562   // Header (4 bytes).
    563   // Chunk:
    564   // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
    565   size_t length = kHeaderLength;
    566   for (std::vector<Chunk>::const_iterator it = chunks_.begin();
    567        it != chunks_.end(); ++it) {
    568     length += 6 + (*it).name.length() + (*it).null_octets;
    569   }
    570   assert(length % 4 == 0);
    571   return length;
    572 }
    573 
    574 void Bye::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    575   if (*length + BlockLength() > max_length) {
    576     LOG(LS_WARNING) << "Max packet size reached.";
    577     return;
    578   }
    579   CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, length);
    580 }
    581 
    582 void Bye::WithCsrc(uint32_t csrc) {
    583   if (csrcs_.size() >= kMaxNumberOfCsrcs) {
    584     LOG(LS_WARNING) << "Max CSRC size reached.";
    585     return;
    586   }
    587   csrcs_.push_back(csrc);
    588 }
    589 
    590 void App::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    591   if (*length + BlockLength() > max_length) {
    592     LOG(LS_WARNING) << "Max packet size reached.";
    593     return;
    594   }
    595   CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, length);
    596 }
    597 
    598 void Pli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    599   if (*length + BlockLength() > max_length) {
    600     LOG(LS_WARNING) << "Max packet size reached.";
    601     return;
    602   }
    603   CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, length);
    604 }
    605 
    606 void Sli::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    607   if (*length + BlockLength() > max_length) {
    608     LOG(LS_WARNING) << "Max packet size reached.";
    609     return;
    610   }
    611   CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet,
    612             length);
    613 }
    614 
    615 void Nack::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    616   assert(!nack_fields_.empty());
    617   if (*length + BlockLength() > max_length) {
    618     LOG(LS_WARNING) << "Max packet size reached.";
    619     return;
    620   }
    621   CreateNack(nack_, nack_fields_, BlockToHeaderLength(BlockLength()), packet,
    622              length);
    623 }
    624 
    625 void Nack::WithList(const uint16_t* nack_list, int length) {
    626   assert(nack_list);
    627   assert(nack_fields_.empty());
    628   int i = 0;
    629   while (i < length) {
    630     uint16_t pid = nack_list[i++];
    631     // Bitmask specifies losses in any of the 16 packets following the pid.
    632     uint16_t bitmask = 0;
    633     while (i < length) {
    634       int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1;
    635       if (shift >= 0 && shift <= 15) {
    636         bitmask |= (1 << shift);
    637         ++i;
    638       } else {
    639         break;
    640       }
    641     }
    642     RTCPUtility::RTCPPacketRTPFBNACKItem item;
    643     item.PacketID = pid;
    644     item.BitMask = bitmask;
    645     nack_fields_.push_back(item);
    646   }
    647 }
    648 
    649 void Rpsi::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    650   assert(rpsi_.NumberOfValidBits > 0);
    651   if (*length + BlockLength() > max_length) {
    652     LOG(LS_WARNING) << "Max packet size reached.";
    653     return;
    654   }
    655   CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet,
    656              length);
    657 }
    658 
    659 void Rpsi::WithPictureId(uint64_t picture_id) {
    660   const uint32_t kPidBits = 7;
    661   const uint64_t k7MsbZeroMask = 0x1ffffffffffffff;
    662   uint8_t required_bytes = 0;
    663   uint64_t shifted_pid = picture_id;
    664   do {
    665     ++required_bytes;
    666     shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
    667   } while (shifted_pid > 0);
    668 
    669   // Convert picture id to native bit string (natively defined by the video
    670   // codec).
    671   int pos = 0;
    672   for (int i = required_bytes - 1; i > 0; i--) {
    673     rpsi_.NativeBitString[pos++] =
    674         0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
    675   }
    676   rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
    677   rpsi_.NumberOfValidBits = pos * 8;
    678 
    679   // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
    680   padding_bytes_ = 4 - ((2 + required_bytes) % 4);
    681   if (padding_bytes_ == 4) {
    682     padding_bytes_ = 0;
    683   }
    684 }
    685 
    686 void Fir::Create(uint8_t* packet, size_t* length, size_t max_length) const {
    687   if (*length + BlockLength() > max_length) {
    688     LOG(LS_WARNING) << "Max packet size reached.";
    689     return;
    690   }
    691   CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet,
    692             length);
    693 }
    694 }  // namespace rtcp
    695 }  // namespace webrtc
    696