blob: 51c86aaa92f69af2b5ca9fd08fa0bd154983ee50 [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
13#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000014#include "webrtc/system_wrappers/interface/logging.h"
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000015
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000016using webrtc::RTCPUtility::PT_BYE;
17using webrtc::RTCPUtility::PT_PSFB;
18using webrtc::RTCPUtility::PT_RR;
19using webrtc::RTCPUtility::PT_RTPFB;
20using webrtc::RTCPUtility::PT_SR;
21
22using webrtc::RTCPUtility::RTCPPacketBYE;
23using webrtc::RTCPUtility::RTCPPacketPSFBFIR;
24using webrtc::RTCPUtility::RTCPPacketPSFBFIRItem;
25using webrtc::RTCPUtility::RTCPPacketPSFBRPSI;
26using webrtc::RTCPUtility::RTCPPacketReportBlockItem;
27using webrtc::RTCPUtility::RTCPPacketRR;
28using webrtc::RTCPUtility::RTCPPacketRTPFBNACK;
29using webrtc::RTCPUtility::RTCPPacketRTPFBNACKItem;
30using webrtc::RTCPUtility::RTCPPacketSR;
31
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000032namespace webrtc {
33namespace rtcp {
34namespace {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000035// Unused SSRC of media source, set to 0.
36const uint32_t kUnusedMediaSourceSsrc0 = 0;
37
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000038void AssignUWord8(uint8_t* buffer, uint16_t* offset, uint8_t value) {
39 buffer[(*offset)++] = value;
40}
41void AssignUWord16(uint8_t* buffer, uint16_t* offset, uint16_t value) {
42 ModuleRTPUtility::AssignUWord16ToBuffer(buffer + *offset, value);
43 *offset += 2;
44}
45void AssignUWord24(uint8_t* buffer, uint16_t* offset, uint32_t value) {
46 ModuleRTPUtility::AssignUWord24ToBuffer(buffer + *offset, value);
47 *offset += 3;
48}
49void AssignUWord32(uint8_t* buffer, uint16_t* offset, uint32_t value) {
50 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + *offset, value);
51 *offset += 4;
52}
53
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000054uint16_t BlockToHeaderLength(uint16_t length_in_bytes) {
55 // Length in 32-bit words minus 1.
56 assert(length_in_bytes > 0);
57 assert(length_in_bytes % 4 == 0);
58 return (length_in_bytes / 4) - 1;
59}
60
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000061// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
62//
asapersson@webrtc.orga8260062014-05-20 09:53:51 +000063// RTP header format.
64// 0 1 2 3
65// 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
66// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67// |V=2|P| RC/FMT | PT | length |
68// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69
70void CreateHeader(uint8_t count_or_format, // Depends on packet type.
71 uint8_t packet_type,
72 uint16_t length,
73 uint8_t* buffer,
74 uint16_t* pos) {
75 const uint8_t kVersion = 2;
76 AssignUWord8(buffer, pos, (kVersion << 6) + count_or_format);
77 AssignUWord8(buffer, pos, packet_type);
78 AssignUWord16(buffer, pos, length);
79}
80
81// Sender report (SR) (RFC 3550).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +000082// 0 1 2 3
83// 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
84// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85// |V=2|P| RC | PT=SR=200 | length |
86// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87// | SSRC of sender |
88// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
89// | NTP timestamp, most significant word |
90// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91// | NTP timestamp, least significant word |
92// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93// | RTP timestamp |
94// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95// | sender's packet count |
96// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97// | sender's octet count |
98// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
99
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000100void CreateSenderReport(const RTCPPacketSR& sr,
101 uint16_t length,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000102 uint8_t* buffer,
103 uint16_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000104 CreateHeader(sr.NumberOfReportBlocks, PT_SR, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000105 AssignUWord32(buffer, pos, sr.SenderSSRC);
106 AssignUWord32(buffer, pos, sr.NTPMostSignificant);
107 AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
108 AssignUWord32(buffer, pos, sr.RTPTimestamp);
109 AssignUWord32(buffer, pos, sr.SenderPacketCount);
110 AssignUWord32(buffer, pos, sr.SenderOctetCount);
111}
112
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000113// Receiver report (RR), header (RFC 3550).
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000114//
115// 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
116// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117// |V=2|P| RC | PT=RR=201 | length |
118// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119// | SSRC of packet sender |
120// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
121
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000122void CreateReceiverReport(const RTCPPacketRR& rr,
123 uint16_t length,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000124 uint8_t* buffer,
125 uint16_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000126 CreateHeader(rr.NumberOfReportBlocks, PT_RR, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000127 AssignUWord32(buffer, pos, rr.SenderSSRC);
128}
129
130// Report block (RFC 3550).
131//
132// 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
133// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
134// | SSRC_1 (SSRC of first source) |
135// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
136// | fraction lost | cumulative number of packets lost |
137// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138// | extended highest sequence number received |
139// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140// | interarrival jitter |
141// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142// | last SR (LSR) |
143// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144// | delay since last SR (DLSR) |
145// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
146
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000147void CreateReportBlock(const RTCPPacketReportBlockItem& report_block,
148 uint8_t* buffer,
149 uint16_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000150 AssignUWord32(buffer, pos, report_block.SSRC);
151 AssignUWord8(buffer, pos, report_block.FractionLost);
152 AssignUWord24(buffer, pos, report_block.CumulativeNumOfPacketsLost);
153 AssignUWord32(buffer, pos, report_block.ExtendedHighestSequenceNumber);
154 AssignUWord32(buffer, pos, report_block.Jitter);
155 AssignUWord32(buffer, pos, report_block.LastSR);
156 AssignUWord32(buffer, pos, report_block.DelayLastSR);
157}
158
159// Bye packet (BYE) (RFC 3550).
160//
161// 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
162// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163// |V=2|P| SC | PT=BYE=203 | length |
164// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165// | SSRC/CSRC |
166// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
167// : ... :
168// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
169// (opt) | length | reason for leaving ...
170// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000172void CreateBye(const RTCPPacketBYE& bye,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000173 const std::vector<uint32_t>& csrcs,
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000174 uint16_t length,
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000175 uint8_t* buffer,
176 uint16_t* pos) {
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000177 CreateHeader(length, PT_BYE, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000178 AssignUWord32(buffer, pos, bye.SenderSSRC);
179 for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
180 it != csrcs.end(); ++it) {
181 AssignUWord32(buffer, pos, *it);
182 }
183}
184
185// RFC 4585: Feedback format.
186//
187// Common packet format:
188//
189// 0 1 2 3
190// 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
191// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192// |V=2|P| FMT | PT | length |
193// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
194// | SSRC of packet sender |
195// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
196// | SSRC of media source |
197// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
198// : Feedback Control Information (FCI) :
199// :
200//
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000201
202// Generic NACK (RFC 4585).
203//
204// FCI:
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// | PID | BLP |
210// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
211
212void CreateNack(const RTCPPacketRTPFBNACK& nack,
213 const std::vector<RTCPPacketRTPFBNACKItem>& nack_fields,
214 uint16_t length,
215 uint8_t* buffer,
216 uint16_t* pos) {
217 const uint8_t kFmt = 1;
218 CreateHeader(kFmt, PT_RTPFB, length, buffer, pos);
219 AssignUWord32(buffer, pos, nack.SenderSSRC);
220 AssignUWord32(buffer, pos, nack.MediaSSRC);
221 for (std::vector<RTCPPacketRTPFBNACKItem>::const_iterator
222 it = nack_fields.begin(); it != nack_fields.end(); ++it) {
223 AssignUWord16(buffer, pos, (*it).PacketID);
224 AssignUWord16(buffer, pos, (*it).BitMask);
225 }
226}
227
228// Reference picture selection indication (RPSI) (RFC 4585).
229//
230// FCI:
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// | PB |0| Payload Type| Native RPSI bit string |
236// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
237// | defined per codec ... | Padding (0) |
238// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
239
240void CreateRpsi(const RTCPPacketPSFBRPSI& rpsi,
241 uint8_t padding_bytes,
242 uint16_t length,
243 uint8_t* buffer,
244 uint16_t* pos) {
245 // Native bit string should be a multiple of 8 bits.
246 assert(rpsi.NumberOfValidBits % 8 == 0);
247 const uint8_t kFmt = 3;
248 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
249 AssignUWord32(buffer, pos, rpsi.SenderSSRC);
250 AssignUWord32(buffer, pos, rpsi.MediaSSRC);
251 AssignUWord8(buffer, pos, padding_bytes * 8);
252 AssignUWord8(buffer, pos, rpsi.PayloadType);
253 memcpy(buffer + *pos, rpsi.NativeBitString, rpsi.NumberOfValidBits / 8);
254 *pos += rpsi.NumberOfValidBits / 8;
255 memset(buffer + *pos, 0, padding_bytes);
256 *pos += padding_bytes;
257}
258
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000259// Full intra request (FIR) (RFC 5104).
260//
261// FCI:
262//
263// 0 1 2 3
264// 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
265// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
266// | SSRC |
267// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
268// | Seq nr. | Reserved |
269// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
270
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000271void CreateFir(const RTCPPacketPSFBFIR& fir,
272 const RTCPPacketPSFBFIRItem& fir_item,
273 uint16_t length,
274 uint8_t* buffer,
275 uint16_t* pos) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000276 const uint8_t kFmt = 4;
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000277 CreateHeader(kFmt, PT_PSFB, length, buffer, pos);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000278 AssignUWord32(buffer, pos, fir.SenderSSRC);
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000279 AssignUWord32(buffer, pos, kUnusedMediaSourceSsrc0);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000280 AssignUWord32(buffer, pos, fir_item.SSRC);
281 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
282 AssignUWord24(buffer, pos, 0);
283}
284
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000285template <typename T>
286void AppendBlocks(const std::vector<T*>& blocks,
287 uint8_t* buffer,
288 uint16_t* pos) {
289 for (typename std::vector<T*>::const_iterator it = blocks.begin();
290 it != blocks.end(); ++it) {
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000291 (*it)->Create(buffer, pos);
292 }
293}
294} // namespace
295
296void RtcpPacket::Append(RtcpPacket* packet) {
297 assert(packet);
298 appended_packets_.push_back(packet);
299}
300
301RawPacket RtcpPacket::Build() const {
302 uint16_t len = 0;
303 uint8_t packet[IP_PACKET_SIZE];
304 CreateAndAddAppended(packet, &len, IP_PACKET_SIZE);
305 return RawPacket(packet, len);
306}
307
308void RtcpPacket::Build(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
309 *len = 0;
310 CreateAndAddAppended(packet, len, max_len);
311}
312
313void RtcpPacket::CreateAndAddAppended(uint8_t* packet,
314 uint16_t* len,
315 uint16_t max_len) const {
316 Create(packet, len, max_len);
317 for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
318 it != appended_packets_.end(); ++it) {
319 (*it)->CreateAndAddAppended(packet, len, max_len);
320 }
321}
322
323void Empty::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
324}
325
326void SenderReport::Create(uint8_t* packet,
327 uint16_t* len,
328 uint16_t max_len) const {
329 if (*len + Length() > max_len) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000330 LOG(LS_WARNING) << "Max packet size reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000331 return;
332 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000333 CreateSenderReport(sr_, BlockToHeaderLength(Length()), packet, len);
334 AppendBlocks(report_blocks_, packet, len);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000335}
336
337void SenderReport::WithReportBlock(ReportBlock* block) {
338 assert(block);
339 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000340 LOG(LS_WARNING) << "Max report blocks reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000341 return;
342 }
343 report_blocks_.push_back(block);
344 sr_.NumberOfReportBlocks = report_blocks_.size();
345}
346
347void ReceiverReport::Create(uint8_t* packet,
348 uint16_t* len,
349 uint16_t max_len) const {
350 if (*len + Length() > max_len) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000351 LOG(LS_WARNING) << "Max packet size reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000352 return;
353 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000354 CreateReceiverReport(rr_, BlockToHeaderLength(Length()), packet, len);
355 AppendBlocks(report_blocks_, packet, len);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000356}
357
358void ReceiverReport::WithReportBlock(ReportBlock* block) {
359 assert(block);
360 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000361 LOG(LS_WARNING) << "Max report blocks reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000362 return;
363 }
364 report_blocks_.push_back(block);
365 rr_.NumberOfReportBlocks = report_blocks_.size();
366}
367
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000368void ReportBlock::Create(uint8_t* packet, uint16_t* len) const {
369 CreateReportBlock(report_block_, packet, len);
370}
371
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000372void Bye::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
373 if (*len + Length() > max_len) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000374 LOG(LS_WARNING) << "Max packet size reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000375 return;
376 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000377 CreateBye(bye_, csrcs_, BlockToHeaderLength(Length()), packet, len);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000378}
379
380void Bye::WithCsrc(uint32_t csrc) {
381 if (csrcs_.size() >= kMaxNumberOfCsrcs) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000382 LOG(LS_WARNING) << "Max CSRC size reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000383 return;
384 }
385 csrcs_.push_back(csrc);
386}
387
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000388void Nack::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
389 assert(!nack_fields_.empty());
390 if (*len + Length() > max_len) {
391 LOG(LS_WARNING) << "Max packet size reached.";
392 return;
393 }
394 CreateNack(nack_, nack_fields_, BlockToHeaderLength(Length()), packet, len);
395}
396
397void Nack::WithList(const uint16_t* nack_list, int length) {
398 assert(nack_list);
399 assert(nack_fields_.empty());
400 int i = 0;
401 while (i < length) {
402 uint16_t pid = nack_list[i++];
403 // Bitmask specifies losses in any of the 16 packets following the pid.
404 uint16_t bitmask = 0;
405 while (i < length) {
406 int shift = static_cast<uint16_t>(nack_list[i] - pid) - 1;
407 if (shift >= 0 && shift <= 15) {
408 bitmask |= (1 << shift);
409 ++i;
410 } else {
411 break;
412 }
413 }
414 RTCPUtility::RTCPPacketRTPFBNACKItem item;
415 item.PacketID = pid;
416 item.BitMask = bitmask;
417 nack_fields_.push_back(item);
418 }
419}
420
421void Rpsi::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
422 assert(rpsi_.NumberOfValidBits > 0);
423 if (*len + Length() > max_len) {
424 LOG(LS_WARNING) << "Max packet size reached.";
425 return;
426 }
427 CreateRpsi(rpsi_, padding_bytes_, BlockToHeaderLength(Length()), packet, len);
428}
429
430void Rpsi::WithPictureId(uint64_t picture_id) {
431 const uint32_t kPidBits = 7;
432 const uint64_t k7MsbZeroMask = 0x1ffffffffffffff;
433 uint8_t required_bytes = 0;
434 uint64_t shifted_pid = picture_id;
435 do {
436 ++required_bytes;
437 shifted_pid = (shifted_pid >> kPidBits) & k7MsbZeroMask;
438 } while (shifted_pid > 0);
439
440 // Convert picture id to native bit string (natively defined by the video
441 // codec).
442 int pos = 0;
443 for (int i = required_bytes - 1; i > 0; i--) {
444 rpsi_.NativeBitString[pos++] =
445 0x80 | static_cast<uint8_t>(picture_id >> (i * kPidBits));
446 }
447 rpsi_.NativeBitString[pos++] = static_cast<uint8_t>(picture_id & 0x7f);
448 rpsi_.NumberOfValidBits = pos * 8;
449
450 // Calculate padding bytes (to reach next 32-bit boundary, 1, 2 or 3 bytes).
451 padding_bytes_ = 4 - ((2 + required_bytes) % 4);
452 if (padding_bytes_ == 4) {
453 padding_bytes_ = 0;
454 }
455}
456
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000457void Fir::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
458 if (*len + Length() > max_len) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000459 LOG(LS_WARNING) << "Max packet size reached.";
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000460 return;
461 }
asapersson@webrtc.orga8260062014-05-20 09:53:51 +0000462 CreateFir(fir_, fir_item_, BlockToHeaderLength(Length()), packet, len);
asapersson@webrtc.org0f2809a2014-02-21 08:14:45 +0000463}
464} // namespace rtcp
465} // namespace webrtc