blob: 8cb6fb0833644077c3aed6f60475b56e9f23b2cc [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.orga8260062014-05-20 09:53:51 +000095// Sender report (SR) (RFC 3550).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000096// 0 1 2 3
97// 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
98// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99// |V=2|P| RC | PT=SR=200 | length |
100// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101// | SSRC of sender |
102// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
103// | NTP timestamp, most significant word |
104// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105// | NTP timestamp, least significant word |
106// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107// | RTP timestamp |
108// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109// | sender's packet count |
110// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111// | sender's octet count |
112// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
113
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000114void CreateSenderReport(const RTCPPacketSR& sr,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000115 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000116 size_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000117 AssignUWord32(buffer, pos, sr.SenderSSRC);
118 AssignUWord32(buffer, pos, sr.NTPMostSignificant);
119 AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
120 AssignUWord32(buffer, pos, sr.RTPTimestamp);
121 AssignUWord32(buffer, pos, sr.SenderPacketCount);
122 AssignUWord32(buffer, pos, sr.SenderOctetCount);
123}
124
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000125// Receiver report (RR), header (RFC 3550).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000126//
127// 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
128// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129// |V=2|P| RC | PT=RR=201 | length |
130// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131// | SSRC of packet sender |
132// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
133
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000134void CreateReceiverReport(const RTCPPacketRR& rr,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000135 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000136 size_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000137 AssignUWord32(buffer, pos, rr.SenderSSRC);
138}
139
140// Report block (RFC 3550).
141//
142// 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
143// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
144// | SSRC_1 (SSRC of first source) |
145// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146// | fraction lost | cumulative number of packets lost |
147// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
148// | extended highest sequence number received |
149// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
150// | interarrival jitter |
151// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152// | last SR (LSR) |
153// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154// | delay since last SR (DLSR) |
155// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
156
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000157void CreateReportBlocks(const std::vector<RTCPPacketReportBlockItem>& blocks,
158 uint8_t* buffer,
159 size_t* pos) {
160 for (std::vector<RTCPPacketReportBlockItem>::const_iterator
161 it = blocks.begin(); it != blocks.end(); ++it) {
162 AssignUWord32(buffer, pos, (*it).SSRC);
163 AssignUWord8(buffer, pos, (*it).FractionLost);
164 AssignUWord24(buffer, pos, (*it).CumulativeNumOfPacketsLost);
165 AssignUWord32(buffer, pos, (*it).ExtendedHighestSequenceNumber);
166 AssignUWord32(buffer, pos, (*it).Jitter);
167 AssignUWord32(buffer, pos, (*it).LastSR);
168 AssignUWord32(buffer, pos, (*it).DelayLastSR);
169 }
170}
171
172// Transmission Time Offsets in RTP Streams (RFC 5450).
173//
174// 0 1 2 3
175// 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
176// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
177// hdr |V=2|P| RC | PT=IJ=195 | length |
178// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
179// | inter-arrival jitter |
180// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
181// . .
182// . .
183// . .
184// | inter-arrival jitter |
185// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
186
187void CreateIj(const std::vector<uint32_t>& ij_items,
188 uint8_t* buffer,
189 size_t* pos) {
Erik Språnga3b87692015-07-29 10:46:54 +0200190 for (uint32_t item : ij_items)
191 AssignUWord32(buffer, pos, item);
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000192}
193
194// Source Description (SDES) (RFC 3550).
195//
196// 0 1 2 3
197// 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
198// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
199// header |V=2|P| SC | PT=SDES=202 | length |
200// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
201// chunk | SSRC/CSRC_1 |
202// 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203// | SDES items |
204// | ... |
205// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
206// chunk | SSRC/CSRC_2 |
207// 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
208// | SDES items |
209// | ... |
210// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
211//
212// Canonical End-Point Identifier SDES Item (CNAME)
213//
214// 0 1 2 3
215// 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
216// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
217// | CNAME=1 | length | user and domain name ...
218// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
219
220void CreateSdes(const std::vector<Sdes::Chunk>& chunks,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000221 uint8_t* buffer,
222 size_t* pos) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000223 const uint8_t kSdesItemType = 1;
224 for (std::vector<Sdes::Chunk>::const_iterator it = chunks.begin();
225 it != chunks.end(); ++it) {
226 AssignUWord32(buffer, pos, (*it).ssrc);
227 AssignUWord8(buffer, pos, kSdesItemType);
228 AssignUWord8(buffer, pos, (*it).name.length());
229 memcpy(buffer + *pos, (*it).name.data(), (*it).name.length());
230 *pos += (*it).name.length();
231 memset(buffer + *pos, 0, (*it).null_octets);
232 *pos += (*it).null_octets;
233 }
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000234}
235
236// Bye packet (BYE) (RFC 3550).
237//
238// 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
239// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
240// |V=2|P| SC | PT=BYE=203 | length |
241// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
242// | SSRC/CSRC |
243// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
244// : ... :
245// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
246// (opt) | length | reason for leaving ...
247// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
248
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000249void CreateBye(const RTCPPacketBYE& bye,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000250 const std::vector<uint32_t>& csrcs,
251 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000252 size_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000253 AssignUWord32(buffer, pos, bye.SenderSSRC);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200254 for (uint32_t csrc : csrcs)
255 AssignUWord32(buffer, pos, csrc);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000256}
257
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000258// Application-Defined packet (APP) (RFC 3550).
259//
260// 0 1 2 3
261// 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
262// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
263// |V=2|P| subtype | PT=APP=204 | length |
264// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
265// | SSRC/CSRC |
266// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
267// | name (ASCII) |
268// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
269// | application-dependent data ...
270// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
271
272void CreateApp(const RTCPPacketAPP& app,
273 uint32_t ssrc,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000274 uint8_t* buffer,
275 size_t* pos) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000276 AssignUWord32(buffer, pos, ssrc);
277 AssignUWord32(buffer, pos, app.Name);
278 memcpy(buffer + *pos, app.Data, app.Size);
279 *pos += app.Size;
280}
281
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000282// RFC 4585: Feedback format.
283//
284// Common packet format:
285//
286// 0 1 2 3
287// 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
288// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
289// |V=2|P| FMT | PT | length |
290// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
291// | SSRC of packet sender |
292// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
293// | SSRC of media source |
294// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
295// : Feedback Control Information (FCI) :
296// :
297//
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000298
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000299// Picture loss indication (PLI) (RFC 4585).
300//
301// FCI: no feedback control information.
302
303void CreatePli(const RTCPPacketPSFBPLI& pli,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000304 uint8_t* buffer,
305 size_t* pos) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000306 AssignUWord32(buffer, pos, pli.SenderSSRC);
307 AssignUWord32(buffer, pos, pli.MediaSSRC);
308}
309
310// Slice loss indication (SLI) (RFC 4585).
311//
312// FCI:
313//
314// 0 1 2 3
315// 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
316// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
317// | First | Number | PictureID |
318// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
319
320void CreateSli(const RTCPPacketPSFBSLI& sli,
321 const RTCPPacketPSFBSLIItem& sli_item,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000322 uint8_t* buffer,
323 size_t* pos) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000324 AssignUWord32(buffer, pos, sli.SenderSSRC);
325 AssignUWord32(buffer, pos, sli.MediaSSRC);
326
327 AssignUWord8(buffer, pos, sli_item.FirstMB >> 5);
328 AssignUWord8(buffer, pos, (sli_item.FirstMB << 3) +
329 ((sli_item.NumberOfMB >> 10) & 0x07));
330 AssignUWord8(buffer, pos, sli_item.NumberOfMB >> 2);
331 AssignUWord8(buffer, pos, (sli_item.NumberOfMB << 6) + sli_item.PictureId);
332}
333
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000334// Generic NACK (RFC 4585).
335//
336// FCI:
337//
338// 0 1 2 3
339// 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
340// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
341// | PID | BLP |
342// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
343
344void CreateNack(const RTCPPacketRTPFBNACK& nack,
345 const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200346 size_t start_index,
347 size_t end_index,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000348 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000349 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000350 AssignUWord32(buffer, pos, nack.SenderSSRC);
351 AssignUWord32(buffer, pos, nack.MediaSSRC);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200352 for (size_t i = start_index; i < end_index; ++i) {
353 const RTCPPacketRTPFBNACKItem& nack_item = nack_fields[i];
354 AssignUWord16(buffer, pos, nack_item.PacketID);
355 AssignUWord16(buffer, pos, nack_item.BitMask);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000356 }
357}
358
359// Reference picture selection indication (RPSI) (RFC 4585).
360//
361// FCI:
362//
363// 0 1 2 3
364// 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
365// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
366// | PB |0| Payload Type| Native RPSI bit string |
367// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
368// | defined per codec ... | Padding (0) |
369// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
370
371void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
372 uint8_t padding_bytes,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000373 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000374 size_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000375 // Native bit string should be a multiple of 8 bits.
376 assert(rpsi.NumberOfValidBits % 8 == 0);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000377 AssignUWord32(buffer, pos, rpsi.SenderSSRC);
378 AssignUWord32(buffer, pos, rpsi.MediaSSRC);
379 AssignUWord8(buffer, pos, padding_bytes * 8);
380 AssignUWord8(buffer, pos, rpsi.PayloadType);
381 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
382 *pos += rpsi.NumberOfValidBits / 8;
383 memset(buffer + *pos, 0, padding_bytes);
384 *pos += padding_bytes;
385}
386
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000387// Full intra request (FIR) (RFC 5104).
388//
389// FCI:
390//
391// 0 1 2 3
392// 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
393// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
394// | SSRC |
395// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
396// | Seq nr. | Reserved |
397// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
398
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000399void CreateFir(const RTCPPacketPSFBFIR& fir,
400 const RTCPPacketPSFBFIRItem& fir_item,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000401 uint8_t* buffer,
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000402 size_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000403 AssignUWord32(buffer, pos, fir.SenderSSRC);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000404 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000405 AssignUWord32(buffer, pos, fir_item.SSRC);
406 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
407 AssignUWord24(buffer, pos, 0);
408}
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000409
410void CreateTmmbrItem(const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
411 uint8_t* buffer,
412 size_t* pos) {
413 uint32_t bitrate_bps = tmmbr_item.MaxTotalMediaBitRate * 1000;
414 uint32_t mantissa = 0;
415 uint8_t exp = 0;
416 ComputeMantissaAnd6bitBase2Exponent(bitrate_bps, 17, &mantissa, &exp);
417
418 AssignUWord32(buffer, pos, tmmbr_item.SSRC);
419 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 15) & 0x03));
420 AssignUWord8(buffer, pos, mantissa >> 7);
421 AssignUWord8(buffer, pos, (mantissa << 1) +
422 ((tmmbr_item.MeasuredOverhead >> 8) & 0x01));
423 AssignUWord8(buffer, pos, tmmbr_item.MeasuredOverhead);
424}
425
426// Temporary Maximum Media Stream Bit Rate Request (TMMBR) (RFC 5104).
427//
428// FCI:
429//
430// 0 1 2 3
431// 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
432// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
433// | SSRC |
434// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
435// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
436// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
437
438void CreateTmmbr(const RTCPPacketRTPFBTMMBR& tmmbr,
439 const RTCPPacketRTPFBTMMBRItem& tmmbr_item,
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000440 uint8_t* buffer,
441 size_t* pos) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000442 AssignUWord32(buffer, pos, tmmbr.SenderSSRC);
443 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
444 CreateTmmbrItem(tmmbr_item, buffer, pos);
445}
446
447// Temporary Maximum Media Stream Bit Rate Notification (TMMBN) (RFC 5104).
448//
449// FCI:
450//
451// 0 1 2 3
452// 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
453// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
454// | SSRC |
455// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
456// | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
457// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458
459void CreateTmmbn(const RTCPPacketRTPFBTMMBN& tmmbn,
460 const std::vector<RTCPPacketRTPFBTMMBRItem>& tmmbn_items,
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000461 uint8_t* buffer,
462 size_t* pos) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000463 AssignUWord32(buffer, pos, tmmbn.SenderSSRC);
464 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
465 for (uint8_t i = 0; i < tmmbn_items.size(); ++i) {
466 CreateTmmbrItem(tmmbn_items[i], buffer, pos);
467 }
468}
469
470// Receiver Estimated Max Bitrate (REMB) (draft-alvestrand-rmcat-remb).
471//
472// 0 1 2 3
473// 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
474// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
475// |V=2|P| FMT=15 | PT=206 | length |
476// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
477// | SSRC of packet sender |
478// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
479// | SSRC of media source |
480// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
481// | Unique identifier 'R' 'E' 'M' 'B' |
482// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
483// | Num SSRC | BR Exp | BR Mantissa |
484// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
485// | SSRC feedback |
486// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
487// | ... |
488
489void CreateRemb(const RTCPPacketPSFBAPP& remb,
490 const RTCPPacketPSFBREMBItem& remb_item,
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000491 uint8_t* buffer,
492 size_t* pos) {
493 uint32_t mantissa = 0;
494 uint8_t exp = 0;
495 ComputeMantissaAnd6bitBase2Exponent(remb_item.BitRate, 18, &mantissa, &exp);
496
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000497 AssignUWord32(buffer, pos, remb.SenderSSRC);
498 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
499 AssignUWord8(buffer, pos, 'R');
500 AssignUWord8(buffer, pos, 'E');
501 AssignUWord8(buffer, pos, 'M');
502 AssignUWord8(buffer, pos, 'B');
503 AssignUWord8(buffer, pos, remb_item.NumberOfSSRCs);
504 AssignUWord8(buffer, pos, (exp << 2) + ((mantissa >> 16) & 0x03));
505 AssignUWord8(buffer, pos, mantissa >> 8);
506 AssignUWord8(buffer, pos, mantissa);
507 for (uint8_t i = 0; i < remb_item.NumberOfSSRCs; ++i) {
508 AssignUWord32(buffer, pos, remb_item.SSRCs[i]);
509 }
510}
511
512// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
513//
514// Format for XR packets:
515//
516// 0 1 2 3
517// 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
518// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519// |V=2|P|reserved | PT=XR=207 | length |
520// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521// | SSRC |
522// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523// : report blocks :
524// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525
526void CreateXrHeader(const RTCPPacketXR& header,
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000527 uint8_t* buffer,
528 size_t* pos) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +0000529 AssignUWord32(buffer, pos, header.OriginatorSSRC);
530}
531
532void CreateXrBlockHeader(uint8_t block_type,
533 uint16_t block_length,
534 uint8_t* buffer,
535 size_t* pos) {
536 AssignUWord8(buffer, pos, block_type);
537 AssignUWord8(buffer, pos, 0);
538 AssignUWord16(buffer, pos, block_length);
539}
540
541// Receiver Reference Time Report Block (RFC 3611).
542//
543// 0 1 2 3
544// 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
545// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546// | BT=4 | reserved | block length = 2 |
547// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
548// | NTP timestamp, most significant word |
549// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
550// | NTP timestamp, least significant word |
551// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
552
553void CreateRrtr(const std::vector<RTCPPacketXRReceiverReferenceTimeItem>& rrtrs,
554 uint8_t* buffer,
555 size_t* pos) {
556 const uint16_t kBlockLength = 2;
557 for (std::vector<RTCPPacketXRReceiverReferenceTimeItem>::const_iterator it =
558 rrtrs.begin(); it != rrtrs.end(); ++it) {
559 CreateXrBlockHeader(kBtReceiverReferenceTime, kBlockLength, buffer, pos);
560 AssignUWord32(buffer, pos, (*it).NTPMostSignificant);
561 AssignUWord32(buffer, pos, (*it).NTPLeastSignificant);
562 }
563}
564
565// DLRR Report Block (RFC 3611).
566//
567// 0 1 2 3
568// 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
569// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
570// | BT=5 | reserved | block length |
571// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
572// | SSRC_1 (SSRC of first receiver) | sub-
573// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
574// | last RR (LRR) | 1
575// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
576// | delay since last RR (DLRR) |
577// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
578// | SSRC_2 (SSRC of second receiver) | sub-
579// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
580// : ... : 2
581
582void CreateDlrr(const std::vector<Xr::DlrrBlock>& dlrrs,
583 uint8_t* buffer,
584 size_t* pos) {
585 for (std::vector<Xr::DlrrBlock>::const_iterator it = dlrrs.begin();
586 it != dlrrs.end(); ++it) {
587 if ((*it).empty()) {
588 continue;
589 }
590 uint16_t block_length = 3 * (*it).size();
591 CreateXrBlockHeader(kBtDlrr, block_length, buffer, pos);
592 for (Xr::DlrrBlock::const_iterator it_block = (*it).begin();
593 it_block != (*it).end(); ++it_block) {
594 AssignUWord32(buffer, pos, (*it_block).SSRC);
595 AssignUWord32(buffer, pos, (*it_block).LastRR);
596 AssignUWord32(buffer, pos, (*it_block).DelayLastRR);
597 }
598 }
599}
600
601// VoIP Metrics Report Block (RFC 3611).
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// | BT=7 | reserved | block length = 8 |
607// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
608// | SSRC of source |
609// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
610// | loss rate | discard rate | burst density | gap density |
611// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
612// | burst duration | gap duration |
613// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
614// | round trip delay | end system delay |
615// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
616// | signal level | noise level | RERL | Gmin |
617// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
618// | R factor | ext. R factor | MOS-LQ | MOS-CQ |
619// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
620// | RX config | reserved | JB nominal |
621// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
622// | JB maximum | JB abs max |
623// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
624
625void CreateVoipMetric(const std::vector<RTCPPacketXRVOIPMetricItem>& metrics,
626 uint8_t* buffer,
627 size_t* pos) {
628 const uint16_t kBlockLength = 8;
629 for (std::vector<RTCPPacketXRVOIPMetricItem>::const_iterator it =
630 metrics.begin(); it != metrics.end(); ++it) {
631 CreateXrBlockHeader(kBtVoipMetric, kBlockLength, buffer, pos);
632 AssignUWord32(buffer, pos, (*it).SSRC);
633 AssignUWord8(buffer, pos, (*it).lossRate);
634 AssignUWord8(buffer, pos, (*it).discardRate);
635 AssignUWord8(buffer, pos, (*it).burstDensity);
636 AssignUWord8(buffer, pos, (*it).gapDensity);
637 AssignUWord16(buffer, pos, (*it).burstDuration);
638 AssignUWord16(buffer, pos, (*it).gapDuration);
639 AssignUWord16(buffer, pos, (*it).roundTripDelay);
640 AssignUWord16(buffer, pos, (*it).endSystemDelay);
641 AssignUWord8(buffer, pos, (*it).signalLevel);
642 AssignUWord8(buffer, pos, (*it).noiseLevel);
643 AssignUWord8(buffer, pos, (*it).RERL);
644 AssignUWord8(buffer, pos, (*it).Gmin);
645 AssignUWord8(buffer, pos, (*it).Rfactor);
646 AssignUWord8(buffer, pos, (*it).extRfactor);
647 AssignUWord8(buffer, pos, (*it).MOSLQ);
648 AssignUWord8(buffer, pos, (*it).MOSCQ);
649 AssignUWord8(buffer, pos, (*it).RXconfig);
650 AssignUWord8(buffer, pos, 0);
651 AssignUWord16(buffer, pos, (*it).JBnominal);
652 AssignUWord16(buffer, pos, (*it).JBmax);
653 AssignUWord16(buffer, pos, (*it).JBabsMax);
654 }
655}
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000656} // namespace
657
658void RtcpPacket::Append(RtcpPacket* packet) {
659 assert(packet);
660 appended_packets_.push_back(packet);
661}
662
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200663rtc::scoped_ptr<RawPacket> RtcpPacket::Build() const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000664 size_t length = 0;
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200665 rtc::scoped_ptr<RawPacket> packet(new RawPacket(IP_PACKET_SIZE));
666
667 class PacketVerifier : public PacketReadyCallback {
668 public:
669 explicit PacketVerifier(RawPacket* packet)
670 : called_(false), packet_(packet) {}
671 virtual ~PacketVerifier() {}
672 void OnPacketReady(uint8_t* data, size_t length) override {
673 CHECK(!called_) << "Fragmentation not supported.";
674 called_ = true;
675 packet_->SetLength(length);
676 }
677
678 private:
679 bool called_;
680 RawPacket* const packet_;
681 } verifier(packet.get());
682 CreateAndAddAppended(packet->MutableBuffer(), &length, packet->BufferLength(),
683 &verifier);
684 OnBufferFull(packet->MutableBuffer(), &length, &verifier);
685 return packet;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000686}
687
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200688bool RtcpPacket::Build(PacketReadyCallback* callback) const {
689 uint8_t buffer[IP_PACKET_SIZE];
690 return BuildExternalBuffer(buffer, IP_PACKET_SIZE, callback);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000691}
692
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200693bool RtcpPacket::BuildExternalBuffer(uint8_t* buffer,
694 size_t max_length,
695 PacketReadyCallback* callback) const {
696 size_t index = 0;
697 if (!CreateAndAddAppended(buffer, &index, max_length, callback))
698 return false;
699 return OnBufferFull(buffer, &index, callback);
700}
701
702bool RtcpPacket::CreateAndAddAppended(uint8_t* packet,
703 size_t* index,
704 size_t max_length,
705 PacketReadyCallback* callback) const {
706 if (!Create(packet, index, max_length, callback))
707 return false;
708 for (RtcpPacket* appended : appended_packets_) {
709 if (!appended->CreateAndAddAppended(packet, index, max_length, callback))
710 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000711 }
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200712 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000713}
714
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200715bool RtcpPacket::OnBufferFull(uint8_t* packet,
716 size_t* index,
717 RtcpPacket::PacketReadyCallback* callback) const {
718 if (*index == 0)
719 return false;
720 callback->OnPacketReady(packet, *index);
721 *index = 0;
722 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000723}
724
Erik Språnga3b87692015-07-29 10:46:54 +0200725size_t RtcpPacket::HeaderLength() const {
726 size_t length_in_bytes = BlockLength();
727 // Length in 32-bit words minus 1.
728 assert(length_in_bytes > 0);
729 return ((length_in_bytes + 3) / 4) - 1;
730}
731
732// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
733//
734// RTP header format.
735// 0 1 2 3
736// 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
737// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
738// |V=2|P| RC/FMT | PT | length |
739// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740
741void RtcpPacket::CreateHeader(
742 uint8_t count_or_format, // Depends on packet type.
743 uint8_t packet_type,
744 size_t length,
745 uint8_t* buffer,
746 size_t* pos) const {
747 assert(length <= 0xffff);
748 const uint8_t kVersion = 2;
749 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
750 AssignUWord8(buffer, pos, packet_type);
751 AssignUWord16(buffer, pos, length);
752}
753
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200754bool Empty::Create(uint8_t* packet,
755 size_t* index,
756 size_t max_length,
757 RtcpPacket::PacketReadyCallback* callback) const {
758 return true;
759}
760
Erik Språnga3b87692015-07-29 10:46:54 +0200761size_t Empty::BlockLength() const {
762 return 0;
763}
764
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200765bool SenderReport::Create(uint8_t* packet,
766 size_t* index,
767 size_t max_length,
768 RtcpPacket::PacketReadyCallback* callback) const {
769 while (*index + BlockLength() > max_length) {
770 if (!OnBufferFull(packet, index, callback))
771 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000772 }
Erik Språnga3b87692015-07-29 10:46:54 +0200773 CreateHeader(sr_.NumberOfReportBlocks, PT_SR, HeaderLength(), packet, index);
774 CreateSenderReport(sr_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200775 CreateReportBlocks(report_blocks_, packet, index);
776 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000777}
778
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200779bool SenderReport::WithReportBlock(const ReportBlock& block) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000780 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000781 LOG(LS_WARNING) << "Max report blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200782 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000783 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200784 report_blocks_.push_back(block.report_block_);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000785 sr_.NumberOfReportBlocks = report_blocks_.size();
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200786 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000787}
788
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200789bool ReceiverReport::Create(uint8_t* packet,
790 size_t* index,
791 size_t max_length,
792 RtcpPacket::PacketReadyCallback* callback) const {
793 while (*index + BlockLength() > max_length) {
794 if (!OnBufferFull(packet, index, callback))
795 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000796 }
Erik Språnga3b87692015-07-29 10:46:54 +0200797 CreateHeader(rr_.NumberOfReportBlocks, PT_RR, HeaderLength(), packet, index);
798 CreateReceiverReport(rr_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200799 CreateReportBlocks(report_blocks_, packet, index);
800 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000801}
802
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200803bool ReceiverReport::WithReportBlock(const ReportBlock& block) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000804 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000805 LOG(LS_WARNING) << "Max report blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200806 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000807 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200808 report_blocks_.push_back(block.report_block_);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000809 rr_.NumberOfReportBlocks = report_blocks_.size();
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200810 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000811}
812
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200813bool Ij::Create(uint8_t* packet,
814 size_t* index,
815 size_t max_length,
816 RtcpPacket::PacketReadyCallback* callback) const {
817 while (*index + BlockLength() > max_length) {
818 if (!OnBufferFull(packet, index, callback))
819 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000820 }
Erik Språnga3b87692015-07-29 10:46:54 +0200821 size_t length = ij_items_.size();
822 CreateHeader(length, PT_IJ, length, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200823 CreateIj(ij_items_, packet, index);
824 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000825}
826
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200827bool Ij::WithJitterItem(uint32_t jitter) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000828 if (ij_items_.size() >= kMaxNumberOfIjItems) {
829 LOG(LS_WARNING) << "Max inter-arrival jitter items reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200830 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000831 }
832 ij_items_.push_back(jitter);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200833 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000834}
835
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200836bool Sdes::Create(uint8_t* packet,
837 size_t* index,
838 size_t max_length,
839 RtcpPacket::PacketReadyCallback* callback) const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000840 assert(!chunks_.empty());
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200841 while (*index + BlockLength() > max_length) {
842 if (!OnBufferFull(packet, index, callback))
843 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000844 }
Erik Språnga3b87692015-07-29 10:46:54 +0200845 CreateHeader(chunks_.size(), PT_SDES, HeaderLength(), packet, index);
846 CreateSdes(chunks_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200847 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000848}
849
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200850bool Sdes::WithCName(uint32_t ssrc, const std::string& cname) {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000851 assert(cname.length() <= 0xff);
852 if (chunks_.size() >= kMaxNumberOfChunks) {
853 LOG(LS_WARNING) << "Max SDES chunks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200854 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000855 }
856 // In each chunk, the list of items must be terminated by one or more null
857 // octets. The next chunk must start on a 32-bit boundary.
858 // CNAME (1 byte) | length (1 byte) | name | padding.
859 int null_octets = 4 - ((2 + cname.length()) % 4);
860 Chunk chunk;
861 chunk.ssrc = ssrc;
862 chunk.name = cname;
863 chunk.null_octets = null_octets;
864 chunks_.push_back(chunk);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200865 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000866}
867
868size_t Sdes::BlockLength() const {
869 // Header (4 bytes).
870 // Chunk:
871 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
872 size_t length = kHeaderLength;
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200873 for (const Chunk& chunk : chunks_)
874 length += 6 + chunk.name.length() + chunk.null_octets;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000875 assert(length % 4 == 0);
876 return length;
877}
878
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200879bool Bye::Create(uint8_t* packet,
880 size_t* index,
881 size_t max_length,
882 RtcpPacket::PacketReadyCallback* callback) const {
883 while (*index + BlockLength() > max_length) {
884 if (!OnBufferFull(packet, index, callback))
885 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000886 }
Erik Språnga3b87692015-07-29 10:46:54 +0200887 size_t length = HeaderLength();
888 CreateHeader(length, PT_BYE, length, packet, index);
889 CreateBye(bye_, csrcs_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200890 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000891}
892
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200893bool Bye::WithCsrc(uint32_t csrc) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000894 if (csrcs_.size() >= kMaxNumberOfCsrcs) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000895 LOG(LS_WARNING) << "Max CSRC size reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200896 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000897 }
898 csrcs_.push_back(csrc);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200899 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000900}
901
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200902bool App::Create(uint8_t* packet,
903 size_t* index,
904 size_t max_length,
905 RtcpPacket::PacketReadyCallback* callback) const {
906 while (*index + BlockLength() > max_length) {
907 if (!OnBufferFull(packet, index, callback))
908 return false;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000909 }
Erik Språnga3b87692015-07-29 10:46:54 +0200910 CreateHeader(app_.SubType, PT_APP, HeaderLength(), packet, index);
911 CreateApp(app_, ssrc_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200912 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000913}
914
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200915bool Pli::Create(uint8_t* packet,
916 size_t* index,
917 size_t max_length,
918 RtcpPacket::PacketReadyCallback* callback) const {
919 while (*index + BlockLength() > max_length) {
920 if (!OnBufferFull(packet, index, callback))
921 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000922 }
Erik Språnga3b87692015-07-29 10:46:54 +0200923 const uint8_t kFmt = 1;
924 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
925 CreatePli(pli_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200926 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000927}
928
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200929bool Sli::Create(uint8_t* packet,
930 size_t* index,
931 size_t max_length,
932 RtcpPacket::PacketReadyCallback* callback) const {
933 while (*index + BlockLength() > max_length) {
934 if (!OnBufferFull(packet, index, callback))
935 return false;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000936 }
Erik Språnga3b87692015-07-29 10:46:54 +0200937 const uint8_t kFmt = 2;
938 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
939 CreateSli(sli_, sli_item_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200940 return true;
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000941}
942
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200943bool Nack::Create(uint8_t* packet,
944 size_t* index,
945 size_t max_length,
946 RtcpPacket::PacketReadyCallback* callback) const {
asapersson@webrtc.org4b12d402014-06-16 14:09:28 +0000947 assert(!nack_fields_.empty());
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200948 // If nack list can't fit in packet, try to fragment.
949 size_t nack_index = 0;
950 do {
951 size_t bytes_left_in_buffer = max_length - *index;
952 if (bytes_left_in_buffer < kCommonFbFmtLength + 4) {
953 if (!OnBufferFull(packet, index, callback))
954 return false;
955 continue;
956 }
957 int64_t num_nack_fields =
958 std::min((bytes_left_in_buffer - kCommonFbFmtLength) / 4,
959 nack_fields_.size() - nack_index);
960
Erik Språnga3b87692015-07-29 10:46:54 +0200961 const uint8_t kFmt = 1;
962 size_t size_bytes = (num_nack_fields * 4) + kCommonFbFmtLength;
963 size_t header_length = ((size_bytes + 3) / 4) - 1; // As 32bit words - 1
964 CreateHeader(kFmt, PT_RTPFB, header_length, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200965 CreateNack(nack_, nack_fields_, nack_index, nack_index + num_nack_fields,
Erik Språngc1b9d4e2015-06-08 09:54:14 +0200966 packet, index);
967
968 nack_index += num_nack_fields;
969 } while (nack_index < nack_fields_.size());
970
971 return true;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000972}
973
Erik Språnga3b87692015-07-29 10:46:54 +0200974size_t Nack::BlockLength() const {
975 return (nack_fields_.size() * 4) + kCommonFbFmtLength;
976}
977
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000978void Nack::WithList(const uint16_t* nack_list, int length) {
979 assert(nack_list);
980 assert(nack_fields_.empty());
981 int i = 0;
982 while (i < length) {
983 uint16_t pid = nack_list[i++];
984 // Bitmask specifies losses in any of the 16 packets following the pid.
985 uint16_t bitmask = 0;
986 while (i < length) {
987 int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1;
988 if (shift >= 0 && shift <= 15) {
989 bitmask |= (1 << shift);
990 ++i;
991 } else {
992 break;
993 }
994 }
995 RTCPUtility::RTCPPacketRTPFBNACKItem item;
996 item.PacketID = pid;
997 item.BitMask = bitmask;
998 nack_fields_.push_back(item);
999 }
1000}
1001
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001002bool Rpsi::Create(uint8_t* packet,
1003 size_t* index,
1004 size_t max_length,
1005 RtcpPacket::PacketReadyCallback* callback) const {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001006 assert(rpsi_.NumberOfValidBits > 0);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001007 while (*index + BlockLength() > max_length) {
1008 if (!OnBufferFull(packet, index, callback))
1009 return false;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001010 }
Erik Språnga3b87692015-07-29 10:46:54 +02001011 const uint8_t kFmt = 3;
1012 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
1013 CreateRpsi(rpsi_, padding_bytes_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001014 return true;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001015}
1016
1017void Rpsi::WithPictureId(uint64_t picture_id) {
1018 const uint32_t kPidBits = 7;
fbarchard@google.comc891fee2014-08-12 22:39:06 +00001019 const uint64_t k7MsbZeroMask = 0x1ffffffffffffffULL;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +00001020 uint8_t required_bytes = 0;
1021 uint64_t shifted_pid = picture_id;
1022 do {
1023 ++required_bytes;
1024 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
1025 } while (shifted_pid > 0);
1026
1027 // Convert picture id to native bit string (natively defined by the video
1028 // codec).
1029 int pos = 0;
1030 for (int i = required_bytes - 1; i > 0; i--) {
1031 rpsi_.NativeBitString[pos++] =
1032 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
1033 }
1034 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
1035 rpsi_.NumberOfValidBits = pos * 8;
1036
1037 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
1038 padding_bytes_ = 4 - ((2 + required_bytes) % 4);
1039 if (padding_bytes_ == 4) {
1040 padding_bytes_ = 0;
1041 }
1042}
1043
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001044bool Fir::Create(uint8_t* packet,
1045 size_t* index,
1046 size_t max_length,
1047 RtcpPacket::PacketReadyCallback* callback) const {
1048 while (*index + BlockLength() > max_length) {
1049 if (!OnBufferFull(packet, index, callback))
1050 return false;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001051 }
Erik Språnga3b87692015-07-29 10:46:54 +02001052 const uint8_t kFmt = 4;
1053 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
1054 CreateFir(fir_, fir_item_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001055 return true;
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001056}
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001057
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001058bool Remb::Create(uint8_t* packet,
1059 size_t* index,
1060 size_t max_length,
1061 RtcpPacket::PacketReadyCallback* callback) const {
1062 while (*index + BlockLength() > max_length) {
1063 if (!OnBufferFull(packet, index, callback))
1064 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001065 }
Erik Språnga3b87692015-07-29 10:46:54 +02001066 const uint8_t kFmt = 15;
1067 CreateHeader(kFmt, PT_PSFB, HeaderLength(), packet, index);
1068 CreateRemb(remb_, remb_item_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001069 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001070}
1071
1072void Remb::AppliesTo(uint32_t ssrc) {
1073 if (remb_item_.NumberOfSSRCs >= kMaxNumberOfSsrcs) {
1074 LOG(LS_WARNING) << "Max number of REMB feedback SSRCs reached.";
1075 return;
1076 }
1077 remb_item_.SSRCs[remb_item_.NumberOfSSRCs++] = ssrc;
1078}
1079
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001080bool Tmmbr::Create(uint8_t* packet,
1081 size_t* index,
1082 size_t max_length,
1083 RtcpPacket::PacketReadyCallback* callback) const {
1084 while (*index + BlockLength() > max_length) {
1085 if (!OnBufferFull(packet, index, callback))
1086 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001087 }
Erik Språnga3b87692015-07-29 10:46:54 +02001088 const uint8_t kFmt = 3;
1089 CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index);
1090 CreateTmmbr(tmmbr_, tmmbr_item_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001091 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001092}
1093
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001094bool Tmmbn::WithTmmbr(uint32_t ssrc, uint32_t bitrate_kbps, uint16_t overhead) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001095 assert(overhead <= 0x1ff);
1096 if (tmmbn_items_.size() >= kMaxNumberOfTmmbrs) {
1097 LOG(LS_WARNING) << "Max TMMBN size reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001098 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001099 }
1100 RTCPPacketRTPFBTMMBRItem tmmbn_item;
1101 tmmbn_item.SSRC = ssrc;
1102 tmmbn_item.MaxTotalMediaBitRate = bitrate_kbps;
1103 tmmbn_item.MeasuredOverhead = overhead;
1104 tmmbn_items_.push_back(tmmbn_item);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001105 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001106}
1107
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001108bool Tmmbn::Create(uint8_t* packet,
1109 size_t* index,
1110 size_t max_length,
1111 RtcpPacket::PacketReadyCallback* callback) const {
1112 while (*index + BlockLength() > max_length) {
1113 if (!OnBufferFull(packet, index, callback))
1114 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001115 }
Erik Språnga3b87692015-07-29 10:46:54 +02001116 const uint8_t kFmt = 4;
1117 CreateHeader(kFmt, PT_RTPFB, HeaderLength(), packet, index);
1118 CreateTmmbn(tmmbn_, tmmbn_items_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001119 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001120}
1121
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001122bool Xr::Create(uint8_t* packet,
1123 size_t* index,
1124 size_t max_length,
1125 RtcpPacket::PacketReadyCallback* callback) const {
1126 while (*index + BlockLength() > max_length) {
1127 if (!OnBufferFull(packet, index, callback))
1128 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001129 }
Erik Språnga3b87692015-07-29 10:46:54 +02001130 CreateHeader(0U, PT_XR, HeaderLength(), packet, index);
1131 CreateXrHeader(xr_header_, packet, index);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001132 CreateRrtr(rrtr_blocks_, packet, index);
1133 CreateDlrr(dlrr_blocks_, packet, index);
1134 CreateVoipMetric(voip_metric_blocks_, packet, index);
1135 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001136}
1137
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001138bool Xr::WithRrtr(Rrtr* rrtr) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001139 assert(rrtr);
1140 if (rrtr_blocks_.size() >= kMaxNumberOfRrtrBlocks) {
1141 LOG(LS_WARNING) << "Max RRTR blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001142 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001143 }
1144 rrtr_blocks_.push_back(rrtr->rrtr_block_);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001145 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001146}
1147
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001148bool Xr::WithDlrr(Dlrr* dlrr) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001149 assert(dlrr);
1150 if (dlrr_blocks_.size() >= kMaxNumberOfDlrrBlocks) {
1151 LOG(LS_WARNING) << "Max DLRR blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001152 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001153 }
1154 dlrr_blocks_.push_back(dlrr->dlrr_block_);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001155 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001156}
1157
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001158bool Xr::WithVoipMetric(VoipMetric* voip_metric) {
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001159 assert(voip_metric);
1160 if (voip_metric_blocks_.size() >= kMaxNumberOfVoipMetricBlocks) {
1161 LOG(LS_WARNING) << "Max Voip Metric blocks reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001162 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001163 }
1164 voip_metric_blocks_.push_back(voip_metric->metric_);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001165 return true;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001166}
1167
1168size_t Xr::DlrrLength() const {
1169 const size_t kBlockHeaderLen = 4;
1170 const size_t kSubBlockLen = 12;
1171 size_t length = 0;
1172 for (std::vector<DlrrBlock>::const_iterator it = dlrr_blocks_.begin();
1173 it != dlrr_blocks_.end(); ++it) {
1174 if (!(*it).empty()) {
1175 length += kBlockHeaderLen + kSubBlockLen * (*it).size();
1176 }
1177 }
1178 return length;
1179}
1180
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001181bool Dlrr::WithDlrrItem(uint32_t ssrc,
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001182 uint32_t last_rr,
1183 uint32_t delay_last_rr) {
1184 if (dlrr_block_.size() >= kMaxNumberOfDlrrItems) {
1185 LOG(LS_WARNING) << "Max DLRR items reached.";
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001186 return false;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001187 }
1188 RTCPPacketXRDLRRReportBlockItem dlrr;
1189 dlrr.SSRC = ssrc;
1190 dlrr.LastRR = last_rr;
1191 dlrr.DelayLastRR = delay_last_rr;
1192 dlrr_block_.push_back(dlrr);
Erik Språngc1b9d4e2015-06-08 09:54:14 +02001193 return true;
1194}
1195
1196RawPacket::RawPacket(size_t buffer_length)
1197 : buffer_length_(buffer_length), length_(0) {
1198 buffer_.reset(new uint8_t[buffer_length]);
1199}
1200
1201RawPacket::RawPacket(const uint8_t* packet, size_t packet_length)
1202 : buffer_length_(packet_length), length_(packet_length) {
1203 buffer_.reset(new uint8_t[packet_length]);
1204 memcpy(buffer_.get(), packet, packet_length);
1205}
1206
1207const uint8_t* RawPacket::Buffer() const {
1208 return buffer_.get();
1209}
1210
1211uint8_t* RawPacket::MutableBuffer() {
1212 return buffer_.get();
1213}
1214
1215size_t RawPacket::BufferLength() const {
1216 return buffer_length_;
1217}
1218
1219size_t RawPacket::Length() const {
1220 return length_;
1221}
1222
1223void RawPacket::SetLength(size_t length) {
1224 assert(length <= buffer_length_);
1225 length_ = length;
asapersson@webrtc.org3b84b3a2014-06-25 12:22:17 +00001226}
1227
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +00001228} // namespace rtcp
1229} // namespace webrtc