blob: 7038532f2e991fa822b364a0e0e2e4327b630c0e [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#include "webrtc/modules/rtp_rtcp/source/rtcp_packet.h"
12
Erik Språngc1b9d4e2015-06-08 09:54:14 +020013#include "webrtc/base/checks.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000014#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000015#include "webrtc/system_wrappers/interface/logging.h"
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000016
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +000017using webrtc::RTCPUtility::kBtDlrr;
18using webrtc::RTCPUtility::kBtReceiverReferenceTime;
19using webrtc::RTCPUtility::kBtVoipMetric;
20
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000021using webrtc::RTCPUtility::PT_APP;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000022using webrtc::RTCPUtility::PT_BYE;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000023using webrtc::RTCPUtility::PT_IJ;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000024using webrtc::RTCPUtility::PT_PSFB;
25using webrtc::RTCPUtility::PT_RR;
26using webrtc::RTCPUtility::PT_RTPFB;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000027using webrtc::RTCPUtility::PT_SDES;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000028using webrtc::RTCPUtility::PT_SR;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000029using webrtc::RTCPUtility::PT_XR;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000030
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000031using webrtc::RTCPUtility::RTCPPacketAPP;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000032using webrtc::RTCPUtility::RTCPPacketBYE;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000033using webrtc::RTCPUtility::RTCPPacketPSFBAPP;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000034using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
35using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000036using webrtc::RTCPUtility::RTCPPacketPSFBPLI;
37using webrtc::RTCPUtility::RTCPPacketPSFBREMBItem;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000038using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000039using webrtc::RTCPUtility::RTCPPacketPSFBSLI;
40using webrtc::RTCPUtility::RTCPPacketPSFBSLIItem;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000041using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
42using webrtc::RTCPUtility::RTCPPacketRR;
43using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
44using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000045using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBN;
46using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBNItem;
47using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBR;
48using webrtc::RTCPUtility::RTCPPacketRTPFBTMMBRItem;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000049using webrtc::RTCPUtility::RTCPPacketSR;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000050using webrtc::RTCPUtility::RTCPPacketXRDLRRReportBlockItem;
51using webrtc::RTCPUtility::RTCPPacketXRReceiverReferenceTimeItem;
52using webrtc::RTCPUtility::RTCPPacketXR;
53using webrtc::RTCPUtility::RTCPPacketXRVOIPMetricItem;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000054
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000055namespace webrtc {
56namespace rtcp {
57namespace {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000058// Unused SSRC of media source, set to 0.
59const uint32_t kUnusedMediaSourceSsrc0 = 0;
60
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000061void AssignUWord8(uint8_t* buffer, size_t* offset, uint8_t value) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000062 buffer[(*offset)++] = value;
63}
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000064void AssignUWord16(uint8_t* buffer, size_t* offset, uint16_t value) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000065 ByteWriter<uint16_t>::WriteBigEndian(buffer + *offset, value);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000066 *offset += 2;
67}
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000068void AssignUWord24(uint8_t* buffer, size_t* offset, uint32_t value) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000069 ByteWriter<uint32_t, 3>::WriteBigEndian(buffer + *offset, value);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000070 *offset += 3;
71}
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000072void AssignUWord32(uint8_t* buffer, size_t* offset, uint32_t value) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000073 ByteWriter<uint32_t>::WriteBigEndian(buffer + *offset, value);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000074 *offset += 4;
75}
76
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +000077void ComputeMantissaAnd6bitBase2Exponent(uint32_t input_base10,
78 uint8_t bits_mantissa,
79 uint32_t* mantissa,
80 uint8_t* exp) {
81 // input_base10 = mantissa * 2^exp
82 assert(bits_mantissa <= 32);
83 uint32_t mantissa_max = (1 << bits_mantissa) - 1;
84 uint8_t exponent = 0;
85 for (uint32_t i = 0; i < 64; ++i) {
86 if (input_base10 <= (mantissa_max << i)) {
87 exponent = i;
88 break;
89 }
90 }
91 *exp = exponent;
92 *mantissa = (input_base10 >> exponent);
93}
94
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +000095size_t BlockToHeaderLength(size_t length_in_bytes) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000096 // Length in 32-bit words minus 1.
97 assert(length_in_bytes > 0);
98 assert(length_in_bytes % 4 == 0);
99 return (length_in_bytes / 4) - 1;
100}
101
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000102// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
103//
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000104// RTP header format.
105// 0 1 2 3
106// 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
107// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108// |V=2|P| RC/FMT | PT | length |
109// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110
111void CreateHeader(uint8_t count_or_format, // Depends on packet type.
112 uint8_t packet_type,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000113 size_t length,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000114 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000115 size_t* pos) {
116 assert(length <= 0xffff);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000117 const uint8_t kVersion = 2;
118 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
119 AssignUWord8(buffer, pos, packet_type);
120 AssignUWord16(buffer, pos, length);
121}
122
123// Sender report (SR) (RFC 3550).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000124// 0 1 2 3
125// 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
126// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127// |V=2|P| RC | PT=SR=200 | length |
128// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129// | SSRC of sender |
130// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
131// | NTP timestamp, most significant word |
132// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133// | NTP timestamp, least significant word |
134// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135// | RTP timestamp |
136// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137// | sender's packet count |
138// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139// | sender's octet count |
140// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
141
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000142void CreateSenderReport(const RTCPPacketSR& sr,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000143 size_t length,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000144 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000145 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000146 CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000147 AssignUWord32(buffer, pos, sr.SenderSSRC);
148 AssignUWord32(buffer, pos, sr.NTPMostSignificant);
149 AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
150 AssignUWord32(buffer, pos, sr.RTPTimestamp);
151 AssignUWord32(buffer, pos, sr.SenderPacketCount);
152 AssignUWord32(buffer, pos, sr.SenderOctetCount);
153}
154
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000155// Receiver report (RR), header (RFC 3550).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000156//
157// 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
158// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159// |V=2|P| RC | PT=RR=201 | length |
160// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161// | SSRC of packet sender |
162// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
163
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000164void CreateReceiverReport(const RTCPPacketRR& rr,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000165 size_t length,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000166 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000167 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000168 CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000169 AssignUWord32(buffer, pos, rr.SenderSSRC);
170}
171
172// Report block (RFC 3550).
173//
174// 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
175// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
176// | SSRC_1 (SSRC of first source) |
177// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
178// | fraction lost | cumulative number of packets lost |
179// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
180// | extended highest sequence number received |
181// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
182// | interarrival jitter |
183// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
184// | last SR (LSR) |
185// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
186// | delay since last SR (DLSR) |
187// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
188
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000189void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
190 uint8_t* buffer,
191 size_t* pos) {
192 for (std::vector<RTCPPacketReportBlockItem>::const_iterator
193 it = blocks.begin(); it != blocks.end(); ++it) {
194 AssignUWord32(buffer, pos, (*it).SSRC);
195 AssignUWord8(buffer, pos, (*it).FractionLost);
196 AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost);
197 AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber);
198 AssignUWord32(buffer, pos, (*it).Jitter);
199 AssignUWord32(buffer, pos, (*it).LastSR);
200 AssignUWord32(buffer, pos, (*it).DelayLastSR);
201 }
202}
203
204// Transmission Time Offsets in RTP Streams (RFC 5450).
205//
206// 0 1 2 3
207// 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
208// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
209// hdr |V=2|P| RC | PT=IJ=195 | length |
210// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
211// | inter-arrival jitter |
212// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
213// . .
214// . .
215// . .
216// | inter-arrival jitter |
217// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
218
219void CreateIj(const std::vector<uint32_t>& ij_items,
220 uint8_t* buffer,
221 size_t* pos) {
222 size_t length = ij_items.size();
223 CreateHeader(length, PT_IJ, length, buffer, pos);
224 for (std::vector<uint32_t>::const_iterator it = ij_items.begin();
225 it != ij_items.end(); ++it) {
226 AssignUWord32(buffer, pos, *it);
227 }
228}
229
230// Source Description (SDES) (RFC 3550).
231//
232// 0 1 2 3
233// 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
234// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
235// header |V=2|P| SC | PT=SDES=202 | length |
236// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
237// chunk | SSRC/CSRC_1 |
238// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239// | SDES items |
240// | ... |
241// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
242// chunk | SSRC/CSRC_2 |
243// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244// | SDES items |
245// | ... |
246// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
247//
248// Canonical End-Point Identifier SDES Item (CNAME)
249//
250// 0 1 2 3
251// 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
252// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
253// | CNAME=1 | length | user and domain name ...
254// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
255
256void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
257 size_t length,
258 uint8_t* buffer,
259 size_t* pos) {
260 CreateHeader(chunks.size(), PT_SDES, length, buffer, pos);
261 const uint8_t kSdesItemType = 1;
262 for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
263 it != chunks.end(); ++it) {
264 AssignUWord32(buffer, pos, (*it).ssrc);
265 AssignUWord8(buffer, pos, kSdesItemType);
266 AssignUWord8(buffer, pos, (*it).name.length());
267 memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
268 *pos += (*it).name.length();
269 memset(buffer + *pos, 0, (*it).null_octets);
270 *pos += (*it).null_octets;
271 }
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000272}
273
274// Bye packet (BYE) (RFC 3550).
275//
276// 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
277// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
278// |V=2|P| SC | PT=BYE=203 | length |
279// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
280// | SSRC/CSRC |
281// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
282// : ... :
283// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
284// (opt) | length | reason for leaving ...
285// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
286
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000287void CreateBye(const RTCPPacketBYE& bye,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000288 const std::vector<uint32_t>& csrcs,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000289 size_t length,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000290 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000291 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000292 CreateHeader(length, PT_BYE, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000293 AssignUWord32(buffer, pos, bye.SenderSSRC);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200294 for (uint32_t csrc : csrcs)
295 AssignUWord32(buffer, pos, csrc);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000296}
297
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000298// Application-Defined packet (APP) (RFC 3550).
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| subtype | PT=APP=204 | length |
304// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
305// | SSRC/CSRC |
306// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307// | name (ASCII) |
308// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
309// | application-dependent data ...
310// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311
312void CreateApp(const RTCPPacketAPP& app,
313 uint32_t ssrc,
314 size_t length,
315 uint8_t* buffer,
316 size_t* pos) {
317 CreateHeader(app.SubType, PT_APP, length, buffer, pos);
318 AssignUWord32(buffer, pos, ssrc);
319 AssignUWord32(buffer, pos, app.Name);
320 memcpy(buffer + *pos, app.Data, app.Size);
321 *pos += app.Size;
322}
323
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000324// RFC 4585: Feedback format.
325//
326// Common packet format:
327//
328// 0 1 2 3
329// 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
330// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
331// |V=2|P| FMT | PT | length |
332// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
333// | SSRC of packet sender |
334// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
335// | SSRC of media source |
336// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
337// : Feedback Control Information (FCI) :
338// :
339//
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000340
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000341// Picture loss indication (PLI) (RFC 4585).
342//
343// FCI: no feedback control information.
344
345void CreatePli(const RTCPPacketPSFBPLI& pli,
346 size_t length,
347 uint8_t* buffer,
348 size_t* pos) {
349 const uint8_t kFmt = 1;
350 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
351 AssignUWord32(buffer, pos, pli.SenderSSRC);
352 AssignUWord32(buffer, pos, pli.MediaSSRC);
353}
354
355// Slice loss indication (SLI) (RFC 4585).
356//
357// FCI:
358//
359// 0 1 2 3
360// 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
361// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
362// | First | Number | PictureID |
363// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
364
365void CreateSli(const RTCPPacketPSFBSLI& sli,
366 const RTCPPacketPSFBSLIItem& sli_item,
367 size_t length,
368 uint8_t* buffer,
369 size_t* pos) {
370 const uint8_t kFmt = 2;
371 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
372 AssignUWord32(buffer, pos, sli.SenderSSRC);
373 AssignUWord32(buffer, pos, sli.MediaSSRC);
374
375 AssignUWord8(buffer, pos, sli_item.FirstMB >> 5);
376 AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) +
377 ((sli_item.NumberOfMB >> 10) & 0x07));
378 AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2);
379 AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId);
380}
381
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000382// Generic NACK (RFC 4585).
383//
384// FCI:
385//
386// 0 1 2 3
387// 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
388// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
389// | PID | BLP |
390// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
391
392void CreateNack(const RTCPPacketRTPFBNACK& nack,
393 const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200394 size_t start_index,
395 size_t end_index,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000396 size_t length,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000397 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000398 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000399 const uint8_t kFmt = 1;
400 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
401 AssignUWord32(buffer, pos, nack.SenderSSRC);
402 AssignUWord32(buffer, pos, nack.MediaSSRC);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200403 for (size_t i = start_index; i < end_index; ++i) {
404 const RTCPPacketRTPFBNACKItem& nack_item = nack_fields[i];
405 AssignUWord16(buffer, pos, nack_item.PacketID);
406 AssignUWord16(buffer, pos, nack_item.BitMask);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000407 }
408}
409
410// Reference picture selection indication (RPSI) (RFC 4585).
411//
412// FCI:
413//
414// 0 1 2 3
415// 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
416// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
417// | PB |0| Payload Type| Native RPSI bit string |
418// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
419// | defined per codec ... | Padding (0) |
420// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
421
422void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
423 uint8_t padding_bytes,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000424 size_t length,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000425 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000426 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000427 // Native bit string should be a multiple of 8 bits.
428 assert(rpsi.NumberOfValidBits % 8 == 0);
429 const uint8_t kFmt = 3;
430 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
431 AssignUWord32(buffer, pos, rpsi.SenderSSRC);
432 AssignUWord32(buffer, pos, rpsi.MediaSSRC);
433 AssignUWord8(buffer, pos, padding_bytes * 8);
434 AssignUWord8(buffer, pos, rpsi.PayloadType);
435 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
436 *pos += rpsi.NumberOfValidBits / 8;
437 memset(buffer + *pos, 0, padding_bytes);
438 *pos += padding_bytes;
439}
440
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000441// Full intra request (FIR) (RFC 5104).
442//
443// FCI:
444//
445// 0 1 2 3
446// 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
447// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
448// | SSRC |
449// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
450// | Seq nr. | Reserved |
451// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
452
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000453void CreateFir(const RTCPPacketPSFBFIR& fir,
454 const RTCPPacketPSFBFIRItem& fir_item,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000455 size_t length,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000456 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000457 size_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000458 const uint8_t kFmt = 4;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000459 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000460 AssignUWord32(buffer, pos, fir.SenderSSRC);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000461 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000462 AssignUWord32(buffer, pos, fir_item.SSRC);
463 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
464 AssignUWord24(buffer, pos, 0);
465}
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000466
467void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
468 uint8_t* buffer,
469 size_t* pos) {
470 uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000;
471 uint32_t mantissa = 0;
472 uint8_t exp = 0;
473 ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp);
474
475 AssignUWord32(buffer, pos, tmmbr_item.SSRC);
476 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03));
477 AssignUWord8(buffer, pos, mantissa >> 7);
478 AssignUWord8(buffer, pos, (mantissa << 1) +
479 ((tmmbr_item.MeasuredOverhead >> 8) & 0x01));
480 AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead);
481}
482
483// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
484//
485// FCI:
486//
487// 0 1 2 3
488// 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
489// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
490// | SSRC |
491// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
492// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
493// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
494
495void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr,
496 const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
497 size_t length,
498 uint8_t* buffer,
499 size_t* pos) {
500 const uint8_t kFmt = 3;
501 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
502 AssignUWord32(buffer, pos, tmmbr.SenderSSRC);
503 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
504 CreateTmmbrItem(tmmbr_item, buffer, pos);
505}
506
507// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
508//
509// FCI:
510//
511// 0 1 2 3
512// 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
513// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
514// | SSRC |
515// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
516// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
517// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
518
519void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn,
520 const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items,
521 size_t length,
522 uint8_t* buffer,
523 size_t* pos) {
524 const uint8_t kFmt = 4;
525 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
526 AssignUWord32(buffer, pos, tmmbn.SenderSSRC);
527 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
528 for (uint8_t i = 0; i < tmmbn_items.size(); ++i) {
529 CreateTmmbrItem(tmmbn_items[i], buffer, pos);
530 }
531}
532
533// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
534//
535// 0 1 2 3
536// 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
537// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538// |V=2|P| FMT=15 | PT=206 | length |
539// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540// | SSRC of packet sender |
541// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542// | SSRC of media source |
543// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544// | Unique identifier 'R' 'E' 'M' 'B' |
545// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546// | Num SSRC | BR Exp | BR Mantissa |
547// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548// | SSRC feedback |
549// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
550// | ... |
551
552void CreateRemb(const RTCPPacketPSFBAPP& remb,
553 const RTCPPacketPSFBREMBItem& remb_item,
554 size_t length,
555 uint8_t* buffer,
556 size_t* pos) {
557 uint32_t mantissa = 0;
558 uint8_t exp = 0;
559 ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp);
560
561 const uint8_t kFmt = 15;
562 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
563 AssignUWord32(buffer, pos, remb.SenderSSRC);
564 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
565 AssignUWord8(buffer, pos, 'R');
566 AssignUWord8(buffer, pos, 'E');
567 AssignUWord8(buffer, pos, 'M');
568 AssignUWord8(buffer, pos, 'B');
569 AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs);
570 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03));
571 AssignUWord8(buffer, pos, mantissa >> 8);
572 AssignUWord8(buffer, pos, mantissa);
573 for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) {
574 AssignUWord32(buffer, pos, remb_item.SSRCs[i]);
575 }
576}
577
578// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
579//
580// Format for XR packets:
581//
582// 0 1 2 3
583// 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
584// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
585// |V=2|P|reserved | PT=XR=207 | length |
586// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
587// | SSRC |
588// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
589// : report blocks :
590// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
591
592void CreateXrHeader(const RTCPPacketXR& header,
593 size_t length,
594 uint8_t* buffer,
595 size_t* pos) {
596 CreateHeader(0U, PT_XR, length, buffer, pos);
597 AssignUWord32(buffer, pos, header.OriginatorSSRC);
598}
599
600void CreateXrBlockHeader(uint8_t block_type,
601 uint16_t block_length,
602 uint8_t* buffer,
603 size_t* pos) {
604 AssignUWord8(buffer, pos, block_type);
605 AssignUWord8(buffer, pos, 0);
606 AssignUWord16(buffer, pos, block_length);
607}
608
609// Receiver Reference Time Report Block (RFC 3611).
610//
611// 0 1 2 3
612// 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
613// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
614// | BT=4 | reserved | block length = 2 |
615// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616// | NTP timestamp, most significant word |
617// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
618// | NTP timestamp, least significant word |
619// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
620
621void CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem>& rrtrs,
622 uint8_t* buffer,
623 size_t* pos) {
624 const uint16_t kBlockLength = 2;
625 for (std::vector<RTCPPacketXRReceiverReferenceTimeItem>::const_iterator it =
626 rrtrs.begin(); it != rrtrs.end(); ++it) {
627 CreateXrBlockHeader(kBtReceiverReferenceTime, kBlockLength, buffer, pos);
628 AssignUWord32(buffer, pos, (*it).NTPMostSignificant);
629 AssignUWord32(buffer, pos, (*it).NTPLeastSignificant);
630 }
631}
632
633// DLRR Report Block (RFC 3611).
634//
635// 0 1 2 3
636// 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
637// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
638// | BT=5 | reserved | block length |
639// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
640// | SSRC_1 (SSRC of first receiver) | sub-
641// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
642// | last RR (LRR) | 1
643// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
644// | delay since last RR (DLRR) |
645// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
646// | SSRC_2 (SSRC of second receiver) | sub-
647// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
648// : ... : 2
649
650void CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs,
651 uint8_t* buffer,
652 size_t* pos) {
653 for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin();
654 it != dlrrs.end(); ++it) {
655 if ((*it).empty()) {
656 continue;
657 }
658 uint16_t block_length = 3 * (*it).size();
659 CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos);
660 for (Xr::DlrrBlock::const_iterator it_block = (*it).begin();
661 it_block != (*it).end(); ++it_block) {
662 AssignUWord32(buffer, pos, (*it_block).SSRC);
663 AssignUWord32(buffer, pos, (*it_block).LastRR);
664 AssignUWord32(buffer, pos, (*it_block).DelayLastRR);
665 }
666 }
667}
668
669// VoIP Metrics Report Block (RFC 3611).
670//
671// 0 1 2 3
672// 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
673// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
674// | BT=7 | reserved | block length = 8 |
675// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
676// | SSRC of source |
677// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
678// | loss rate | discard rate | burst density | gap density |
679// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680// | burst duration | gap duration |
681// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
682// | round trip delay | end system delay |
683// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
684// | signal level | noise level | RERL | Gmin |
685// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
686// | R factor | ext. R factor | MOS-LQ | MOS-CQ |
687// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
688// | RX config | reserved | JB nominal |
689// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
690// | JB maximum | JB abs max |
691// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
692
693void CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem>& metrics,
694 uint8_t* buffer,
695 size_t* pos) {
696 const uint16_t kBlockLength = 8;
697 for (std::vector<RTCPPacketXRVOIPMetricItem>::const_iterator it =
698 metrics.begin(); it != metrics.end(); ++it) {
699 CreateXrBlockHeader(kBtVoipMetric, kBlockLength, buffer, pos);
700 AssignUWord32(buffer, pos, (*it).SSRC);
701 AssignUWord8(buffer, pos, (*it).lossRate);
702 AssignUWord8(buffer, pos, (*it).discardRate);
703 AssignUWord8(buffer, pos, (*it).burstDensity);
704 AssignUWord8(buffer, pos, (*it).gapDensity);
705 AssignUWord16(buffer, pos, (*it).burstDuration);
706 AssignUWord16(buffer, pos, (*it).gapDuration);
707 AssignUWord16(buffer, pos, (*it).roundTripDelay);
708 AssignUWord16(buffer, pos, (*it).endSystemDelay);
709 AssignUWord8(buffer, pos, (*it).signalLevel);
710 AssignUWord8(buffer, pos, (*it).noiseLevel);
711 AssignUWord8(buffer, pos, (*it).RERL);
712 AssignUWord8(buffer, pos, (*it).Gmin);
713 AssignUWord8(buffer, pos, (*it).Rfactor);
714 AssignUWord8(buffer, pos, (*it).extRfactor);
715 AssignUWord8(buffer, pos, (*it).MOSLQ);
716 AssignUWord8(buffer, pos, (*it).MOSCQ);
717 AssignUWord8(buffer, pos, (*it).RXconfig);
718 AssignUWord8(buffer, pos, 0);
719 AssignUWord16(buffer, pos, (*it).JBnominal);
720 AssignUWord16(buffer, pos, (*it).JBmax);
721 AssignUWord16(buffer, pos, (*it).JBabsMax);
722 }
723}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000724} // namespace
725
726void RtcpPacket::Append(RtcpPacket* packet) {
727 assert(packet);
728 appended_packets_.push_back(packet);
729}
730
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200731rtc::scoped_ptr<RawPacket> RtcpPacket::Build() const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000732 size_t length = 0;
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200733 rtc::scoped_ptr<RawPacket> packet(new RawPacket(IP_PACKET_SIZE));
734
735 class PacketVerifier : public PacketReadyCallback {
736 public:
737 explicit PacketVerifier(RawPacket* packet)
738 : called_(false), packet_(packet) {}
739 virtual ~PacketVerifier() {}
740 void OnPacketReady(uint8_t* data, size_t length) override {
741 CHECK(!called_) << "Fragmentation not supported.";
742 called_ = true;
743 packet_->SetLength(length);
744 }
745
746 private:
747 bool called_;
748 RawPacket* const packet_;
749 } verifier(packet.get());
750 CreateAndAddAppended(packet->MutableBuffer(), &length, packet->BufferLength(),
751 &verifier);
752 OnBufferFull(packet->MutableBuffer(), &length, &verifier);
753 return packet;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000754}
755
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200756bool RtcpPacket::Build(PacketReadyCallback* callback) const {
757 uint8_t buffer[IP_PACKET_SIZE];
758 return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000759}
760
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200761bool RtcpPacket::BuildExternalBuffer(uint8_t* buffer,
762 size_t max_length,
763 PacketReadyCallback* callback) const {
764 size_t index = 0;
765 if (!CreateAndAddAppended(buffer, &index, max_length, callback))
766 return false;
767 return OnBufferFull(buffer, &index, callback);
768}
769
770bool RtcpPacket::CreateAndAddAppended(uint8_t* packet,
771 size_t* index,
772 size_t max_length,
773 PacketReadyCallback* callback) const {
774 if (!Create(packet, index, max_length, callback))
775 return false;
776 for (RtcpPacket* appended : appended_packets_) {
777 if (!appended->CreateAndAddAppended(packet, index, max_length, callback))
778 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000779 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200780 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000781}
782
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200783bool RtcpPacket::OnBufferFull(uint8_t* packet,
784 size_t* index,
785 RtcpPacket::PacketReadyCallback* callback) const {
786 if (*index == 0)
787 return false;
788 callback->OnPacketReady(packet, *index);
789 *index = 0;
790 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000791}
792
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200793bool Empty::Create(uint8_t* packet,
794 size_t* index,
795 size_t max_length,
796 RtcpPacket::PacketReadyCallback* callback) const {
797 return true;
798}
799
800bool SenderReport::Create(uint8_t* packet,
801 size_t* index,
802 size_t max_length,
803 RtcpPacket::PacketReadyCallback* callback) const {
804 while (*index + BlockLength() > max_length) {
805 if (!OnBufferFull(packet, index, callback))
806 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000807 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200808 CreateSenderReport(sr_, BlockToHeaderLength(BlockLength()), packet, index);
809 CreateReportBlocks(report_blocks_, packet, index);
810 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000811}
812
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200813bool SenderReport::WithReportBlock(const ReportBlock& block) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000814 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000815 LOG(LS_WARNING) << "Max report blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200816 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000817 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200818 report_blocks_.push_back(block.report_block_);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000819 sr_.NumberOfReportBlocks = report_blocks_.size();
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200820 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000821}
822
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200823bool ReceiverReport::Create(uint8_t* packet,
824 size_t* index,
825 size_t max_length,
826 RtcpPacket::PacketReadyCallback* callback) const {
827 while (*index + BlockLength() > max_length) {
828 if (!OnBufferFull(packet, index, callback))
829 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000830 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200831 CreateReceiverReport(rr_, BlockToHeaderLength(BlockLength()), packet, index);
832 CreateReportBlocks(report_blocks_, packet, index);
833 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000834}
835
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200836bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000837 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000838 LOG(LS_WARNING) << "Max report blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200839 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000840 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200841 report_blocks_.push_back(block.report_block_);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000842 rr_.NumberOfReportBlocks = report_blocks_.size();
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200843 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000844}
845
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200846bool Ij::Create(uint8_t* packet,
847 size_t* index,
848 size_t max_length,
849 RtcpPacket::PacketReadyCallback* callback) const {
850 while (*index + BlockLength() > max_length) {
851 if (!OnBufferFull(packet, index, callback))
852 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000853 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200854 CreateIj(ij_items_, packet, index);
855 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000856}
857
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200858bool Ij::WithJitterItem(uint32_t jitter) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000859 if (ij_items_.size() >= kMaxNumberOfIjItems) {
860 LOG(LS_WARNING) << "Max inter-arrival jitter items reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200861 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000862 }
863 ij_items_.push_back(jitter);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200864 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000865}
866
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200867bool Sdes::Create(uint8_t* packet,
868 size_t* index,
869 size_t max_length,
870 RtcpPacket::PacketReadyCallback* callback) const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000871 assert(!chunks_.empty());
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200872 while (*index + BlockLength() > max_length) {
873 if (!OnBufferFull(packet, index, callback))
874 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000875 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200876 CreateSdes(chunks_, BlockToHeaderLength(BlockLength()), packet, index);
877 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000878}
879
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200880bool Sdes::WithCName(uint32_t ssrc, const std::string& cname) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000881 assert(cname.length() <= 0xff);
882 if (chunks_.size() >= kMaxNumberOfChunks) {
883 LOG(LS_WARNING) << "Max SDES chunks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200884 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000885 }
886 // In each chunk, the list of items must be terminated by one or more null
887 // octets. The next chunk must start on a 32-bit boundary.
888 // CNAME (1 byte) | length (1 byte) | name | padding.
889 int null_octets = 4 - ((2 + cname.length()) % 4);
890 Chunk chunk;
891 chunk.ssrc = ssrc;
892 chunk.name = cname;
893 chunk.null_octets = null_octets;
894 chunks_.push_back(chunk);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200895 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000896}
897
898size_t Sdes::BlockLength() const {
899 // Header (4 bytes).
900 // Chunk:
901 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
902 size_t length = kHeaderLength;
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200903 for (const Chunk& chunk : chunks_)
904 length += 6 + chunk.name.length() + chunk.null_octets;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000905 assert(length % 4 == 0);
906 return length;
907}
908
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200909bool Bye::Create(uint8_t* packet,
910 size_t* index,
911 size_t max_length,
912 RtcpPacket::PacketReadyCallback* callback) const {
913 while (*index + BlockLength() > max_length) {
914 if (!OnBufferFull(packet, index, callback))
915 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000916 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200917 CreateBye(bye_, csrcs_, BlockToHeaderLength(BlockLength()), packet, index);
918 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000919}
920
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200921bool Bye::WithCsrc(uint32_t csrc) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000922 if (csrcs_.size() >= kMaxNumberOfCsrcs) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000923 LOG(LS_WARNING) << "Max CSRC size reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200924 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000925 }
926 csrcs_.push_back(csrc);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200927 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000928}
929
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200930bool App::Create(uint8_t* packet,
931 size_t* index,
932 size_t max_length,
933 RtcpPacket::PacketReadyCallback* callback) const {
934 while (*index + BlockLength() > max_length) {
935 if (!OnBufferFull(packet, index, callback))
936 return false;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000937 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200938 CreateApp(app_, ssrc_, BlockToHeaderLength(BlockLength()), packet, index);
939 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000940}
941
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200942bool Pli::Create(uint8_t* packet,
943 size_t* index,
944 size_t max_length,
945 RtcpPacket::PacketReadyCallback* callback) const {
946 while (*index + BlockLength() > max_length) {
947 if (!OnBufferFull(packet, index, callback))
948 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000949 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200950 CreatePli(pli_, BlockToHeaderLength(BlockLength()), packet, index);
951 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000952}
953
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200954bool Sli::Create(uint8_t* packet,
955 size_t* index,
956 size_t max_length,
957 RtcpPacket::PacketReadyCallback* callback) const {
958 while (*index + BlockLength() > max_length) {
959 if (!OnBufferFull(packet, index, callback))
960 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000961 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200962 CreateSli(sli_, sli_item_, BlockToHeaderLength(BlockLength()), packet, index);
963 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000964}
965
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200966bool Nack::Create(uint8_t* packet,
967 size_t* index,
968 size_t max_length,
969 RtcpPacket::PacketReadyCallback* callback) const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000970 assert(!nack_fields_.empty());
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200971 // If nack list can't fit in packet, try to fragment.
972 size_t nack_index = 0;
973 do {
974 size_t bytes_left_in_buffer = max_length - *index;
975 if (bytes_left_in_buffer < kCommonFbFmtLength + 4) {
976 if (!OnBufferFull(packet, index, callback))
977 return false;
978 continue;
979 }
980 int64_t num_nack_fields =
981 std::min((bytes_left_in_buffer - kCommonFbFmtLength) / 4,
982 nack_fields_.size() - nack_index);
983
984 CreateNack(nack_, nack_fields_, nack_index, nack_index + num_nack_fields,
985 BlockToHeaderLength((num_nack_fields * 4) + kCommonFbFmtLength),
986 packet, index);
987
988 nack_index += num_nack_fields;
989 } while (nack_index < nack_fields_.size());
990
991 return true;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000992}
993
994void Nack::WithList(const uint16_t* nack_list, int length) {
995 assert(nack_list);
996 assert(nack_fields_.empty());
997 int i = 0;
998 while (i < length) {
999 uint16_t pid = nack_list[i++];
1000 // Bitmask specifies losses in any of the 16 packets following the pid.
1001 uint16_t bitmask = 0;
1002 while (i < length) {
1003 int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1;
1004 if (shift >= 0 && shift <= 15) {
1005 bitmask |= (1 << shift);
1006 ++i;
1007 } else {
1008 break;
1009 }
1010 }
1011 RTCPUtility::RTCPPacketRTPFBNACKItem item;
1012 item.PacketID = pid;
1013 item.BitMask = bitmask;
1014 nack_fields_.push_back(item);
1015 }
1016}
1017
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001018bool Rpsi::Create(uint8_t* packet,
1019 size_t* index,
1020 size_t max_length,
1021 RtcpPacket::PacketReadyCallback* callback) const {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001022 assert(rpsi_.NumberOfValidBits > 0);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001023 while (*index + BlockLength() > max_length) {
1024 if (!OnBufferFull(packet, index, callback))
1025 return false;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001026 }
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +00001027 CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(BlockLength()), packet,
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001028 index);
1029 return true;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001030}
1031
1032void Rpsi::WithPictureId(uint64_t picture_id) {
1033 const uint32_t kPidBits = 7;
fbarchard@google.comc891fee2014-08-12 22:39:06 +00001034 const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001035 uint8_t required_bytes = 0;
1036 uint64_t shifted_pid = picture_id;
1037 do {
1038 ++required_bytes;
1039 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
1040 } while (shifted_pid > 0);
1041
1042 // Convert picture id to native bit string (natively defined by the video
1043 // codec).
1044 int pos = 0;
1045 for (int i = required_bytes - 1; i > 0; i--) {
1046 rpsi_.NativeBitString[pos++] =
1047 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
1048 }
1049 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
1050 rpsi_.NumberOfValidBits = pos * 8;
1051
1052 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
1053 padding_bytes_ = 4 - ((2 + required_bytes) % 4);
1054 if (padding_bytes_ == 4) {
1055 padding_bytes_ = 0;
1056 }
1057}
1058
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001059bool Fir::Create(uint8_t* packet,
1060 size_t* index,
1061 size_t max_length,
1062 RtcpPacket::PacketReadyCallback* callback) const {
1063 while (*index + BlockLength() > max_length) {
1064 if (!OnBufferFull(packet, index, callback))
1065 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001066 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001067 CreateFir(fir_, fir_item_, BlockToHeaderLength(BlockLength()), packet, index);
1068 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001069}
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001070
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001071bool Remb::Create(uint8_t* packet,
1072 size_t* index,
1073 size_t max_length,
1074 RtcpPacket::PacketReadyCallback* callback) const {
1075 while (*index + BlockLength() > max_length) {
1076 if (!OnBufferFull(packet, index, callback))
1077 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001078 }
1079 CreateRemb(remb_, remb_item_, BlockToHeaderLength(BlockLength()), packet,
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001080 index);
1081 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001082}
1083
1084void Remb::AppliesTo(uint32_t ssrc) {
1085 if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) {
1086 LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached.";
1087 return;
1088 }
1089 remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc;
1090}
1091
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001092bool Tmmbr::Create(uint8_t* packet,
1093 size_t* index,
1094 size_t max_length,
1095 RtcpPacket::PacketReadyCallback* callback) const {
1096 while (*index + BlockLength() > max_length) {
1097 if (!OnBufferFull(packet, index, callback))
1098 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001099 }
1100 CreateTmmbr(tmmbr_, tmmbr_item_, BlockToHeaderLength(BlockLength()), packet,
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001101 index);
1102 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001103}
1104
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001105bool Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001106 assert(overhead <= 0x1ff);
1107 if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) {
1108 LOG(LS_WARNING) << "Max TMMBN size reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001109 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001110 }
1111 RTCPPacketRTPFBTMMBRItem tmmbn_item;
1112 tmmbn_item.SSRC = ssrc;
1113 tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps;
1114 tmmbn_item.MeasuredOverhead = overhead;
1115 tmmbn_items_.push_back(tmmbn_item);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001116 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001117}
1118
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001119bool Tmmbn::Create(uint8_t* packet,
1120 size_t* index,
1121 size_t max_length,
1122 RtcpPacket::PacketReadyCallback* callback) const {
1123 while (*index + BlockLength() > max_length) {
1124 if (!OnBufferFull(packet, index, callback))
1125 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001126 }
1127 CreateTmmbn(tmmbn_, tmmbn_items_, BlockToHeaderLength(BlockLength()), packet,
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001128 index);
1129 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001130}
1131
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001132bool Xr::Create(uint8_t* packet,
1133 size_t* index,
1134 size_t max_length,
1135 RtcpPacket::PacketReadyCallback* callback) const {
1136 while (*index + BlockLength() > max_length) {
1137 if (!OnBufferFull(packet, index, callback))
1138 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001139 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001140 CreateXrHeader(xr_header_, BlockToHeaderLength(BlockLength()), packet, index);
1141 CreateRrtr(rrtr_blocks_, packet, index);
1142 CreateDlrr(dlrr_blocks_, packet, index);
1143 CreateVoipMetric(voip_metric_blocks_, packet, index);
1144 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001145}
1146
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001147bool Xr::WithRrtr(Rrtr* rrtr) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001148 assert(rrtr);
1149 if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) {
1150 LOG(LS_WARNING) << "Max RRTR blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001151 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001152 }
1153 rrtr_blocks_.push_back(rrtr->rrtr_block_);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001154 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001155}
1156
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001157bool Xr::WithDlrr(Dlrr* dlrr) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001158 assert(dlrr);
1159 if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) {
1160 LOG(LS_WARNING) << "Max DLRR blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001161 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001162 }
1163 dlrr_blocks_.push_back(dlrr->dlrr_block_);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001164 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001165}
1166
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001167bool Xr::WithVoipMetric(VoipMetric* voip_metric) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001168 assert(voip_metric);
1169 if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) {
1170 LOG(LS_WARNING) << "Max Voip Metric blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001171 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001172 }
1173 voip_metric_blocks_.push_back(voip_metric->metric_);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001174 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001175}
1176
1177size_t Xr::DlrrLength() const {
1178 const size_t kBlockHeaderLen = 4;
1179 const size_t kSubBlockLen = 12;
1180 size_t length = 0;
1181 for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin();
1182 it != dlrr_blocks_.end(); ++it) {
1183 if (!(*it).empty()) {
1184 length += kBlockHeaderLen + kSubBlockLen * (*it).size();
1185 }
1186 }
1187 return length;
1188}
1189
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001190bool Dlrr::WithDlrrItem(uint32_t ssrc,
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001191 uint32_t last_rr,
1192 uint32_t delay_last_rr) {
1193 if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) {
1194 LOG(LS_WARNING) << "Max DLRR items reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001195 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001196 }
1197 RTCPPacketXRDLRRReportBlockItem dlrr;
1198 dlrr.SSRC = ssrc;
1199 dlrr.LastRR = last_rr;
1200 dlrr.DelayLastRR = delay_last_rr;
1201 dlrr_block_.push_back(dlrr);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001202 return true;
1203}
1204
1205RawPacket::RawPacket(size_t buffer_length)
1206 : buffer_length_(buffer_length), length_(0) {
1207 buffer_.reset(new uint8_t[buffer_length]);
1208}
1209
1210RawPacket::RawPacket(const uint8_t* packet, size_t packet_length)
1211 : buffer_length_(packet_length), length_(packet_length) {
1212 buffer_.reset(new uint8_t[packet_length]);
1213 memcpy(buffer_.get(), packet, packet_length);
1214}
1215
1216const uint8_t* RawPacket::Buffer() const {
1217 return buffer_.get();
1218}
1219
1220uint8_t* RawPacket::MutableBuffer() {
1221 return buffer_.get();
1222}
1223
1224size_t RawPacket::BufferLength() const {
1225 return buffer_length_;
1226}
1227
1228size_t RawPacket::Length() const {
1229 return length_;
1230}
1231
1232void RawPacket::SetLength(size_t length) {
1233 assert(length <= buffer_length_);
1234 length_ = length;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001235}
1236
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001237} // namespace rtcp
1238} // namespace webrtc