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