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_RTCP_PACKET_H_ 13 #define WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_ 14 15 #include <map> 16 #include <string> 17 #include <vector> 18 19 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h" 20 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h" 21 #include "webrtc/typedefs.h" 22 23 namespace webrtc { 24 namespace rtcp { 25 26 enum { kCommonFbFmtLength = 12 }; 27 enum { kReportBlockLength = 24 }; 28 29 class RawPacket; 30 31 // Class for building RTCP packets. 32 // 33 // Example: 34 // ReportBlock report_block; 35 // report_block.To(234) 36 // report_block.FractionLost(10); 37 // 38 // ReceiverReport rr; 39 // rr.From(123); 40 // rr.WithReportBlock(&report_block) 41 // 42 // Fir fir; 43 // fir.From(123); 44 // fir.To(234) 45 // fir.WithCommandSeqNum(123); 46 // 47 // size_t length = 0; // Builds an intra frame request 48 // uint8_t packet[kPacketSize]; // with sequence number 123. 49 // fir.Build(packet, &length, kPacketSize); 50 // 51 // RawPacket packet = fir.Build(); // Returns a RawPacket holding 52 // // the built rtcp packet. 53 // 54 // rr.Append(&fir) // Builds a compound RTCP packet with 55 // RawPacket packet = rr.Build(); // a receiver report, report block 56 // // and fir message. 57 58 class RtcpPacket { 59 public: 60 virtual ~RtcpPacket() {} 61 62 void Append(RtcpPacket* packet); 63 64 RawPacket Build() const; 65 66 void Build(uint8_t* packet, size_t* length, size_t max_length) const; 67 68 protected: 69 RtcpPacket() : kHeaderLength(4) {} 70 71 virtual void Create( 72 uint8_t* packet, size_t* length, size_t max_length) const = 0; 73 74 const size_t kHeaderLength; 75 76 private: 77 void CreateAndAddAppended( 78 uint8_t* packet, size_t* length, size_t max_length) const; 79 80 std::vector<RtcpPacket*> appended_packets_; 81 }; 82 83 class Empty : public RtcpPacket { 84 public: 85 Empty() {} 86 87 virtual ~Empty() {} 88 89 protected: 90 virtual void Create(uint8_t* packet, size_t* length, size_t max_length) const; 91 }; 92 93 // From RFC 3550, RTP: A Transport Protocol for Real-Time Applications. 94 // 95 // RTCP report block (RFC 3550). 96 // 97 // 0 1 2 3 98 // 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 99 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 100 // | SSRC_1 (SSRC of first source) | 101 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 102 // | fraction lost | cumulative number of packets lost | 103 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 104 // | extended highest sequence number received | 105 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 106 // | interarrival jitter | 107 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 108 // | last SR (LSR) | 109 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 110 // | delay since last SR (DLSR) | 111 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 112 113 class ReportBlock { 114 public: 115 ReportBlock() { 116 // TODO(asapersson): Consider adding a constructor to struct. 117 memset(&report_block_, 0, sizeof(report_block_)); 118 } 119 120 ~ReportBlock() {} 121 122 void To(uint32_t ssrc) { 123 report_block_.SSRC = ssrc; 124 } 125 void WithFractionLost(uint8_t fraction_lost) { 126 report_block_.FractionLost = fraction_lost; 127 } 128 void WithCumulativeLost(uint32_t cumulative_lost) { 129 report_block_.CumulativeNumOfPacketsLost = cumulative_lost; 130 } 131 void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) { 132 report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num; 133 } 134 void WithJitter(uint32_t jitter) { 135 report_block_.Jitter = jitter; 136 } 137 void WithLastSr(uint32_t last_sr) { 138 report_block_.LastSR = last_sr; 139 } 140 void WithDelayLastSr(uint32_t delay_last_sr) { 141 report_block_.DelayLastSR = delay_last_sr; 142 } 143 144 private: 145 friend class SenderReport; 146 friend class ReceiverReport; 147 RTCPUtility::RTCPPacketReportBlockItem report_block_; 148 }; 149 150 // RTCP sender report (RFC 3550). 151 // 152 // 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 153 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 154 // |V=2|P| RC | PT=SR=200 | length | 155 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 156 // | SSRC of sender | 157 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 158 // | NTP timestamp, most significant word | 159 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 160 // | NTP timestamp, least significant word | 161 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 162 // | RTP timestamp | 163 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 164 // | sender's packet count | 165 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 166 // | sender's octet count | 167 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 168 // | report block(s) | 169 // | .... | 170 171 class SenderReport : public RtcpPacket { 172 public: 173 SenderReport() : RtcpPacket() { 174 memset(&sr_, 0, sizeof(sr_)); 175 } 176 177 virtual ~SenderReport() {} 178 179 void From(uint32_t ssrc) { 180 sr_.SenderSSRC = ssrc; 181 } 182 void WithNtpSec(uint32_t sec) { 183 sr_.NTPMostSignificant = sec; 184 } 185 void WithNtpFrac(uint32_t frac) { 186 sr_.NTPLeastSignificant = frac; 187 } 188 void WithRtpTimestamp(uint32_t rtp_timestamp) { 189 sr_.RTPTimestamp = rtp_timestamp; 190 } 191 void WithPacketCount(uint32_t packet_count) { 192 sr_.SenderPacketCount = packet_count; 193 } 194 void WithOctetCount(uint32_t octet_count) { 195 sr_.SenderOctetCount = octet_count; 196 } 197 void WithReportBlock(ReportBlock* block); 198 199 protected: 200 virtual void Create( 201 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 202 203 private: 204 enum { kMaxNumberOfReportBlocks = 0x1f }; 205 206 size_t BlockLength() const { 207 const size_t kSrHeaderLength = 8; 208 const size_t kSenderInfoLength = 20; 209 return kSrHeaderLength + kSenderInfoLength + 210 report_blocks_.size() * kReportBlockLength; 211 } 212 213 RTCPUtility::RTCPPacketSR sr_; 214 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_; 215 }; 216 217 // 218 // RTCP receiver report (RFC 3550). 219 // 220 // 0 1 2 3 221 // 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 222 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 223 // |V=2|P| RC | PT=RR=201 | length | 224 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 225 // | SSRC of packet sender | 226 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 227 // | report block(s) | 228 // | .... | 229 230 class ReceiverReport : public RtcpPacket { 231 public: 232 ReceiverReport() : RtcpPacket() { 233 memset(&rr_, 0, sizeof(rr_)); 234 } 235 236 virtual ~ReceiverReport() {} 237 238 void From(uint32_t ssrc) { 239 rr_.SenderSSRC = ssrc; 240 } 241 void WithReportBlock(ReportBlock* block); 242 243 protected: 244 virtual void Create( 245 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 246 247 private: 248 enum { kMaxNumberOfReportBlocks = 0x1f }; 249 250 size_t BlockLength() const { 251 const size_t kRrHeaderLength = 8; 252 return kRrHeaderLength + report_blocks_.size() * kReportBlockLength; 253 } 254 255 RTCPUtility::RTCPPacketRR rr_; 256 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_; 257 }; 258 259 // Transmission Time Offsets in RTP Streams (RFC 5450). 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 // hdr |V=2|P| RC | PT=IJ=195 | length | 265 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 266 // | inter-arrival jitter | 267 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 268 // . . 269 // . . 270 // . . 271 // | inter-arrival jitter | 272 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 273 // 274 // If present, this RTCP packet must be placed after a receiver report 275 // (inside a compound RTCP packet), and MUST have the same value for RC 276 // (reception report count) as the receiver report. 277 278 class Ij : public RtcpPacket { 279 public: 280 Ij() : RtcpPacket() {} 281 282 virtual ~Ij() {} 283 284 void WithJitterItem(uint32_t jitter); 285 286 protected: 287 virtual void Create( 288 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 289 290 private: 291 enum { kMaxNumberOfIjItems = 0x1f }; 292 293 size_t BlockLength() const { 294 return kHeaderLength + 4 * ij_items_.size(); 295 } 296 297 std::vector<uint32_t> ij_items_; 298 299 DISALLOW_COPY_AND_ASSIGN(Ij); 300 }; 301 302 // Source Description (SDES) (RFC 3550). 303 // 304 // 0 1 2 3 305 // 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 306 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 307 // header |V=2|P| SC | PT=SDES=202 | length | 308 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 309 // chunk | SSRC/CSRC_1 | 310 // 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 311 // | SDES items | 312 // | ... | 313 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 314 // chunk | SSRC/CSRC_2 | 315 // 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 316 // | SDES items | 317 // | ... | 318 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 319 // 320 // Canonical End-Point Identifier SDES Item (CNAME) 321 // 322 // 0 1 2 3 323 // 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 324 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 325 // | CNAME=1 | length | user and domain name ... 326 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 327 328 class Sdes : public RtcpPacket { 329 public: 330 Sdes() : RtcpPacket() {} 331 332 virtual ~Sdes() {} 333 334 void WithCName(uint32_t ssrc, std::string cname); 335 336 struct Chunk { 337 uint32_t ssrc; 338 std::string name; 339 int null_octets; 340 }; 341 342 protected: 343 virtual void Create( 344 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 345 346 private: 347 enum { kMaxNumberOfChunks = 0x1f }; 348 349 size_t BlockLength() const; 350 351 std::vector<Chunk> chunks_; 352 353 DISALLOW_COPY_AND_ASSIGN(Sdes); 354 }; 355 356 // 357 // Bye packet (BYE) (RFC 3550). 358 // 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| SC | PT=BYE=203 | length | 362 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 363 // | SSRC/CSRC | 364 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 365 // : ... : 366 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 367 // (opt) | length | reason for leaving ... 368 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 369 370 class Bye : public RtcpPacket { 371 public: 372 Bye() : RtcpPacket() { 373 memset(&bye_, 0, sizeof(bye_)); 374 } 375 376 virtual ~Bye() {} 377 378 void From(uint32_t ssrc) { 379 bye_.SenderSSRC = ssrc; 380 } 381 void WithCsrc(uint32_t csrc); 382 383 protected: 384 virtual void Create( 385 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 386 387 private: 388 enum { kMaxNumberOfCsrcs = 0x1f - 1 }; 389 390 size_t BlockLength() const { 391 size_t source_count = 1 + csrcs_.size(); 392 return kHeaderLength + 4 * source_count; 393 } 394 395 RTCPUtility::RTCPPacketBYE bye_; 396 std::vector<uint32_t> csrcs_; 397 }; 398 399 // Application-Defined packet (APP) (RFC 3550). 400 // 401 // 0 1 2 3 402 // 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 403 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 404 // |V=2|P| subtype | PT=APP=204 | length | 405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 406 // | SSRC/CSRC | 407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 408 // | name (ASCII) | 409 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 410 // | application-dependent data ... 411 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 412 413 class App : public RtcpPacket { 414 public: 415 App() 416 : RtcpPacket(), 417 ssrc_(0) { 418 memset(&app_, 0, sizeof(app_)); 419 } 420 421 virtual ~App() {} 422 423 void From(uint32_t ssrc) { 424 ssrc_ = ssrc; 425 } 426 void WithSubType(uint8_t subtype) { 427 assert(subtype <= 0x1f); 428 app_.SubType = subtype; 429 } 430 void WithName(uint32_t name) { 431 app_.Name = name; 432 } 433 void WithData(const uint8_t* data, uint16_t data_length) { 434 assert(data); 435 assert(data_length <= kRtcpAppCode_DATA_SIZE); 436 assert(data_length % 4 == 0); 437 memcpy(app_.Data, data, data_length); 438 app_.Size = data_length; 439 } 440 441 protected: 442 virtual void Create( 443 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 444 445 private: 446 size_t BlockLength() const { 447 return 12 + app_.Size; 448 } 449 450 uint32_t ssrc_; 451 RTCPUtility::RTCPPacketAPP app_; 452 453 DISALLOW_COPY_AND_ASSIGN(App); 454 }; 455 456 // RFC 4585: Feedback format. 457 // 458 // Common packet format: 459 // 460 // 0 1 2 3 461 // 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 462 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 463 // |V=2|P| FMT | PT | length | 464 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 465 // | SSRC of packet sender | 466 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 467 // | SSRC of media source | 468 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 469 // : Feedback Control Information (FCI) : 470 // : 471 472 // Picture loss indication (PLI) (RFC 4585). 473 // 474 // FCI: no feedback control information. 475 476 class Pli : public RtcpPacket { 477 public: 478 Pli() : RtcpPacket() { 479 memset(&pli_, 0, sizeof(pli_)); 480 } 481 482 virtual ~Pli() {} 483 484 void From(uint32_t ssrc) { 485 pli_.SenderSSRC = ssrc; 486 } 487 void To(uint32_t ssrc) { 488 pli_.MediaSSRC = ssrc; 489 } 490 491 protected: 492 virtual void Create( 493 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 494 495 private: 496 size_t BlockLength() const { 497 return kCommonFbFmtLength; 498 } 499 500 RTCPUtility::RTCPPacketPSFBPLI pli_; 501 502 DISALLOW_COPY_AND_ASSIGN(Pli); 503 }; 504 505 // Slice loss indication (SLI) (RFC 4585). 506 // 507 // FCI: 508 // 0 1 2 3 509 // 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 510 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 511 // | First | Number | PictureID | 512 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 513 514 class Sli : public RtcpPacket { 515 public: 516 Sli() : RtcpPacket() { 517 memset(&sli_, 0, sizeof(sli_)); 518 memset(&sli_item_, 0, sizeof(sli_item_)); 519 } 520 521 virtual ~Sli() {} 522 523 void From(uint32_t ssrc) { 524 sli_.SenderSSRC = ssrc; 525 } 526 void To(uint32_t ssrc) { 527 sli_.MediaSSRC = ssrc; 528 } 529 void WithFirstMb(uint16_t first_mb) { 530 assert(first_mb <= 0x1fff); 531 sli_item_.FirstMB = first_mb; 532 } 533 void WithNumberOfMb(uint16_t number_mb) { 534 assert(number_mb <= 0x1fff); 535 sli_item_.NumberOfMB = number_mb; 536 } 537 void WithPictureId(uint8_t picture_id) { 538 assert(picture_id <= 0x3f); 539 sli_item_.PictureId = picture_id; 540 } 541 542 protected: 543 virtual void Create( 544 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 545 546 private: 547 size_t BlockLength() const { 548 const size_t kFciLength = 4; 549 return kCommonFbFmtLength + kFciLength; 550 } 551 552 RTCPUtility::RTCPPacketPSFBSLI sli_; 553 RTCPUtility::RTCPPacketPSFBSLIItem sli_item_; 554 555 DISALLOW_COPY_AND_ASSIGN(Sli); 556 }; 557 558 // Generic NACK (RFC 4585). 559 // 560 // FCI: 561 // 0 1 2 3 562 // 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 563 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 564 // | PID | BLP | 565 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 566 567 class Nack : public RtcpPacket { 568 public: 569 Nack() : RtcpPacket() { 570 memset(&nack_, 0, sizeof(nack_)); 571 } 572 573 virtual ~Nack() {} 574 575 void From(uint32_t ssrc) { 576 nack_.SenderSSRC = ssrc; 577 } 578 void To(uint32_t ssrc) { 579 nack_.MediaSSRC = ssrc; 580 } 581 void WithList(const uint16_t* nack_list, int length); 582 583 protected: 584 virtual void Create( 585 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 586 587 private: 588 size_t BlockLength() const { 589 size_t fci_length = 4 * nack_fields_.size(); 590 return kCommonFbFmtLength + fci_length; 591 } 592 593 RTCPUtility::RTCPPacketRTPFBNACK nack_; 594 std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_; 595 596 DISALLOW_COPY_AND_ASSIGN(Nack); 597 }; 598 599 // Reference picture selection indication (RPSI) (RFC 4585). 600 // 601 // FCI: 602 // 603 // 0 1 2 3 604 // 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 605 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 606 // | PB |0| Payload Type| Native RPSI bit string | 607 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 608 // | defined per codec ... | Padding (0) | 609 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 610 611 class Rpsi : public RtcpPacket { 612 public: 613 Rpsi() 614 : RtcpPacket(), 615 padding_bytes_(0) { 616 memset(&rpsi_, 0, sizeof(rpsi_)); 617 } 618 619 virtual ~Rpsi() {} 620 621 void From(uint32_t ssrc) { 622 rpsi_.SenderSSRC = ssrc; 623 } 624 void To(uint32_t ssrc) { 625 rpsi_.MediaSSRC = ssrc; 626 } 627 void WithPayloadType(uint8_t payload) { 628 assert(payload <= 0x7f); 629 rpsi_.PayloadType = payload; 630 } 631 void WithPictureId(uint64_t picture_id); 632 633 protected: 634 virtual void Create( 635 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 636 637 private: 638 size_t BlockLength() const { 639 size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_; 640 return kCommonFbFmtLength + fci_length; 641 } 642 643 uint8_t padding_bytes_; 644 RTCPUtility::RTCPPacketPSFBRPSI rpsi_; 645 646 DISALLOW_COPY_AND_ASSIGN(Rpsi); 647 }; 648 649 // Full intra request (FIR) (RFC 5104). 650 // 651 // FCI: 652 // 653 // 0 1 2 3 654 // 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 655 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 656 // | SSRC | 657 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 658 // | Seq nr. | Reserved | 659 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 660 661 class Fir : public RtcpPacket { 662 public: 663 Fir() 664 : RtcpPacket() { 665 memset(&fir_, 0, sizeof(fir_)); 666 memset(&fir_item_, 0, sizeof(fir_item_)); 667 } 668 669 virtual ~Fir() {} 670 671 void From(uint32_t ssrc) { 672 fir_.SenderSSRC = ssrc; 673 } 674 void To(uint32_t ssrc) { 675 fir_item_.SSRC = ssrc; 676 } 677 void WithCommandSeqNum(uint8_t seq_num) { 678 fir_item_.CommandSequenceNumber = seq_num; 679 } 680 681 protected: 682 virtual void Create( 683 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE; 684 685 private: 686 size_t BlockLength() const { 687 const size_t kFciLength = 8; 688 return kCommonFbFmtLength + kFciLength; 689 } 690 691 RTCPUtility::RTCPPacketPSFBFIR fir_; 692 RTCPUtility::RTCPPacketPSFBFIRItem fir_item_; 693 }; 694 695 // Class holding a RTCP packet. 696 // 697 // Takes a built rtcp packet. 698 // RawPacket raw_packet(buffer, length); 699 // 700 // To access the raw packet: 701 // raw_packet.buffer(); - pointer to the raw packet 702 // raw_packet.buffer_length(); - the length of the raw packet 703 704 class RawPacket { 705 public: 706 RawPacket(const uint8_t* packet, size_t length) { 707 assert(length <= IP_PACKET_SIZE); 708 memcpy(buffer_, packet, length); 709 buffer_length_ = length; 710 } 711 712 const uint8_t* buffer() { 713 return buffer_; 714 } 715 size_t buffer_length() const { 716 return buffer_length_; 717 } 718 719 private: 720 size_t buffer_length_; 721 uint8_t buffer_[IP_PACKET_SIZE]; 722 }; 723 724 } // namespace rtcp 725 } // namespace webrtc 726 #endif // WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_ 727