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 12 #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ 13 #define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ 14 15 #include <map> 16 #include <string> 17 #include <vector> 18 19 #include "webrtc/base/scoped_ptr.h" 20 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" 21 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/dlrr.h" 22 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/report_block.h" 23 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h" 24 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/voip_metric.h" 25 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 26 #include "webrtc/typedefs.h" 27 28 namespace webrtc { 29 namespace rtcp { 30 31 static const int kCommonFbFmtLength = 12; 32 static const int kReportBlockLength = 24; 33 34 class RawPacket; 35 36 // Class for building RTCP packets. 37 // 38 // Example: 39 // ReportBlock report_block; 40 // report_block.To(234) 41 // report_block.FractionLost(10); 42 // 43 // ReceiverReport rr; 44 // rr.From(123); 45 // rr.WithReportBlock(&report_block) 46 // 47 // Fir fir; 48 // fir.From(123); 49 // fir.To(234) 50 // fir.WithCommandSeqNum(123); 51 // 52 // size_t length = 0; // Builds an intra frame request 53 // uint8_t packet[kPacketSize]; // with sequence number 123. 54 // fir.Build(packet, &length, kPacketSize); 55 // 56 // RawPacket packet = fir.Build(); // Returns a RawPacket holding 57 // // the built rtcp packet. 58 // 59 // rr.Append(&fir) // Builds a compound RTCP packet with 60 // RawPacket packet = rr.Build(); // a receiver report, report block 61 // // and fir message. 62 63 class RtcpPacket { 64 public: ~RtcpPacket()65 virtual ~RtcpPacket() {} 66 67 void Append(RtcpPacket* packet); 68 69 // Callback used to signal that an RTCP packet is ready. Note that this may 70 // not contain all data in this RtcpPacket; if a packet cannot fit in 71 // max_length bytes, it will be fragmented and multiple calls to this 72 // callback will be made. 73 class PacketReadyCallback { 74 public: PacketReadyCallback()75 PacketReadyCallback() {} ~PacketReadyCallback()76 virtual ~PacketReadyCallback() {} 77 78 virtual void OnPacketReady(uint8_t* data, size_t length) = 0; 79 }; 80 81 // Convenience method mostly used for test. Max length of IP_PACKET_SIZE is 82 // used, will cause assertion error if fragmentation occurs. 83 rtc::scoped_ptr<RawPacket> Build() const; 84 85 // Returns true if all calls to Create succeeded. A buffer of size 86 // IP_PACKET_SIZE will be allocated and reused between calls to callback. 87 bool Build(PacketReadyCallback* callback) const; 88 89 // Returns true if all calls to Create succeeded. Provided buffer reference 90 // will be used for all calls to callback. 91 bool BuildExternalBuffer(uint8_t* buffer, 92 size_t max_length, 93 PacketReadyCallback* callback) const; 94 95 // Size of this packet in bytes (including headers, excluding nested packets). 96 virtual size_t BlockLength() const = 0; 97 98 protected: RtcpPacket()99 RtcpPacket() {} 100 101 virtual bool Create(uint8_t* packet, 102 size_t* index, 103 size_t max_length, 104 PacketReadyCallback* callback) const = 0; 105 106 static void CreateHeader(uint8_t count_or_format, 107 uint8_t packet_type, 108 size_t block_length, // Size in 32bit words - 1. 109 uint8_t* buffer, 110 size_t* pos); 111 112 bool OnBufferFull(uint8_t* packet, 113 size_t* index, 114 RtcpPacket::PacketReadyCallback* callback) const; 115 116 size_t HeaderLength() const; 117 118 static const size_t kHeaderLength = 4; 119 std::vector<RtcpPacket*> appended_packets_; 120 121 private: 122 bool CreateAndAddAppended(uint8_t* packet, 123 size_t* index, 124 size_t max_length, 125 PacketReadyCallback* callback) const; 126 }; 127 128 // TODO(sprang): Move RtcpPacket subclasses out to separate files. 129 130 // RTCP sender report (RFC 3550). 131 // 132 // 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 133 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 134 // |V=2|P| RC | PT=SR=200 | length | 135 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 136 // | SSRC of sender | 137 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 138 // | NTP timestamp, most significant word | 139 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 140 // | NTP timestamp, least significant word | 141 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 142 // | RTP timestamp | 143 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 144 // | sender's packet count | 145 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 146 // | sender's octet count | 147 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 148 // | report block(s) | 149 // | .... | 150 151 class SenderReport : public RtcpPacket { 152 public: SenderReport()153 SenderReport() : RtcpPacket() { 154 memset(&sr_, 0, sizeof(sr_)); 155 } 156 ~SenderReport()157 virtual ~SenderReport() {} 158 From(uint32_t ssrc)159 void From(uint32_t ssrc) { 160 sr_.SenderSSRC = ssrc; 161 } WithNtpSec(uint32_t sec)162 void WithNtpSec(uint32_t sec) { 163 sr_.NTPMostSignificant = sec; 164 } WithNtpFrac(uint32_t frac)165 void WithNtpFrac(uint32_t frac) { 166 sr_.NTPLeastSignificant = frac; 167 } WithRtpTimestamp(uint32_t rtp_timestamp)168 void WithRtpTimestamp(uint32_t rtp_timestamp) { 169 sr_.RTPTimestamp = rtp_timestamp; 170 } WithPacketCount(uint32_t packet_count)171 void WithPacketCount(uint32_t packet_count) { 172 sr_.SenderPacketCount = packet_count; 173 } WithOctetCount(uint32_t octet_count)174 void WithOctetCount(uint32_t octet_count) { 175 sr_.SenderOctetCount = octet_count; 176 } 177 bool WithReportBlock(const ReportBlock& block); 178 179 protected: 180 bool Create(uint8_t* packet, 181 size_t* index, 182 size_t max_length, 183 RtcpPacket::PacketReadyCallback* callback) const override; 184 185 private: 186 static const int kMaxNumberOfReportBlocks = 0x1f; 187 BlockLength()188 size_t BlockLength() const { 189 const size_t kSrHeaderLength = 8; 190 const size_t kSenderInfoLength = 20; 191 return kSrHeaderLength + kSenderInfoLength + 192 report_blocks_.size() * kReportBlockLength; 193 } 194 195 RTCPUtility::RTCPPacketSR sr_; 196 std::vector<ReportBlock> report_blocks_; 197 198 RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport); 199 }; 200 201 // Source Description (SDES) (RFC 3550). 202 // 203 // 0 1 2 3 204 // 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 205 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 206 // header |V=2|P| SC | PT=SDES=202 | length | 207 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 208 // chunk | SSRC/CSRC_1 | 209 // 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 210 // | SDES items | 211 // | ... | 212 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 213 // chunk | SSRC/CSRC_2 | 214 // 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 215 // | SDES items | 216 // | ... | 217 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 218 // 219 // Canonical End-Point Identifier SDES Item (CNAME) 220 // 221 // 0 1 2 3 222 // 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 223 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 224 // | CNAME=1 | length | user and domain name ... 225 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 226 227 class Sdes : public RtcpPacket { 228 public: Sdes()229 Sdes() : RtcpPacket() {} 230 ~Sdes()231 virtual ~Sdes() {} 232 233 bool WithCName(uint32_t ssrc, const std::string& cname); 234 235 struct Chunk { 236 uint32_t ssrc; 237 std::string name; 238 int null_octets; 239 }; 240 241 protected: 242 bool Create(uint8_t* packet, 243 size_t* index, 244 size_t max_length, 245 RtcpPacket::PacketReadyCallback* callback) const override; 246 247 private: 248 static const int kMaxNumberOfChunks = 0x1f; 249 250 size_t BlockLength() const; 251 252 std::vector<Chunk> chunks_; 253 254 RTC_DISALLOW_COPY_AND_ASSIGN(Sdes); 255 }; 256 257 // Reference picture selection indication (RPSI) (RFC 4585). 258 // 259 // FCI: 260 // 261 // 0 1 2 3 262 // 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 263 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 264 // | PB |0| Payload Type| Native RPSI bit string | 265 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 266 // | defined per codec ... | Padding (0) | 267 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 268 269 class Rpsi : public RtcpPacket { 270 public: Rpsi()271 Rpsi() 272 : RtcpPacket(), 273 padding_bytes_(0) { 274 memset(&rpsi_, 0, sizeof(rpsi_)); 275 } 276 ~Rpsi()277 virtual ~Rpsi() {} 278 From(uint32_t ssrc)279 void From(uint32_t ssrc) { 280 rpsi_.SenderSSRC = ssrc; 281 } To(uint32_t ssrc)282 void To(uint32_t ssrc) { 283 rpsi_.MediaSSRC = ssrc; 284 } WithPayloadType(uint8_t payload)285 void WithPayloadType(uint8_t payload) { 286 assert(payload <= 0x7f); 287 rpsi_.PayloadType = payload; 288 } 289 void WithPictureId(uint64_t picture_id); 290 291 protected: 292 bool Create(uint8_t* packet, 293 size_t* index, 294 size_t max_length, 295 RtcpPacket::PacketReadyCallback* callback) const override; 296 297 private: BlockLength()298 size_t BlockLength() const { 299 size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_; 300 return kCommonFbFmtLength + fci_length; 301 } 302 303 uint8_t padding_bytes_; 304 RTCPUtility::RTCPPacketPSFBRPSI rpsi_; 305 306 RTC_DISALLOW_COPY_AND_ASSIGN(Rpsi); 307 }; 308 309 // Full intra request (FIR) (RFC 5104). 310 // 311 // FCI: 312 // 313 // 0 1 2 3 314 // 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 315 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 316 // | SSRC | 317 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 318 // | Seq nr. | Reserved | 319 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 320 321 class Fir : public RtcpPacket { 322 public: Fir()323 Fir() : RtcpPacket() { 324 memset(&fir_, 0, sizeof(fir_)); 325 memset(&fir_item_, 0, sizeof(fir_item_)); 326 } 327 ~Fir()328 virtual ~Fir() {} 329 From(uint32_t ssrc)330 void From(uint32_t ssrc) { 331 fir_.SenderSSRC = ssrc; 332 } To(uint32_t ssrc)333 void To(uint32_t ssrc) { 334 fir_item_.SSRC = ssrc; 335 } WithCommandSeqNum(uint8_t seq_num)336 void WithCommandSeqNum(uint8_t seq_num) { 337 fir_item_.CommandSequenceNumber = seq_num; 338 } 339 340 protected: 341 bool Create(uint8_t* packet, 342 size_t* index, 343 size_t max_length, 344 RtcpPacket::PacketReadyCallback* callback) const override; 345 346 private: BlockLength()347 size_t BlockLength() const { 348 const size_t kFciLength = 8; 349 return kCommonFbFmtLength + kFciLength; 350 } 351 352 RTCPUtility::RTCPPacketPSFBFIR fir_; 353 RTCPUtility::RTCPPacketPSFBFIRItem fir_item_; 354 }; 355 356 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb). 357 // 358 // 0 1 2 3 359 // 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 360 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 361 // |V=2|P| FMT=15 | PT=206 | length | 362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 363 // | SSRC of packet sender | 364 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 365 // | SSRC of media source | 366 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 367 // | Unique identifier 'R' 'E' 'M' 'B' | 368 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 369 // | Num SSRC | BR Exp | BR Mantissa | 370 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 371 // | SSRC feedback | 372 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 373 // | ... 374 375 class Remb : public RtcpPacket { 376 public: Remb()377 Remb() : RtcpPacket() { 378 memset(&remb_, 0, sizeof(remb_)); 379 memset(&remb_item_, 0, sizeof(remb_item_)); 380 } 381 ~Remb()382 virtual ~Remb() {} 383 From(uint32_t ssrc)384 void From(uint32_t ssrc) { 385 remb_.SenderSSRC = ssrc; 386 } 387 void AppliesTo(uint32_t ssrc); 388 WithBitrateBps(uint32_t bitrate_bps)389 void WithBitrateBps(uint32_t bitrate_bps) { 390 remb_item_.BitRate = bitrate_bps; 391 } 392 393 protected: 394 bool Create(uint8_t* packet, 395 size_t* index, 396 size_t max_length, 397 RtcpPacket::PacketReadyCallback* callback) const override; 398 399 private: 400 static const int kMaxNumberOfSsrcs = 0xff; 401 BlockLength()402 size_t BlockLength() const { 403 return (remb_item_.NumberOfSSRCs + 5) * 4; 404 } 405 406 RTCPUtility::RTCPPacketPSFBAPP remb_; 407 RTCPUtility::RTCPPacketPSFBREMBItem remb_item_; 408 409 RTC_DISALLOW_COPY_AND_ASSIGN(Remb); 410 }; 411 412 // From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR). 413 // 414 // Format for XR packets: 415 // 416 // 0 1 2 3 417 // 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 418 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 419 // |V=2|P|reserved | PT=XR=207 | length | 420 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 421 // | SSRC | 422 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 423 // : report blocks : 424 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 425 426 class Xr : public RtcpPacket { 427 public: 428 typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock; Xr()429 Xr() : RtcpPacket() { 430 memset(&xr_header_, 0, sizeof(xr_header_)); 431 } 432 ~Xr()433 virtual ~Xr() {} 434 From(uint32_t ssrc)435 void From(uint32_t ssrc) { 436 xr_header_.OriginatorSSRC = ssrc; 437 } 438 439 // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr. 440 bool WithRrtr(Rrtr* rrtr); 441 bool WithDlrr(Dlrr* dlrr); 442 bool WithVoipMetric(VoipMetric* voip_metric); 443 444 protected: 445 bool Create(uint8_t* packet, 446 size_t* index, 447 size_t max_length, 448 RtcpPacket::PacketReadyCallback* callback) const override; 449 450 private: 451 static const int kMaxNumberOfRrtrBlocks = 50; 452 static const int kMaxNumberOfDlrrBlocks = 50; 453 static const int kMaxNumberOfVoipMetricBlocks = 50; 454 BlockLength()455 size_t BlockLength() const { 456 const size_t kXrHeaderLength = 8; 457 return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength(); 458 } 459 RrtrLength()460 size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); } 461 462 size_t DlrrLength() const; 463 VoipMetricLength()464 size_t VoipMetricLength() const { 465 return VoipMetric::kLength * voip_metric_blocks_.size(); 466 } 467 468 RTCPUtility::RTCPPacketXR xr_header_; 469 std::vector<Rrtr> rrtr_blocks_; 470 std::vector<Dlrr> dlrr_blocks_; 471 std::vector<VoipMetric> voip_metric_blocks_; 472 473 RTC_DISALLOW_COPY_AND_ASSIGN(Xr); 474 }; 475 476 // Class holding a RTCP packet. 477 // 478 // Takes a built rtcp packet. 479 // RawPacket raw_packet(buffer, length); 480 // 481 // To access the raw packet: 482 // raw_packet.Buffer(); - pointer to the raw packet 483 // raw_packet.BufferLength(); - the length of the raw packet 484 485 class RawPacket { 486 public: 487 explicit RawPacket(size_t buffer_length); 488 RawPacket(const uint8_t* packet, size_t packet_length); 489 490 const uint8_t* Buffer() const; 491 uint8_t* MutableBuffer(); 492 size_t BufferLength() const; 493 size_t Length() const; 494 void SetLength(size_t length); 495 496 private: 497 const size_t buffer_length_; 498 size_t length_; 499 rtc::scoped_ptr<uint8_t[]> buffer_; 500 }; 501 502 } // namespace rtcp 503 } // namespace webrtc 504 #endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_ 505