blob: cfbe8cee92952afde9b61c0e3df81a25d1072ab5 [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:
Erik Språnga3b87692015-07-29 10:46:54 +020095 RtcpPacket() {}
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
sprang73a93e82015-09-14 12:50:39 -0700102 static void CreateHeader(uint8_t count_or_format,
103 uint8_t packet_type,
104 size_t block_length, // Size in 32bit words - 1.
105 uint8_t* buffer,
106 size_t* pos);
Erik Språnga3b87692015-07-29 10:46:54 +0200107
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200108 bool OnBufferFull(uint8_t* packet,
109 size_t* index,
110 RtcpPacket::PacketReadyCallback* callback) const;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000111
Erik Språnga3b87692015-07-29 10:46:54 +0200112 virtual size_t BlockLength() const = 0;
113 size_t HeaderLength() const;
114
115 static const size_t kHeaderLength = 4;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000116
117 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200118 bool CreateAndAddAppended(uint8_t* packet,
119 size_t* index,
120 size_t max_length,
121 PacketReadyCallback* callback) const;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000122
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000123 std::vector<RtcpPacket*> appended_packets_;
124};
125
Erik Språnga3b87692015-07-29 10:46:54 +0200126// TODO(sprang): Move RtcpPacket subclasses out to separate files.
127
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000128class Empty : public RtcpPacket {
129 public:
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000130 Empty() : RtcpPacket() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000131
132 virtual ~Empty() {}
133
134 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200135 bool Create(uint8_t* packet,
136 size_t* index,
137 size_t max_length,
138 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000139
Erik Språnga3b87692015-07-29 10:46:54 +0200140 size_t BlockLength() const override;
141
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000142 private:
143 DISALLOW_COPY_AND_ASSIGN(Empty);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000144};
145
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000146// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000147//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000148// RTCP report block (RFC 3550).
149//
150// 0 1 2 3
151// 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
152// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
153// | SSRC_1 (SSRC of first source) |
154// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155// | fraction lost | cumulative number of packets lost |
156// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157// | extended highest sequence number received |
158// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159// | interarrival jitter |
160// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161// | last SR (LSR) |
162// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163// | delay since last SR (DLSR) |
164// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
165
166class ReportBlock {
167 public:
168 ReportBlock() {
169 // TODO(asapersson): Consider adding a constructor to struct.
170 memset(&report_block_, 0, sizeof(report_block_));
171 }
172
173 ~ReportBlock() {}
174
175 void To(uint32_t ssrc) {
176 report_block_.SSRC = ssrc;
177 }
178 void WithFractionLost(uint8_t fraction_lost) {
179 report_block_.FractionLost = fraction_lost;
180 }
181 void WithCumulativeLost(uint32_t cumulative_lost) {
182 report_block_.CumulativeNumOfPacketsLost = cumulative_lost;
183 }
184 void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) {
185 report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num;
186 }
187 void WithJitter(uint32_t jitter) {
188 report_block_.Jitter = jitter;
189 }
190 void WithLastSr(uint32_t last_sr) {
191 report_block_.LastSR = last_sr;
192 }
193 void WithDelayLastSr(uint32_t delay_last_sr) {
194 report_block_.DelayLastSR = delay_last_sr;
195 }
196
197 private:
198 friend class SenderReport;
199 friend class ReceiverReport;
200 RTCPUtility::RTCPPacketReportBlockItem report_block_;
201};
202
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000203// RTCP sender report (RFC 3550).
204//
205// 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
206// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
207// |V=2|P| RC | PT=SR=200 | length |
208// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
209// | SSRC of sender |
210// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
211// | NTP timestamp, most significant word |
212// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213// | NTP timestamp, least significant word |
214// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
215// | RTP timestamp |
216// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217// | sender's packet count |
218// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219// | sender's octet count |
220// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
221// | report block(s) |
222// | .... |
223
224class SenderReport : public RtcpPacket {
225 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000226 SenderReport() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000227 memset(&sr_, 0, sizeof(sr_));
228 }
229
230 virtual ~SenderReport() {}
231
232 void From(uint32_t ssrc) {
233 sr_.SenderSSRC = ssrc;
234 }
235 void WithNtpSec(uint32_t sec) {
236 sr_.NTPMostSignificant = sec;
237 }
238 void WithNtpFrac(uint32_t frac) {
239 sr_.NTPLeastSignificant = frac;
240 }
241 void WithRtpTimestamp(uint32_t rtp_timestamp) {
242 sr_.RTPTimestamp = rtp_timestamp;
243 }
244 void WithPacketCount(uint32_t packet_count) {
245 sr_.SenderPacketCount = packet_count;
246 }
247 void WithOctetCount(uint32_t octet_count) {
248 sr_.SenderOctetCount = octet_count;
249 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200250 bool WithReportBlock(const ReportBlock& block);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000251
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000252 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200253 bool Create(uint8_t* packet,
254 size_t* index,
255 size_t max_length,
256 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000257
258 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200259 static const int kMaxNumberOfReportBlocks = 0x1f;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000260
261 size_t BlockLength() const {
262 const size_t kSrHeaderLength = 8;
263 const size_t kSenderInfoLength = 20;
264 return kSrHeaderLength + kSenderInfoLength +
265 report_blocks_.size() * kReportBlockLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000266 }
267
268 RTCPUtility::RTCPPacketSR sr_;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000269 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000270
271 DISALLOW_COPY_AND_ASSIGN(SenderReport);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000272};
273
274//
275// RTCP receiver report (RFC 3550).
276//
277// 0 1 2 3
278// 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
279// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
280// |V=2|P| RC | PT=RR=201 | length |
281// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
282// | SSRC of packet sender |
283// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
284// | report block(s) |
285// | .... |
286
287class ReceiverReport : public RtcpPacket {
288 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000289 ReceiverReport() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000290 memset(&rr_, 0, sizeof(rr_));
291 }
292
293 virtual ~ReceiverReport() {}
294
295 void From(uint32_t ssrc) {
296 rr_.SenderSSRC = ssrc;
297 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200298 bool WithReportBlock(const ReportBlock& block);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000299
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000300 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200301 bool Create(uint8_t* packet,
302 size_t* index,
303 size_t max_length,
304 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000305
306 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200307 static const int kMaxNumberOfReportBlocks = 0x1F;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000308
309 size_t BlockLength() const {
310 const size_t kRrHeaderLength = 8;
311 return kRrHeaderLength + report_blocks_.size() * kReportBlockLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000312 }
313
314 RTCPUtility::RTCPPacketRR rr_;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000315 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000316
317 DISALLOW_COPY_AND_ASSIGN(ReceiverReport);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000318};
319
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000320// Transmission Time Offsets in RTP Streams (RFC 5450).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000321//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000322// 0 1 2 3
323// 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
324// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
325// hdr |V=2|P| RC | PT=IJ=195 | length |
326// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
327// | inter-arrival jitter |
328// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329// . .
330// . .
331// . .
332// | inter-arrival jitter |
333// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000334//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000335// If present, this RTCP packet must be placed after a receiver report
336// (inside a compound RTCP packet), and MUST have the same value for RC
337// (reception report count) as the receiver report.
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000338
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000339class Ij : public RtcpPacket {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000340 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000341 Ij() : RtcpPacket() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000342
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000343 virtual ~Ij() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000344
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200345 bool WithJitterItem(uint32_t jitter);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000346
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000347 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200348 bool Create(uint8_t* packet,
349 size_t* index,
350 size_t max_length,
351 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000352
353 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200354 static const int kMaxNumberOfIjItems = 0x1f;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000355
356 size_t BlockLength() const {
357 return kHeaderLength + 4 * ij_items_.size();
358 }
359
360 std::vector<uint32_t> ij_items_;
361
362 DISALLOW_COPY_AND_ASSIGN(Ij);
363};
364
365// Source Description (SDES) (RFC 3550).
366//
367// 0 1 2 3
368// 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
369// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
370// header |V=2|P| SC | PT=SDES=202 | length |
371// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
372// chunk | SSRC/CSRC_1 |
373// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
374// | SDES items |
375// | ... |
376// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
377// chunk | SSRC/CSRC_2 |
378// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379// | SDES items |
380// | ... |
381// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
382//
383// Canonical End-Point Identifier SDES Item (CNAME)
384//
385// 0 1 2 3
386// 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
387// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
388// | CNAME=1 | length | user and domain name ...
389// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
390
391class Sdes : public RtcpPacket {
392 public:
393 Sdes() : RtcpPacket() {}
394
395 virtual ~Sdes() {}
396
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200397 bool WithCName(uint32_t ssrc, const std::string& cname);
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000398
399 struct Chunk {
400 uint32_t ssrc;
401 std::string name;
402 int null_octets;
403 };
404
405 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200406 bool Create(uint8_t* packet,
407 size_t* index,
408 size_t max_length,
409 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000410
411 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200412 static const int kMaxNumberOfChunks = 0x1f;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000413
414 size_t BlockLength() const;
415
416 std::vector<Chunk> chunks_;
417
418 DISALLOW_COPY_AND_ASSIGN(Sdes);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000419};
420
421//
422// Bye packet (BYE) (RFC 3550).
423//
424// 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
425// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
426// |V=2|P| SC | PT=BYE=203 | length |
427// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
428// | SSRC/CSRC |
429// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
430// : ... :
431// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
432// (opt) | length | reason for leaving ...
433// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
434
435class Bye : public RtcpPacket {
436 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000437 Bye() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000438 memset(&bye_, 0, sizeof(bye_));
439 }
440
441 virtual ~Bye() {}
442
443 void From(uint32_t ssrc) {
444 bye_.SenderSSRC = ssrc;
445 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200446
447 bool WithCsrc(uint32_t csrc);
448
449 // TODO(sprang): Add support for reason field?
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000450
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000451 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200452 bool Create(uint8_t* packet,
453 size_t* index,
454 size_t max_length,
455 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000456
457 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200458 static const int kMaxNumberOfCsrcs = 0x1f - 1; // First item is sender SSRC.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000459
460 size_t BlockLength() const {
461 size_t source_count = 1 + csrcs_.size();
462 return kHeaderLength + 4 * source_count;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000463 }
464
465 RTCPUtility::RTCPPacketBYE bye_;
466 std::vector<uint32_t> csrcs_;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000467
468 DISALLOW_COPY_AND_ASSIGN(Bye);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000469};
470
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000471// Application-Defined packet (APP) (RFC 3550).
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// |V=2|P| subtype | PT=APP=204 | length |
477// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
478// | SSRC/CSRC |
479// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
480// | name (ASCII) |
481// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
482// | application-dependent data ...
483// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
484
485class App : public RtcpPacket {
486 public:
487 App()
488 : RtcpPacket(),
489 ssrc_(0) {
490 memset(&app_, 0, sizeof(app_));
491 }
492
493 virtual ~App() {}
494
495 void From(uint32_t ssrc) {
496 ssrc_ = ssrc;
497 }
498 void WithSubType(uint8_t subtype) {
499 assert(subtype <= 0x1f);
500 app_.SubType = subtype;
501 }
502 void WithName(uint32_t name) {
503 app_.Name = name;
504 }
505 void WithData(const uint8_t* data, uint16_t data_length) {
506 assert(data);
507 assert(data_length <= kRtcpAppCode_DATA_SIZE);
508 assert(data_length % 4 == 0);
509 memcpy(app_.Data, data, data_length);
510 app_.Size = data_length;
511 }
512
513 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200514 bool Create(uint8_t* packet,
515 size_t* index,
516 size_t max_length,
517 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000518
519 private:
520 size_t BlockLength() const {
521 return 12 + app_.Size;
522 }
523
524 uint32_t ssrc_;
525 RTCPUtility::RTCPPacketAPP app_;
526
527 DISALLOW_COPY_AND_ASSIGN(App);
528};
529
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000530// RFC 4585: Feedback format.
531//
532// Common packet format:
533//
534// 0 1 2 3
535// 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
536// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
537// |V=2|P| FMT | PT | length |
538// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539// | SSRC of packet sender |
540// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541// | SSRC of media source |
542// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543// : Feedback Control Information (FCI) :
544// :
545
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000546// Picture loss indication (PLI) (RFC 4585).
547//
548// FCI: no feedback control information.
549
550class Pli : public RtcpPacket {
551 public:
552 Pli() : RtcpPacket() {
553 memset(&pli_, 0, sizeof(pli_));
554 }
555
556 virtual ~Pli() {}
557
558 void From(uint32_t ssrc) {
559 pli_.SenderSSRC = ssrc;
560 }
561 void To(uint32_t ssrc) {
562 pli_.MediaSSRC = ssrc;
563 }
564
565 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200566 bool Create(uint8_t* packet,
567 size_t* index,
568 size_t max_length,
569 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000570
571 private:
572 size_t BlockLength() const {
573 return kCommonFbFmtLength;
574 }
575
576 RTCPUtility::RTCPPacketPSFBPLI pli_;
577
578 DISALLOW_COPY_AND_ASSIGN(Pli);
579};
580
581// Slice loss indication (SLI) (RFC 4585).
582//
583// FCI:
584// 0 1 2 3
585// 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
586// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
587// | First | Number | PictureID |
588// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589
590class Sli : public RtcpPacket {
591 public:
592 Sli() : RtcpPacket() {
593 memset(&sli_, 0, sizeof(sli_));
594 memset(&sli_item_, 0, sizeof(sli_item_));
595 }
596
597 virtual ~Sli() {}
598
599 void From(uint32_t ssrc) {
600 sli_.SenderSSRC = ssrc;
601 }
602 void To(uint32_t ssrc) {
603 sli_.MediaSSRC = ssrc;
604 }
605 void WithFirstMb(uint16_t first_mb) {
606 assert(first_mb <= 0x1fff);
607 sli_item_.FirstMB = first_mb;
608 }
609 void WithNumberOfMb(uint16_t number_mb) {
610 assert(number_mb <= 0x1fff);
611 sli_item_.NumberOfMB = number_mb;
612 }
613 void WithPictureId(uint8_t picture_id) {
614 assert(picture_id <= 0x3f);
615 sli_item_.PictureId = picture_id;
616 }
617
618 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200619 bool Create(uint8_t* packet,
620 size_t* index,
621 size_t max_length,
622 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000623
624 private:
625 size_t BlockLength() const {
626 const size_t kFciLength = 4;
627 return kCommonFbFmtLength + kFciLength;
628 }
629
630 RTCPUtility::RTCPPacketPSFBSLI sli_;
631 RTCPUtility::RTCPPacketPSFBSLIItem sli_item_;
632
633 DISALLOW_COPY_AND_ASSIGN(Sli);
634};
635
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000636// Generic NACK (RFC 4585).
637//
638// FCI:
639// 0 1 2 3
640// 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
641// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
642// | PID | BLP |
643// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
644
645class Nack : public RtcpPacket {
646 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000647 Nack() : RtcpPacket() {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000648 memset(&nack_, 0, sizeof(nack_));
649 }
650
651 virtual ~Nack() {}
652
653 void From(uint32_t ssrc) {
654 nack_.SenderSSRC = ssrc;
655 }
656 void To(uint32_t ssrc) {
657 nack_.MediaSSRC = ssrc;
658 }
659 void WithList(const uint16_t* nack_list, int length);
660
661 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200662 bool Create(uint8_t* packet,
663 size_t* index,
664 size_t max_length,
665 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000666
Erik Språnga3b87692015-07-29 10:46:54 +0200667 size_t BlockLength() const override;
668
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000669 private:
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000670
671 RTCPUtility::RTCPPacketRTPFBNACK nack_;
672 std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_;
673
674 DISALLOW_COPY_AND_ASSIGN(Nack);
675};
676
677// Reference picture selection indication (RPSI) (RFC 4585).
678//
679// FCI:
680//
681// 0 1 2 3
682// 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
683// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
684// | PB |0| Payload Type| Native RPSI bit string |
685// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
686// | defined per codec ... | Padding (0) |
687// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
688
689class Rpsi : public RtcpPacket {
690 public:
691 Rpsi()
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000692 : RtcpPacket(),
693 padding_bytes_(0) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000694 memset(&rpsi_, 0, sizeof(rpsi_));
695 }
696
697 virtual ~Rpsi() {}
698
699 void From(uint32_t ssrc) {
700 rpsi_.SenderSSRC = ssrc;
701 }
702 void To(uint32_t ssrc) {
703 rpsi_.MediaSSRC = ssrc;
704 }
705 void WithPayloadType(uint8_t payload) {
706 assert(payload <= 0x7f);
707 rpsi_.PayloadType = payload;
708 }
709 void WithPictureId(uint64_t picture_id);
710
711 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200712 bool Create(uint8_t* packet,
713 size_t* index,
714 size_t max_length,
715 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000716
717 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000718 size_t BlockLength() const {
719 size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
720 return kCommonFbFmtLength + fci_length;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000721 }
722
723 uint8_t padding_bytes_;
724 RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
725
726 DISALLOW_COPY_AND_ASSIGN(Rpsi);
727};
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000728
729// Full intra request (FIR) (RFC 5104).
730//
731// FCI:
732//
733// 0 1 2 3
734// 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
735// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
736// | SSRC |
737// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
738// | Seq nr. | Reserved |
739// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740
741class Fir : public RtcpPacket {
742 public:
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000743 Fir() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000744 memset(&fir_, 0, sizeof(fir_));
745 memset(&fir_item_, 0, sizeof(fir_item_));
746 }
747
748 virtual ~Fir() {}
749
750 void From(uint32_t ssrc) {
751 fir_.SenderSSRC = ssrc;
752 }
753 void To(uint32_t ssrc) {
754 fir_item_.SSRC = ssrc;
755 }
756 void WithCommandSeqNum(uint8_t seq_num) {
757 fir_item_.CommandSequenceNumber = seq_num;
758 }
759
760 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200761 bool Create(uint8_t* packet,
762 size_t* index,
763 size_t max_length,
764 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000765
766 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000767 size_t BlockLength() const {
768 const size_t kFciLength = 8;
769 return kCommonFbFmtLength + kFciLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000770 }
771
772 RTCPUtility::RTCPPacketPSFBFIR fir_;
773 RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
774};
775
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000776// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
777//
778// FCI:
779//
780// 0 1 2 3
781// 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
782// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
783// | SSRC |
784// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
785// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
786// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
787
788class Tmmbr : public RtcpPacket {
789 public:
790 Tmmbr() : RtcpPacket() {
791 memset(&tmmbr_, 0, sizeof(tmmbr_));
792 memset(&tmmbr_item_, 0, sizeof(tmmbr_item_));
793 }
794
795 virtual ~Tmmbr() {}
796
797 void From(uint32_t ssrc) {
798 tmmbr_.SenderSSRC = ssrc;
799 }
800 void To(uint32_t ssrc) {
801 tmmbr_item_.SSRC = ssrc;
802 }
803 void WithBitrateKbps(uint32_t bitrate_kbps) {
804 tmmbr_item_.MaxTotalMediaBitRate = bitrate_kbps;
805 }
806 void WithOverhead(uint16_t overhead) {
807 assert(overhead <= 0x1ff);
808 tmmbr_item_.MeasuredOverhead = overhead;
809 }
810
811 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200812 bool Create(uint8_t* packet,
813 size_t* index,
814 size_t max_length,
815 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000816
817 private:
818 size_t BlockLength() const {
819 const size_t kFciLen = 8;
820 return kCommonFbFmtLength + kFciLen;
821 }
822
823 RTCPUtility::RTCPPacketRTPFBTMMBR tmmbr_;
824 RTCPUtility::RTCPPacketRTPFBTMMBRItem tmmbr_item_;
825
826 DISALLOW_COPY_AND_ASSIGN(Tmmbr);
827};
828
829// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
830//
831// FCI:
832//
833// 0 1 2 3
834// 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
835// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
836// | SSRC |
837// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
838// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
839// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
840
841class Tmmbn : public RtcpPacket {
842 public:
843 Tmmbn() : RtcpPacket() {
844 memset(&tmmbn_, 0, sizeof(tmmbn_));
845 }
846
847 virtual ~Tmmbn() {}
848
849 void From(uint32_t ssrc) {
850 tmmbn_.SenderSSRC = ssrc;
851 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200852 // Max 50 TMMBR can be added per TMMBN.
853 bool WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead);
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000854
855 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200856 bool Create(uint8_t* packet,
857 size_t* index,
858 size_t max_length,
859 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000860
861 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200862 static const int kMaxNumberOfTmmbrs = 50;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000863
864 size_t BlockLength() const {
865 const size_t kFciLen = 8;
866 return kCommonFbFmtLength + kFciLen * tmmbn_items_.size();
867 }
868
869 RTCPUtility::RTCPPacketRTPFBTMMBN tmmbn_;
870 std::vector<RTCPUtility::RTCPPacketRTPFBTMMBRItem> tmmbn_items_;
871
872 DISALLOW_COPY_AND_ASSIGN(Tmmbn);
873};
874
875// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
876//
877// 0 1 2 3
878// 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
879// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
880// |V=2|P| FMT=15 | PT=206 | length |
881// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
882// | SSRC of packet sender |
883// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
884// | SSRC of media source |
885// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
886// | Unique identifier 'R' 'E' 'M' 'B' |
887// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
888// | Num SSRC | BR Exp | BR Mantissa |
889// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
890// | SSRC feedback |
891// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
892// | ...
893
894class Remb : public RtcpPacket {
895 public:
896 Remb() : RtcpPacket() {
897 memset(&remb_, 0, sizeof(remb_));
898 memset(&remb_item_, 0, sizeof(remb_item_));
899 }
900
901 virtual ~Remb() {}
902
903 void From(uint32_t ssrc) {
904 remb_.SenderSSRC = ssrc;
905 }
906 void AppliesTo(uint32_t ssrc);
907
908 void WithBitrateBps(uint32_t bitrate_bps) {
909 remb_item_.BitRate = bitrate_bps;
910 }
911
912 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200913 bool Create(uint8_t* packet,
914 size_t* index,
915 size_t max_length,
916 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000917
918 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200919 static const int kMaxNumberOfSsrcs = 0xff;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000920
921 size_t BlockLength() const {
922 return (remb_item_.NumberOfSSRCs + 5) * 4;
923 }
924
925 RTCPUtility::RTCPPacketPSFBAPP remb_;
926 RTCPUtility::RTCPPacketPSFBREMBItem remb_item_;
927
928 DISALLOW_COPY_AND_ASSIGN(Remb);
929};
930
931// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
932//
933// Format for XR packets:
934//
935// 0 1 2 3
936// 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
937// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
938// |V=2|P|reserved | PT=XR=207 | length |
939// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
940// | SSRC |
941// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
942// : report blocks :
943// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
944
945class Xr : public RtcpPacket {
946 public:
947 typedef std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> DlrrBlock;
948 Xr() : RtcpPacket() {
949 memset(&xr_header_, 0, sizeof(xr_header_));
950 }
951
952 virtual ~Xr() {}
953
954 void From(uint32_t ssrc) {
955 xr_header_.OriginatorSSRC = ssrc;
956 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200957
958 // Max 50 items of each of {Rrtr, Dlrr, VoipMetric} allowed per Xr.
959 bool WithRrtr(Rrtr* rrtr);
960 bool WithDlrr(Dlrr* dlrr);
961 bool WithVoipMetric(VoipMetric* voip_metric);
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000962
963 protected:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200964 bool Create(uint8_t* packet,
965 size_t* index,
966 size_t max_length,
967 RtcpPacket::PacketReadyCallback* callback) const override;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000968
969 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200970 static const int kMaxNumberOfRrtrBlocks = 50;
971 static const int kMaxNumberOfDlrrBlocks = 50;
972 static const int kMaxNumberOfVoipMetricBlocks = 50;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000973
974 size_t BlockLength() const {
975 const size_t kXrHeaderLength = 8;
976 return kXrHeaderLength + RrtrLength() + DlrrLength() + VoipMetricLength();
977 }
978
979 size_t RrtrLength() const {
980 const size_t kRrtrBlockLength = 12;
981 return kRrtrBlockLength * rrtr_blocks_.size();
982 }
983
984 size_t DlrrLength() const;
985
986 size_t VoipMetricLength() const {
987 const size_t kVoipMetricBlockLength = 36;
988 return kVoipMetricBlockLength * voip_metric_blocks_.size();
989 }
990
991 RTCPUtility::RTCPPacketXR xr_header_;
992 std::vector<RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem> rrtr_blocks_;
993 std::vector<DlrrBlock> dlrr_blocks_;
994 std::vector<RTCPUtility::RTCPPacketXRVOIPMetricItem> voip_metric_blocks_;
995
996 DISALLOW_COPY_AND_ASSIGN(Xr);
997};
998
999// Receiver Reference Time Report Block (RFC 3611).
1000//
1001// 0 1 2 3
1002// 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
1003// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1004// | BT=4 | reserved | block length = 2 |
1005// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1006// | NTP timestamp, most significant word |
1007// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1008// | NTP timestamp, least significant word |
1009// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1010
1011class Rrtr {
1012 public:
1013 Rrtr() {
1014 memset(&rrtr_block_, 0, sizeof(rrtr_block_));
1015 }
1016 ~Rrtr() {}
1017
1018 void WithNtpSec(uint32_t sec) {
1019 rrtr_block_.NTPMostSignificant = sec;
1020 }
1021 void WithNtpFrac(uint32_t frac) {
1022 rrtr_block_.NTPLeastSignificant = frac;
1023 }
1024
1025 private:
1026 friend class Xr;
1027 RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem rrtr_block_;
1028
1029 DISALLOW_COPY_AND_ASSIGN(Rrtr);
1030};
1031
1032// DLRR Report Block (RFC 3611).
1033//
1034// 0 1 2 3
1035// 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
1036// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1037// | BT=5 | reserved | block length |
1038// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1039// | SSRC_1 (SSRC of first receiver) | sub-
1040// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1041// | last RR (LRR) | 1
1042// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1043// | delay since last RR (DLRR) |
1044// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1045// | SSRC_2 (SSRC of second receiver) | sub-
1046// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1047// : ... : 2
1048
1049class Dlrr {
1050 public:
1051 Dlrr() {}
1052 ~Dlrr() {}
1053
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001054 // Max 100 DLRR Items can be added per DLRR report block.
1055 bool WithDlrrItem(uint32_t ssrc, uint32_t last_rr, uint32_t delay_last_rr);
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001056
1057 private:
1058 friend class Xr;
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001059 static const int kMaxNumberOfDlrrItems = 100;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001060
1061 std::vector<RTCPUtility::RTCPPacketXRDLRRReportBlockItem> dlrr_block_;
1062
1063 DISALLOW_COPY_AND_ASSIGN(Dlrr);
1064};
1065
1066// VoIP Metrics Report Block (RFC 3611).
1067//
1068// 0 1 2 3
1069// 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
1070// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1071// | BT=7 | reserved | block length = 8 |
1072// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1073// | SSRC of source |
1074// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1075// | loss rate | discard rate | burst density | gap density |
1076// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1077// | burst duration | gap duration |
1078// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1079// | round trip delay | end system delay |
1080// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1081// | signal level | noise level | RERL | Gmin |
1082// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1083// | R factor | ext. R factor | MOS-LQ | MOS-CQ |
1084// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1085// | RX config | reserved | JB nominal |
1086// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1087// | JB maximum | JB abs max |
1088// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1089
1090class VoipMetric {
1091 public:
1092 VoipMetric() {
1093 memset(&metric_, 0, sizeof(metric_));
1094 }
1095 ~VoipMetric() {}
1096
1097 void To(uint32_t ssrc) { metric_.SSRC = ssrc; }
1098 void LossRate(uint8_t loss_rate) { metric_.lossRate = loss_rate; }
1099 void DiscardRate(uint8_t discard_rate) { metric_.discardRate = discard_rate; }
1100 void BurstDensity(uint8_t burst_density) {
1101 metric_.burstDensity = burst_density;
1102 }
1103 void GapDensity(uint8_t gap_density) { metric_.gapDensity = gap_density; }
1104 void BurstDuration(uint16_t burst_duration) {
1105 metric_.burstDuration = burst_duration;
1106 }
1107 void GapDuration(uint16_t gap_duration) {
1108 metric_.gapDuration = gap_duration;
1109 }
1110 void RoundTripDelay(uint16_t round_trip_delay) {
1111 metric_.roundTripDelay = round_trip_delay;
1112 }
1113 void EndSystemDelay(uint16_t end_system_delay) {
1114 metric_.endSystemDelay = end_system_delay;
1115 }
1116 void SignalLevel(uint8_t signal_level) { metric_.signalLevel = signal_level; }
1117 void NoiseLevel(uint8_t noise_level) { metric_.noiseLevel = noise_level; }
1118 void Rerl(uint8_t rerl) { metric_.RERL = rerl; }
1119 void Gmin(uint8_t gmin) { metric_.Gmin = gmin; }
1120 void Rfactor(uint8_t rfactor) { metric_.Rfactor = rfactor; }
1121 void ExtRfactor(uint8_t extrfactor) { metric_.extRfactor = extrfactor; }
1122 void MosLq(uint8_t moslq) { metric_.MOSLQ = moslq; }
1123 void MosCq(uint8_t moscq) { metric_.MOSCQ = moscq; }
1124 void RxConfig(uint8_t rxconfig) { metric_.RXconfig = rxconfig; }
1125 void JbNominal(uint16_t jbnominal) { metric_.JBnominal = jbnominal; }
1126 void JbMax(uint16_t jbmax) { metric_.JBmax = jbmax; }
1127 void JbAbsMax(uint16_t jbabsmax) { metric_.JBabsMax = jbabsmax; }
1128
1129 private:
1130 friend class Xr;
1131 RTCPUtility::RTCPPacketXRVOIPMetricItem metric_;
1132
1133 DISALLOW_COPY_AND_ASSIGN(VoipMetric);
1134};
1135
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001136// Class holding a RTCP packet.
1137//
1138// Takes a built rtcp packet.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +00001139// RawPacket raw_packet(buffer, length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001140//
1141// To access the raw packet:
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001142// raw_packet.Buffer(); - pointer to the raw packet
1143// raw_packet.BufferLength(); - the length of the raw packet
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001144
1145class RawPacket {
1146 public:
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001147 explicit RawPacket(size_t buffer_length);
1148 RawPacket(const uint8_t* packet, size_t packet_length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001149
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001150 const uint8_t* Buffer() const;
1151 uint8_t* MutableBuffer();
1152 size_t BufferLength() const;
1153 size_t Length() const;
1154 void SetLength(size_t length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001155
1156 private:
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001157 const size_t buffer_length_;
1158 size_t length_;
1159 rtc::scoped_ptr<uint8_t[]> buffer_;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001160};
1161
1162} // namespace rtcp
1163} // namespace webrtc
1164#endif // WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_