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