rtcp_packet.h revision b8b6fbb7a5d2f5a14f7f6f81c253747aa28e4c7f
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/report_block.h"
22#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rrtr.h"
23#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
24#include "webrtc/typedefs.h"
25
26namespace webrtc {
27namespace rtcp {
28
29static const int kCommonFbFmtLength = 12;
30static const int kReportBlockLength = 24;
31
32class Dlrr;
33class RawPacket;
34class VoipMetric;
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// Generic NACK (RFC 4585).
331//
332// FCI:
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//   |            PID                |             BLP               |
337//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
338
339class Nack : public RtcpPacket {
340 public:
341  Nack() : RtcpPacket() {
342    memset(&nack_, 0, sizeof(nack_));
343  }
344
345  virtual ~Nack() {}
346
347  void From(uint32_t ssrc) {
348    nack_.SenderSSRC = ssrc;
349  }
350  void To(uint32_t ssrc) {
351    nack_.MediaSSRC = ssrc;
352  }
353  void WithList(const uint16_t* nack_list, int length);
354
355 protected:
356  bool Create(uint8_t* packet,
357              size_t* index,
358              size_t max_length,
359              RtcpPacket::PacketReadyCallback* callback) const override;
360
361  size_t BlockLength() const override;
362
363 private:
364  RTCPUtility::RTCPPacketRTPFBNACK nack_;
365  std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_;
366
367  RTC_DISALLOW_COPY_AND_ASSIGN(Nack);
368};
369
370// Reference picture selection indication (RPSI) (RFC 4585).
371//
372// FCI:
373//
374//    0                   1                   2                   3
375//    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
376//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
377//   |      PB       |0| Payload Type|    Native RPSI bit string     |
378//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379//   |   defined per codec          ...                | Padding (0) |
380//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
381
382class Rpsi : public RtcpPacket {
383 public:
384  Rpsi()
385      : RtcpPacket(),
386        padding_bytes_(0) {
387    memset(&rpsi_, 0, sizeof(rpsi_));
388  }
389
390  virtual ~Rpsi() {}
391
392  void From(uint32_t ssrc) {
393    rpsi_.SenderSSRC = ssrc;
394  }
395  void To(uint32_t ssrc) {
396    rpsi_.MediaSSRC = ssrc;
397  }
398  void WithPayloadType(uint8_t payload) {
399    assert(payload <= 0x7f);
400    rpsi_.PayloadType = payload;
401  }
402  void WithPictureId(uint64_t picture_id);
403
404 protected:
405  bool Create(uint8_t* packet,
406              size_t* index,
407              size_t max_length,
408              RtcpPacket::PacketReadyCallback* callback) const override;
409
410 private:
411  size_t BlockLength() const {
412    size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
413    return kCommonFbFmtLength + fci_length;
414  }
415
416  uint8_t padding_bytes_;
417  RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
418
419  RTC_DISALLOW_COPY_AND_ASSIGN(Rpsi);
420};
421
422// Full intra request (FIR) (RFC 5104).
423//
424// FCI:
425//
426//    0                   1                   2                   3
427//    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
428//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
429//   |                              SSRC                             |
430//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
431//   | Seq nr.       |    Reserved                                   |
432//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
433
434class Fir : public RtcpPacket {
435 public:
436  Fir() : RtcpPacket() {
437    memset(&fir_, 0, sizeof(fir_));
438    memset(&fir_item_, 0, sizeof(fir_item_));
439  }
440
441  virtual ~Fir() {}
442
443  void From(uint32_t ssrc) {
444    fir_.SenderSSRC = ssrc;
445  }
446  void To(uint32_t ssrc) {
447    fir_item_.SSRC = ssrc;
448  }
449  void WithCommandSeqNum(uint8_t seq_num) {
450    fir_item_.CommandSequenceNumber = seq_num;
451  }
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  size_t BlockLength() const {
461    const size_t kFciLength = 8;
462    return kCommonFbFmtLength + kFciLength;
463  }
464
465  RTCPUtility::RTCPPacketPSFBFIR fir_;
466  RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
467};
468
469// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
470//
471// FCI:
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//   |                              SSRC                             |
477//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
478//   | MxTBR Exp |  MxTBR Mantissa                 |Measured Overhead|
479//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
480
481class Tmmbr : public RtcpPacket {
482 public:
483  Tmmbr() : RtcpPacket() {
484    memset(&tmmbr_, 0, sizeof(tmmbr_));
485    memset(&tmmbr_item_, 0, sizeof(tmmbr_item_));
486  }
487
488  virtual ~Tmmbr() {}
489
490  void From(uint32_t ssrc) {
491    tmmbr_.SenderSSRC = ssrc;
492  }
493  void To(uint32_t ssrc) {
494    tmmbr_item_.SSRC = ssrc;
495  }
496  void WithBitrateKbps(uint32_t bitrate_kbps) {
497    tmmbr_item_.MaxTotalMediaBitRate = bitrate_kbps;
498  }
499  void WithOverhead(uint16_t overhead) {
500    assert(overhead <= 0x1ff);
501    tmmbr_item_.MeasuredOverhead = overhead;
502  }
503
504 protected:
505  bool Create(uint8_t* packet,
506              size_t* index,
507              size_t max_length,
508              RtcpPacket::PacketReadyCallback* callback) const override;
509
510 private:
511  size_t BlockLength() const {
512    const size_t kFciLen = 8;
513    return kCommonFbFmtLength + kFciLen;
514  }
515
516  RTCPUtility::RTCPPacketRTPFBTMMBR tmmbr_;
517  RTCPUtility::RTCPPacketRTPFBTMMBRItem tmmbr_item_;
518
519  RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbr);
520};
521
522// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
523//
524// FCI:
525//
526//    0                   1                   2                   3
527//    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
528//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
529//   |                              SSRC                             |
530//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
531//   | MxTBR Exp |  MxTBR Mantissa                 |Measured Overhead|
532//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
533
534class Tmmbn : public RtcpPacket {
535 public:
536  Tmmbn() : RtcpPacket() {
537    memset(&tmmbn_, 0, sizeof(tmmbn_));
538  }
539
540  virtual ~Tmmbn() {}
541
542  void From(uint32_t ssrc) {
543    tmmbn_.SenderSSRC = ssrc;
544  }
545  // Max 50 TMMBR can be added per TMMBN.
546  bool WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead);
547
548 protected:
549  bool Create(uint8_t* packet,
550              size_t* index,
551              size_t max_length,
552              RtcpPacket::PacketReadyCallback* callback) const override;
553
554 private:
555  static const int kMaxNumberOfTmmbrs = 50;
556
557  size_t BlockLength() const {
558    const size_t kFciLen = 8;
559    return kCommonFbFmtLength + kFciLen * tmmbn_items_.size();
560  }
561
562  RTCPUtility::RTCPPacketRTPFBTMMBN tmmbn_;
563  std::vector<RTCPUtility::RTCPPacketRTPFBTMMBRItem> tmmbn_items_;
564
565  RTC_DISALLOW_COPY_AND_ASSIGN(Tmmbn);
566};
567
568// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
569//
570//    0                   1                   2                   3
571//    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
572//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573//   |V=2|P| FMT=15  |   PT=206      |             length            |
574//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
575//   |                  SSRC of packet sender                        |
576//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
577//   |                  SSRC of media source                         |
578//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
579//   |  Unique identifier 'R' 'E' 'M' 'B'                            |
580//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
581//   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
582//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
583//   |   SSRC feedback                                               |
584//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
585//   |  ...
586
587class Remb : public RtcpPacket {
588 public:
589  Remb() : RtcpPacket() {
590    memset(&remb_, 0, sizeof(remb_));
591    memset(&remb_item_, 0, sizeof(remb_item_));
592  }
593
594  virtual ~Remb() {}
595
596  void From(uint32_t ssrc) {
597    remb_.SenderSSRC = ssrc;
598  }
599  void AppliesTo(uint32_t ssrc);
600
601  void WithBitrateBps(uint32_t bitrate_bps) {
602    remb_item_.BitRate = bitrate_bps;
603  }
604
605 protected:
606  bool Create(uint8_t* packet,
607              size_t* index,
608              size_t max_length,
609              RtcpPacket::PacketReadyCallback* callback) const override;
610
611 private:
612  static const int kMaxNumberOfSsrcs = 0xff;
613
614  size_t BlockLength() const {
615    return (remb_item_.NumberOfSSRCs + 5) * 4;
616  }
617
618  RTCPUtility::RTCPPacketPSFBAPP remb_;
619  RTCPUtility::RTCPPacketPSFBREMBItem remb_item_;
620
621  RTC_DISALLOW_COPY_AND_ASSIGN(Remb);
622};
623
624// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
625//
626// Format for XR packets:
627//
628//   0                   1                   2                   3
629//   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
630//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
631//  |V=2|P|reserved |   PT=XR=207   |             length            |
632//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
633//  |                              SSRC                             |
634//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
635//  :                         report blocks                         :
636//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
637
638class Xr : public RtcpPacket {
639 public:
640  typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock;
641  Xr() : RtcpPacket() {
642    memset(&xr_header_, 0, sizeof(xr_header_));
643  }
644
645  virtual ~Xr() {}
646
647  void From(uint32_t ssrc) {
648    xr_header_.OriginatorSSRC = ssrc;
649  }
650
651  // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr.
652  bool WithRrtr(Rrtr* rrtr);
653  bool WithDlrr(Dlrr* dlrr);
654  bool WithVoipMetric(VoipMetric* voip_metric);
655
656 protected:
657  bool Create(uint8_t* packet,
658              size_t* index,
659              size_t max_length,
660              RtcpPacket::PacketReadyCallback* callback) const override;
661
662 private:
663  static const int kMaxNumberOfRrtrBlocks = 50;
664  static const int kMaxNumberOfDlrrBlocks = 50;
665  static const int kMaxNumberOfVoipMetricBlocks = 50;
666
667  size_t BlockLength() const {
668    const size_t kXrHeaderLength = 8;
669    return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength();
670  }
671
672  size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); }
673
674  size_t DlrrLength() const;
675
676  size_t VoipMetricLength() const {
677    const size_t kVoipMetricBlockLength = 36;
678    return kVoipMetricBlockLength * voip_metric_blocks_.size();
679  }
680
681  RTCPUtility::RTCPPacketXR xr_header_;
682  std::vector<Rrtr> rrtr_blocks_;
683  std::vector<DlrrBlock> dlrr_blocks_;
684  std::vector<RTCPUtility::RTCPPacketXRVOIPMetricItem> voip_metric_blocks_;
685
686  RTC_DISALLOW_COPY_AND_ASSIGN(Xr);
687};
688
689// DLRR Report Block (RFC 3611).
690//
691//   0                   1                   2                   3
692//   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
693//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
694//  |     BT=5      |   reserved    |         block length          |
695//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
696//  |                 SSRC_1 (SSRC of first receiver)               | sub-
697//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
698//  |                         last RR (LRR)                         |   1
699//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
700//  |                   delay since last RR (DLRR)                  |
701//  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
702//  |                 SSRC_2 (SSRC of second receiver)              | sub-
703//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
704//  :                               ...                             :   2
705
706class Dlrr {
707 public:
708  Dlrr() {}
709  ~Dlrr() {}
710
711  // Max 100 DLRR Items can be added per DLRR report block.
712  bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr);
713
714 private:
715  friend class Xr;
716  static const int kMaxNumberOfDlrrItems = 100;
717
718  std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> dlrr_block_;
719
720  RTC_DISALLOW_COPY_AND_ASSIGN(Dlrr);
721};
722
723// VoIP Metrics Report Block (RFC 3611).
724//
725//   0                   1                   2                   3
726//   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
727//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
728//  |     BT=7      |   reserved    |       block length = 8        |
729//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
730//  |                        SSRC of source                         |
731//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
732//  |   loss rate   | discard rate  | burst density |  gap density  |
733//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
734//  |       burst duration          |         gap duration          |
735//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
736//  |     round trip delay          |       end system delay        |
737//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
738//  | signal level  |  noise level  |     RERL      |     Gmin      |
739//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740//  |   R factor    | ext. R factor |    MOS-LQ     |    MOS-CQ     |
741//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
742//  |   RX config   |   reserved    |          JB nominal           |
743//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
744//  |          JB maximum           |          JB abs max           |
745//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
746
747class VoipMetric {
748 public:
749  VoipMetric() {
750    memset(&metric_, 0, sizeof(metric_));
751  }
752  ~VoipMetric() {}
753
754  void To(uint32_t ssrc) { metric_.SSRC = ssrc; }
755  void LossRate(uint8_t loss_rate) { metric_.lossRate = loss_rate; }
756  void DiscardRate(uint8_t discard_rate) { metric_.discardRate = discard_rate; }
757  void BurstDensity(uint8_t burst_density) {
758    metric_.burstDensity = burst_density;
759  }
760  void GapDensity(uint8_t gap_density) { metric_.gapDensity = gap_density; }
761  void BurstDuration(uint16_t burst_duration) {
762    metric_.burstDuration = burst_duration;
763  }
764  void GapDuration(uint16_t gap_duration) {
765    metric_.gapDuration = gap_duration;
766  }
767  void RoundTripDelay(uint16_t round_trip_delay) {
768    metric_.roundTripDelay = round_trip_delay;
769  }
770  void EndSystemDelay(uint16_t end_system_delay) {
771    metric_.endSystemDelay = end_system_delay;
772  }
773  void SignalLevel(uint8_t signal_level) { metric_.signalLevel = signal_level; }
774  void NoiseLevel(uint8_t noise_level) { metric_.noiseLevel = noise_level; }
775  void Rerl(uint8_t rerl) { metric_.RERL = rerl; }
776  void Gmin(uint8_t gmin) { metric_.Gmin = gmin; }
777  void Rfactor(uint8_t rfactor) { metric_.Rfactor = rfactor; }
778  void ExtRfactor(uint8_t extrfactor) { metric_.extRfactor = extrfactor; }
779  void MosLq(uint8_t moslq) { metric_.MOSLQ = moslq; }
780  void MosCq(uint8_t moscq) { metric_.MOSCQ = moscq; }
781  void RxConfig(uint8_t rxconfig) { metric_.RXconfig = rxconfig; }
782  void JbNominal(uint16_t jbnominal) { metric_.JBnominal = jbnominal; }
783  void JbMax(uint16_t jbmax) { metric_.JBmax = jbmax; }
784  void JbAbsMax(uint16_t jbabsmax) { metric_.JBabsMax = jbabsmax; }
785
786 private:
787  friend class Xr;
788  RTCPUtility::RTCPPacketXRVOIPMetricItem metric_;
789
790  RTC_DISALLOW_COPY_AND_ASSIGN(VoipMetric);
791};
792
793// Class holding a RTCP packet.
794//
795// Takes a built rtcp packet.
796//  RawPacket raw_packet(buffer, length);
797//
798// To access the raw packet:
799//  raw_packet.Buffer();         - pointer to the raw packet
800//  raw_packet.BufferLength();   - the length of the raw packet
801
802class RawPacket {
803 public:
804  explicit RawPacket(size_t buffer_length);
805  RawPacket(const uint8_t* packet, size_t packet_length);
806
807  const uint8_t* Buffer() const;
808  uint8_t* MutableBuffer();
809  size_t BufferLength() const;
810  size_t Length() const;
811  void SetLength(size_t length);
812
813 private:
814  const size_t buffer_length_;
815  size_t length_;
816  rtc::scoped_ptr<uint8_t[]> buffer_;
817};
818
819}  // namespace rtcp
820}  // namespace webrtc
821#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_
822