rtcp_packet.h revision ef3d805f6e50bc488f8e4e9e353068b78c73d17f
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
28namespace webrtc {
29namespace rtcp {
30
31static const int kCommonFbFmtLength = 12;
32static const int kReportBlockLength = 24;
33
34class 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
63class RtcpPacket {
64 public:
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:
75    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:
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
130class Empty : public RtcpPacket {
131 public:
132  Empty() : RtcpPacket() {}
133
134  virtual ~Empty() {}
135
136 protected:
137  bool Create(uint8_t* packet,
138              size_t* index,
139              size_t max_length,
140              RtcpPacket::PacketReadyCallback* callback) const override;
141
142  size_t BlockLength() const override;
143
144 private:
145  RTC_DISALLOW_COPY_AND_ASSIGN(Empty);
146};
147
148// RTCP sender report (RFC 3550).
149//
150//   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
151//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152//  |V=2|P|    RC   |   PT=SR=200   |             length            |
153//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154//  |                         SSRC of sender                        |
155//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
156//  |              NTP timestamp, most significant word             |
157//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158//  |             NTP timestamp, least significant word             |
159//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160//  |                         RTP timestamp                         |
161//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162//  |                     sender's packet count                     |
163//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164//  |                      sender's octet count                     |
165//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
166//  |                         report block(s)                       |
167//  |                            ....                               |
168
169class SenderReport : public RtcpPacket {
170 public:
171  SenderReport() : RtcpPacket() {
172    memset(&sr_, 0, sizeof(sr_));
173  }
174
175  virtual ~SenderReport() {}
176
177  void From(uint32_t ssrc) {
178    sr_.SenderSSRC = ssrc;
179  }
180  void WithNtpSec(uint32_t sec) {
181    sr_.NTPMostSignificant = sec;
182  }
183  void WithNtpFrac(uint32_t frac) {
184    sr_.NTPLeastSignificant = frac;
185  }
186  void WithRtpTimestamp(uint32_t rtp_timestamp) {
187    sr_.RTPTimestamp = rtp_timestamp;
188  }
189  void WithPacketCount(uint32_t packet_count) {
190    sr_.SenderPacketCount = packet_count;
191  }
192  void WithOctetCount(uint32_t octet_count) {
193    sr_.SenderOctetCount = octet_count;
194  }
195  bool WithReportBlock(const ReportBlock& block);
196
197 protected:
198  bool Create(uint8_t* packet,
199              size_t* index,
200              size_t max_length,
201              RtcpPacket::PacketReadyCallback* callback) const override;
202
203 private:
204  static const int 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<ReportBlock> report_blocks_;
215
216  RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport);
217};
218
219// Source Description (SDES) (RFC 3550).
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// header |V=2|P|    SC   |  PT=SDES=202  |             length            |
225//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
226// chunk  |                          SSRC/CSRC_1                          |
227//   1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
228//        |                           SDES items                          |
229//        |                              ...                              |
230//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
231// chunk  |                          SSRC/CSRC_2                          |
232//   2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
233//        |                           SDES items                          |
234//        |                              ...                              |
235//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
236//
237// Canonical End-Point Identifier SDES Item (CNAME)
238//
239//    0                   1                   2                   3
240//    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
241//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242//   |    CNAME=1    |     length    | user and domain name        ...
243//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244
245class Sdes : public RtcpPacket {
246 public:
247  Sdes() : RtcpPacket() {}
248
249  virtual ~Sdes() {}
250
251  bool WithCName(uint32_t ssrc, const std::string& cname);
252
253  struct Chunk {
254    uint32_t ssrc;
255    std::string name;
256    int null_octets;
257  };
258
259 protected:
260  bool Create(uint8_t* packet,
261              size_t* index,
262              size_t max_length,
263              RtcpPacket::PacketReadyCallback* callback) const override;
264
265 private:
266  static const int kMaxNumberOfChunks = 0x1f;
267
268  size_t BlockLength() const;
269
270  std::vector<Chunk> chunks_;
271
272  RTC_DISALLOW_COPY_AND_ASSIGN(Sdes);
273};
274
275// Slice loss indication (SLI) (RFC 4585).
276//
277// FCI:
278//    0                   1                   2                   3
279//    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
280//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
281//   |            First        |        Number           | PictureID |
282//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
283
284class Sli : public RtcpPacket {
285 public:
286  Sli() : RtcpPacket() {
287    memset(&sli_, 0, sizeof(sli_));
288    memset(&sli_item_, 0, sizeof(sli_item_));
289  }
290
291  virtual ~Sli() {}
292
293  void From(uint32_t ssrc) {
294    sli_.SenderSSRC = ssrc;
295  }
296  void To(uint32_t ssrc) {
297    sli_.MediaSSRC = ssrc;
298  }
299  void WithFirstMb(uint16_t first_mb) {
300    assert(first_mb <= 0x1fff);
301    sli_item_.FirstMB = first_mb;
302  }
303  void WithNumberOfMb(uint16_t number_mb) {
304    assert(number_mb <= 0x1fff);
305    sli_item_.NumberOfMB = number_mb;
306  }
307  void WithPictureId(uint8_t picture_id) {
308    assert(picture_id <= 0x3f);
309    sli_item_.PictureId = picture_id;
310  }
311
312 protected:
313  bool Create(uint8_t* packet,
314              size_t* index,
315              size_t max_length,
316              RtcpPacket::PacketReadyCallback* callback) const override;
317
318 private:
319  size_t BlockLength() const {
320    const size_t kFciLength = 4;
321    return kCommonFbFmtLength + kFciLength;
322  }
323
324  RTCPUtility::RTCPPacketPSFBSLI sli_;
325  RTCPUtility::RTCPPacketPSFBSLIItem sli_item_;
326
327  RTC_DISALLOW_COPY_AND_ASSIGN(Sli);
328};
329
330// Reference picture selection indication (RPSI) (RFC 4585).
331//
332// FCI:
333//
334//    0                   1                   2                   3
335//    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
336//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
337//   |      PB       |0| Payload Type|    Native RPSI bit string     |
338//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
339//   |   defined per codec          ...                | Padding (0) |
340//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
341
342class Rpsi : public RtcpPacket {
343 public:
344  Rpsi()
345      : RtcpPacket(),
346        padding_bytes_(0) {
347    memset(&rpsi_, 0, sizeof(rpsi_));
348  }
349
350  virtual ~Rpsi() {}
351
352  void From(uint32_t ssrc) {
353    rpsi_.SenderSSRC = ssrc;
354  }
355  void To(uint32_t ssrc) {
356    rpsi_.MediaSSRC = ssrc;
357  }
358  void WithPayloadType(uint8_t payload) {
359    assert(payload <= 0x7f);
360    rpsi_.PayloadType = payload;
361  }
362  void WithPictureId(uint64_t picture_id);
363
364 protected:
365  bool Create(uint8_t* packet,
366              size_t* index,
367              size_t max_length,
368              RtcpPacket::PacketReadyCallback* callback) const override;
369
370 private:
371  size_t BlockLength() const {
372    size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
373    return kCommonFbFmtLength + fci_length;
374  }
375
376  uint8_t padding_bytes_;
377  RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
378
379  RTC_DISALLOW_COPY_AND_ASSIGN(Rpsi);
380};
381
382// Full intra request (FIR) (RFC 5104).
383//
384// FCI:
385//
386//    0                   1                   2                   3
387//    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
388//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
389//   |                              SSRC                             |
390//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391//   | Seq nr.       |    Reserved                                   |
392//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
393
394class Fir : public RtcpPacket {
395 public:
396  Fir() : RtcpPacket() {
397    memset(&fir_, 0, sizeof(fir_));
398    memset(&fir_item_, 0, sizeof(fir_item_));
399  }
400
401  virtual ~Fir() {}
402
403  void From(uint32_t ssrc) {
404    fir_.SenderSSRC = ssrc;
405  }
406  void To(uint32_t ssrc) {
407    fir_item_.SSRC = ssrc;
408  }
409  void WithCommandSeqNum(uint8_t seq_num) {
410    fir_item_.CommandSequenceNumber = seq_num;
411  }
412
413 protected:
414  bool Create(uint8_t* packet,
415              size_t* index,
416              size_t max_length,
417              RtcpPacket::PacketReadyCallback* callback) const override;
418
419 private:
420  size_t BlockLength() const {
421    const size_t kFciLength = 8;
422    return kCommonFbFmtLength + kFciLength;
423  }
424
425  RTCPUtility::RTCPPacketPSFBFIR fir_;
426  RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
427};
428
429// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
430//
431// FCI:
432//
433//    0                   1                   2                   3
434//    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
435//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
436//   |                              SSRC                             |
437//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
438//   | MxTBR Exp |  MxTBR Mantissa                 |Measured Overhead|
439//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
440
441class Tmmbr : public RtcpPacket {
442 public:
443  Tmmbr() : RtcpPacket() {
444    memset(&tmmbr_, 0, sizeof(tmmbr_));
445    memset(&tmmbr_item_, 0, sizeof(tmmbr_item_));
446  }
447
448  virtual ~Tmmbr() {}
449
450  void From(uint32_t ssrc) {
451    tmmbr_.SenderSSRC = ssrc;
452  }
453  void To(uint32_t ssrc) {
454    tmmbr_item_.SSRC = ssrc;
455  }
456  void WithBitrateKbps(uint32_t bitrate_kbps) {
457    tmmbr_item_.MaxTotalMediaBitRate = bitrate_kbps;
458  }
459  void WithOverhead(uint16_t overhead) {
460    assert(overhead <= 0x1ff);
461    tmmbr_item_.MeasuredOverhead = overhead;
462  }
463
464 protected:
465  bool Create(uint8_t* packet,
466              size_t* index,
467              size_t max_length,
468              RtcpPacket::PacketReadyCallback* callback) const override;
469
470 private:
471  size_t BlockLength() const {
472    const size_t kFciLen = 8;
473    return kCommonFbFmtLength + kFciLen;
474  }
475
476  RTCPUtility::RTCPPacketRTPFBTMMBR tmmbr_;
477  RTCPUtility::RTCPPacketRTPFBTMMBRItem tmmbr_item_;
478
479  RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbr);
480};
481
482// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
483//
484//    0                   1                   2                   3
485//    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
486//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
487//   |V=2|P| FMT=15  |   PT=206      |             length            |
488//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
489//   |                  SSRC of packet sender                        |
490//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
491//   |                  SSRC of media source                         |
492//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
493//   |  Unique identifier 'R' 'E' 'M' 'B'                            |
494//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
495//   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
496//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
497//   |   SSRC feedback                                               |
498//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
499//   |  ...
500
501class Remb : public RtcpPacket {
502 public:
503  Remb() : RtcpPacket() {
504    memset(&remb_, 0, sizeof(remb_));
505    memset(&remb_item_, 0, sizeof(remb_item_));
506  }
507
508  virtual ~Remb() {}
509
510  void From(uint32_t ssrc) {
511    remb_.SenderSSRC = ssrc;
512  }
513  void AppliesTo(uint32_t ssrc);
514
515  void WithBitrateBps(uint32_t bitrate_bps) {
516    remb_item_.BitRate = bitrate_bps;
517  }
518
519 protected:
520  bool Create(uint8_t* packet,
521              size_t* index,
522              size_t max_length,
523              RtcpPacket::PacketReadyCallback* callback) const override;
524
525 private:
526  static const int kMaxNumberOfSsrcs = 0xff;
527
528  size_t BlockLength() const {
529    return (remb_item_.NumberOfSSRCs + 5) * 4;
530  }
531
532  RTCPUtility::RTCPPacketPSFBAPP remb_;
533  RTCPUtility::RTCPPacketPSFBREMBItem remb_item_;
534
535  RTC_DISALLOW_COPY_AND_ASSIGN(Remb);
536};
537
538// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
539//
540// Format for XR packets:
541//
542//   0                   1                   2                   3
543//   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
544//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
545//  |V=2|P|reserved |   PT=XR=207   |             length            |
546//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
547//  |                              SSRC                             |
548//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
549//  :                         report blocks                         :
550//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
551
552class Xr : public RtcpPacket {
553 public:
554  typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock;
555  Xr() : RtcpPacket() {
556    memset(&xr_header_, 0, sizeof(xr_header_));
557  }
558
559  virtual ~Xr() {}
560
561  void From(uint32_t ssrc) {
562    xr_header_.OriginatorSSRC = ssrc;
563  }
564
565  // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr.
566  bool WithRrtr(Rrtr* rrtr);
567  bool WithDlrr(Dlrr* dlrr);
568  bool WithVoipMetric(VoipMetric* voip_metric);
569
570 protected:
571  bool Create(uint8_t* packet,
572              size_t* index,
573              size_t max_length,
574              RtcpPacket::PacketReadyCallback* callback) const override;
575
576 private:
577  static const int kMaxNumberOfRrtrBlocks = 50;
578  static const int kMaxNumberOfDlrrBlocks = 50;
579  static const int kMaxNumberOfVoipMetricBlocks = 50;
580
581  size_t BlockLength() const {
582    const size_t kXrHeaderLength = 8;
583    return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength();
584  }
585
586  size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); }
587
588  size_t DlrrLength() const;
589
590  size_t VoipMetricLength() const {
591    return VoipMetric::kLength * voip_metric_blocks_.size();
592  }
593
594  RTCPUtility::RTCPPacketXR xr_header_;
595  std::vector<Rrtr> rrtr_blocks_;
596  std::vector<Dlrr> dlrr_blocks_;
597  std::vector<VoipMetric> voip_metric_blocks_;
598
599  RTC_DISALLOW_COPY_AND_ASSIGN(Xr);
600};
601
602// Class holding a RTCP packet.
603//
604// Takes a built rtcp packet.
605//  RawPacket raw_packet(buffer, length);
606//
607// To access the raw packet:
608//  raw_packet.Buffer();         - pointer to the raw packet
609//  raw_packet.BufferLength();   - the length of the raw packet
610
611class RawPacket {
612 public:
613  explicit RawPacket(size_t buffer_length);
614  RawPacket(const uint8_t* packet, size_t packet_length);
615
616  const uint8_t* Buffer() const;
617  uint8_t* MutableBuffer();
618  size_t BufferLength() const;
619  size_t Length() const;
620  void SetLength(size_t length);
621
622 private:
623  const size_t buffer_length_;
624  size_t length_;
625  rtc::scoped_ptr<uint8_t[]> buffer_;
626};
627
628}  // namespace rtcp
629}  // namespace webrtc
630#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_
631