blob: 0c3197fe1d9e6214aa9c2154d49b7bbccf2edf25 [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"
14#include "webrtc/system_wrappers/interface/trace.h"
15
16namespace webrtc {
17namespace rtcp {
18namespace {
19void AssignUWord8(uint8_t* buffer, uint16_t* offset, uint8_t value) {
20 buffer[(*offset)++] = value;
21}
22void AssignUWord16(uint8_t* buffer, uint16_t* offset, uint16_t value) {
23 ModuleRTPUtility::AssignUWord16ToBuffer(buffer + *offset, value);
24 *offset += 2;
25}
26void AssignUWord24(uint8_t* buffer, uint16_t* offset, uint32_t value) {
27 ModuleRTPUtility::AssignUWord24ToBuffer(buffer + *offset, value);
28 *offset += 3;
29}
30void AssignUWord32(uint8_t* buffer, uint16_t* offset, uint32_t value) {
31 ModuleRTPUtility::AssignUWord32ToBuffer(buffer + *offset, value);
32 *offset += 4;
33}
34
35// From RFC 3550, RTP: A Transport Protocol for Real-Time Applications.
36//
37// Sender report
38// 0 1 2 3
39// 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
40// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41// |V=2|P| RC | PT=SR=200 | length |
42// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
43// | SSRC of sender |
44// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
45// | NTP timestamp, most significant word |
46// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47// | NTP timestamp, least significant word |
48// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49// | RTP timestamp |
50// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51// | sender's packet count |
52// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53// | sender's octet count |
54// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
55
56void CreateSenderReport(const RTCPUtility::RTCPPacketSR& sr,
57 uint8_t* buffer,
58 uint16_t* pos) {
59 const uint16_t kLength = 6 + (6 * sr.NumberOfReportBlocks);
60 AssignUWord8(buffer, pos, 0x80 + sr.NumberOfReportBlocks);
61 AssignUWord8(buffer, pos, RTCPUtility::PT_SR);
62 AssignUWord16(buffer, pos, kLength);
63 AssignUWord32(buffer, pos, sr.SenderSSRC);
64 AssignUWord32(buffer, pos, sr.NTPMostSignificant);
65 AssignUWord32(buffer, pos, sr.NTPLeastSignificant);
66 AssignUWord32(buffer, pos, sr.RTPTimestamp);
67 AssignUWord32(buffer, pos, sr.SenderPacketCount);
68 AssignUWord32(buffer, pos, sr.SenderOctetCount);
69}
70
71// Receiver report, header (RFC 3550).
72//
73// 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
74// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
75// |V=2|P| RC | PT=RR=201 | length |
76// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77// | SSRC of packet sender |
78// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
79
80void CreateReceiverReport(const RTCPUtility::RTCPPacketRR& rr,
81 uint8_t* buffer,
82 uint16_t* pos) {
83 const uint16_t kLength = 1 + (6 * rr.NumberOfReportBlocks);
84 AssignUWord8(buffer, pos, 0x80 + rr.NumberOfReportBlocks);
85 AssignUWord8(buffer, pos, RTCPUtility::PT_RR);
86 AssignUWord16(buffer, pos, kLength);
87 AssignUWord32(buffer, pos, rr.SenderSSRC);
88}
89
90// Report block (RFC 3550).
91//
92// 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
93// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
94// | SSRC_1 (SSRC of first source) |
95// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96// | fraction lost | cumulative number of packets lost |
97// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98// | extended highest sequence number received |
99// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100// | interarrival jitter |
101// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
102// | last SR (LSR) |
103// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104// | delay since last SR (DLSR) |
105// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
106
107void CreateReportBlock(
108 const RTCPUtility::RTCPPacketReportBlockItem& report_block,
109 uint8_t* buffer,
110 uint16_t* pos) {
111 AssignUWord32(buffer, pos, report_block.SSRC);
112 AssignUWord8(buffer, pos, report_block.FractionLost);
113 AssignUWord24(buffer, pos, report_block.CumulativeNumOfPacketsLost);
114 AssignUWord32(buffer, pos, report_block.ExtendedHighestSequenceNumber);
115 AssignUWord32(buffer, pos, report_block.Jitter);
116 AssignUWord32(buffer, pos, report_block.LastSR);
117 AssignUWord32(buffer, pos, report_block.DelayLastSR);
118}
119
120// Bye packet (BYE) (RFC 3550).
121//
122// 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
123// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124// |V=2|P| SC | PT=BYE=203 | length |
125// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
126// | SSRC/CSRC |
127// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128// : ... :
129// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
130// (opt) | length | reason for leaving ...
131// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132
133void CreateBye(const RTCPUtility::RTCPPacketBYE& bye,
134 const std::vector<uint32_t>& csrcs,
135 uint8_t* buffer,
136 uint16_t* pos) {
137 const uint8_t kNumSsrcAndCsrcs = 1 + csrcs.size();
138 AssignUWord8(buffer, pos, 0x80 + kNumSsrcAndCsrcs);
139 AssignUWord8(buffer, pos, RTCPUtility::PT_BYE);
140 AssignUWord16(buffer, pos, kNumSsrcAndCsrcs);
141 AssignUWord32(buffer, pos, bye.SenderSSRC);
142 for (std::vector<uint32_t>::const_iterator it = csrcs.begin();
143 it != csrcs.end(); ++it) {
144 AssignUWord32(buffer, pos, *it);
145 }
146}
147
148// RFC 4585: Feedback format.
149//
150// Common packet format:
151//
152// 0 1 2 3
153// 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
154// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155// |V=2|P| FMT | PT | length |
156// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157// | SSRC of packet sender |
158// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159// | SSRC of media source |
160// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161// : Feedback Control Information (FCI) :
162// :
163//
164// Full intra request (FIR) (RFC 5104).
165//
166// FCI:
167//
168// 0 1 2 3
169// 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
170// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171// | SSRC |
172// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173// | Seq nr. | Reserved |
174// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175
176void CreateFirRequest(const RTCPUtility::RTCPPacketPSFBFIR& fir,
177 const RTCPUtility::RTCPPacketPSFBFIRItem& fir_item,
178 uint8_t* buffer,
179 uint16_t* pos) {
180 const uint16_t kLength = 4;
181 const uint8_t kFmt = 4;
182 AssignUWord8(buffer, pos, 0x80 + kFmt);
183 AssignUWord8(buffer, pos, RTCPUtility::PT_PSFB);
184 AssignUWord16(buffer, pos, kLength);
185 AssignUWord32(buffer, pos, fir.SenderSSRC);
186 AssignUWord32(buffer, pos, 0);
187 AssignUWord32(buffer, pos, fir_item.SSRC);
188 AssignUWord8(buffer, pos, fir_item.CommandSequenceNumber);
189 AssignUWord24(buffer, pos, 0);
190}
191
192void AppendReportBlocks(const std::vector<ReportBlock*>& report_blocks,
193 uint8_t* buffer,
194 uint16_t* pos) {
195 for (std::vector<ReportBlock*>::const_iterator it = report_blocks.begin();
196 it != report_blocks.end(); ++it) {
197 (*it)->Create(buffer, pos);
198 }
199}
200} // namespace
201
202void RtcpPacket::Append(RtcpPacket* packet) {
203 assert(packet);
204 appended_packets_.push_back(packet);
205}
206
207RawPacket RtcpPacket::Build() const {
208 uint16_t len = 0;
209 uint8_t packet[IP_PACKET_SIZE];
210 CreateAndAddAppended(packet, &len, IP_PACKET_SIZE);
211 return RawPacket(packet, len);
212}
213
214void RtcpPacket::Build(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
215 *len = 0;
216 CreateAndAddAppended(packet, len, max_len);
217}
218
219void RtcpPacket::CreateAndAddAppended(uint8_t* packet,
220 uint16_t* len,
221 uint16_t max_len) const {
222 Create(packet, len, max_len);
223 for (std::vector<RtcpPacket*>::const_iterator it = appended_packets_.begin();
224 it != appended_packets_.end(); ++it) {
225 (*it)->CreateAndAddAppended(packet, len, max_len);
226 }
227}
228
229void Empty::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
230}
231
232void SenderReport::Create(uint8_t* packet,
233 uint16_t* len,
234 uint16_t max_len) const {
235 if (*len + Length() > max_len) {
236 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
237 "Max packet size reached, skipped SR.");
238 return;
239 }
240 CreateSenderReport(sr_, packet, len);
241 AppendReportBlocks(report_blocks_, packet, len);
242}
243
244void SenderReport::WithReportBlock(ReportBlock* block) {
245 assert(block);
246 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
247 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
248 "Max report block size reached.");
249 return;
250 }
251 report_blocks_.push_back(block);
252 sr_.NumberOfReportBlocks = report_blocks_.size();
253}
254
255void ReceiverReport::Create(uint8_t* packet,
256 uint16_t* len,
257 uint16_t max_len) const {
258 if (*len + Length() > max_len) {
259 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
260 "Max packet size reached, skipped RR.");
261 return;
262 }
263 CreateReceiverReport(rr_, packet, len);
264 AppendReportBlocks(report_blocks_, packet, len);
265}
266
267void ReceiverReport::WithReportBlock(ReportBlock* block) {
268 assert(block);
269 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
270 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
271 "Max report block size reached.");
272 return;
273 }
274 report_blocks_.push_back(block);
275 rr_.NumberOfReportBlocks = report_blocks_.size();
276}
277
278void Bye::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
279 if (*len + Length() > max_len) {
280 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
281 "Max packet size reached, skipped BYE.");
282 return;
283 }
284 CreateBye(bye_, csrcs_, packet, len);
285}
286
287void Bye::WithCsrc(uint32_t csrc) {
288 if (csrcs_.size() >= kMaxNumberOfCsrcs) {
289 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
290 "Max CSRC size reached.");
291 return;
292 }
293 csrcs_.push_back(csrc);
294}
295
296void Fir::Create(uint8_t* packet, uint16_t* len, uint16_t max_len) const {
297 if (*len + Length() > max_len) {
298 WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, -1,
299 "Max packet size reached, skipped FIR.");
300 return;
301 }
302 CreateFirRequest(fir_, fir_item_, packet, len);
303}
304
305void ReportBlock::Create(uint8_t* packet, uint16_t* len) const {
306 CreateReportBlock(report_block_, packet, len);
307}
308} // namespace rtcp
309} // namespace webrtc