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