blob: 641bd7fda638a4a31feb4f1a0e6ee453c8ea1639 [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
15#include <vector>
16
17#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
18#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
19#include "webrtc/typedefs.h"
20
21namespace webrtc {
22namespace rtcp {
23
24class RawPacket;
25class ReportBlock;
26
27// Class for building RTCP packets.
28//
29// Example:
30// ReportBlock report_block;
31// report_block.To(234)
32// report_block.FractionLost(10);
33//
34// ReceiverReport rr;
35// rr.From(123);
36// rr.WithReportBlock(&report_block)
37//
38// Fir fir;
39// fir.From(123);
40// fir.To(234)
41// fir.WithCommandSeqNum(123);
42//
43// uint16_t len = 0; // Builds an intra frame request
44// uint8_t packet[kPacketSize]; // with sequence number 123.
45// fir.Build(packet, &len, kPacketSize);
46//
47// RawPacket packet = fir.Build(); // Returns a RawPacket holding
48// // the built rtcp packet.
49//
50// rr.Append(&fir) // Builds a compound RTCP packet with
51// RawPacket packet = rr.Build(); // a receiver report, report block
52// // and fir message.
53
54class RtcpPacket {
55 public:
56 virtual ~RtcpPacket() {}
57
58 void Append(RtcpPacket* packet);
59
60 RawPacket Build() const;
61
62 void Build(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
63
64 protected:
65 RtcpPacket() {}
66
67 virtual void Create(
68 uint8_t* packet, uint16_t* len, uint16_t max_len) const = 0;
69
70 void CreateAndAddAppended(
71 uint8_t* packet, uint16_t* len, uint16_t max_len) const;
72
73 private:
74 std::vector<RtcpPacket*> appended_packets_;
75};
76
77class Empty : public RtcpPacket {
78 public:
79 Empty() {}
80
81 virtual ~Empty() {}
82
83 protected:
84 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
85};
86
87//// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
88//
89// RTCP sender report (RFC 3550).
90//
91// 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
92// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93// |V=2|P| RC | PT=SR=200 | length |
94// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95// | SSRC of sender |
96// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
97// | NTP timestamp, most significant word |
98// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99// | NTP timestamp, least significant word |
100// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101// | RTP timestamp |
102// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103// | sender's packet count |
104// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105// | sender's octet count |
106// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
107// | report block(s) |
108// | .... |
109
110class SenderReport : public RtcpPacket {
111 public:
112 SenderReport()
113 : RtcpPacket() {
114 memset(&sr_, 0, sizeof(sr_));
115 }
116
117 virtual ~SenderReport() {}
118
119 void From(uint32_t ssrc) {
120 sr_.SenderSSRC = ssrc;
121 }
122 void WithNtpSec(uint32_t sec) {
123 sr_.NTPMostSignificant = sec;
124 }
125 void WithNtpFrac(uint32_t frac) {
126 sr_.NTPLeastSignificant = frac;
127 }
128 void WithRtpTimestamp(uint32_t rtp_timestamp) {
129 sr_.RTPTimestamp = rtp_timestamp;
130 }
131 void WithPacketCount(uint32_t packet_count) {
132 sr_.SenderPacketCount = packet_count;
133 }
134 void WithOctetCount(uint32_t octet_count) {
135 sr_.SenderOctetCount = octet_count;
136 }
137 void WithReportBlock(ReportBlock* block);
138
139 enum { kMaxNumberOfReportBlocks = 0x1f };
140
141 protected:
142 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
143
144 private:
145 uint16_t Length() const {
146 const uint16_t kSrBlockLen = 28;
147 const uint16_t kReportBlockLen = 24;
148 return kSrBlockLen + report_blocks_.size() * kReportBlockLen;
149 }
150
151 RTCPUtility::RTCPPacketSR sr_;
152 std::vector<ReportBlock*> report_blocks_;
153};
154
155//
156// RTCP receiver report (RFC 3550).
157//
158// 0 1 2 3
159// 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
160// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161// |V=2|P| RC | PT=RR=201 | length |
162// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163// | SSRC of packet sender |
164// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
165// | report block(s) |
166// | .... |
167
168class ReceiverReport : public RtcpPacket {
169 public:
170 ReceiverReport()
171 : RtcpPacket() {
172 memset(&rr_, 0, sizeof(rr_));
173 }
174
175 virtual ~ReceiverReport() {}
176
177 void From(uint32_t ssrc) {
178 rr_.SenderSSRC = ssrc;
179 }
180 void WithReportBlock(ReportBlock* block);
181
182 enum { kMaxNumberOfReportBlocks = 0x1f };
183
184 protected:
185 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
186
187 private:
188 uint16_t Length() const {
189 const uint16_t kRrBlockLen = 8;
190 const uint16_t kReportBlockLen = 24;
191 return kRrBlockLen + report_blocks_.size() * kReportBlockLen;
192 }
193
194 RTCPUtility::RTCPPacketRR rr_;
195 std::vector<ReportBlock*> report_blocks_;
196};
197
198//
199// RTCP report block (RFC 3550).
200//
201// 0 1 2 3
202// 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
203// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
204// | SSRC_1 (SSRC of first source) |
205// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
206// | fraction lost | cumulative number of packets lost |
207// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208// | extended highest sequence number received |
209// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
210// | interarrival jitter |
211// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212// | last SR (LSR) |
213// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
214// | delay since last SR (DLSR) |
215// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
216
217class ReportBlock {
218 public:
219 ReportBlock() {
220 memset(&report_block_, 0, sizeof(report_block_));
221 }
222
223 ~ReportBlock() {}
224
225 void To(uint32_t ssrc) {
226 report_block_.SSRC = ssrc;
227 }
228 void WithFractionLost(uint8_t fraction_lost) {
229 report_block_.FractionLost = fraction_lost;
230 }
231 void WithCumPacketsLost(uint32_t cum_packets_lost) {
232 report_block_.CumulativeNumOfPacketsLost = cum_packets_lost;
233 }
234 void WithExtHighestSeqNum(uint32_t ext_highest_seq_num) {
235 report_block_.ExtendedHighestSequenceNumber = ext_highest_seq_num;
236 }
237 void WithJitter(uint32_t jitter) {
238 report_block_.Jitter = jitter;
239 }
240 void WithLastSr(uint32_t last_sr) {
241 report_block_.LastSR = last_sr;
242 }
243 void WithDelayLastSr(uint32_t delay_last_sr) {
244 report_block_.DelayLastSR = delay_last_sr;
245 }
246
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000247 void Create(uint8_t* packet, uint16_t* len) const;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000248
249 private:
250 RTCPUtility::RTCPPacketReportBlockItem report_block_;
251};
252
253//
254// Bye packet (BYE) (RFC 3550).
255//
256// 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
257// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
258// |V=2|P| SC | PT=BYE=203 | length |
259// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260// | SSRC/CSRC |
261// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
262// : ... :
263// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
264// (opt) | length | reason for leaving ...
265// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266
267class Bye : public RtcpPacket {
268 public:
269 Bye()
270 : RtcpPacket() {
271 memset(&bye_, 0, sizeof(bye_));
272 }
273
274 virtual ~Bye() {}
275
276 void From(uint32_t ssrc) {
277 bye_.SenderSSRC = ssrc;
278 }
279 void WithCsrc(uint32_t csrc);
280
281 enum { kMaxNumberOfCsrcs = 0x1f - 1 };
282
283 protected:
284 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
285
286 private:
287 uint16_t Length() const {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000288 const uint16_t kByeBlockLen = 8 + 4 * csrcs_.size();
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000289 return kByeBlockLen;
290 }
291
292 RTCPUtility::RTCPPacketBYE bye_;
293 std::vector<uint32_t> csrcs_;
294};
295
296// RFC 4585: Feedback format.
297//
298// Common packet format:
299//
300// 0 1 2 3
301// 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
302// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
303// |V=2|P| FMT | PT | length |
304// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305// | SSRC of packet sender |
306// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307// | SSRC of media source |
308// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
309// : Feedback Control Information (FCI) :
310// :
311
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000312// Generic NACK (RFC 4585).
313//
314// FCI:
315// 0 1 2 3
316// 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
317// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
318// | PID | BLP |
319// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
320
321class Nack : public RtcpPacket {
322 public:
323 Nack()
324 : RtcpPacket() {
325 memset(&nack_, 0, sizeof(nack_));
326 }
327
328 virtual ~Nack() {}
329
330 void From(uint32_t ssrc) {
331 nack_.SenderSSRC = ssrc;
332 }
333 void To(uint32_t ssrc) {
334 nack_.MediaSSRC = ssrc;
335 }
336 void WithList(const uint16_t* nack_list, int length);
337
338 protected:
339 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const
340 OVERRIDE;
341
342 private:
343 uint16_t Length() const {
344 const uint16_t kNackBlockLen = 4 * (3 + nack_fields_.size());
345 return kNackBlockLen;
346 }
347
348 RTCPUtility::RTCPPacketRTPFBNACK nack_;
349 std::vector<RTCPUtility::RTCPPacketRTPFBNACKItem> nack_fields_;
350
351 DISALLOW_COPY_AND_ASSIGN(Nack);
352};
353
354// Reference picture selection indication (RPSI) (RFC 4585).
355//
356// FCI:
357//
358// 0 1 2 3
359// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
360// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
361// | PB |0| Payload Type| Native RPSI bit string |
362// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
363// | defined per codec ... | Padding (0) |
364// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
365
366class Rpsi : public RtcpPacket {
367 public:
368 Rpsi()
369 : RtcpPacket(),
370 padding_bytes_(0) {
371 memset(&rpsi_, 0, sizeof(rpsi_));
372 }
373
374 virtual ~Rpsi() {}
375
376 void From(uint32_t ssrc) {
377 rpsi_.SenderSSRC = ssrc;
378 }
379 void To(uint32_t ssrc) {
380 rpsi_.MediaSSRC = ssrc;
381 }
382 void WithPayloadType(uint8_t payload) {
383 assert(payload <= 0x7f);
384 rpsi_.PayloadType = payload;
385 }
386 void WithPictureId(uint64_t picture_id);
387
388 protected:
389 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const
390 OVERRIDE;
391
392 private:
393 uint16_t Length() const {
394 const uint16_t kRpsiBlockLen =
395 12 + 2 + (rpsi_.NumberOfValidBits / 8) + padding_bytes_;
396 return kRpsiBlockLen;
397 }
398
399 uint8_t padding_bytes_;
400 RTCPUtility::RTCPPacketPSFBRPSI rpsi_;
401
402 DISALLOW_COPY_AND_ASSIGN(Rpsi);
403};
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000404
405// Full intra request (FIR) (RFC 5104).
406//
407// FCI:
408//
409// 0 1 2 3
410// 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
411// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
412// | SSRC |
413// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
414// | Seq nr. | Reserved |
415// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
416
417class Fir : public RtcpPacket {
418 public:
419 Fir()
420 : RtcpPacket() {
421 memset(&fir_, 0, sizeof(fir_));
422 memset(&fir_item_, 0, sizeof(fir_item_));
423 }
424
425 virtual ~Fir() {}
426
427 void From(uint32_t ssrc) {
428 fir_.SenderSSRC = ssrc;
429 }
430 void To(uint32_t ssrc) {
431 fir_item_.SSRC = ssrc;
432 }
433 void WithCommandSeqNum(uint8_t seq_num) {
434 fir_item_.CommandSequenceNumber = seq_num;
435 }
436
437 protected:
438 virtual void Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const;
439
440 private:
441 uint16_t Length() const {
442 const uint16_t kFirBlockLen = 20;
443 return kFirBlockLen;
444 }
445
446 RTCPUtility::RTCPPacketPSFBFIR fir_;
447 RTCPUtility::RTCPPacketPSFBFIRItem fir_item_;
448};
449
450// Class holding a RTCP packet.
451//
452// Takes a built rtcp packet.
453// RawPacket raw_packet(buffer, len);
454//
455// To access the raw packet:
456// raw_packet.buffer(); - pointer to the raw packet
457// raw_packet.buffer_length(); - the length of the raw packet
458
459class RawPacket {
460 public:
461 RawPacket(const uint8_t* buffer, uint16_t len) {
462 assert(len <= IP_PACKET_SIZE);
463 memcpy(packet_, buffer, len);
464 packet_length_ = len;
465 }
466
467 const uint8_t* buffer() {
468 return packet_;
469 }
470 uint16_t buffer_length() const {
471 return packet_length_;
472 }
473
474 private:
475 uint16_t packet_length_;
476 uint8_t packet_[IP_PACKET_SIZE];
477};
478
479} // namespace rtcp
480} // namespace webrtc
481#endif // WEBRTC_MODULES_RTP_RTCP_RTCP_PACKET_H_