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 16using webrtc::RTCPUtility::kBtDlrr; 17using webrtc::RTCPUtility::kBtReceiverReferenceTime; 18using webrtc::RTCPUtility::kBtVoipMetric; 19 20using webrtc::RTCPUtility::PT_APP; 21using webrtc::RTCPUtility::PT_BYE; 22using webrtc::RTCPUtility::PT_IJ; 23using webrtc::RTCPUtility::PT_PSFB; 24using webrtc::RTCPUtility::PT_RR; 25using webrtc::RTCPUtility::PT_RTPFB; 26using webrtc::RTCPUtility::PT_SDES; 27using webrtc::RTCPUtility::PT_SR; 28using webrtc::RTCPUtility::PT_XR; 29 30using webrtc::RTCPUtility::RTCPPacketAPP; 31using webrtc::RTCPUtility::RTCPPacketBYE; 32using webrtc::RTCPUtility::RTCPPacketPSFBAPP; 33using webrtc::RTCPUtility::RTCPPacketPSFBFIR; 34using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem; 35using webrtc::RTCPUtility::RTCPPacketPSFBPLI; 36using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem; 37using webrtc::RTCPUtility::RTCPPacketPSFBRPSI; 38using webrtc::RTCPUtility::RTCPPacketPSFBSLI; 39using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem; 40using webrtc::RTCPUtility::RTCPPacketReportBlockItem; 41using webrtc::RTCPUtility::RTCPPacketRR; 42using webrtc::RTCPUtility::RTCPPacketRTPFBNACK; 43using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem; 44using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN; 45using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem; 46using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR; 47using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem; 48using webrtc::RTCPUtility::RTCPPacketSR; 49using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem; 50using webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem; 51using webrtc::RTCPUtility::RTCPPacketXR; 52using webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem; 53 54namespace webrtc { 55namespace rtcp { 56namespace { 57// Unused SSRC of media source, set to 0. 58const uint32_t kUnusedMediaSourceSsrc0 = 0; 59 60void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) { 61 buffer[(*offset)++] = value; 62} 63void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) { 64 RtpUtility::AssignUWord16ToBuffer(buffer + *offset, value); 65 *offset += 2; 66} 67void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) { 68 RtpUtility::AssignUWord24ToBuffer(buffer + *offset, value); 69 *offset += 3; 70} 71void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) { 72 RtpUtility::AssignUWord32ToBuffer(buffer + *offset, value); 73 *offset += 4; 74} 75 76void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10, 77 uint8_t bits_mantissa, 78 uint32_t* mantissa, 79 uint8_t* exp) { 80 // input_base10 = mantissa * 2^exp 81 assert(bits_mantissa <= 32); 82 uint32_t mantissa_max = (1 << bits_mantissa) - 1; 83 uint8_t exponent = 0; 84 for (uint32_t i = 0; i < 64; ++i) { 85 if (input_base10 <= (mantissa_max << i)) { 86 exponent = i; 87 break; 88 } 89 } 90 *exp = exponent; 91 *mantissa = (input_base10 >> exponent); 92} 93 94size_t BlockToHeaderLength(size_t length_in_bytes) { 95 // Length in 32-bit words minus 1. 96 assert(length_in_bytes > 0); 97 assert(length_in_bytes % 4 == 0); 98 return (length_in_bytes / 4) - 1; 99} 100 101// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications. 102// 103// RTP header format. 104// 0 1 2 3 105// 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 106// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 107// |V=2|P| RC/FMT | PT | length | 108// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 109 110void CreateHeader(uint8_t count_or_format, // Depends on packet type. 111 uint8_t packet_type, 112 size_t length, 113 uint8_t* buffer, 114 size_t* pos) { 115 assert(length <= 0xffff); 116 const uint8_t kVersion = 2; 117 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format); 118 AssignUWord8(buffer, pos, packet_type); 119 AssignUWord16(buffer, pos, length); 120} 121 122// Sender report (SR) (RFC 3550). 123// 0 1 2 3 124// 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 125// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 126// |V=2|P| RC | PT=SR=200 | length | 127// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 128// | SSRC of sender | 129// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 130// | NTP timestamp, most significant word | 131// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 132// | NTP timestamp, least significant word | 133// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 134// | RTP timestamp | 135// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 136// | sender's packet count | 137// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 138// | sender's octet count | 139// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 140 141void CreateSenderReport(const RTCPPacketSR& sr, 142 size_t length, 143 uint8_t* buffer, 144 size_t* pos) { 145 CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos); 146 AssignUWord32(buffer, pos, sr.SenderSSRC); 147 AssignUWord32(buffer, pos, sr.NTPMostSignificant); 148 AssignUWord32(buffer, pos, sr.NTPLeastSignificant); 149 AssignUWord32(buffer, pos, sr.RTPTimestamp); 150 AssignUWord32(buffer, pos, sr.SenderPacketCount); 151 AssignUWord32(buffer, pos, sr.SenderOctetCount); 152} 153 154// Receiver report (RR), header (RFC 3550). 155// 156// 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 157// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 158// |V=2|P| RC | PT=RR=201 | length | 159// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 160// | SSRC of packet sender | 161// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 162 163void CreateReceiverReport(const RTCPPacketRR& rr, 164 size_t length, 165 uint8_t* buffer, 166 size_t* pos) { 167 CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos); 168 AssignUWord32(buffer, pos, rr.SenderSSRC); 169} 170 171// Report block (RFC 3550). 172// 173// 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 174// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 175// | SSRC_1 (SSRC of first source) | 176// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 177// | fraction lost | cumulative number of packets lost | 178// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 179// | extended highest sequence number received | 180// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 181// | interarrival jitter | 182// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 183// | last SR (LSR) | 184// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 185// | delay since last SR (DLSR) | 186// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 187 188void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks, 189 uint8_t* buffer, 190 size_t* pos) { 191 for (std::vector<RTCPPacketReportBlockItem>::const_iterator 192 it = blocks.begin(); it != blocks.end(); ++it) { 193 AssignUWord32(buffer, pos, (*it).SSRC); 194 AssignUWord8(buffer, pos, (*it).FractionLost); 195 AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost); 196 AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber); 197 AssignUWord32(buffer, pos, (*it).Jitter); 198 AssignUWord32(buffer, pos, (*it).LastSR); 199 AssignUWord32(buffer, pos, (*it).DelayLastSR); 200 } 201} 202 203// Transmission Time Offsets in RTP Streams (RFC 5450). 204// 205// 0 1 2 3 206// 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 207// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 208// hdr |V=2|P| RC | PT=IJ=195 | length | 209// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 210// | inter-arrival jitter | 211// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 212// . . 213// . . 214// . . 215// | inter-arrival jitter | 216// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 217 218void CreateIj(const std::vector<uint32_t>& ij_items, 219 uint8_t* buffer, 220 size_t* pos) { 221 size_t length = ij_items.size(); 222 CreateHeader(length, PT_IJ, length, buffer, pos); 223 for (std::vector<uint32_t>::const_iterator it = ij_items.begin(); 224 it != ij_items.end(); ++it) { 225 AssignUWord32(buffer, pos, *it); 226 } 227} 228 229// Source Description (SDES) (RFC 3550). 230// 231// 0 1 2 3 232// 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 233// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 234// header |V=2|P| SC | PT=SDES=202 | length | 235// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 236// chunk | SSRC/CSRC_1 | 237// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 238// | SDES items | 239// | ... | 240// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 241// chunk | SSRC/CSRC_2 | 242// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 243// | SDES items | 244// | ... | 245// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 246// 247// Canonical End-Point Identifier SDES Item (CNAME) 248// 249// 0 1 2 3 250// 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 251// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 252// | CNAME=1 | length | user and domain name ... 253// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 254 255void CreateSdes(const std::vector<Sdes::Chunk>& chunks, 256 size_t length, 257 uint8_t* buffer, 258 size_t* pos) { 259 CreateHeader(chunks.size(), PT_SDES, length, buffer, pos); 260 const uint8_t kSdesItemType = 1; 261 for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin(); 262 it != chunks.end(); ++it) { 263 AssignUWord32(buffer, pos, (*it).ssrc); 264 AssignUWord8(buffer, pos, kSdesItemType); 265 AssignUWord8(buffer, pos, (*it).name.length()); 266 memcpy(buffer + *pos, (*it).name.data(), (*it).name.length()); 267 *pos += (*it).name.length(); 268 memset(buffer + *pos, 0, (*it).null_octets); 269 *pos += (*it).null_octets; 270 } 271} 272 273// Bye packet (BYE) (RFC 3550). 274// 275// 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 276// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 277// |V=2|P| SC | PT=BYE=203 | length | 278// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 279// | SSRC/CSRC | 280// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 281// : ... : 282// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 283// (opt) | length | reason for leaving ... 284// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 285 286void CreateBye(const RTCPPacketBYE& bye, 287 const std::vector<uint32_t>& csrcs, 288 size_t length, 289 uint8_t* buffer, 290 size_t* pos) { 291 CreateHeader(length, PT_BYE, length, buffer, pos); 292 AssignUWord32(buffer, pos, bye.SenderSSRC); 293 for (std::vector<uint32_t>::const_iterator it = csrcs.begin(); 294 it != csrcs.end(); ++it) { 295 AssignUWord32(buffer, pos, *it); 296 } 297} 298 299// Application-Defined packet (APP) (RFC 3550). 300// 301// 0 1 2 3 302// 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 303// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 304// |V=2|P| subtype | PT=APP=204 | length | 305// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 306// | SSRC/CSRC | 307// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 308// | name (ASCII) | 309// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 310// | application-dependent data ... 311// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 312 313void CreateApp(const RTCPPacketAPP& app, 314 uint32_t ssrc, 315 size_t length, 316 uint8_t* buffer, 317 size_t* pos) { 318 CreateHeader(app.SubType, PT_APP, length, buffer, pos); 319 AssignUWord32(buffer, pos, ssrc); 320 AssignUWord32(buffer, pos, app.Name); 321 memcpy(buffer + *pos, app.Data, app.Size); 322 *pos += app.Size; 323} 324 325// RFC 4585: Feedback format. 326// 327// Common packet format: 328// 329// 0 1 2 3 330// 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 331// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 332// |V=2|P| FMT | PT | length | 333// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 334// | SSRC of packet sender | 335// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 336// | SSRC of media source | 337// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 338// : Feedback Control Information (FCI) : 339// : 340// 341 342// Picture loss indication (PLI) (RFC 4585). 343// 344// FCI: no feedback control information. 345 346void CreatePli(const RTCPPacketPSFBPLI& pli, 347 size_t length, 348 uint8_t* buffer, 349 size_t* pos) { 350 const uint8_t kFmt = 1; 351 CreateHeader(kFmt, PT_PSFB, length, buffer, pos); 352 AssignUWord32(buffer, pos, pli.SenderSSRC); 353 AssignUWord32(buffer, pos, pli.MediaSSRC); 354} 355 356// Slice loss indication (SLI) (RFC 4585). 357// 358// FCI: 359// 360// 0 1 2 3 361// 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 362// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 363// | First | Number | PictureID | 364// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 365 366void CreateSli(const RTCPPacketPSFBSLI& sli, 367 const RTCPPacketPSFBSLIItem& sli_item, 368 size_t length, 369 uint8_t* buffer, 370 size_t* pos) { 371 const uint8_t kFmt = 2; 372 CreateHeader(kFmt, PT_PSFB, length, buffer, pos); 373 AssignUWord32(buffer, pos, sli.SenderSSRC); 374 AssignUWord32(buffer, pos, sli.MediaSSRC); 375 376 AssignUWord8(buffer, pos, sli_item.FirstMB >> 5); 377 AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) + 378 ((sli_item.NumberOfMB >> 10) & 0x07)); 379 AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2); 380 AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId); 381} 382 383// Generic NACK (RFC 4585). 384// 385// FCI: 386// 387// 0 1 2 3 388// 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 389// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 390// | PID | BLP | 391// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 392 393void CreateNack(const RTCPPacketRTPFBNACK& nack, 394 const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields, 395 size_t length, 396 uint8_t* buffer, 397 size_t* pos) { 398 const uint8_t kFmt = 1; 399 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos); 400 AssignUWord32(buffer, pos, nack.SenderSSRC); 401 AssignUWord32(buffer, pos, nack.MediaSSRC); 402 for (std::vector<RTCPPacketRTPFBNACKItem>::const_iterator 403 it = nack_fields.begin(); it != nack_fields.end(); ++it) { 404 AssignUWord16(buffer, pos, (*it).PacketID); 405 AssignUWord16(buffer, pos, (*it).BitMask); 406 } 407} 408 409// Reference picture selection indication (RPSI) (RFC 4585). 410// 411// FCI: 412// 413// 0 1 2 3 414// 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 415// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 416// | PB |0| Payload Type| Native RPSI bit string | 417// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 418// | defined per codec ... | Padding (0) | 419// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 420 421void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi, 422 uint8_t padding_bytes, 423 size_t length, 424 uint8_t* buffer, 425 size_t* pos) { 426 // Native bit string should be a multiple of 8 bits. 427 assert(rpsi.NumberOfValidBits % 8 == 0); 428 const uint8_t kFmt = 3; 429 CreateHeader(kFmt, PT_PSFB, length, buffer, pos); 430 AssignUWord32(buffer, pos, rpsi.SenderSSRC); 431 AssignUWord32(buffer, pos, rpsi.MediaSSRC); 432 AssignUWord8(buffer, pos, padding_bytes * 8); 433 AssignUWord8(buffer, pos, rpsi.PayloadType); 434 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8); 435 *pos += rpsi.NumberOfValidBits / 8; 436 memset(buffer + *pos, 0, padding_bytes); 437 *pos += padding_bytes; 438} 439 440// Full intra request (FIR) (RFC 5104). 441// 442// FCI: 443// 444// 0 1 2 3 445// 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 446// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 447// | SSRC | 448// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 449// | Seq nr. | Reserved | 450// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 451 452void CreateFir(const RTCPPacketPSFBFIR& fir, 453 const RTCPPacketPSFBFIRItem& fir_item, 454 size_t length, 455 uint8_t* buffer, 456 size_t* pos) { 457 const uint8_t kFmt = 4; 458 CreateHeader(kFmt, PT_PSFB, length, buffer, pos); 459 AssignUWord32(buffer, pos, fir.SenderSSRC); 460 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 461 AssignUWord32(buffer, pos, fir_item.SSRC); 462 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber); 463 AssignUWord24(buffer, pos, 0); 464} 465 466void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item, 467 uint8_t* buffer, 468 size_t* pos) { 469 uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000; 470 uint32_t mantissa = 0; 471 uint8_t exp = 0; 472 ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp); 473 474 AssignUWord32(buffer, pos, tmmbr_item.SSRC); 475 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03)); 476 AssignUWord8(buffer, pos, mantissa >> 7); 477 AssignUWord8(buffer, pos, (mantissa << 1) + 478 ((tmmbr_item.MeasuredOverhead >> 8) & 0x01)); 479 AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead); 480} 481 482// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104). 483// 484// FCI: 485// 486// 0 1 2 3 487// 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 488// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 489// | SSRC | 490// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 491// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| 492// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 493 494void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr, 495 const RTCPPacketRTPFBTMMBRItem& tmmbr_item, 496 size_t length, 497 uint8_t* buffer, 498 size_t* pos) { 499 const uint8_t kFmt = 3; 500 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos); 501 AssignUWord32(buffer, pos, tmmbr.SenderSSRC); 502 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 503 CreateTmmbrItem(tmmbr_item, buffer, pos); 504} 505 506// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104). 507// 508// FCI: 509// 510// 0 1 2 3 511// 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 512// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 513// | SSRC | 514// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 515// | MxTBR Exp | MxTBR Mantissa |Measured Overhead| 516// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 517 518void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn, 519 const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items, 520 size_t length, 521 uint8_t* buffer, 522 size_t* pos) { 523 const uint8_t kFmt = 4; 524 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos); 525 AssignUWord32(buffer, pos, tmmbn.SenderSSRC); 526 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 527 for (uint8_t i = 0; i < tmmbn_items.size(); ++i) { 528 CreateTmmbrItem(tmmbn_items[i], buffer, pos); 529 } 530} 531 532// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb). 533// 534// 0 1 2 3 535// 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 536// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 537// |V=2|P| FMT=15 | PT=206 | length | 538// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 539// | SSRC of packet sender | 540// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 541// | SSRC of media source | 542// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 543// | Unique identifier 'R' 'E' 'M' 'B' | 544// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 545// | Num SSRC | BR Exp | BR Mantissa | 546// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 547// | SSRC feedback | 548// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 549// | ... | 550 551void CreateRemb(const RTCPPacketPSFBAPP& remb, 552 const RTCPPacketPSFBREMBItem& remb_item, 553 size_t length, 554 uint8_t* buffer, 555 size_t* pos) { 556 uint32_t mantissa = 0; 557 uint8_t exp = 0; 558 ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp); 559 560 const uint8_t kFmt = 15; 561 CreateHeader(kFmt, PT_PSFB, length, buffer, pos); 562 AssignUWord32(buffer, pos, remb.SenderSSRC); 563 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0); 564 AssignUWord8(buffer, pos, 'R'); 565 AssignUWord8(buffer, pos, 'E'); 566 AssignUWord8(buffer, pos, 'M'); 567 AssignUWord8(buffer, pos, 'B'); 568 AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs); 569 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03)); 570 AssignUWord8(buffer, pos, mantissa >> 8); 571 AssignUWord8(buffer, pos, mantissa); 572 for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) { 573 AssignUWord32(buffer, pos, remb_item.SSRCs[i]); 574 } 575} 576 577// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR). 578// 579// Format for XR packets: 580// 581// 0 1 2 3 582// 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 583// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 584// |V=2|P|reserved | PT=XR=207 | length | 585// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 586// | SSRC | 587// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 588// : report blocks : 589// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 590 591void CreateXrHeader(const RTCPPacketXR& header, 592 size_t length, 593 uint8_t* buffer, 594 size_t* pos) { 595 CreateHeader(0U, PT_XR, length, buffer, pos); 596 AssignUWord32(buffer, pos, header.OriginatorSSRC); 597} 598 599void CreateXrBlockHeader(uint8_t block_type, 600 uint16_t block_length, 601 uint8_t* buffer, 602 size_t* pos) { 603 AssignUWord8(buffer, pos, block_type); 604 AssignUWord8(buffer, pos, 0); 605 AssignUWord16(buffer, pos, block_length); 606} 607 608// Receiver Reference Time Report Block (RFC 3611). 609// 610// 0 1 2 3 611// 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 612// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 613// | BT=4 | reserved | block length = 2 | 614// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 615// | NTP timestamp, most significant word | 616// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 617// | NTP timestamp, least significant word | 618// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 619 620void CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem>& rrtrs, 621 uint8_t* buffer, 622 size_t* pos) { 623 const uint16_t kBlockLength = 2; 624 for (std::vector<RTCPPacketXRReceiverReferenceTimeItem>::const_iterator it = 625 rrtrs.begin(); it != rrtrs.end(); ++it) { 626 CreateXrBlockHeader(kBtReceiverReferenceTime, kBlockLength, buffer, pos); 627 AssignUWord32(buffer, pos, (*it).NTPMostSignificant); 628 AssignUWord32(buffer, pos, (*it).NTPLeastSignificant); 629 } 630} 631 632// DLRR Report Block (RFC 3611). 633// 634// 0 1 2 3 635// 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 636// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 637// | BT=5 | reserved | block length | 638// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 639// | SSRC_1 (SSRC of first receiver) | sub- 640// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block 641// | last RR (LRR) | 1 642// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 643// | delay since last RR (DLRR) | 644// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 645// | SSRC_2 (SSRC of second receiver) | sub- 646// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block 647// : ... : 2 648 649void CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs, 650 uint8_t* buffer, 651 size_t* pos) { 652 for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin(); 653 it != dlrrs.end(); ++it) { 654 if ((*it).empty()) { 655 continue; 656 } 657 uint16_t block_length = 3 * (*it).size(); 658 CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos); 659 for (Xr::DlrrBlock::const_iterator it_block = (*it).begin(); 660 it_block != (*it).end(); ++it_block) { 661 AssignUWord32(buffer, pos, (*it_block).SSRC); 662 AssignUWord32(buffer, pos, (*it_block).LastRR); 663 AssignUWord32(buffer, pos, (*it_block).DelayLastRR); 664 } 665 } 666} 667 668// VoIP Metrics Report Block (RFC 3611). 669// 670// 0 1 2 3 671// 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 672// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 673// | BT=7 | reserved | block length = 8 | 674// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 675// | SSRC of source | 676// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 677// | loss rate | discard rate | burst density | gap density | 678// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 679// | burst duration | gap duration | 680// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 681// | round trip delay | end system delay | 682// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 683// | signal level | noise level | RERL | Gmin | 684// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 685// | R factor | ext. R factor | MOS-LQ | MOS-CQ | 686// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 687// | RX config | reserved | JB nominal | 688// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 689// | JB maximum | JB abs max | 690// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 691 692void CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem>& metrics, 693 uint8_t* buffer, 694 size_t* pos) { 695 const uint16_t kBlockLength = 8; 696 for (std::vector<RTCPPacketXRVOIPMetricItem>::const_iterator it = 697 metrics.begin(); it != metrics.end(); ++it) { 698 CreateXrBlockHeader(kBtVoipMetric, kBlockLength, buffer, pos); 699 AssignUWord32(buffer, pos, (*it).SSRC); 700 AssignUWord8(buffer, pos, (*it).lossRate); 701 AssignUWord8(buffer, pos, (*it).discardRate); 702 AssignUWord8(buffer, pos, (*it).burstDensity); 703 AssignUWord8(buffer, pos, (*it).gapDensity); 704 AssignUWord16(buffer, pos, (*it).burstDuration); 705 AssignUWord16(buffer, pos, (*it).gapDuration); 706 AssignUWord16(buffer, pos, (*it).roundTripDelay); 707 AssignUWord16(buffer, pos, (*it).endSystemDelay); 708 AssignUWord8(buffer, pos, (*it).signalLevel); 709 AssignUWord8(buffer, pos, (*it).noiseLevel); 710 AssignUWord8(buffer, pos, (*it).RERL); 711 AssignUWord8(buffer, pos, (*it).Gmin); 712 AssignUWord8(buffer, pos, (*it).Rfactor); 713 AssignUWord8(buffer, pos, (*it).extRfactor); 714 AssignUWord8(buffer, pos, (*it).MOSLQ); 715 AssignUWord8(buffer, pos, (*it).MOSCQ); 716 AssignUWord8(buffer, pos, (*it).RXconfig); 717 AssignUWord8(buffer, pos, 0); 718 AssignUWord16(buffer, pos, (*it).JBnominal); 719 AssignUWord16(buffer, pos, (*it).JBmax); 720 AssignUWord16(buffer, pos, (*it).JBabsMax); 721 } 722} 723} // namespace 724 725void RtcpPacket::Append(RtcpPacket* packet) { 726 assert(packet); 727 appended_packets_.push_back(packet); 728} 729 730RawPacket RtcpPacket::Build() const { 731 size_t length = 0; 732 uint8_t packet[IP_PACKET_SIZE]; 733 CreateAndAddAppended(packet, &length, IP_PACKET_SIZE); 734 return RawPacket(packet, length); 735} 736 737void RtcpPacket::Build(uint8_t* packet, 738 size_t* length, 739 size_t max_length) const { 740 *length = 0; 741 CreateAndAddAppended(packet, length, max_length); 742} 743 744void RtcpPacket::CreateAndAddAppended(uint8_t* packet, 745 size_t* length, 746 size_t max_length) const { 747 Create(packet, length, max_length); 748 for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin(); 749 it != appended_packets_.end(); ++it) { 750 (*it)->CreateAndAddAppended(packet, length, max_length); 751 } 752} 753 754void Empty::Create(uint8_t* packet, size_t* length, size_t max_length) const { 755} 756 757void SenderReport::Create(uint8_t* packet, 758 size_t* length, 759 size_t max_length) const { 760 if (*length + BlockLength() > max_length) { 761 LOG(LS_WARNING) << "Max packet size reached."; 762 return; 763 } 764 CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, length); 765 CreateReportBlocks(report_blocks_, packet, length); 766} 767 768void SenderReport::WithReportBlock(ReportBlock* block) { 769 assert(block); 770 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { 771 LOG(LS_WARNING) << "Max report blocks reached."; 772 return; 773 } 774 report_blocks_.push_back(block->report_block_); 775 sr_.NumberOfReportBlocks = report_blocks_.size(); 776} 777 778void ReceiverReport::Create(uint8_t* packet, 779 size_t* length, 780 size_t max_length) const { 781 if (*length + BlockLength() > max_length) { 782 LOG(LS_WARNING) << "Max packet size reached."; 783 return; 784 } 785 CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, length); 786 CreateReportBlocks(report_blocks_, packet, length); 787} 788 789void ReceiverReport::WithReportBlock(ReportBlock* block) { 790 assert(block); 791 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) { 792 LOG(LS_WARNING) << "Max report blocks reached."; 793 return; 794 } 795 report_blocks_.push_back(block->report_block_); 796 rr_.NumberOfReportBlocks = report_blocks_.size(); 797} 798 799void Ij::Create(uint8_t* packet, size_t* length, size_t max_length) const { 800 if (*length + BlockLength() > max_length) { 801 LOG(LS_WARNING) << "Max packet size reached."; 802 return; 803 } 804 CreateIj(ij_items_, packet, length); 805} 806 807void Ij::WithJitterItem(uint32_t jitter) { 808 if (ij_items_.size() >= kMaxNumberOfIjItems) { 809 LOG(LS_WARNING) << "Max inter-arrival jitter items reached."; 810 return; 811 } 812 ij_items_.push_back(jitter); 813} 814 815void Sdes::Create(uint8_t* packet, size_t* length, size_t max_length) const { 816 assert(!chunks_.empty()); 817 if (*length + BlockLength() > max_length) { 818 LOG(LS_WARNING) << "Max packet size reached."; 819 return; 820 } 821 CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, length); 822} 823 824void Sdes::WithCName(uint32_t ssrc, std::string cname) { 825 assert(cname.length() <= 0xff); 826 if (chunks_.size() >= kMaxNumberOfChunks) { 827 LOG(LS_WARNING) << "Max SDES chunks reached."; 828 return; 829 } 830 // In each chunk, the list of items must be terminated by one or more null 831 // octets. The next chunk must start on a 32-bit boundary. 832 // CNAME (1 byte) | length (1 byte) | name | padding. 833 int null_octets = 4 - ((2 + cname.length()) % 4); 834 Chunk chunk; 835 chunk.ssrc = ssrc; 836 chunk.name = cname; 837 chunk.null_octets = null_octets; 838 chunks_.push_back(chunk); 839} 840 841size_t Sdes::BlockLength() const { 842 // Header (4 bytes). 843 // Chunk: 844 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding. 845 size_t length = kHeaderLength; 846 for (std::vector<Chunk>::const_iterator it = chunks_.begin(); 847 it != chunks_.end(); ++it) { 848 length += 6 + (*it).name.length() + (*it).null_octets; 849 } 850 assert(length % 4 == 0); 851 return length; 852} 853 854void Bye::Create(uint8_t* packet, size_t* length, size_t max_length) const { 855 if (*length + BlockLength() > max_length) { 856 LOG(LS_WARNING) << "Max packet size reached."; 857 return; 858 } 859 CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, length); 860} 861 862void Bye::WithCsrc(uint32_t csrc) { 863 if (csrcs_.size() >= kMaxNumberOfCsrcs) { 864 LOG(LS_WARNING) << "Max CSRC size reached."; 865 return; 866 } 867 csrcs_.push_back(csrc); 868} 869 870void App::Create(uint8_t* packet, size_t* length, size_t max_length) const { 871 if (*length + BlockLength() > max_length) { 872 LOG(LS_WARNING) << "Max packet size reached."; 873 return; 874 } 875 CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, length); 876} 877 878void Pli::Create(uint8_t* packet, size_t* length, size_t max_length) const { 879 if (*length + BlockLength() > max_length) { 880 LOG(LS_WARNING) << "Max packet size reached."; 881 return; 882 } 883 CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, length); 884} 885 886void Sli::Create(uint8_t* packet, size_t* length, size_t max_length) const { 887 if (*length + BlockLength() > max_length) { 888 LOG(LS_WARNING) << "Max packet size reached."; 889 return; 890 } 891 CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet, 892 length); 893} 894 895void Nack::Create(uint8_t* packet, size_t* length, size_t max_length) const { 896 assert(!nack_fields_.empty()); 897 if (*length + BlockLength() > max_length) { 898 LOG(LS_WARNING) << "Max packet size reached."; 899 return; 900 } 901 CreateNack(nack_, nack_fields_, BlockToHeaderLength(BlockLength()), packet, 902 length); 903} 904 905void Nack::WithList(const uint16_t* nack_list, int length) { 906 assert(nack_list); 907 assert(nack_fields_.empty()); 908 int i = 0; 909 while (i < length) { 910 uint16_t pid = nack_list[i++]; 911 // Bitmask specifies losses in any of the 16 packets following the pid. 912 uint16_t bitmask = 0; 913 while (i < length) { 914 int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1; 915 if (shift >= 0 && shift <= 15) { 916 bitmask |= (1 << shift); 917 ++i; 918 } else { 919 break; 920 } 921 } 922 RTCPUtility::RTCPPacketRTPFBNACKItem item; 923 item.PacketID = pid; 924 item.BitMask = bitmask; 925 nack_fields_.push_back(item); 926 } 927} 928 929void Rpsi::Create(uint8_t* packet, size_t* length, size_t max_length) const { 930 assert(rpsi_.NumberOfValidBits > 0); 931 if (*length + BlockLength() > max_length) { 932 LOG(LS_WARNING) << "Max packet size reached."; 933 return; 934 } 935 CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet, 936 length); 937} 938 939void Rpsi::WithPictureId(uint64_t picture_id) { 940 const uint32_t kPidBits = 7; 941 const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL; 942 uint8_t required_bytes = 0; 943 uint64_t shifted_pid = picture_id; 944 do { 945 ++required_bytes; 946 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask; 947 } while (shifted_pid > 0); 948 949 // Convert picture id to native bit string (natively defined by the video 950 // codec). 951 int pos = 0; 952 for (int i = required_bytes - 1; i > 0; i--) { 953 rpsi_.NativeBitString[pos++] = 954 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits)); 955 } 956 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f); 957 rpsi_.NumberOfValidBits = pos * 8; 958 959 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes). 960 padding_bytes_ = 4 - ((2 + required_bytes) % 4); 961 if (padding_bytes_ == 4) { 962 padding_bytes_ = 0; 963 } 964} 965 966void Fir::Create(uint8_t* packet, size_t* length, size_t max_length) const { 967 if (*length + BlockLength() > max_length) { 968 LOG(LS_WARNING) << "Max packet size reached."; 969 return; 970 } 971 CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet, 972 length); 973} 974 975void Remb::Create(uint8_t* packet, size_t* length, size_t max_length) const { 976 if (*length + BlockLength() > max_length) { 977 LOG(LS_WARNING) << "Max packet size reached."; 978 return; 979 } 980 CreateRemb(remb_, remb_item_, BlockToHeaderLength(BlockLength()), packet, 981 length); 982} 983 984void Remb::AppliesTo(uint32_t ssrc) { 985 if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) { 986 LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached."; 987 return; 988 } 989 remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc; 990} 991 992void Tmmbr::Create(uint8_t* packet, size_t* length, size_t max_length) const { 993 if (*length + BlockLength() > max_length) { 994 LOG(LS_WARNING) << "Max packet size reached."; 995 return; 996 } 997 CreateTmmbr(tmmbr_, tmmbr_item_, BlockToHeaderLength(BlockLength()), packet, 998 length); 999} 1000 1001void Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) { 1002 assert(overhead <= 0x1ff); 1003 if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) { 1004 LOG(LS_WARNING) << "Max TMMBN size reached."; 1005 return; 1006 } 1007 RTCPPacketRTPFBTMMBRItem tmmbn_item; 1008 tmmbn_item.SSRC = ssrc; 1009 tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps; 1010 tmmbn_item.MeasuredOverhead = overhead; 1011 tmmbn_items_.push_back(tmmbn_item); 1012} 1013 1014void Tmmbn::Create(uint8_t* packet, size_t* length, size_t max_length) const { 1015 if (*length + BlockLength() > max_length) { 1016 LOG(LS_WARNING) << "Max packet size reached."; 1017 return; 1018 } 1019 CreateTmmbn(tmmbn_, tmmbn_items_, BlockToHeaderLength(BlockLength()), packet, 1020 length); 1021} 1022 1023void Xr::Create(uint8_t* packet, size_t* length, size_t max_length) const { 1024 if (*length + BlockLength() > max_length) { 1025 LOG(LS_WARNING) << "Max packet size reached."; 1026 return; 1027 } 1028 CreateXrHeader(xr_header_, BlockToHeaderLength(BlockLength()), packet, 1029 length); 1030 CreateRrtr(rrtr_blocks_, packet, length); 1031 CreateDlrr(dlrr_blocks_, packet, length); 1032 CreateVoipMetric(voip_metric_blocks_, packet, length); 1033} 1034 1035void Xr::WithRrtr(Rrtr* rrtr) { 1036 assert(rrtr); 1037 if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) { 1038 LOG(LS_WARNING) << "Max RRTR blocks reached."; 1039 return; 1040 } 1041 rrtr_blocks_.push_back(rrtr->rrtr_block_); 1042} 1043 1044void Xr::WithDlrr(Dlrr* dlrr) { 1045 assert(dlrr); 1046 if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) { 1047 LOG(LS_WARNING) << "Max DLRR blocks reached."; 1048 return; 1049 } 1050 dlrr_blocks_.push_back(dlrr->dlrr_block_); 1051} 1052 1053void Xr::WithVoipMetric(VoipMetric* voip_metric) { 1054 assert(voip_metric); 1055 if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) { 1056 LOG(LS_WARNING) << "Max Voip Metric blocks reached."; 1057 return; 1058 } 1059 voip_metric_blocks_.push_back(voip_metric->metric_); 1060} 1061 1062size_t Xr::DlrrLength() const { 1063 const size_t kBlockHeaderLen = 4; 1064 const size_t kSubBlockLen = 12; 1065 size_t length = 0; 1066 for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin(); 1067 it != dlrr_blocks_.end(); ++it) { 1068 if (!(*it).empty()) { 1069 length += kBlockHeaderLen + kSubBlockLen * (*it).size(); 1070 } 1071 } 1072 return length; 1073} 1074 1075void Dlrr::WithDlrrItem(uint32_t ssrc, 1076 uint32_t last_rr, 1077 uint32_t delay_last_rr) { 1078 if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) { 1079 LOG(LS_WARNING) << "Max DLRR items reached."; 1080 return; 1081 } 1082 RTCPPacketXRDLRRReportBlockItem dlrr; 1083 dlrr.SSRC = ssrc; 1084 dlrr.LastRR = last_rr; 1085 dlrr.DelayLastRR = delay_last_rr; 1086 dlrr_block_.push_back(dlrr); 1087} 1088 1089} // namespace rtcp 1090} // namespace webrtc 1091