1/* 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h" 12 13#include <algorithm> 14 15#include "webrtc/base/checks.h" 16#include "webrtc/base/logging.h" 17#include "webrtc/modules/rtp_rtcp/source/byte_io.h" 18 19using webrtc::RTCPUtility::kBtDlrr; 20using webrtc::RTCPUtility::kBtReceiverReferenceTime; 21using webrtc::RTCPUtility::kBtVoipMetric; 22 23using webrtc::RTCPUtility::PT_APP; 24using webrtc::RTCPUtility::PT_IJ; 25using webrtc::RTCPUtility::PT_PSFB; 26using webrtc::RTCPUtility::PT_RTPFB; 27using webrtc::RTCPUtility::PT_SDES; 28using webrtc::RTCPUtility::PT_SR; 29using webrtc::RTCPUtility::PT_XR; 30 31using webrtc::RTCPUtility::RTCPPacketAPP; 32using webrtc::RTCPUtility::RTCPPacketPSFBAPP; 33using webrtc::RTCPUtility::RTCPPacketPSFBFIR; 34using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem; 35using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem; 36using webrtc::RTCPUtility::RTCPPacketPSFBRPSI; 37using webrtc::RTCPUtility::RTCPPacketReportBlockItem; 38using webrtc::RTCPUtility::RTCPPacketRTPFBNACK; 39using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem; 40using webrtc::RTCPUtility::RTCPPacketSR; 41using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem; 42using webrtc::RTCPUtility::RTCPPacketXR; 43 44namespace webrtc { 45namespace rtcp { 46namespace { 47// Unused SSRC of media source, set to 0. 48const uint32_t kUnusedMediaSourceSsrc0 = 0; 49 50void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) { 51 buffer[(*offset)++] = value; 52} 53void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) { 54 ByteWriter<uint16_t>::WriteBigEndian(buffer + *offset, value); 55 *offset += 2; 56} 57void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) { 58 ByteWriter<uint32_t, 3>::WriteBigEndian(buffer + *offset, value); 59 *offset += 3; 60} 61void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { 62 ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value); 63 *offset += 4; 64} 65 66void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10, 67 uint8_t bits_mantissa, 68 uint32_t* mantissa, 69 uint8_t* exp) { 70 // input_base10 = mantissa * 2^exp 71 assert(bits_mantissa <= 32); 72 uint32_t mantissa_max = (1 << bits_mantissa) - 1; 73 uint8_t exponent = 0; 74 for (uint32_t i = 0; i < 64; ++i) { 75 if (input_base10 <= (mantissa_max << i)) { 76 exponent = i; 77 break; 78 } 79 } 80 *exp = exponent; 81 *mantissa = (input_base10 >> exponent); 82} 83 84// Sender report (SR) (RFC 3550). 85// 0 1 2 3 86// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 87// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 88// |V=2|P| RC | PT=SR=200 | length | 89// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 90// | SSRC of sender | 91// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 92// | NTP timestamp, most significant word | 93// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 94// | NTP timestamp, least significant word | 95// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 96// | RTP timestamp | 97// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 98// | sender's packet count | 99// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 100// | sender's octet count | 101// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 102 103void CreateSenderReport(const RTCPPacketSR& sr, 104 uint8_t* buffer, 105 size_t* pos) { 106 AssignUWord32(buffer, pos, sr.SenderSSRC); 107 AssignUWord32(buffer, pos, sr.NTPMostSignificant); 108 AssignUWord32(buffer, pos, sr.NTPLeastSignificant); 109 AssignUWord32(buffer, pos, sr.RTPTimestamp); 110 AssignUWord32(buffer, pos, sr.SenderPacketCount); 111 AssignUWord32(buffer, pos, sr.SenderOctetCount); 112} 113 114// Report block (RFC 3550). 115// 116// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 117// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 118// | SSRC_1 (SSRC of first source) | 119// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 120// | fraction lost | cumulative number of packets lost | 121// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 122// | extended highest sequence number received | 123// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 124// | interarrival jitter | 125// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 126// | last SR (LSR) | 127// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 128// | delay since last SR (DLSR) | 129// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 130 131void CreateReportBlocks(const std::vector<ReportBlock>& blocks, 132 uint8_t* buffer, 133 size_t* pos) { 134 for (const ReportBlock& block : blocks) { 135 block.Create(buffer + *pos); 136 *pos += ReportBlock::kLength; 137 } 138} 139 140// Source Description (SDES) (RFC 3550). 141// 142// 0 1 2 3 143// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 144// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 145// header |V=2|P| SC | PT=SDES=202 | length | 146// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 147// chunk | SSRC/CSRC_1 | 148// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 149// | SDES items | 150// | ... | 151// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 152// chunk | SSRC/CSRC_2 | 153// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 154// | SDES items | 155// | ... | 156// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 157// 158// Canonical End-Point Identifier SDES Item (CNAME) 159// 160// 0 1 2 3 161// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 162// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 163// | CNAME=1 | length | user and domain name ... 164// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 165 166void CreateSdes(const std::vector<Sdes::Chunk>& chunks, 167 uint8_t* buffer, 168 size_t* pos) { 169 const uint8_t kSdesItemType = 1; 170 for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin(); 171 it != chunks.end(); ++it) { 172 AssignUWord32(buffer, pos, (*it).ssrc); 173 AssignUWord8(buffer, pos, kSdesItemType); 174 AssignUWord8(buffer, pos, (*it).name.length()); 175 memcpy(buffer + *pos, (*it).name.data(), (*it).name.length()); 176 *pos += (*it).name.length(); 177 memset(buffer + *pos, 0, (*it).null_octets); 178 *pos += (*it).null_octets; 179 } 180} 181 182// Reference picture selection indication (RPSI) (RFC 4585). 183// 184// FCI: 185// 186// 0 1 2 3 187// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 188// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 189// | PB |0| Payload Type| Native RPSI bit string | 190// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 191// | defined per codec ... | Padding (0) | 192// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 193 194void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi, 195 uint8_t padding_bytes, 196 uint8_t* buffer, 197 size_t* pos) { 198 // Native bit string should be a multiple of 8 bits. 199 assert(rpsi.NumberOfValidBits % 8 == 0); 200 AssignUWord32(buffer, pos, rpsi.SenderSSRC); 201 AssignUWord32(buffer, pos, rpsi.MediaSSRC); 202 AssignUWord8(buffer, pos, padding_bytes * 8); 203 AssignUWord8(buffer, pos, rpsi.PayloadType); 204 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8); 205 *pos += rpsi.NumberOfValidBits / 8; 206 memset(buffer + *pos, 0, padding_bytes); 207 *pos += padding_bytes; 208} 209 210// Full intra request (FIR) (RFC 5104). 211// 212// FCI: 213// 214// 0 1 2 3 215// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 216// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 217// | SSRC | 218// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 219// | Seq nr. | Reserved | 220// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 221 222void CreateFir(const RTCPPacketPSFBFIR& fir, 223 const RTCPPacketPSFBFIRItem& fir_item, 224 uint8_t* buffer, 225 size_t* pos) { 226 AssignUWord32(buffer, pos, fir.SenderSSRC); 227 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 228 AssignUWord32(buffer, pos, fir_item.SSRC); 229 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber); 230 AssignUWord24(buffer, pos, 0); 231} 232 233// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb). 234// 235// 0 1 2 3 236// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 237// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 238// |V=2|P| FMT=15 | PT=206 | length | 239// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 240// | SSRC of packet sender | 241// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 242// | SSRC of media source | 243// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 244// | Unique identifier 'R' 'E' 'M' 'B' | 245// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 246// | Num SSRC | BR Exp | BR Mantissa | 247// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 248// | SSRC feedback | 249// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 250// | ... | 251 252void CreateRemb(const RTCPPacketPSFBAPP& remb, 253 const RTCPPacketPSFBREMBItem& remb_item, 254 uint8_t* buffer, 255 size_t* pos) { 256 uint32_t mantissa = 0; 257 uint8_t exp = 0; 258 ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp); 259 260 AssignUWord32(buffer, pos, remb.SenderSSRC); 261 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 262 AssignUWord8(buffer, pos, 'R'); 263 AssignUWord8(buffer, pos, 'E'); 264 AssignUWord8(buffer, pos, 'M'); 265 AssignUWord8(buffer, pos, 'B'); 266 AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs); 267 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03)); 268 AssignUWord8(buffer, pos, mantissa >> 8); 269 AssignUWord8(buffer, pos, mantissa); 270 for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) { 271 AssignUWord32(buffer, pos, remb_item.SSRCs[i]); 272 } 273} 274 275// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR). 276// 277// Format for XR packets: 278// 279// 0 1 2 3 280// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 281// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 282// |V=2|P|reserved | PT=XR=207 | length | 283// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 284// | SSRC | 285// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 286// : report blocks : 287// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 288 289void CreateXrHeader(const RTCPPacketXR& header, 290 uint8_t* buffer, 291 size_t* pos) { 292 AssignUWord32(buffer, pos, header.OriginatorSSRC); 293} 294 295} // namespace 296 297void RtcpPacket::Append(RtcpPacket* packet) { 298 assert(packet); 299 appended_packets_.push_back(packet); 300} 301 302rtc::scoped_ptr<RawPacket> RtcpPacket::Build() const { 303 size_t length = 0; 304 rtc::scoped_ptr<RawPacket> packet(new RawPacket(IP_PACKET_SIZE)); 305 306 class PacketVerifier : public PacketReadyCallback { 307 public: 308 explicit PacketVerifier(RawPacket* packet) 309 : called_(false), packet_(packet) {} 310 virtual ~PacketVerifier() {} 311 void OnPacketReady(uint8_t* data, size_t length) override { 312 RTC_CHECK(!called_) << "Fragmentation not supported."; 313 called_ = true; 314 packet_->SetLength(length); 315 } 316 317 private: 318 bool called_; 319 RawPacket* const packet_; 320 } verifier(packet.get()); 321 CreateAndAddAppended(packet->MutableBuffer(), &length, packet->BufferLength(), 322 &verifier); 323 OnBufferFull(packet->MutableBuffer(), &length, &verifier); 324 return packet; 325} 326 327bool RtcpPacket::Build(PacketReadyCallback* callback) const { 328 uint8_t buffer[IP_PACKET_SIZE]; 329 return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback); 330} 331 332bool RtcpPacket::BuildExternalBuffer(uint8_t* buffer, 333 size_t max_length, 334 PacketReadyCallback* callback) const { 335 size_t index = 0; 336 if (!CreateAndAddAppended(buffer, &index, max_length, callback)) 337 return false; 338 return OnBufferFull(buffer, &index, callback); 339} 340 341bool RtcpPacket::CreateAndAddAppended(uint8_t* packet, 342 size_t* index, 343 size_t max_length, 344 PacketReadyCallback* callback) const { 345 if (!Create(packet, index, max_length, callback)) 346 return false; 347 for (RtcpPacket* appended : appended_packets_) { 348 if (!appended->CreateAndAddAppended(packet, index, max_length, callback)) 349 return false; 350 } 351 return true; 352} 353 354bool RtcpPacket::OnBufferFull(uint8_t* packet, 355 size_t* index, 356 RtcpPacket::PacketReadyCallback* callback) const { 357 if (*index == 0) 358 return false; 359 callback->OnPacketReady(packet, *index); 360 *index = 0; 361 return true; 362} 363 364size_t RtcpPacket::HeaderLength() const { 365 size_t length_in_bytes = BlockLength(); 366 // Length in 32-bit words minus 1. 367 assert(length_in_bytes > 0); 368 return ((length_in_bytes + 3) / 4) - 1; 369} 370 371// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications. 372// 373// RTP header format. 374// 0 1 2 3 375// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 376// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 377// |V=2|P| RC/FMT | PT | length | 378// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 379 380void RtcpPacket::CreateHeader( 381 uint8_t count_or_format, // Depends on packet type. 382 uint8_t packet_type, 383 size_t length, 384 uint8_t* buffer, 385 size_t* pos) { 386 assert(length <= 0xffff); 387 const uint8_t kVersion = 2; 388 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format); 389 AssignUWord8(buffer, pos, packet_type); 390 AssignUWord16(buffer, pos, length); 391} 392 393bool SenderReport::Create(uint8_t* packet, 394 size_t* index, 395 size_t max_length, 396 RtcpPacket::PacketReadyCallback* callback) const { 397 while (*index + BlockLength() > max_length) { 398 if (!OnBufferFull(packet, index, callback)) 399 return false; 400 } 401 CreateHeader(sr_.NumberOfReportBlocks, PT_SR, HeaderLength(), packet, index); 402 CreateSenderReport(sr_, packet, index); 403 CreateReportBlocks(report_blocks_, packet, index); 404 return true; 405} 406 407bool SenderReport::WithReportBlock(const ReportBlock& block) { 408 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { 409 LOG(LS_WARNING) << "Max report blocks reached."; 410 return false; 411 } 412 report_blocks_.push_back(block); 413 sr_.NumberOfReportBlocks = report_blocks_.size(); 414 return true; 415} 416 417bool Sdes::Create(uint8_t* packet, 418 size_t* index, 419 size_t max_length, 420 RtcpPacket::PacketReadyCallback* callback) const { 421 assert(!chunks_.empty()); 422 while (*index + BlockLength() > max_length) { 423 if (!OnBufferFull(packet, index, callback)) 424 return false; 425 } 426 CreateHeader(chunks_.size(), PT_SDES, HeaderLength(), packet, index); 427 CreateSdes(chunks_, packet, index); 428 return true; 429} 430 431bool Sdes::WithCName(uint32_t ssrc, const std::string& cname) { 432 assert(cname.length() <= 0xff); 433 if (chunks_.size() >= kMaxNumberOfChunks) { 434 LOG(LS_WARNING) << "Max SDES chunks reached."; 435 return false; 436 } 437 // In each chunk, the list of items must be terminated by one or more null 438 // octets. The next chunk must start on a 32-bit boundary. 439 // CNAME (1 byte) | length (1 byte) | name | padding. 440 int null_octets = 4 - ((2 + cname.length()) % 4); 441 Chunk chunk; 442 chunk.ssrc = ssrc; 443 chunk.name = cname; 444 chunk.null_octets = null_octets; 445 chunks_.push_back(chunk); 446 return true; 447} 448 449size_t Sdes::BlockLength() const { 450 // Header (4 bytes). 451 // Chunk: 452 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding. 453 size_t length = kHeaderLength; 454 for (const Chunk& chunk : chunks_) 455 length += 6 + chunk.name.length() + chunk.null_octets; 456 assert(length % 4 == 0); 457 return length; 458} 459 460bool Rpsi::Create(uint8_t* packet, 461 size_t* index, 462 size_t max_length, 463 RtcpPacket::PacketReadyCallback* callback) const { 464 assert(rpsi_.NumberOfValidBits > 0); 465 while (*index + BlockLength() > max_length) { 466 if (!OnBufferFull(packet, index, callback)) 467 return false; 468 } 469 const uint8_t kFmt = 3; 470 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index); 471 CreateRpsi(rpsi_, padding_bytes_, packet, index); 472 return true; 473} 474 475void Rpsi::WithPictureId(uint64_t picture_id) { 476 const uint32_t kPidBits = 7; 477 const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL; 478 uint8_t required_bytes = 0; 479 uint64_t shifted_pid = picture_id; 480 do { 481 ++required_bytes; 482 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask; 483 } while (shifted_pid > 0); 484 485 // Convert picture id to native bit string (natively defined by the video 486 // codec). 487 int pos = 0; 488 for (int i = required_bytes - 1; i > 0; i--) { 489 rpsi_.NativeBitString[pos++] = 490 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits)); 491 } 492 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f); 493 rpsi_.NumberOfValidBits = pos * 8; 494 495 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes). 496 padding_bytes_ = 4 - ((2 + required_bytes) % 4); 497 if (padding_bytes_ == 4) { 498 padding_bytes_ = 0; 499 } 500} 501 502bool Fir::Create(uint8_t* packet, 503 size_t* index, 504 size_t max_length, 505 RtcpPacket::PacketReadyCallback* callback) const { 506 while (*index + BlockLength() > max_length) { 507 if (!OnBufferFull(packet, index, callback)) 508 return false; 509 } 510 const uint8_t kFmt = 4; 511 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index); 512 CreateFir(fir_, fir_item_, packet, index); 513 return true; 514} 515 516bool Remb::Create(uint8_t* packet, 517 size_t* index, 518 size_t max_length, 519 RtcpPacket::PacketReadyCallback* callback) const { 520 while (*index + BlockLength() > max_length) { 521 if (!OnBufferFull(packet, index, callback)) 522 return false; 523 } 524 const uint8_t kFmt = 15; 525 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index); 526 CreateRemb(remb_, remb_item_, packet, index); 527 return true; 528} 529 530void Remb::AppliesTo(uint32_t ssrc) { 531 if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) { 532 LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached."; 533 return; 534 } 535 remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc; 536} 537 538bool Xr::Create(uint8_t* packet, 539 size_t* index, 540 size_t max_length, 541 RtcpPacket::PacketReadyCallback* callback) const { 542 while (*index + BlockLength() > max_length) { 543 if (!OnBufferFull(packet, index, callback)) 544 return false; 545 } 546 CreateHeader(0U, PT_XR, HeaderLength(), packet, index); 547 CreateXrHeader(xr_header_, packet, index); 548 for (const Rrtr& block : rrtr_blocks_) { 549 block.Create(packet + *index); 550 *index += Rrtr::kLength; 551 } 552 for (const Dlrr& block : dlrr_blocks_) { 553 block.Create(packet + *index); 554 *index += block.BlockLength(); 555 } 556 for (const VoipMetric& block : voip_metric_blocks_) { 557 block.Create(packet + *index); 558 *index += VoipMetric::kLength; 559 } 560 return true; 561} 562 563bool Xr::WithRrtr(Rrtr* rrtr) { 564 RTC_DCHECK(rrtr); 565 if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) { 566 LOG(LS_WARNING) << "Max RRTR blocks reached."; 567 return false; 568 } 569 rrtr_blocks_.push_back(*rrtr); 570 return true; 571} 572 573bool Xr::WithDlrr(Dlrr* dlrr) { 574 RTC_DCHECK(dlrr); 575 if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) { 576 LOG(LS_WARNING) << "Max DLRR blocks reached."; 577 return false; 578 } 579 dlrr_blocks_.push_back(*dlrr); 580 return true; 581} 582 583bool Xr::WithVoipMetric(VoipMetric* voip_metric) { 584 assert(voip_metric); 585 if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) { 586 LOG(LS_WARNING) << "Max Voip Metric blocks reached."; 587 return false; 588 } 589 voip_metric_blocks_.push_back(*voip_metric); 590 return true; 591} 592 593size_t Xr::DlrrLength() const { 594 size_t length = 0; 595 for (const Dlrr& block : dlrr_blocks_) { 596 length += block.BlockLength(); 597 } 598 return length; 599} 600 601RawPacket::RawPacket(size_t buffer_length) 602 : buffer_length_(buffer_length), length_(0) { 603 buffer_.reset(new uint8_t[buffer_length]); 604} 605 606RawPacket::RawPacket(const uint8_t* packet, size_t packet_length) 607 : buffer_length_(packet_length), length_(packet_length) { 608 buffer_.reset(new uint8_t[packet_length]); 609 memcpy(buffer_.get(), packet, packet_length); 610} 611 612const uint8_t* RawPacket::Buffer() const { 613 return buffer_.get(); 614} 615 616uint8_t* RawPacket::MutableBuffer() { 617 return buffer_.get(); 618} 619 620size_t RawPacket::BufferLength() const { 621 return buffer_length_; 622} 623 624size_t RawPacket::Length() const { 625 return length_; 626} 627 628void RawPacket::SetLength(size_t length) { 629 assert(length <= buffer_length_); 630 length_ = length; 631} 632 633} // namespace rtcp 634} // namespace webrtc 635