blob: d212497edde322b73fe252b1b92c0e33af8602b2 [file] [log] [blame]
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001/*
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
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000015#include <map>
16#include <string>
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000017#include <vector>
18
Erik Språngc1b9d4e2015-06-08 09:54:14 +020019#include "webrtc/base/scoped_ptr.h"
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000020#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
21#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
22#include "webrtc/typedefs.h"
23
24namespace webrtc {
25namespace rtcp {
26
Erik Språngc1b9d4e2015-06-08 09:54:14 +020027static const int kCommonFbFmtLength = 12;
28static const int kReportBlockLength = 24;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000029
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +000030class Dlrr;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000031class RawPacket;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +000032class Rrtr;
33class VoipMetric;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000034
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//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000051// size_t length = 0; // Builds an intra frame request
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000052// uint8_t packet[kPacketSize]; // with sequence number 123.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000053// fir.Build(packet, &length, kPacketSize);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000054//
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
Erik Språngc1b9d4e2015-06-08 09:54:14 +020068 // 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() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000076
Erik Språngc1b9d4e2015-06-08 09:54:14 +020077 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;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000093
94 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000095 RtcpPacket() : kHeaderLength(4) {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000096
Erik Språngc1b9d4e2015-06-08 09:54:14 +020097 virtual bool Create(uint8_t* packet,
98 size_t* index,
99 size_t max_length,
100 PacketReadyCallback* callback) const = 0;
101
102 bool OnBufferFull(uint8_t* packet,
103 size_t* index,
104 RtcpPacket::PacketReadyCallback* callback) const;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000105
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000106 const size_t kHeaderLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000107
108 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200109 bool CreateAndAddAppended(uint8_t* packet,
110 size_t* index,
111 size_t max_length,
112 PacketReadyCallback* callback) const;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000113
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000114 std::vector<RtcpPacket*> appended_packets_;
115};
116
117class Empty : public RtcpPacket {
118 public:
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000119 Empty() : RtcpPacket() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000120
121 virtual ~Empty() {}
122
123 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200124 bool Create(uint8_t* packet,
125 size_t* index,
126 size_t max_length,
127 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000128
129 private:
130 DISALLOW_COPY_AND_ASSIGN(Empty);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000131};
132
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000133// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000134//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000135// RTCP report block (RFC 3550).
136//
137// 0 1 2 3
138// 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
139// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
140// | SSRC_1 (SSRC of first source) |
141// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142// | fraction lost | cumulative number of packets lost |
143// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144// | extended highest sequence number received |
145// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146// | interarrival jitter |
147// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148// | last SR (LSR) |
149// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
150// | delay since last SR (DLSR) |
151// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
152
153class ReportBlock {
154 public:
155 ReportBlock() {
156 // TODO(asapersson): Consider adding a constructor to struct.
157 memset(&report_block_, 0, sizeof(report_block_));
158 }
159
160 ~ReportBlock() {}
161
162 void To(uint32_t ssrc) {
163 report_block_.SSRC = ssrc;
164 }
165 void WithFractionLost(uint8_t fraction_lost) {
166 report_block_.FractionLost = fraction_lost;
167 }
168 void WithCumulativeLost(uint32_t cumulative_lost) {
169 report_block_.CumulativeNumOfPacketsLost = cumulative_lost;
170 }
171 void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) {
172 report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num;
173 }
174 void WithJitter(uint32_t jitter) {
175 report_block_.Jitter = jitter;
176 }
177 void WithLastSr(uint32_t last_sr) {
178 report_block_.LastSR = last_sr;
179 }
180 void WithDelayLastSr(uint32_t delay_last_sr) {
181 report_block_.DelayLastSR = delay_last_sr;
182 }
183
184 private:
185 friend class SenderReport;
186 friend class ReceiverReport;
187 RTCPUtility::RTCPPacketReportBlockItem report_block_;
188};
189
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000190// RTCP sender report (RFC 3550).
191//
192// 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
193// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
194// |V=2|P| RC | PT=SR=200 | length |
195// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
196// | SSRC of sender |
197// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
198// | NTP timestamp, most significant word |
199// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
200// | NTP timestamp, least significant word |
201// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202// | RTP timestamp |
203// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204// | sender's packet count |
205// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206// | sender's octet count |
207// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
208// | report block(s) |
209// | .... |
210
211class SenderReport : public RtcpPacket {
212 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000213 SenderReport() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000214 memset(&sr_, 0, sizeof(sr_));
215 }
216
217 virtual ~SenderReport() {}
218
219 void From(uint32_t ssrc) {
220 sr_.SenderSSRC = ssrc;
221 }
222 void WithNtpSec(uint32_t sec) {
223 sr_.NTPMostSignificant = sec;
224 }
225 void WithNtpFrac(uint32_t frac) {
226 sr_.NTPLeastSignificant = frac;
227 }
228 void WithRtpTimestamp(uint32_t rtp_timestamp) {
229 sr_.RTPTimestamp = rtp_timestamp;
230 }
231 void WithPacketCount(uint32_t packet_count) {
232 sr_.SenderPacketCount = packet_count;
233 }
234 void WithOctetCount(uint32_t octet_count) {
235 sr_.SenderOctetCount = octet_count;
236 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200237 bool WithReportBlock(const ReportBlock& block);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000238
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000239 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200240 bool Create(uint8_t* packet,
241 size_t* index,
242 size_t max_length,
243 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000244
245 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200246 static const int kMaxNumberOfReportBlocks = 0x1f;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000247
248 size_t BlockLength() const {
249 const size_t kSrHeaderLength = 8;
250 const size_t kSenderInfoLength = 20;
251 return kSrHeaderLength + kSenderInfoLength +
252 report_blocks_.size() * kReportBlockLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000253 }
254
255 RTCPUtility::RTCPPacketSR sr_;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000256 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000257
258 DISALLOW_COPY_AND_ASSIGN(SenderReport);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000259};
260
261//
262// RTCP receiver report (RFC 3550).
263//
264// 0 1 2 3
265// 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
266// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267// |V=2|P| RC | PT=RR=201 | length |
268// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269// | SSRC of packet sender |
270// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
271// | report block(s) |
272// | .... |
273
274class ReceiverReport : public RtcpPacket {
275 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000276 ReceiverReport() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000277 memset(&rr_, 0, sizeof(rr_));
278 }
279
280 virtual ~ReceiverReport() {}
281
282 void From(uint32_t ssrc) {
283 rr_.SenderSSRC = ssrc;
284 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200285 bool WithReportBlock(const ReportBlock& block);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000286
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000287 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200288 bool Create(uint8_t* packet,
289 size_t* index,
290 size_t max_length,
291 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000292
293 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200294 static const int kMaxNumberOfReportBlocks = 0x1F;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000295
296 size_t BlockLength() const {
297 const size_t kRrHeaderLength = 8;
298 return kRrHeaderLength + report_blocks_.size() * kReportBlockLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000299 }
300
301 RTCPUtility::RTCPPacketRR rr_;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000302 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000303
304 DISALLOW_COPY_AND_ASSIGN(ReceiverReport);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000305};
306
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000307// Transmission Time Offsets in RTP Streams (RFC 5450).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000308//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000309// 0 1 2 3
310// 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
311// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
312// hdr |V=2|P| RC | PT=IJ=195 | length |
313// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
314// | inter-arrival jitter |
315// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
316// . .
317// . .
318// . .
319// | inter-arrival jitter |
320// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000321//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000322// If present, this RTCP packet must be placed after a receiver report
323// (inside a compound RTCP packet), and MUST have the same value for RC
324// (reception report count) as the receiver report.
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000325
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000326class Ij : public RtcpPacket {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000327 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000328 Ij() : RtcpPacket() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000329
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000330 virtual ~Ij() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000331
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200332 bool WithJitterItem(uint32_t jitter);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000333
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000334 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200335 bool Create(uint8_t* packet,
336 size_t* index,
337 size_t max_length,
338 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000339
340 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200341 static const int kMaxNumberOfIjItems = 0x1f;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000342
343 size_t BlockLength() const {
344 return kHeaderLength + 4 * ij_items_.size();
345 }
346
347 std::vector<uint32_t> ij_items_;
348
349 DISALLOW_COPY_AND_ASSIGN(Ij);
350};
351
352// Source Description (SDES) (RFC 3550).
353//
354// 0 1 2 3
355// 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
356// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
357// header |V=2|P| SC | PT=SDES=202 | length |
358// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
359// chunk | SSRC/CSRC_1 |
360// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361// | SDES items |
362// | ... |
363// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
364// chunk | SSRC/CSRC_2 |
365// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
366// | SDES items |
367// | ... |
368// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
369//
370// Canonical End-Point Identifier SDES Item (CNAME)
371//
372// 0 1 2 3
373// 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
374// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
375// | CNAME=1 | length | user and domain name ...
376// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
377
378class Sdes : public RtcpPacket {
379 public:
380 Sdes() : RtcpPacket() {}
381
382 virtual ~Sdes() {}
383
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200384 bool WithCName(uint32_t ssrc, const std::string& cname);
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000385
386 struct Chunk {
387 uint32_t ssrc;
388 std::string name;
389 int null_octets;
390 };
391
392 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200393 bool Create(uint8_t* packet,
394 size_t* index,
395 size_t max_length,
396 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000397
398 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200399 static const int kMaxNumberOfChunks = 0x1f;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000400
401 size_t BlockLength() const;
402
403 std::vector<Chunk> chunks_;
404
405 DISALLOW_COPY_AND_ASSIGN(Sdes);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000406};
407
408//
409// Bye packet (BYE) (RFC 3550).
410//
411// 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
412// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
413// |V=2|P| SC | PT=BYE=203 | length |
414// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
415// | SSRC/CSRC |
416// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
417// : ... :
418// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
419// (opt) | length | reason for leaving ...
420// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
421
422class Bye : public RtcpPacket {
423 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000424 Bye() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000425 memset(&bye_, 0, sizeof(bye_));
426 }
427
428 virtual ~Bye() {}
429
430 void From(uint32_t ssrc) {
431 bye_.SenderSSRC = ssrc;
432 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200433
434 bool WithCsrc(uint32_t csrc);
435
436 // TODO(sprang): Add support for reason field?
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000437
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000438 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200439 bool Create(uint8_t* packet,
440 size_t* index,
441 size_t max_length,
442 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000443
444 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200445 static const int kMaxNumberOfCsrcs = 0x1f - 1; // First item is sender SSRC.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000446
447 size_t BlockLength() const {
448 size_t source_count = 1 + csrcs_.size();
449 return kHeaderLength + 4 * source_count;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000450 }
451
452 RTCPUtility::RTCPPacketBYE bye_;
453 std::vector<uint32_t> csrcs_;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000454
455 DISALLOW_COPY_AND_ASSIGN(Bye);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000456};
457
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000458// Application-Defined packet (APP) (RFC 3550).
459//
460// 0 1 2 3
461// 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
462// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463// |V=2|P| subtype | PT=APP=204 | length |
464// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465// | SSRC/CSRC |
466// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467// | name (ASCII) |
468// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
469// | application-dependent data ...
470// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
471
472class App : public RtcpPacket {
473 public:
474 App()
475 : RtcpPacket(),
476 ssrc_(0) {
477 memset(&app_, 0, sizeof(app_));
478 }
479
480 virtual ~App() {}
481
482 void From(uint32_t ssrc) {
483 ssrc_ = ssrc;
484 }
485 void WithSubType(uint8_t subtype) {
486 assert(subtype <= 0x1f);
487 app_.SubType = subtype;
488 }
489 void WithName(uint32_t name) {
490 app_.Name = name;
491 }
492 void WithData(const uint8_t* data, uint16_t data_length) {
493 assert(data);
494 assert(data_length <= kRtcpAppCode_DATA_SIZE);
495 assert(data_length % 4 == 0);
496 memcpy(app_.Data, data, data_length);
497 app_.Size = data_length;
498 }
499
500 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200501 bool Create(uint8_t* packet,
502 size_t* index,
503 size_t max_length,
504 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000505
506 private:
507 size_t BlockLength() const {
508 return 12 + app_.Size;
509 }
510
511 uint32_t ssrc_;
512 RTCPUtility::RTCPPacketAPP app_;
513
514 DISALLOW_COPY_AND_ASSIGN(App);
515};
516
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000517// RFC 4585: Feedback format.
518//
519// Common packet format:
520//
521// 0 1 2 3
522// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
523// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
524// |V=2|P| FMT | PT | length |
525// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
526// | SSRC of packet sender |
527// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
528// | SSRC of media source |
529// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
530// : Feedback Control Information (FCI) :
531// :
532
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000533// Picture loss indication (PLI) (RFC 4585).
534//
535// FCI: no feedback control information.
536
537class Pli : public RtcpPacket {
538 public:
539 Pli() : RtcpPacket() {
540 memset(&pli_, 0, sizeof(pli_));
541 }
542
543 virtual ~Pli() {}
544
545 void From(uint32_t ssrc) {
546 pli_.SenderSSRC = ssrc;
547 }
548 void To(uint32_t ssrc) {
549 pli_.MediaSSRC = ssrc;
550 }
551
552 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200553 bool Create(uint8_t* packet,
554 size_t* index,
555 size_t max_length,
556 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000557
558 private:
559 size_t BlockLength() const {
560 return kCommonFbFmtLength;
561 }
562
563 RTCPUtility::RTCPPacketPSFBPLI pli_;
564
565 DISALLOW_COPY_AND_ASSIGN(Pli);
566};
567
568// Slice loss indication (SLI) (RFC 4585).
569//
570// FCI:
571// 0 1 2 3
572// 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
573// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
574// | First | Number | PictureID |
575// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
576
577class Sli : public RtcpPacket {
578 public:
579 Sli() : RtcpPacket() {
580 memset(&sli_, 0, sizeof(sli_));
581 memset(&sli_item_, 0, sizeof(sli_item_));
582 }
583
584 virtual ~Sli() {}
585
586 void From(uint32_t ssrc) {
587 sli_.SenderSSRC = ssrc;
588 }
589 void To(uint32_t ssrc) {
590 sli_.MediaSSRC = ssrc;
591 }
592 void WithFirstMb(uint16_t first_mb) {
593 assert(first_mb <= 0x1fff);
594 sli_item_.FirstMB = first_mb;
595 }
596 void WithNumberOfMb(uint16_t number_mb) {
597 assert(number_mb <= 0x1fff);
598 sli_item_.NumberOfMB = number_mb;
599 }
600 void WithPictureId(uint8_t picture_id) {
601 assert(picture_id <= 0x3f);
602 sli_item_.PictureId = picture_id;
603 }
604
605 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200606 bool Create(uint8_t* packet,
607 size_t* index,
608 size_t max_length,
609 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000610
611 private:
612 size_t BlockLength() const {
613 const size_t kFciLength = 4;
614 return kCommonFbFmtLength + kFciLength;
615 }
616
617 RTCPUtility::RTCPPacketPSFBSLI sli_;
618 RTCPUtility::RTCPPacketPSFBSLIItem sli_item_;
619
620 DISALLOW_COPY_AND_ASSIGN(Sli);
621};
622
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000623// Generic NACK (RFC 4585).
624//
625// FCI:
626// 0 1 2 3
627// 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
628// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
629// | PID | BLP |
630// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
631
632class Nack : public RtcpPacket {
633 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000634 Nack() : RtcpPacket() {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000635 memset(&nack_, 0, sizeof(nack_));
636 }
637
638 virtual ~Nack() {}
639
640 void From(uint32_t ssrc) {
641 nack_.SenderSSRC = ssrc;
642 }
643 void To(uint32_t ssrc) {
644 nack_.MediaSSRC = ssrc;
645 }
646 void WithList(const uint16_t* nack_list, int length);
647
648 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200649 bool Create(uint8_t* packet,
650 size_t* index,
651 size_t max_length,
652 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000653
654 private:
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000655
656 RTCPUtility::RTCPPacketRTPFBNACK nack_;
657 std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_;
658
659 DISALLOW_COPY_AND_ASSIGN(Nack);
660};
661
662// Reference picture selection indication (RPSI) (RFC 4585).
663//
664// FCI:
665//
666// 0 1 2 3
667// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
668// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
669// | PB |0| Payload Type| Native RPSI bit string |
670// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
671// | defined per codec ... | Padding (0) |
672// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
673
674class Rpsi : public RtcpPacket {
675 public:
676 Rpsi()
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000677 : RtcpPacket(),
678 padding_bytes_(0) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000679 memset(&rpsi_, 0, sizeof(rpsi_));
680 }
681
682 virtual ~Rpsi() {}
683
684 void From(uint32_t ssrc) {
685 rpsi_.SenderSSRC = ssrc;
686 }
687 void To(uint32_t ssrc) {
688 rpsi_.MediaSSRC = ssrc;
689 }
690 void WithPayloadType(uint8_t payload) {
691 assert(payload <= 0x7f);
692 rpsi_.PayloadType = payload;
693 }
694 void WithPictureId(uint64_t picture_id);
695
696 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200697 bool Create(uint8_t* packet,
698 size_t* index,
699 size_t max_length,
700 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000701
702 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000703 size_t BlockLength() const {
704 size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
705 return kCommonFbFmtLength + fci_length;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000706 }
707
708 uint8_t padding_bytes_;
709 RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
710
711 DISALLOW_COPY_AND_ASSIGN(Rpsi);
712};
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000713
714// Full intra request (FIR) (RFC 5104).
715//
716// FCI:
717//
718// 0 1 2 3
719// 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
720// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
721// | SSRC |
722// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
723// | Seq nr. | Reserved |
724// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
725
726class Fir : public RtcpPacket {
727 public:
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000728 Fir() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000729 memset(&fir_, 0, sizeof(fir_));
730 memset(&fir_item_, 0, sizeof(fir_item_));
731 }
732
733 virtual ~Fir() {}
734
735 void From(uint32_t ssrc) {
736 fir_.SenderSSRC = ssrc;
737 }
738 void To(uint32_t ssrc) {
739 fir_item_.SSRC = ssrc;
740 }
741 void WithCommandSeqNum(uint8_t seq_num) {
742 fir_item_.CommandSequenceNumber = seq_num;
743 }
744
745 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200746 bool Create(uint8_t* packet,
747 size_t* index,
748 size_t max_length,
749 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000750
751 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000752 size_t BlockLength() const {
753 const size_t kFciLength = 8;
754 return kCommonFbFmtLength + kFciLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000755 }
756
757 RTCPUtility::RTCPPacketPSFBFIR fir_;
758 RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
759};
760
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000761// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
762//
763// FCI:
764//
765// 0 1 2 3
766// 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
767// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
768// | SSRC |
769// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
770// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
771// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
772
773class Tmmbr : public RtcpPacket {
774 public:
775 Tmmbr() : RtcpPacket() {
776 memset(&tmmbr_, 0, sizeof(tmmbr_));
777 memset(&tmmbr_item_, 0, sizeof(tmmbr_item_));
778 }
779
780 virtual ~Tmmbr() {}
781
782 void From(uint32_t ssrc) {
783 tmmbr_.SenderSSRC = ssrc;
784 }
785 void To(uint32_t ssrc) {
786 tmmbr_item_.SSRC = ssrc;
787 }
788 void WithBitrateKbps(uint32_t bitrate_kbps) {
789 tmmbr_item_.MaxTotalMediaBitRate = bitrate_kbps;
790 }
791 void WithOverhead(uint16_t overhead) {
792 assert(overhead <= 0x1ff);
793 tmmbr_item_.MeasuredOverhead = overhead;
794 }
795
796 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200797 bool Create(uint8_t* packet,
798 size_t* index,
799 size_t max_length,
800 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000801
802 private:
803 size_t BlockLength() const {
804 const size_t kFciLen = 8;
805 return kCommonFbFmtLength + kFciLen;
806 }
807
808 RTCPUtility::RTCPPacketRTPFBTMMBR tmmbr_;
809 RTCPUtility::RTCPPacketRTPFBTMMBRItem tmmbr_item_;
810
811 DISALLOW_COPY_AND_ASSIGN(Tmmbr);
812};
813
814// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
815//
816// FCI:
817//
818// 0 1 2 3
819// 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
820// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
821// | SSRC |
822// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
823// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
824// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825
826class Tmmbn : public RtcpPacket {
827 public:
828 Tmmbn() : RtcpPacket() {
829 memset(&tmmbn_, 0, sizeof(tmmbn_));
830 }
831
832 virtual ~Tmmbn() {}
833
834 void From(uint32_t ssrc) {
835 tmmbn_.SenderSSRC = ssrc;
836 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200837 // Max 50 TMMBR can be added per TMMBN.
838 bool WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead);
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000839
840 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200841 bool Create(uint8_t* packet,
842 size_t* index,
843 size_t max_length,
844 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000845
846 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200847 static const int kMaxNumberOfTmmbrs = 50;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000848
849 size_t BlockLength() const {
850 const size_t kFciLen = 8;
851 return kCommonFbFmtLength + kFciLen * tmmbn_items_.size();
852 }
853
854 RTCPUtility::RTCPPacketRTPFBTMMBN tmmbn_;
855 std::vector<RTCPUtility::RTCPPacketRTPFBTMMBRItem> tmmbn_items_;
856
857 DISALLOW_COPY_AND_ASSIGN(Tmmbn);
858};
859
860// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
861//
862// 0 1 2 3
863// 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
864// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
865// |V=2|P| FMT=15 | PT=206 | length |
866// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
867// | SSRC of packet sender |
868// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
869// | SSRC of media source |
870// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
871// | Unique identifier 'R' 'E' 'M' 'B' |
872// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
873// | Num SSRC | BR Exp | BR Mantissa |
874// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
875// | SSRC feedback |
876// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
877// | ...
878
879class Remb : public RtcpPacket {
880 public:
881 Remb() : RtcpPacket() {
882 memset(&remb_, 0, sizeof(remb_));
883 memset(&remb_item_, 0, sizeof(remb_item_));
884 }
885
886 virtual ~Remb() {}
887
888 void From(uint32_t ssrc) {
889 remb_.SenderSSRC = ssrc;
890 }
891 void AppliesTo(uint32_t ssrc);
892
893 void WithBitrateBps(uint32_t bitrate_bps) {
894 remb_item_.BitRate = bitrate_bps;
895 }
896
897 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200898 bool Create(uint8_t* packet,
899 size_t* index,
900 size_t max_length,
901 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000902
903 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200904 static const int kMaxNumberOfSsrcs = 0xff;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000905
906 size_t BlockLength() const {
907 return (remb_item_.NumberOfSSRCs + 5) * 4;
908 }
909
910 RTCPUtility::RTCPPacketPSFBAPP remb_;
911 RTCPUtility::RTCPPacketPSFBREMBItem remb_item_;
912
913 DISALLOW_COPY_AND_ASSIGN(Remb);
914};
915
916// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
917//
918// Format for XR packets:
919//
920// 0 1 2 3
921// 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
922// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
923// |V=2|P|reserved | PT=XR=207 | length |
924// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
925// | SSRC |
926// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
927// : report blocks :
928// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
929
930class Xr : public RtcpPacket {
931 public:
932 typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock;
933 Xr() : RtcpPacket() {
934 memset(&xr_header_, 0, sizeof(xr_header_));
935 }
936
937 virtual ~Xr() {}
938
939 void From(uint32_t ssrc) {
940 xr_header_.OriginatorSSRC = ssrc;
941 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200942
943 // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr.
944 bool WithRrtr(Rrtr* rrtr);
945 bool WithDlrr(Dlrr* dlrr);
946 bool WithVoipMetric(VoipMetric* voip_metric);
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000947
948 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200949 bool Create(uint8_t* packet,
950 size_t* index,
951 size_t max_length,
952 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000953
954 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200955 static const int kMaxNumberOfRrtrBlocks = 50;
956 static const int kMaxNumberOfDlrrBlocks = 50;
957 static const int kMaxNumberOfVoipMetricBlocks = 50;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000958
959 size_t BlockLength() const {
960 const size_t kXrHeaderLength = 8;
961 return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength();
962 }
963
964 size_t RrtrLength() const {
965 const size_t kRrtrBlockLength = 12;
966 return kRrtrBlockLength * rrtr_blocks_.size();
967 }
968
969 size_t DlrrLength() const;
970
971 size_t VoipMetricLength() const {
972 const size_t kVoipMetricBlockLength = 36;
973 return kVoipMetricBlockLength * voip_metric_blocks_.size();
974 }
975
976 RTCPUtility::RTCPPacketXR xr_header_;
977 std::vector<RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem> rrtr_blocks_;
978 std::vector<DlrrBlock> dlrr_blocks_;
979 std::vector<RTCPUtility::RTCPPacketXRVOIPMetricItem> voip_metric_blocks_;
980
981 DISALLOW_COPY_AND_ASSIGN(Xr);
982};
983
984// Receiver Reference Time Report Block (RFC 3611).
985//
986// 0 1 2 3
987// 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
988// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
989// | BT=4 | reserved | block length = 2 |
990// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
991// | NTP timestamp, most significant word |
992// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
993// | NTP timestamp, least significant word |
994// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
995
996class Rrtr {
997 public:
998 Rrtr() {
999 memset(&rrtr_block_, 0, sizeof(rrtr_block_));
1000 }
1001 ~Rrtr() {}
1002
1003 void WithNtpSec(uint32_t sec) {
1004 rrtr_block_.NTPMostSignificant = sec;
1005 }
1006 void WithNtpFrac(uint32_t frac) {
1007 rrtr_block_.NTPLeastSignificant = frac;
1008 }
1009
1010 private:
1011 friend class Xr;
1012 RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem rrtr_block_;
1013
1014 DISALLOW_COPY_AND_ASSIGN(Rrtr);
1015};
1016
1017// DLRR Report Block (RFC 3611).
1018//
1019// 0 1 2 3
1020// 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
1021// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1022// | BT=5 | reserved | block length |
1023// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1024// | SSRC_1 (SSRC of first receiver) | sub-
1025// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1026// | last RR (LRR) | 1
1027// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1028// | delay since last RR (DLRR) |
1029// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1030// | SSRC_2 (SSRC of second receiver) | sub-
1031// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1032// : ... : 2
1033
1034class Dlrr {
1035 public:
1036 Dlrr() {}
1037 ~Dlrr() {}
1038
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001039 // Max 100 DLRR Items can be added per DLRR report block.
1040 bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr);
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001041
1042 private:
1043 friend class Xr;
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001044 static const int kMaxNumberOfDlrrItems = 100;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001045
1046 std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> dlrr_block_;
1047
1048 DISALLOW_COPY_AND_ASSIGN(Dlrr);
1049};
1050
1051// VoIP Metrics Report Block (RFC 3611).
1052//
1053// 0 1 2 3
1054// 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
1055// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1056// | BT=7 | reserved | block length = 8 |
1057// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1058// | SSRC of source |
1059// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1060// | loss rate | discard rate | burst density | gap density |
1061// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1062// | burst duration | gap duration |
1063// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1064// | round trip delay | end system delay |
1065// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1066// | signal level | noise level | RERL | Gmin |
1067// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1068// | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1069// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1070// | RX config | reserved | JB nominal |
1071// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1072// | JB maximum | JB abs max |
1073// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1074
1075class VoipMetric {
1076 public:
1077 VoipMetric() {
1078 memset(&metric_, 0, sizeof(metric_));
1079 }
1080 ~VoipMetric() {}
1081
1082 void To(uint32_t ssrc) { metric_.SSRC = ssrc; }
1083 void LossRate(uint8_t loss_rate) { metric_.lossRate = loss_rate; }
1084 void DiscardRate(uint8_t discard_rate) { metric_.discardRate = discard_rate; }
1085 void BurstDensity(uint8_t burst_density) {
1086 metric_.burstDensity = burst_density;
1087 }
1088 void GapDensity(uint8_t gap_density) { metric_.gapDensity = gap_density; }
1089 void BurstDuration(uint16_t burst_duration) {
1090 metric_.burstDuration = burst_duration;
1091 }
1092 void GapDuration(uint16_t gap_duration) {
1093 metric_.gapDuration = gap_duration;
1094 }
1095 void RoundTripDelay(uint16_t round_trip_delay) {
1096 metric_.roundTripDelay = round_trip_delay;
1097 }
1098 void EndSystemDelay(uint16_t end_system_delay) {
1099 metric_.endSystemDelay = end_system_delay;
1100 }
1101 void SignalLevel(uint8_t signal_level) { metric_.signalLevel = signal_level; }
1102 void NoiseLevel(uint8_t noise_level) { metric_.noiseLevel = noise_level; }
1103 void Rerl(uint8_t rerl) { metric_.RERL = rerl; }
1104 void Gmin(uint8_t gmin) { metric_.Gmin = gmin; }
1105 void Rfactor(uint8_t rfactor) { metric_.Rfactor = rfactor; }
1106 void ExtRfactor(uint8_t extrfactor) { metric_.extRfactor = extrfactor; }
1107 void MosLq(uint8_t moslq) { metric_.MOSLQ = moslq; }
1108 void MosCq(uint8_t moscq) { metric_.MOSCQ = moscq; }
1109 void RxConfig(uint8_t rxconfig) { metric_.RXconfig = rxconfig; }
1110 void JbNominal(uint16_t jbnominal) { metric_.JBnominal = jbnominal; }
1111 void JbMax(uint16_t jbmax) { metric_.JBmax = jbmax; }
1112 void JbAbsMax(uint16_t jbabsmax) { metric_.JBabsMax = jbabsmax; }
1113
1114 private:
1115 friend class Xr;
1116 RTCPUtility::RTCPPacketXRVOIPMetricItem metric_;
1117
1118 DISALLOW_COPY_AND_ASSIGN(VoipMetric);
1119};
1120
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001121// Class holding a RTCP packet.
1122//
1123// Takes a built rtcp packet.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +00001124// RawPacket raw_packet(buffer, length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001125//
1126// To access the raw packet:
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001127// raw_packet.Buffer(); - pointer to the raw packet
1128// raw_packet.BufferLength(); - the length of the raw packet
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001129
1130class RawPacket {
1131 public:
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001132 explicit RawPacket(size_t buffer_length);
1133 RawPacket(const uint8_t* packet, size_t packet_length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001134
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001135 const uint8_t* Buffer() const;
1136 uint8_t* MutableBuffer();
1137 size_t BufferLength() const;
1138 size_t Length() const;
1139 void SetLength(size_t length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001140
1141 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001142 const size_t buffer_length_;
1143 size_t length_;
1144 rtc::scoped_ptr<uint8_t[]> buffer_;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001145};
1146
1147} // namespace rtcp
1148} // namespace webrtc
1149#endif // WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_