• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 namespace webrtc {
29 namespace rtcp {
30 
31 static const int kCommonFbFmtLength = 12;
32 static const int kReportBlockLength = 24;
33 
34 class 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 
63 class RtcpPacket {
64  public:
~RtcpPacket()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:
PacketReadyCallback()75     PacketReadyCallback() {}
~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:
RtcpPacket()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 
130 // RTCP sender report (RFC 3550).
131 //
132 //   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
133 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
134 //  |V=2|P|    RC   |   PT=SR=200   |             length            |
135 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136 //  |                         SSRC of sender                        |
137 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
138 //  |              NTP timestamp, most significant word             |
139 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140 //  |             NTP timestamp, least significant word             |
141 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142 //  |                         RTP timestamp                         |
143 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144 //  |                     sender's packet count                     |
145 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146 //  |                      sender's octet count                     |
147 //  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
148 //  |                         report block(s)                       |
149 //  |                            ....                               |
150 
151 class SenderReport : public RtcpPacket {
152  public:
SenderReport()153   SenderReport() : RtcpPacket() {
154     memset(&sr_, 0, sizeof(sr_));
155   }
156 
~SenderReport()157   virtual ~SenderReport() {}
158 
From(uint32_t ssrc)159   void From(uint32_t ssrc) {
160     sr_.SenderSSRC = ssrc;
161   }
WithNtpSec(uint32_t sec)162   void WithNtpSec(uint32_t sec) {
163     sr_.NTPMostSignificant = sec;
164   }
WithNtpFrac(uint32_t frac)165   void WithNtpFrac(uint32_t frac) {
166     sr_.NTPLeastSignificant = frac;
167   }
WithRtpTimestamp(uint32_t rtp_timestamp)168   void WithRtpTimestamp(uint32_t rtp_timestamp) {
169     sr_.RTPTimestamp = rtp_timestamp;
170   }
WithPacketCount(uint32_t packet_count)171   void WithPacketCount(uint32_t packet_count) {
172     sr_.SenderPacketCount = packet_count;
173   }
WithOctetCount(uint32_t octet_count)174   void WithOctetCount(uint32_t octet_count) {
175     sr_.SenderOctetCount = octet_count;
176   }
177   bool WithReportBlock(const ReportBlock& block);
178 
179  protected:
180   bool Create(uint8_t* packet,
181               size_t* index,
182               size_t max_length,
183               RtcpPacket::PacketReadyCallback* callback) const override;
184 
185  private:
186   static const int kMaxNumberOfReportBlocks = 0x1f;
187 
BlockLength()188   size_t BlockLength() const {
189     const size_t kSrHeaderLength = 8;
190     const size_t kSenderInfoLength = 20;
191     return kSrHeaderLength + kSenderInfoLength +
192            report_blocks_.size() * kReportBlockLength;
193   }
194 
195   RTCPUtility::RTCPPacketSR sr_;
196   std::vector<ReportBlock> report_blocks_;
197 
198   RTC_DISALLOW_COPY_AND_ASSIGN(SenderReport);
199 };
200 
201 // Source Description (SDES) (RFC 3550).
202 //
203 //         0                   1                   2                   3
204 //         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
205 //        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206 // header |V=2|P|    SC   |  PT=SDES=202  |             length            |
207 //        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
208 // chunk  |                          SSRC/CSRC_1                          |
209 //   1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210 //        |                           SDES items                          |
211 //        |                              ...                              |
212 //        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
213 // chunk  |                          SSRC/CSRC_2                          |
214 //   2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215 //        |                           SDES items                          |
216 //        |                              ...                              |
217 //        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
218 //
219 // Canonical End-Point Identifier SDES Item (CNAME)
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 //   |    CNAME=1    |     length    | user and domain name        ...
225 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
226 
227 class Sdes : public RtcpPacket {
228  public:
Sdes()229   Sdes() : RtcpPacket() {}
230 
~Sdes()231   virtual ~Sdes() {}
232 
233   bool WithCName(uint32_t ssrc, const std::string& cname);
234 
235   struct Chunk {
236     uint32_t ssrc;
237     std::string name;
238     int null_octets;
239   };
240 
241  protected:
242   bool Create(uint8_t* packet,
243               size_t* index,
244               size_t max_length,
245               RtcpPacket::PacketReadyCallback* callback) const override;
246 
247  private:
248   static const int kMaxNumberOfChunks = 0x1f;
249 
250   size_t BlockLength() const;
251 
252   std::vector<Chunk> chunks_;
253 
254   RTC_DISALLOW_COPY_AND_ASSIGN(Sdes);
255 };
256 
257 // Reference picture selection indication (RPSI) (RFC 4585).
258 //
259 // FCI:
260 //
261 //    0                   1                   2                   3
262 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
263 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
264 //   |      PB       |0| Payload Type|    Native RPSI bit string     |
265 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266 //   |   defined per codec          ...                | Padding (0) |
267 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268 
269 class Rpsi : public RtcpPacket {
270  public:
Rpsi()271   Rpsi()
272       : RtcpPacket(),
273         padding_bytes_(0) {
274     memset(&rpsi_, 0, sizeof(rpsi_));
275   }
276 
~Rpsi()277   virtual ~Rpsi() {}
278 
From(uint32_t ssrc)279   void From(uint32_t ssrc) {
280     rpsi_.SenderSSRC = ssrc;
281   }
To(uint32_t ssrc)282   void To(uint32_t ssrc) {
283     rpsi_.MediaSSRC = ssrc;
284   }
WithPayloadType(uint8_t payload)285   void WithPayloadType(uint8_t payload) {
286     assert(payload <= 0x7f);
287     rpsi_.PayloadType = payload;
288   }
289   void WithPictureId(uint64_t picture_id);
290 
291  protected:
292   bool Create(uint8_t* packet,
293               size_t* index,
294               size_t max_length,
295               RtcpPacket::PacketReadyCallback* callback) const override;
296 
297  private:
BlockLength()298   size_t BlockLength() const {
299     size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
300     return kCommonFbFmtLength + fci_length;
301   }
302 
303   uint8_t padding_bytes_;
304   RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
305 
306   RTC_DISALLOW_COPY_AND_ASSIGN(Rpsi);
307 };
308 
309 // Full intra request (FIR) (RFC 5104).
310 //
311 // FCI:
312 //
313 //    0                   1                   2                   3
314 //    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
315 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
316 //   |                              SSRC                             |
317 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
318 //   | Seq nr.       |    Reserved                                   |
319 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
320 
321 class Fir : public RtcpPacket {
322  public:
Fir()323   Fir() : RtcpPacket() {
324     memset(&fir_, 0, sizeof(fir_));
325     memset(&fir_item_, 0, sizeof(fir_item_));
326   }
327 
~Fir()328   virtual ~Fir() {}
329 
From(uint32_t ssrc)330   void From(uint32_t ssrc) {
331     fir_.SenderSSRC = ssrc;
332   }
To(uint32_t ssrc)333   void To(uint32_t ssrc) {
334     fir_item_.SSRC = ssrc;
335   }
WithCommandSeqNum(uint8_t seq_num)336   void WithCommandSeqNum(uint8_t seq_num) {
337     fir_item_.CommandSequenceNumber = seq_num;
338   }
339 
340  protected:
341   bool Create(uint8_t* packet,
342               size_t* index,
343               size_t max_length,
344               RtcpPacket::PacketReadyCallback* callback) const override;
345 
346  private:
BlockLength()347   size_t BlockLength() const {
348     const size_t kFciLength = 8;
349     return kCommonFbFmtLength + kFciLength;
350   }
351 
352   RTCPUtility::RTCPPacketPSFBFIR fir_;
353   RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
354 };
355 
356 // Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
357 //
358 //    0                   1                   2                   3
359 //    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
360 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361 //   |V=2|P| FMT=15  |   PT=206      |             length            |
362 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363 //   |                  SSRC of packet sender                        |
364 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365 //   |                  SSRC of media source                         |
366 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
367 //   |  Unique identifier 'R' 'E' 'M' 'B'                            |
368 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369 //   |  Num SSRC     | BR Exp    |  BR Mantissa                      |
370 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
371 //   |   SSRC feedback                                               |
372 //   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
373 //   |  ...
374 
375 class Remb : public RtcpPacket {
376  public:
Remb()377   Remb() : RtcpPacket() {
378     memset(&remb_, 0, sizeof(remb_));
379     memset(&remb_item_, 0, sizeof(remb_item_));
380   }
381 
~Remb()382   virtual ~Remb() {}
383 
From(uint32_t ssrc)384   void From(uint32_t ssrc) {
385     remb_.SenderSSRC = ssrc;
386   }
387   void AppliesTo(uint32_t ssrc);
388 
WithBitrateBps(uint32_t bitrate_bps)389   void WithBitrateBps(uint32_t bitrate_bps) {
390     remb_item_.BitRate = bitrate_bps;
391   }
392 
393  protected:
394   bool Create(uint8_t* packet,
395               size_t* index,
396               size_t max_length,
397               RtcpPacket::PacketReadyCallback* callback) const override;
398 
399  private:
400   static const int kMaxNumberOfSsrcs = 0xff;
401 
BlockLength()402   size_t BlockLength() const {
403     return (remb_item_.NumberOfSSRCs + 5) * 4;
404   }
405 
406   RTCPUtility::RTCPPacketPSFBAPP remb_;
407   RTCPUtility::RTCPPacketPSFBREMBItem remb_item_;
408 
409   RTC_DISALLOW_COPY_AND_ASSIGN(Remb);
410 };
411 
412 // From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
413 //
414 // Format for XR packets:
415 //
416 //   0                   1                   2                   3
417 //   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
418 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
419 //  |V=2|P|reserved |   PT=XR=207   |             length            |
420 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
421 //  |                              SSRC                             |
422 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
423 //  :                         report blocks                         :
424 //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
425 
426 class Xr : public RtcpPacket {
427  public:
428   typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock;
Xr()429   Xr() : RtcpPacket() {
430     memset(&xr_header_, 0, sizeof(xr_header_));
431   }
432 
~Xr()433   virtual ~Xr() {}
434 
From(uint32_t ssrc)435   void From(uint32_t ssrc) {
436     xr_header_.OriginatorSSRC = ssrc;
437   }
438 
439   // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr.
440   bool WithRrtr(Rrtr* rrtr);
441   bool WithDlrr(Dlrr* dlrr);
442   bool WithVoipMetric(VoipMetric* voip_metric);
443 
444  protected:
445   bool Create(uint8_t* packet,
446               size_t* index,
447               size_t max_length,
448               RtcpPacket::PacketReadyCallback* callback) const override;
449 
450  private:
451   static const int kMaxNumberOfRrtrBlocks = 50;
452   static const int kMaxNumberOfDlrrBlocks = 50;
453   static const int kMaxNumberOfVoipMetricBlocks = 50;
454 
BlockLength()455   size_t BlockLength() const {
456     const size_t kXrHeaderLength = 8;
457     return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength();
458   }
459 
RrtrLength()460   size_t RrtrLength() const { return Rrtr::kLength * rrtr_blocks_.size(); }
461 
462   size_t DlrrLength() const;
463 
VoipMetricLength()464   size_t VoipMetricLength() const {
465     return VoipMetric::kLength * voip_metric_blocks_.size();
466   }
467 
468   RTCPUtility::RTCPPacketXR xr_header_;
469   std::vector<Rrtr> rrtr_blocks_;
470   std::vector<Dlrr> dlrr_blocks_;
471   std::vector<VoipMetric> voip_metric_blocks_;
472 
473   RTC_DISALLOW_COPY_AND_ASSIGN(Xr);
474 };
475 
476 // Class holding a RTCP packet.
477 //
478 // Takes a built rtcp packet.
479 //  RawPacket raw_packet(buffer, length);
480 //
481 // To access the raw packet:
482 //  raw_packet.Buffer();         - pointer to the raw packet
483 //  raw_packet.BufferLength();   - the length of the raw packet
484 
485 class RawPacket {
486  public:
487   explicit RawPacket(size_t buffer_length);
488   RawPacket(const uint8_t* packet, size_t packet_length);
489 
490   const uint8_t* Buffer() const;
491   uint8_t* MutableBuffer();
492   size_t BufferLength() const;
493   size_t Length() const;
494   void SetLength(size_t length);
495 
496  private:
497   const size_t buffer_length_;
498   size_t length_;
499   rtc::scoped_ptr<uint8_t[]> buffer_;
500 };
501 
502 }  // namespace rtcp
503 }  // namespace webrtc
504 #endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_RTCP_PACKET_H_
505