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