blob: f60e848b50b7a33a760bc876d1ebe3ace90982f6 [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
19#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
20#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
21#include "webrtc/typedefs.h"
22
23namespace webrtc {
24namespace rtcp {
25
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000026enum { kCommonFbFmtLength = 12 };
27enum { kReportBlockLength = 24 };
28
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000029class RawPacket;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000030
31// Class for building RTCP packets.
32//
33// Example:
34// ReportBlock report_block;
35// report_block.To(234)
36// report_block.FractionLost(10);
37//
38// ReceiverReport rr;
39// rr.From(123);
40// rr.WithReportBlock(&report_block)
41//
42// Fir fir;
43// fir.From(123);
44// fir.To(234)
45// fir.WithCommandSeqNum(123);
46//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000047// size_t length = 0; // Builds an intra frame request
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000048// uint8_t packet[kPacketSize]; // with sequence number 123.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000049// fir.Build(packet, &length, kPacketSize);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000050//
51// RawPacket packet = fir.Build(); // Returns a RawPacket holding
52// // the built rtcp packet.
53//
54// rr.Append(&fir) // Builds a compound RTCP packet with
55// RawPacket packet = rr.Build(); // a receiver report, report block
56// // and fir message.
57
58class RtcpPacket {
59 public:
60 virtual ~RtcpPacket() {}
61
62 void Append(RtcpPacket* packet);
63
64 RawPacket Build() const;
65
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000066 void Build(uint8_t* packet, size_t* length, size_t max_length) const;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000067
68 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000069 RtcpPacket() : kHeaderLength(4) {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000070
71 virtual void Create(
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000072 uint8_t* packet, size_t* length, size_t max_length) const = 0;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000073
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000074 const size_t kHeaderLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000075
76 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000077 void CreateAndAddAppended(
78 uint8_t* packet, size_t* length, size_t max_length) const;
79
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000080 std::vector<RtcpPacket*> appended_packets_;
81};
82
83class Empty : public RtcpPacket {
84 public:
85 Empty() {}
86
87 virtual ~Empty() {}
88
89 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000090 virtual void Create(uint8_t* packet, size_t* length, size_t max_length) const;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000091};
92
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000093// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000094//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000095// RTCP report block (RFC 3550).
96//
97// 0 1 2 3
98// 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
99// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
100// | SSRC_1 (SSRC of first source) |
101// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102// | fraction lost | cumulative number of packets lost |
103// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104// | extended highest sequence number received |
105// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106// | interarrival jitter |
107// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108// | last SR (LSR) |
109// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110// | delay since last SR (DLSR) |
111// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
112
113class ReportBlock {
114 public:
115 ReportBlock() {
116 // TODO(asapersson): Consider adding a constructor to struct.
117 memset(&report_block_, 0, sizeof(report_block_));
118 }
119
120 ~ReportBlock() {}
121
122 void To(uint32_t ssrc) {
123 report_block_.SSRC = ssrc;
124 }
125 void WithFractionLost(uint8_t fraction_lost) {
126 report_block_.FractionLost = fraction_lost;
127 }
128 void WithCumulativeLost(uint32_t cumulative_lost) {
129 report_block_.CumulativeNumOfPacketsLost = cumulative_lost;
130 }
131 void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) {
132 report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num;
133 }
134 void WithJitter(uint32_t jitter) {
135 report_block_.Jitter = jitter;
136 }
137 void WithLastSr(uint32_t last_sr) {
138 report_block_.LastSR = last_sr;
139 }
140 void WithDelayLastSr(uint32_t delay_last_sr) {
141 report_block_.DelayLastSR = delay_last_sr;
142 }
143
144 private:
145 friend class SenderReport;
146 friend class ReceiverReport;
147 RTCPUtility::RTCPPacketReportBlockItem report_block_;
148};
149
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000150// RTCP sender report (RFC 3550).
151//
152// 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
153// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154// |V=2|P| RC | PT=SR=200 | length |
155// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156// | SSRC of sender |
157// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
158// | NTP timestamp, most significant word |
159// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160// | NTP timestamp, least significant word |
161// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
162// | RTP timestamp |
163// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164// | sender's packet count |
165// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166// | sender's octet count |
167// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
168// | report block(s) |
169// | .... |
170
171class SenderReport : public RtcpPacket {
172 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000173 SenderReport() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000174 memset(&sr_, 0, sizeof(sr_));
175 }
176
177 virtual ~SenderReport() {}
178
179 void From(uint32_t ssrc) {
180 sr_.SenderSSRC = ssrc;
181 }
182 void WithNtpSec(uint32_t sec) {
183 sr_.NTPMostSignificant = sec;
184 }
185 void WithNtpFrac(uint32_t frac) {
186 sr_.NTPLeastSignificant = frac;
187 }
188 void WithRtpTimestamp(uint32_t rtp_timestamp) {
189 sr_.RTPTimestamp = rtp_timestamp;
190 }
191 void WithPacketCount(uint32_t packet_count) {
192 sr_.SenderPacketCount = packet_count;
193 }
194 void WithOctetCount(uint32_t octet_count) {
195 sr_.SenderOctetCount = octet_count;
196 }
197 void WithReportBlock(ReportBlock* block);
198
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000199 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000200 virtual void Create(
201 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000202
203 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000204 enum { kMaxNumberOfReportBlocks = 0x1f };
205
206 size_t BlockLength() const {
207 const size_t kSrHeaderLength = 8;
208 const size_t kSenderInfoLength = 20;
209 return kSrHeaderLength + kSenderInfoLength +
210 report_blocks_.size() * kReportBlockLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000211 }
212
213 RTCPUtility::RTCPPacketSR sr_;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000214 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000215};
216
217//
218// RTCP receiver report (RFC 3550).
219//
220// 0 1 2 3
221// 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
222// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
223// |V=2|P| RC | PT=RR=201 | length |
224// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
225// | SSRC of packet sender |
226// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
227// | report block(s) |
228// | .... |
229
230class ReceiverReport : public RtcpPacket {
231 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000232 ReceiverReport() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000233 memset(&rr_, 0, sizeof(rr_));
234 }
235
236 virtual ~ReceiverReport() {}
237
238 void From(uint32_t ssrc) {
239 rr_.SenderSSRC = ssrc;
240 }
241 void WithReportBlock(ReportBlock* block);
242
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000243 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000244 virtual void Create(
245 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000246
247 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000248 enum { kMaxNumberOfReportBlocks = 0x1f };
249
250 size_t BlockLength() const {
251 const size_t kRrHeaderLength = 8;
252 return kRrHeaderLength + report_blocks_.size() * kReportBlockLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000253 }
254
255 RTCPUtility::RTCPPacketRR rr_;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000256 std::vector<RTCPUtility::RTCPPacketReportBlockItem> report_blocks_;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000257};
258
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000259// Transmission Time Offsets in RTP Streams (RFC 5450).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000260//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000261// 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// hdr |V=2|P| RC | PT=IJ=195 | length |
265// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266// | inter-arrival jitter |
267// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268// . .
269// . .
270// . .
271// | inter-arrival jitter |
272// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000273//
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000274// If present, this RTCP packet must be placed after a receiver report
275// (inside a compound RTCP packet), and MUST have the same value for RC
276// (reception report count) as the receiver report.
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000277
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000278class Ij : public RtcpPacket {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000279 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000280 Ij() : RtcpPacket() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000281
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000282 virtual ~Ij() {}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000283
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000284 void WithJitterItem(uint32_t jitter);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000285
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000286 protected:
287 virtual void Create(
288 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000289
290 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000291 enum { kMaxNumberOfIjItems = 0x1f };
292
293 size_t BlockLength() const {
294 return kHeaderLength + 4 * ij_items_.size();
295 }
296
297 std::vector<uint32_t> ij_items_;
298
299 DISALLOW_COPY_AND_ASSIGN(Ij);
300};
301
302// Source Description (SDES) (RFC 3550).
303//
304// 0 1 2 3
305// 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
306// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307// header |V=2|P| SC | PT=SDES=202 | length |
308// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
309// chunk | SSRC/CSRC_1 |
310// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311// | SDES items |
312// | ... |
313// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
314// chunk | SSRC/CSRC_2 |
315// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
316// | SDES items |
317// | ... |
318// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
319//
320// Canonical End-Point Identifier SDES Item (CNAME)
321//
322// 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// | CNAME=1 | length | user and domain name ...
326// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
327
328class Sdes : public RtcpPacket {
329 public:
330 Sdes() : RtcpPacket() {}
331
332 virtual ~Sdes() {}
333
334 void WithCName(uint32_t ssrc, std::string cname);
335
336 struct Chunk {
337 uint32_t ssrc;
338 std::string name;
339 int null_octets;
340 };
341
342 protected:
343 virtual void Create(
344 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
345
346 private:
347 enum { kMaxNumberOfChunks = 0x1f };
348
349 size_t BlockLength() const;
350
351 std::vector<Chunk> chunks_;
352
353 DISALLOW_COPY_AND_ASSIGN(Sdes);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000354};
355
356//
357// Bye packet (BYE) (RFC 3550).
358//
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| SC | PT=BYE=203 | length |
362// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363// | SSRC/CSRC |
364// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365// : ... :
366// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
367// (opt) | length | reason for leaving ...
368// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
369
370class Bye : public RtcpPacket {
371 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000372 Bye() : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000373 memset(&bye_, 0, sizeof(bye_));
374 }
375
376 virtual ~Bye() {}
377
378 void From(uint32_t ssrc) {
379 bye_.SenderSSRC = ssrc;
380 }
381 void WithCsrc(uint32_t csrc);
382
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000383 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000384 virtual void Create(
385 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000386
387 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000388 enum { kMaxNumberOfCsrcs = 0x1f - 1 };
389
390 size_t BlockLength() const {
391 size_t source_count = 1 + csrcs_.size();
392 return kHeaderLength + 4 * source_count;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000393 }
394
395 RTCPUtility::RTCPPacketBYE bye_;
396 std::vector<uint32_t> csrcs_;
397};
398
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000399// Application-Defined packet (APP) (RFC 3550).
400//
401// 0 1 2 3
402// 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
403// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
404// |V=2|P| subtype | PT=APP=204 | length |
405// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
406// | SSRC/CSRC |
407// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
408// | name (ASCII) |
409// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
410// | application-dependent data ...
411// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412
413class App : public RtcpPacket {
414 public:
415 App()
416 : RtcpPacket(),
417 ssrc_(0) {
418 memset(&app_, 0, sizeof(app_));
419 }
420
421 virtual ~App() {}
422
423 void From(uint32_t ssrc) {
424 ssrc_ = ssrc;
425 }
426 void WithSubType(uint8_t subtype) {
427 assert(subtype <= 0x1f);
428 app_.SubType = subtype;
429 }
430 void WithName(uint32_t name) {
431 app_.Name = name;
432 }
433 void WithData(const uint8_t* data, uint16_t data_length) {
434 assert(data);
435 assert(data_length <= kRtcpAppCode_DATA_SIZE);
436 assert(data_length % 4 == 0);
437 memcpy(app_.Data, data, data_length);
438 app_.Size = data_length;
439 }
440
441 protected:
442 virtual void Create(
443 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
444
445 private:
446 size_t BlockLength() const {
447 return 12 + app_.Size;
448 }
449
450 uint32_t ssrc_;
451 RTCPUtility::RTCPPacketAPP app_;
452
453 DISALLOW_COPY_AND_ASSIGN(App);
454};
455
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000456// RFC 4585: Feedback format.
457//
458// Common packet format:
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| FMT | PT | length |
464// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
465// | SSRC of packet sender |
466// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467// | SSRC of media source |
468// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
469// : Feedback Control Information (FCI) :
470// :
471
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000472// Picture loss indication (PLI) (RFC 4585).
473//
474// FCI: no feedback control information.
475
476class Pli : public RtcpPacket {
477 public:
478 Pli() : RtcpPacket() {
479 memset(&pli_, 0, sizeof(pli_));
480 }
481
482 virtual ~Pli() {}
483
484 void From(uint32_t ssrc) {
485 pli_.SenderSSRC = ssrc;
486 }
487 void To(uint32_t ssrc) {
488 pli_.MediaSSRC = ssrc;
489 }
490
491 protected:
492 virtual void Create(
493 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
494
495 private:
496 size_t BlockLength() const {
497 return kCommonFbFmtLength;
498 }
499
500 RTCPUtility::RTCPPacketPSFBPLI pli_;
501
502 DISALLOW_COPY_AND_ASSIGN(Pli);
503};
504
505// Slice loss indication (SLI) (RFC 4585).
506//
507// FCI:
508// 0 1 2 3
509// 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
510// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511// | First | Number | PictureID |
512// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513
514class Sli : public RtcpPacket {
515 public:
516 Sli() : RtcpPacket() {
517 memset(&sli_, 0, sizeof(sli_));
518 memset(&sli_item_, 0, sizeof(sli_item_));
519 }
520
521 virtual ~Sli() {}
522
523 void From(uint32_t ssrc) {
524 sli_.SenderSSRC = ssrc;
525 }
526 void To(uint32_t ssrc) {
527 sli_.MediaSSRC = ssrc;
528 }
529 void WithFirstMb(uint16_t first_mb) {
530 assert(first_mb <= 0x1fff);
531 sli_item_.FirstMB = first_mb;
532 }
533 void WithNumberOfMb(uint16_t number_mb) {
534 assert(number_mb <= 0x1fff);
535 sli_item_.NumberOfMB = number_mb;
536 }
537 void WithPictureId(uint8_t picture_id) {
538 assert(picture_id <= 0x3f);
539 sli_item_.PictureId = picture_id;
540 }
541
542 protected:
543 virtual void Create(
544 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
545
546 private:
547 size_t BlockLength() const {
548 const size_t kFciLength = 4;
549 return kCommonFbFmtLength + kFciLength;
550 }
551
552 RTCPUtility::RTCPPacketPSFBSLI sli_;
553 RTCPUtility::RTCPPacketPSFBSLIItem sli_item_;
554
555 DISALLOW_COPY_AND_ASSIGN(Sli);
556};
557
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000558// Generic NACK (RFC 4585).
559//
560// FCI:
561// 0 1 2 3
562// 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
563// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
564// | PID | BLP |
565// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
566
567class Nack : public RtcpPacket {
568 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000569 Nack() : RtcpPacket() {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000570 memset(&nack_, 0, sizeof(nack_));
571 }
572
573 virtual ~Nack() {}
574
575 void From(uint32_t ssrc) {
576 nack_.SenderSSRC = ssrc;
577 }
578 void To(uint32_t ssrc) {
579 nack_.MediaSSRC = ssrc;
580 }
581 void WithList(const uint16_t* nack_list, int length);
582
583 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000584 virtual void Create(
585 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000586
587 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000588 size_t BlockLength() const {
589 size_t fci_length = 4 * nack_fields_.size();
590 return kCommonFbFmtLength + fci_length;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000591 }
592
593 RTCPUtility::RTCPPacketRTPFBNACK nack_;
594 std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_;
595
596 DISALLOW_COPY_AND_ASSIGN(Nack);
597};
598
599// Reference picture selection indication (RPSI) (RFC 4585).
600//
601// FCI:
602//
603// 0 1 2 3
604// 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
605// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
606// | PB |0| Payload Type| Native RPSI bit string |
607// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
608// | defined per codec ... | Padding (0) |
609// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
610
611class Rpsi : public RtcpPacket {
612 public:
613 Rpsi()
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000614 : RtcpPacket(),
615 padding_bytes_(0) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000616 memset(&rpsi_, 0, sizeof(rpsi_));
617 }
618
619 virtual ~Rpsi() {}
620
621 void From(uint32_t ssrc) {
622 rpsi_.SenderSSRC = ssrc;
623 }
624 void To(uint32_t ssrc) {
625 rpsi_.MediaSSRC = ssrc;
626 }
627 void WithPayloadType(uint8_t payload) {
628 assert(payload <= 0x7f);
629 rpsi_.PayloadType = payload;
630 }
631 void WithPictureId(uint64_t picture_id);
632
633 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000634 virtual void Create(
635 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000636
637 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000638 size_t BlockLength() const {
639 size_t fci_length = 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
640 return kCommonFbFmtLength + fci_length;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000641 }
642
643 uint8_t padding_bytes_;
644 RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
645
646 DISALLOW_COPY_AND_ASSIGN(Rpsi);
647};
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000648
649// Full intra request (FIR) (RFC 5104).
650//
651// FCI:
652//
653// 0 1 2 3
654// 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
655// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
656// | SSRC |
657// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
658// | Seq nr. | Reserved |
659// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
660
661class Fir : public RtcpPacket {
662 public:
663 Fir()
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000664 : RtcpPacket() {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000665 memset(&fir_, 0, sizeof(fir_));
666 memset(&fir_item_, 0, sizeof(fir_item_));
667 }
668
669 virtual ~Fir() {}
670
671 void From(uint32_t ssrc) {
672 fir_.SenderSSRC = ssrc;
673 }
674 void To(uint32_t ssrc) {
675 fir_item_.SSRC = ssrc;
676 }
677 void WithCommandSeqNum(uint8_t seq_num) {
678 fir_item_.CommandSequenceNumber = seq_num;
679 }
680
681 protected:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000682 virtual void Create(
683 uint8_t* packet, size_t* length, size_t max_length) const OVERRIDE;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000684
685 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000686 size_t BlockLength() const {
687 const size_t kFciLength = 8;
688 return kCommonFbFmtLength + kFciLength;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000689 }
690
691 RTCPUtility::RTCPPacketPSFBFIR fir_;
692 RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
693};
694
695// Class holding a RTCP packet.
696//
697// Takes a built rtcp packet.
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000698// RawPacket raw_packet(buffer, length);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000699//
700// To access the raw packet:
701// raw_packet.buffer(); - pointer to the raw packet
702// raw_packet.buffer_length(); - the length of the raw packet
703
704class RawPacket {
705 public:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000706 RawPacket(const uint8_t* packet, size_t length) {
707 assert(length <= IP_PACKET_SIZE);
708 memcpy(buffer_, packet, length);
709 buffer_length_ = length;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000710 }
711
712 const uint8_t* buffer() {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000713 return buffer_;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000714 }
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000715 size_t buffer_length() const {
716 return buffer_length_;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000717 }
718
719 private:
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000720 size_t buffer_length_;
721 uint8_t buffer_[IP_PACKET_SIZE];
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000722};
723
724} // namespace rtcp
725} // namespace webrtc
726#endif // WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_