blob: b8cdbe801e3cd4121ff285bf463d33eabffc018a [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000022#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000025#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000026#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000027
niklase@google.com470e71d2011-07-07 08:21:25 +000028namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000029
30using RTCPUtility::RTCPCnameInformation;
31
Erik Språng61be2a42015-04-27 13:32:52 +020032NACKStringBuilder::NACKStringBuilder()
33 : _stream(""), _count(0), _prevNack(0), _consecutive(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000034}
35
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000036NACKStringBuilder::~NACKStringBuilder() {}
37
pbos@webrtc.org2f446732013-04-08 11:08:41 +000038void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000039{
Erik Språng61be2a42015-04-27 13:32:52 +020040 if (_count == 0) {
41 _stream << nack;
42 } else if (nack == _prevNack + 1) {
43 _consecutive = true;
44 } else {
45 if (_consecutive) {
46 _stream << "-" << _prevNack;
47 _consecutive = false;
edjee@google.com79b02892013-04-04 19:43:34 +000048 }
Erik Språng61be2a42015-04-27 13:32:52 +020049 _stream << "," << nack;
50 }
51 _count++;
52 _prevNack = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000053}
54
Erik Språng61be2a42015-04-27 13:32:52 +020055std::string NACKStringBuilder::GetResult() {
56 if (_consecutive) {
57 _stream << "-" << _prevNack;
58 _consecutive = false;
59 }
60 return _stream.str();
edjee@google.com79b02892013-04-04 19:43:34 +000061}
62
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000063RTCPSender::FeedbackState::FeedbackState()
64 : send_payload_type(0),
65 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000066 packets_sent(0),
67 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068 send_bitrate(0),
69 last_rr_ntp_secs(0),
70 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000071 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020072 has_last_xr_rr(false),
73 module(nullptr) {
74}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000076RTCPSender::RTCPSender(
77 int32_t id,
78 bool audio,
79 Clock* clock,
80 ReceiveStatistics* receive_statistics,
81 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000082 : _id(id),
83 _audio(audio),
84 _clock(clock),
85 _method(kRtcpOff),
86 _criticalSectionTransport(
87 CriticalSectionWrapper::CreateCriticalSection()),
88 _cbTransport(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000089
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000090 _criticalSectionRTCPSender(
91 CriticalSectionWrapper::CreateCriticalSection()),
92 _usingNack(false),
93 _sending(false),
94 _sendTMMBN(false),
95 _REMB(false),
96 _sendREMB(false),
97 _TMMBR(false),
98 _IJ(false),
99 _nextTimeToSendRTCP(0),
100 start_timestamp_(0),
101 last_rtp_timestamp_(0),
102 last_frame_capture_time_ms_(-1),
103 _SSRC(0),
104 _remoteSSRC(0),
105 _CNAME(),
106 receive_statistics_(receive_statistics),
107 internal_report_blocks_(),
108 external_report_blocks_(),
109 _csrcCNAMEs(),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000110 _lastSendReport(),
111 _lastRTCPTime(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000112
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000113 last_xr_rr_(),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000114
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000115 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000116
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000117 _rembBitrate(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000118
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000119 _tmmbrHelp(),
120 _tmmbr_Send(0),
121 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000122
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000123 _appSend(false),
124 _appSubType(0),
125 _appName(),
Erik Språng61be2a42015-04-27 13:32:52 +0200126 _appData(nullptr),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000127 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000128
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000129 xrSendReceiverReferenceTimeEnabled_(false),
130 _xrSendVoIPMetric(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000131 _xrVoIPMetric(),
132 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng61be2a42015-04-27 13:32:52 +0200133 memset(_CNAME, 0, sizeof(_CNAME));
134 memset(_lastSendReport, 0, sizeof(_lastSendReport));
135 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000136}
137
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000138RTCPSender::~RTCPSender() {
Erik Språng61be2a42015-04-27 13:32:52 +0200139 for (auto it : internal_report_blocks_)
140 delete it.second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000141
Erik Språng61be2a42015-04-27 13:32:52 +0200142 for (auto it : external_report_blocks_)
143 delete it.second;
144
145 for (auto it : _csrcCNAMEs)
146 delete it.second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000147}
148
Erik Språng61be2a42015-04-27 13:32:52 +0200149int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
150 CriticalSectionScoped lock(_criticalSectionTransport.get());
151 _cbTransport = outgoingTransport;
152 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000153}
154
Erik Språng61be2a42015-04-27 13:32:52 +0200155RTCPMethod RTCPSender::Status() const {
156 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
157 return _method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000158}
159
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng61be2a42015-04-27 13:32:52 +0200161 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000162 _method = method;
163
164 if (method == kRtcpOff)
165 return;
166 _nextTimeToSendRTCP =
167 _clock->TimeInMilliseconds() +
168 (_audio ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000169}
170
Erik Språng61be2a42015-04-27 13:32:52 +0200171bool RTCPSender::Sending() const {
172 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
173 return _sending;
niklase@google.com470e71d2011-07-07 08:21:25 +0000174}
175
Erik Språng61be2a42015-04-27 13:32:52 +0200176int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
177 bool sending) {
178 bool sendRTCPBye = false;
179 {
180 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000181
Erik Språng61be2a42015-04-27 13:32:52 +0200182 if (_method != kRtcpOff) {
183 if (sending == false && _sending == true) {
184 // Trigger RTCP bye
185 sendRTCPBye = true;
186 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000187 }
Erik Språng61be2a42015-04-27 13:32:52 +0200188 _sending = sending;
189 }
190 if (sendRTCPBye)
191 return SendRTCP(feedback_state, kRtcpBye);
192 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000193}
194
Erik Språng61be2a42015-04-27 13:32:52 +0200195bool RTCPSender::REMB() const {
196 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
197 return _REMB;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000198}
199
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000200void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng61be2a42015-04-27 13:32:52 +0200201 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000202 _REMB = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000203}
204
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000205void RTCPSender::SetREMBData(uint32_t bitrate,
206 const std::vector<uint32_t>& ssrcs) {
Erik Språng61be2a42015-04-27 13:32:52 +0200207 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000208 _rembBitrate = bitrate;
209 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000210
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000211 _sendREMB = true;
212 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
213 // throttled by the caller.
214 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000215}
216
Erik Språng61be2a42015-04-27 13:32:52 +0200217bool RTCPSender::TMMBR() const {
218 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
219 return _TMMBR;
niklase@google.com470e71d2011-07-07 08:21:25 +0000220}
221
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000222void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng61be2a42015-04-27 13:32:52 +0200223 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000224 _TMMBR = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000225}
226
Erik Språng61be2a42015-04-27 13:32:52 +0200227bool RTCPSender::IJ() const {
228 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
229 return _IJ;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000230}
231
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000232void RTCPSender::SetIJStatus(bool enable) {
Erik Språng61be2a42015-04-27 13:32:52 +0200233 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000234 _IJ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000235}
236
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000237void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng61be2a42015-04-27 13:32:52 +0200238 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000239 start_timestamp_ = start_timestamp;
240}
241
242void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
243 int64_t capture_time_ms) {
Erik Språng61be2a42015-04-27 13:32:52 +0200244 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000245 last_rtp_timestamp_ = rtp_timestamp;
246 if (capture_time_ms < 0) {
247 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000248 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000249 } else {
250 last_frame_capture_time_ms_ = capture_time_ms;
251 }
252}
253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng61be2a42015-04-27 13:32:52 +0200255 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000256
Erik Språng61be2a42015-04-27 13:32:52 +0200257 if (_SSRC != 0) {
258 // not first SetSSRC, probably due to a collision
259 // schedule a new RTCP report
260 // make sure that we send a RTP packet
261 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
262 }
263 _SSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000264}
265
Erik Språng61be2a42015-04-27 13:32:52 +0200266void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
267 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
268 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000269}
270
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000271int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000272 if (!cName)
273 return -1;
274
Erik Språng61be2a42015-04-27 13:32:52 +0200275 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000276 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
277 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
278 return 0;
279}
280
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000281int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000282 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000283 assert(cName);
Erik Språng61be2a42015-04-27 13:32:52 +0200284 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000285 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
286 return -1;
287 }
288 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000289 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
290 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000291 _csrcCNAMEs[SSRC] = ptr;
292 return 0;
293}
294
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000295int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng61be2a42015-04-27 13:32:52 +0200296 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000297 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000298 _csrcCNAMEs.find(SSRC);
299
Erik Språng61be2a42015-04-27 13:32:52 +0200300 if (it == _csrcCNAMEs.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000301 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200302
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000303 delete it->second;
304 _csrcCNAMEs.erase(it);
305 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000308bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000309/*
310 For audio we use a fix 5 sec interval
311
312 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000313 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
314 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000315
316
317From RFC 3550
318
319 MAX RTCP BW is 5% if the session BW
320 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000321 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000322
323 The RECOMMENDED value for the reduced minimum in seconds is 360
324 divided by the session bandwidth in kilobits/second. This minimum
325 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
326
327 If the participant has not yet sent an RTCP packet (the variable
328 initial is true), the constant Tmin is set to 2.5 seconds, else it
329 is set to 5 seconds.
330
331 The interval between RTCP packets is varied randomly over the
332 range [0.5,1.5] times the calculated interval to avoid unintended
333 synchronization of all participants
334
335 if we send
336 If the participant is a sender (we_sent true), the constant C is
337 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
338 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
339 number of senders.
340
341 if we receive only
342 If we_sent is not true, the constant C is set
343 to the average RTCP packet size divided by 75% of the RTCP
344 bandwidth. The constant n is set to the number of receivers
345 (members - senders). If the number of senders is greater than
346 25%, senders and receivers are treated together.
347
348 reconsideration NOT required for peer-to-peer
349 "timer reconsideration" is
350 employed. This algorithm implements a simple back-off mechanism
351 which causes users to hold back RTCP packet transmission if the
352 group sizes are increasing.
353
354 n = number of members
355 C = avg_size/(rtcpBW/4)
356
357 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
358
359 4. The calculated interval T is set to a number uniformly distributed
360 between 0.5 and 1.5 times the deterministic calculated interval.
361
362 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
363 for the fact that the timer reconsideration algorithm converges to
364 a value of the RTCP bandwidth below the intended average
365*/
366
Erik Språng61be2a42015-04-27 13:32:52 +0200367 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000368
Erik Språng61be2a42015-04-27 13:32:52 +0200369 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000370
Erik Språng61be2a42015-04-27 13:32:52 +0200371 if (_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000372 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
Erik Språng61be2a42015-04-27 13:32:52 +0200374 if (!_audio && sendKeyframeBeforeRTP) {
375 // for video key-frames we want to send the RTCP before the large key-frame
376 // if we have a 100 ms margin
377 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
378 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
Erik Språng61be2a42015-04-27 13:32:52 +0200380 if (now >= _nextTimeToSendRTCP) {
381 return true;
382 } else if (now < 0x0000ffff &&
383 _nextTimeToSendRTCP > 0xffff0000) { // 65 sec margin
384 // wrap
385 return true;
386 }
387 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000388}
389
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000390int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng61be2a42015-04-27 13:32:52 +0200391 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
Erik Språng61be2a42015-04-27 13:32:52 +0200393 // This is only saved when we are the sender
394 if ((_lastSendReport[0] == 0) || (sendReport == 0)) {
395 return 0; // will be ignored
396 } else {
397 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
398 if (_lastSendReport[i] == sendReport)
399 return _lastRTCPTime[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000400 }
Erik Språng61be2a42015-04-27 13:32:52 +0200401 }
402 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000403}
404
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000405bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
406 int64_t* time_ms) const {
Erik Språng61be2a42015-04-27 13:32:52 +0200407 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000408
409 if (last_xr_rr_.empty()) {
410 return false;
411 }
412 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
413 if (it == last_xr_rr_.end()) {
414 return false;
415 }
416 *time_ms = it->second;
417 return true;
418}
419
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000420int32_t RTCPSender::AddExternalReportBlock(
421 uint32_t SSRC,
422 const RTCPReportBlock* reportBlock) {
Erik Språng61be2a42015-04-27 13:32:52 +0200423 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000424 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
425}
426
427int32_t RTCPSender::AddReportBlock(
428 uint32_t SSRC,
429 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
430 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000431 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000432
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000433 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000434 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000435 return -1;
436 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000437 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000438 report_blocks->find(SSRC);
439 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000440 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000441 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000442 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000443 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
444 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000445 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000446 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000447}
448
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000449int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
Erik Språng61be2a42015-04-27 13:32:52 +0200450 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000452 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000453 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000454
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000455 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000456 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000457 }
458 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000459 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000460 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000461}
462
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000463int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
464 uint8_t* rtcpbuffer,
Erik Språng61be2a42015-04-27 13:32:52 +0200465 int32_t pos,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000466 uint32_t NTPsec,
Erik Språng61be2a42015-04-27 13:32:52 +0200467 uint32_t NTPfrac) {
468 // sanity
469 if (pos + 52 >= IP_PACKET_SIZE) {
470 LOG(LS_WARNING) << "Failed to build Sender Report.";
471 return -2;
472 }
473 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000474
Erik Språng61be2a42015-04-27 13:32:52 +0200475 uint32_t posNumberOfReportBlocks = pos;
476 rtcpbuffer[pos++] = 0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000477
Erik Språng61be2a42015-04-27 13:32:52 +0200478 // Sender report
479 rtcpbuffer[pos++] = 200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
Erik Språng61be2a42015-04-27 13:32:52 +0200481 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
482 // shift old
483 _lastSendReport[i + 1] = _lastSendReport[i];
484 _lastRTCPTime[i + 1] = _lastRTCPTime[i];
485 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000486
Erik Språng61be2a42015-04-27 13:32:52 +0200487 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
488 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
Erik Språng61be2a42015-04-27 13:32:52 +0200490 // The timestamp of this RTCP packet should be estimated as the timestamp of
491 // the frame being captured at this moment. We are calculating that
492 // timestamp as the last frame's timestamp + the time since the last frame
493 // was captured.
494 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
495 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
496 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
Erik Språng61be2a42015-04-27 13:32:52 +0200498 // Add sender data
499 // Save for our length field
500 pos++;
501 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
Erik Språng61be2a42015-04-27 13:32:52 +0200503 // Add our own SSRC
504 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
505 pos += 4;
506 // NTP
507 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, NTPsec);
508 pos += 4;
509 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, NTPfrac);
510 pos += 4;
511 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, RTPtime);
512 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000513
Erik Språng61be2a42015-04-27 13:32:52 +0200514 // sender's packet count
515 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos,
516 feedback_state.packets_sent);
517 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000518
Erik Språng61be2a42015-04-27 13:32:52 +0200519 // sender's octet count
520 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos,
521 feedback_state.media_bytes_sent);
522 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523
Erik Språng61be2a42015-04-27 13:32:52 +0200524 uint8_t numberOfReportBlocks = 0;
525 int32_t retVal = WriteAllReportBlocksToBuffer(
526 rtcpbuffer, pos, &numberOfReportBlocks, NTPsec, NTPfrac);
527 if (retVal < 0)
528 return retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
Erik Språng61be2a42015-04-27 13:32:52 +0200530 pos = retVal;
531 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
532
533 uint16_t len = static_cast<uint16_t>((pos / 4) - 1);
534 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + 2, len);
535 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000536}
537
Erik Språng61be2a42015-04-27 13:32:52 +0200538int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int32_t pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000539 size_t lengthCname = strlen(_CNAME);
540 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000542 // sanity
543 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000544 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000545 return -2;
546 }
547 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000548
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000549 // We always need to add SDES CNAME
Erik Språng61be2a42015-04-27 13:32:52 +0200550 size_t size = 0x80 + 1 + _csrcCNAMEs.size();
551 DCHECK_LE(size, std::numeric_limits<uint8_t>::max());
552 rtcpbuffer[pos++] = static_cast<uint8_t>(size);
553 rtcpbuffer[pos++] = 202;
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000555 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000556 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000557 pos++;
558 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000559
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000560 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000561 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000562 pos += 4;
563
564 // CNAME = 1
Erik Språng61be2a42015-04-27 13:32:52 +0200565 rtcpbuffer[pos++] = 1;
566 DCHECK_LE(lengthCname, std::numeric_limits<uint8_t>::max());
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000567 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000568
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000569 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000570
571 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
572 pos += lengthCname;
Erik Språng61be2a42015-04-27 13:32:52 +0200573 SDESLength += static_cast<uint16_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000574
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000575 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000576 // We must have a zero field even if we have an even multiple of 4 bytes
577 if ((pos % 4) == 0) {
578 padding++;
Erik Språng61be2a42015-04-27 13:32:52 +0200579 rtcpbuffer[pos++] = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000580 }
581 while ((pos % 4) != 0) {
582 padding++;
Erik Språng61be2a42015-04-27 13:32:52 +0200583 rtcpbuffer[pos++] = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584 }
585 SDESLength += padding;
586
Erik Språng61be2a42015-04-27 13:32:52 +0200587 for (auto it = _csrcCNAMEs.begin(); it != _csrcCNAMEs.end(); ++it) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000589 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000590
591 // Add SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000592 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000593 pos += 4;
594
595 // CNAME = 1
Erik Språng61be2a42015-04-27 13:32:52 +0200596 rtcpbuffer[pos++] = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000598 size_t length = strlen(cname->name);
599 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000600
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000601 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000603
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000604 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000605
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000606 pos += length;
607 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000608 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000609
610 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000611 if((pos % 4) == 0){
612 padding++;
613 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000615 while((pos % 4) != 0){
616 padding++;
617 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618 }
619 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000620 }
621 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000622 uint16_t buffer_length = (SDESLength / 4) - 1;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000623 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + SDESLengthPos,
624 buffer_length);
Erik Språng61be2a42015-04-27 13:32:52 +0200625 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000626}
627
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000628int32_t RTCPSender::BuildRR(uint8_t* rtcpbuffer,
Erik Språng61be2a42015-04-27 13:32:52 +0200629 int32_t pos,
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000630 uint32_t NTPsec,
631 uint32_t NTPfrac) {
Erik Språng61be2a42015-04-27 13:32:52 +0200632 // sanity one block
633 if (pos + 32 >= IP_PACKET_SIZE)
634 return -2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000635
Erik Språng61be2a42015-04-27 13:32:52 +0200636 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000637
Erik Språng61be2a42015-04-27 13:32:52 +0200638 rtcpbuffer[pos++] = 0x80;
639 rtcpbuffer[pos++] = 201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000640
Erik Språng61be2a42015-04-27 13:32:52 +0200641 // Save for our length field
642 pos += 2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
Erik Språng61be2a42015-04-27 13:32:52 +0200644 // Add our own SSRC
645 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
646 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
Erik Språng61be2a42015-04-27 13:32:52 +0200648 uint8_t numberOfReportBlocks = 0;
649 int retVal = WriteAllReportBlocksToBuffer(
650 rtcpbuffer, pos, &numberOfReportBlocks, NTPsec, NTPfrac);
651 if (retVal < 0)
652 return pos;
653
654 pos = retVal;
655 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
656
657 uint16_t len = uint16_t((pos) / 4 - 1);
658 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + 2, len);
659 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000660}
661
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000662// From RFC 5450: Transmission Time Offsets in RTP Streams.
663// 0 1 2 3
664// 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
665// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
666// hdr |V=2|P| RC | PT=IJ=195 | length |
667// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
668// | inter-arrival jitter |
669// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
670// . .
671// . .
672// . .
673// | inter-arrival jitter |
674// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
675//
676// If present, this RTCP packet must be placed after a receiver report
677// (inside a compound RTCP packet), and MUST have the same value for RC
678// (reception report count) as the receiver report.
679
Erik Språng61be2a42015-04-27 13:32:52 +0200680int32_t RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000681 uint8_t* rtcpbuffer,
Erik Språng61be2a42015-04-27 13:32:52 +0200682 int32_t pos,
683 const uint32_t jitterTransmissionTimeOffset) {
684 if (external_report_blocks_.size() > 0) {
685 // TODO(andresp): Remove external report blocks since they are not
686 // supported.
687 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000688 return 0;
Erik Språng61be2a42015-04-27 13:32:52 +0200689 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000690
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000691 // sanity
Erik Språng61be2a42015-04-27 13:32:52 +0200692 if (pos + 8 >= IP_PACKET_SIZE)
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000693 return -2;
Erik Språng61be2a42015-04-27 13:32:52 +0200694
695 // add picture loss indicator
696 uint8_t RC = 1;
697 rtcpbuffer[pos++] = 0x80 + RC;
698 rtcpbuffer[pos++] = 195;
699
700 // Used fixed length of 2
701 rtcpbuffer[pos++] = 0;
702 rtcpbuffer[pos++] = 1;
703
704 // Add inter-arrival jitter
705 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos,
706 jitterTransmissionTimeOffset);
707 pos += 4;
708 return pos;
709}
710
711int32_t RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int32_t pos) {
712 // sanity
713 if (pos + 12 >= IP_PACKET_SIZE)
714 return -2;
715
716 // add picture loss indicator
717 uint8_t FMT = 1;
718 rtcpbuffer[pos++] = 0x80 + FMT;
719 rtcpbuffer[pos++] = 206;
720
721 // Used fixed length of 2
722 rtcpbuffer[pos++] = 0;
723 rtcpbuffer[pos++] = 2;
724
725 // Add our own SSRC
726 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
727 pos += 4;
728
729 // Add the remote SSRC
730 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
731 pos += 4;
732 return pos;
733}
734
735int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer, int32_t pos, bool repeat) {
736 // sanity
737 if (pos + 20 >= IP_PACKET_SIZE)
738 return -2;
739
740 if (!repeat)
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000741 _sequenceNumberFIR++; // do not increase if repetition
niklase@google.com470e71d2011-07-07 08:21:25 +0000742
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000743 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000744 uint8_t FMT = 4;
Erik Språng61be2a42015-04-27 13:32:52 +0200745 rtcpbuffer[pos++] = 0x80 + FMT;
746 rtcpbuffer[pos++] = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000747
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000748 //Length of 4
Erik Språng61be2a42015-04-27 13:32:52 +0200749 rtcpbuffer[pos++] = 0;
750 rtcpbuffer[pos++] = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000751
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000752 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000753 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000754 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000755
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000756 // RFC 5104 4.3.1.2. Semantics
757 // SSRC of media source
Erik Språng61be2a42015-04-27 13:32:52 +0200758 ByteWriter<uint32_t>::WriteBigEndian(&rtcpbuffer[pos], 0);
759 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000760
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000761 // Additional Feedback Control Information (FCI)
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000762 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000763 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000764
Erik Språng61be2a42015-04-27 13:32:52 +0200765 rtcpbuffer[pos++] = _sequenceNumberFIR;
766 rtcpbuffer[pos++] = 0;
767 rtcpbuffer[pos++] = 0;
768 rtcpbuffer[pos++] = 0;
769 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000770}
771
772/*
773 0 1 2 3
774 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
775 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
776 | First | Number | PictureID |
777 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
778*/
Erik Språng61be2a42015-04-27 13:32:52 +0200779int32_t RTCPSender::BuildSLI(uint8_t* rtcpbuffer,
780 int32_t pos,
781 uint8_t pictureID) {
782 // sanity
783 if (pos + 16 >= IP_PACKET_SIZE)
784 return -2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000785
Erik Språng61be2a42015-04-27 13:32:52 +0200786 // add slice loss indicator
787 uint8_t FMT = 2;
788 rtcpbuffer[pos++] = 0x80 + FMT;
789 rtcpbuffer[pos++] = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000790
Erik Språng61be2a42015-04-27 13:32:52 +0200791 // Used fixed length of 3
792 rtcpbuffer[pos++] = 0;
793 rtcpbuffer[pos++] = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000794
Erik Språng61be2a42015-04-27 13:32:52 +0200795 // Add our own SSRC
796 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
797 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000798
Erik Språng61be2a42015-04-27 13:32:52 +0200799 // Add the remote SSRC
800 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
801 pos += 4;
802
803 // Add first, number & picture ID 6 bits
804 // first = 0, 13 - bits
805 // number = 0x1fff, 13 - bits only ones for now
806 uint32_t sliField = (0x1fff << 6) + (0x3f & pictureID);
807 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, sliField);
808 pos += 4;
809 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000810}
811
812/*
813 0 1 2 3
814 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
815 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
816 | PB |0| Payload Type| Native RPSI bit string |
817 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
818 | defined per codec ... | Padding (0) |
819 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
820*/
821/*
822* Note: not generic made for VP8
823*/
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000824int32_t RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
Erik Språng61be2a42015-04-27 13:32:52 +0200825 int32_t pos,
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000826 uint64_t pictureID,
827 uint8_t payloadType) {
Erik Språng61be2a42015-04-27 13:32:52 +0200828 // sanity
829 if (pos + 24 >= IP_PACKET_SIZE)
830 return -2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
Erik Språng61be2a42015-04-27 13:32:52 +0200832 // add Reference Picture Selection Indication
833 uint8_t FMT = 3;
834 rtcpbuffer[pos++] = 0x80 + FMT;
835 rtcpbuffer[pos++] = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000836
Erik Språng61be2a42015-04-27 13:32:52 +0200837 // calc length
838 uint32_t bitsRequired = 7;
839 uint8_t bytesRequired = 1;
840 while ((pictureID >> bitsRequired) > 0) {
841 bitsRequired += 7;
842 bytesRequired++;
843 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000844
Erik Språng61be2a42015-04-27 13:32:52 +0200845 uint8_t size = 3;
846 if (bytesRequired > 6) {
847 size = 5;
848 } else if (bytesRequired > 2) {
849 size = 4;
850 }
851 rtcpbuffer[pos++] = 0;
852 rtcpbuffer[pos++] = size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000853
Erik Språng61be2a42015-04-27 13:32:52 +0200854 // Add our own SSRC
855 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
856 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000857
Erik Språng61be2a42015-04-27 13:32:52 +0200858 // Add the remote SSRC
859 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
860 pos += 4;
861
862 // calc padding length
863 uint8_t paddingBytes = 4 - ((2 + bytesRequired) % 4);
864 if (paddingBytes == 4)
865 paddingBytes = 0;
866 // add padding length in bits
867 rtcpbuffer[pos] = paddingBytes * 8; // padding can be 0, 8, 16 or 24
868 pos++;
869
870 // add payload type
871 rtcpbuffer[pos] = payloadType;
872 pos++;
873
874 // add picture ID
875 for (int i = bytesRequired - 1; i > 0; --i) {
876 rtcpbuffer[pos] = 0x80 | static_cast<uint8_t>(pictureID >> (i * 7));
niklase@google.com470e71d2011-07-07 08:21:25 +0000877 pos++;
Erik Språng61be2a42015-04-27 13:32:52 +0200878 }
879 // add last byte of picture ID
880 rtcpbuffer[pos] = static_cast<uint8_t>(pictureID & 0x7f);
881 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000882
Erik Språng61be2a42015-04-27 13:32:52 +0200883 // add padding
884 for (int j = 0; j < paddingBytes; j++) {
885 rtcpbuffer[pos] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000886 pos++;
Erik Språng61be2a42015-04-27 13:32:52 +0200887 }
888 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000889}
890
Erik Språng61be2a42015-04-27 13:32:52 +0200891int32_t RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int32_t pos) {
892 // sanity
893 if (pos + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
894 return -2;
895
896 // add application layer feedback
897 uint8_t FMT = 15;
898 rtcpbuffer[pos++] = 0x80 + FMT;
899 rtcpbuffer[pos++] = 206;
900
901 rtcpbuffer[pos++] = 0;
902 rtcpbuffer[pos++] = static_cast<uint8_t>(remb_ssrcs_.size() + 4);
903
904 // Add our own SSRC
905 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
906 pos += 4;
907
908 // Remote SSRC must be 0
909 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, 0);
910 pos += 4;
911
912 rtcpbuffer[pos++] = 'R';
913 rtcpbuffer[pos++] = 'E';
914 rtcpbuffer[pos++] = 'M';
915 rtcpbuffer[pos++] = 'B';
916
917 rtcpbuffer[pos++] = remb_ssrcs_.size();
918 // 6 bit Exp
919 // 18 bit mantissa
920 uint8_t brExp = 0;
921 for (uint32_t i = 0; i < 64; i++) {
922 if (_rembBitrate <= (262143u << i)) {
923 brExp = i;
924 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000925 }
Erik Språng61be2a42015-04-27 13:32:52 +0200926 }
927 const uint32_t brMantissa = (_rembBitrate >> brExp);
928 rtcpbuffer[pos++] = (uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
929 rtcpbuffer[pos++] = (uint8_t)(brMantissa >> 8);
930 rtcpbuffer[pos++] = (uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000931
Erik Språng61be2a42015-04-27 13:32:52 +0200932 for (size_t i = 0; i < remb_ssrcs_.size(); i++) {
933 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, remb_ssrcs_[i]);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000934 pos += 4;
Erik Språng61be2a42015-04-27 13:32:52 +0200935 }
936 return pos;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000937}
938
Erik Språng61be2a42015-04-27 13:32:52 +0200939void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
940 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000941 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000942}
943
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000944int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
945 uint8_t* rtcpbuffer,
Erik Språng61be2a42015-04-27 13:32:52 +0200946 int32_t pos) {
947 if (rtp_rtcp_module == NULL)
948 return -1;
949 // Before sending the TMMBR check the received TMMBN, only an owner is
950 // allowed to raise the bitrate:
951 // * If the sender is an owner of the TMMBN -> send TMMBR
952 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000953
Erik Språng61be2a42015-04-27 13:32:52 +0200954 // get current bounding set from RTCP receiver
955 bool tmmbrOwner = false;
956 // store in candidateSet, allocates one extra slot
957 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000958
Erik Språng61be2a42015-04-27 13:32:52 +0200959 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
960 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
961 // since RTCPreceiver is not doing the reverse we should be fine
962 int32_t lengthOfBoundingSet =
963 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000964
Erik Språng61be2a42015-04-27 13:32:52 +0200965 if (lengthOfBoundingSet > 0) {
966 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
967 if (candidateSet->Tmmbr(i) == _tmmbr_Send &&
968 candidateSet->PacketOH(i) == _packetOH_Send) {
969 // do not send the same tuple
970 return 0;
971 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000972 }
Erik Språng61be2a42015-04-27 13:32:52 +0200973 if (!tmmbrOwner) {
974 // use received bounding set as candidate set
975 // add current tuple
976 candidateSet->SetEntry(lengthOfBoundingSet, _tmmbr_Send, _packetOH_Send,
977 _SSRC);
978 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000979
Erik Språng61be2a42015-04-27 13:32:52 +0200980 // find bounding set
981 TMMBRSet* boundingSet = NULL;
982 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
983 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
984 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
985 if (!tmmbrOwner) {
986 // did not enter bounding set, no meaning to send this request
987 return 0;
988 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000989 }
Erik Språng61be2a42015-04-27 13:32:52 +0200990 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000991
Erik Språng61be2a42015-04-27 13:32:52 +0200992 if (_tmmbr_Send) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000993 // sanity
Erik Språng61be2a42015-04-27 13:32:52 +0200994 if (pos + 20 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +0000995 return -2;
niklase@google.com470e71d2011-07-07 08:21:25 +0000996
Erik Språng61be2a42015-04-27 13:32:52 +0200997 // add TMMBR indicator
998 uint8_t FMT = 3;
999 rtcpbuffer[pos++] = 0x80 + FMT;
1000 rtcpbuffer[pos++] = 205;
1001
1002 // Length of 4
1003 rtcpbuffer[pos++] = 0;
1004 rtcpbuffer[pos++] = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001005
1006 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001007 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001008 pos += 4;
1009
Erik Språng61be2a42015-04-27 13:32:52 +02001010 // RFC 5104 4.2.1.2. Semantics
niklase@google.com470e71d2011-07-07 08:21:25 +00001011
1012 // SSRC of media source
Erik Språng61be2a42015-04-27 13:32:52 +02001013 ByteWriter<uint32_t>::WriteBigEndian(&rtcpbuffer[pos], 0);
1014 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001015
1016 // Additional Feedback Control Information (FCI)
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001017 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001018 pos += 4;
1019
Erik Språng61be2a42015-04-27 13:32:52 +02001020 uint32_t bitRate = _tmmbr_Send * 1000;
1021 uint32_t mmbrExp = 0;
1022 for (uint32_t i = 0; i < 64; i++) {
1023 if (bitRate <= (0x1FFFFu << i)) {
1024 mmbrExp = i;
1025 break;
1026 }
1027 }
1028 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1029
1030 rtcpbuffer[pos++] =
1031 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1032 rtcpbuffer[pos++] = (uint8_t)(mmbrMantissa >> 7);
1033 rtcpbuffer[pos++] = static_cast<uint8_t>((mmbrMantissa << 1) +
1034 ((_packetOH_Send >> 8) & 0x01));
1035 rtcpbuffer[pos++] = static_cast<uint8_t>(_packetOH_Send);
1036 }
1037 return pos;
1038}
1039
1040int32_t RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int32_t pos) {
1041 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1042 if (boundingSet == NULL)
1043 return -1;
1044
1045 // sanity
1046 if (pos + 12 + boundingSet->lengthOfSet() * 8 >= IP_PACKET_SIZE) {
1047 LOG(LS_WARNING) << "Failed to build TMMBN.";
1048 return -2;
1049 }
1050
1051 uint8_t FMT = 4;
1052 // add TMMBN indicator
1053 rtcpbuffer[pos++] = 0x80 + FMT;
1054 rtcpbuffer[pos++] = 205;
1055
1056 // Add length later
1057 int posLength = pos;
1058 pos++;
1059 pos++;
1060
1061 // Add our own SSRC
1062 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
1063 pos += 4;
1064
1065 // RFC 5104 4.2.2.2. Semantics
1066
1067 // SSRC of media source
1068 ByteWriter<uint32_t>::WriteBigEndian(&rtcpbuffer[pos], 0);
1069 pos += 4;
1070
1071 // Additional Feedback Control Information (FCI)
1072 int numBoundingSet = 0;
1073 for (uint32_t n = 0; n < boundingSet->lengthOfSet(); n++) {
1074 if (boundingSet->Tmmbr(n) > 0) {
1075 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
1076 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, tmmbrSSRC);
1077 pos += 4;
1078
1079 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1080 uint32_t mmbrExp = 0;
1081 for (int i = 0; i < 64; i++) {
1082 if (bitRate <= (0x1FFFFu << i)) {
1083 mmbrExp = i;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001084 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001085 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001086 }
Erik Språng61be2a42015-04-27 13:32:52 +02001087 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1088 uint32_t measuredOH = boundingSet->PacketOH(n);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001089
Erik Språng61be2a42015-04-27 13:32:52 +02001090 rtcpbuffer[pos++] =
1091 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1092 rtcpbuffer[pos++] = (uint8_t)(mmbrMantissa >> 7);
1093 rtcpbuffer[pos++] = static_cast<uint8_t>((mmbrMantissa << 1) +
1094 ((measuredOH >> 8) & 0x01));
1095 rtcpbuffer[pos++] = static_cast<uint8_t>(measuredOH);
1096 numBoundingSet++;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001097 }
Erik Språng61be2a42015-04-27 13:32:52 +02001098 }
1099 uint16_t length = static_cast<uint16_t>(2 + 2 * numBoundingSet);
1100 rtcpbuffer[posLength++] = static_cast<uint8_t>(length >> 8);
1101 rtcpbuffer[posLength] = static_cast<uint8_t>(length);
1102 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001103}
1104
Erik Språng61be2a42015-04-27 13:32:52 +02001105int32_t RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int32_t pos) {
1106 // sanity
1107 if (_appData == NULL) {
1108 LOG(LS_WARNING) << "Failed to build app specific.";
1109 return -1;
1110 }
1111 if (pos + 12 + _appLength >= IP_PACKET_SIZE) {
1112 LOG(LS_WARNING) << "Failed to build app specific.";
1113 return -2;
1114 }
1115 rtcpbuffer[pos++] = 0x80 + _appSubType;
1116
1117 // Add APP ID
1118 rtcpbuffer[pos++] = 204;
1119
1120 uint16_t length = (_appLength >> 2) + 2; // include SSRC and name
1121 rtcpbuffer[pos++] = static_cast<uint8_t>(length >> 8);
1122 rtcpbuffer[pos++] = static_cast<uint8_t>(length);
1123
1124 // Add our own SSRC
1125 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
1126 pos += 4;
1127
1128 // Add our application name
1129 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _appName);
1130 pos += 4;
1131
1132 // Add the data
1133 memcpy(rtcpbuffer + pos, _appData.get(), _appLength);
1134 pos += _appLength;
1135 return pos;
1136}
1137
1138int32_t RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1139 int32_t pos,
1140 int32_t nackSize,
1141 const uint16_t* nackList,
1142 std::string* nackString) {
1143 // sanity
1144 if (pos + 16 >= IP_PACKET_SIZE) {
1145 LOG(LS_WARNING) << "Failed to build NACK.";
1146 return -2;
1147 }
1148
1149 // int size, uint16_t* nackList
1150 // add nack list
1151 uint8_t FMT = 1;
1152 rtcpbuffer[pos++] = 0x80 + FMT;
1153 rtcpbuffer[pos++] = 205;
1154
1155 rtcpbuffer[pos++] = 0;
1156 int nackSizePos = pos;
1157 rtcpbuffer[pos++] = 3; // setting it to one kNACK signal as default
1158
1159 // Add our own SSRC
1160 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
1161 pos += 4;
1162
1163 // Add the remote SSRC
1164 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
1165 pos += 4;
1166
1167 // Build NACK bitmasks and write them to the RTCP message.
1168 // The nack list should be sorted and not contain duplicates if one
1169 // wants to build the smallest rtcp nack packet.
1170 int numOfNackFields = 0;
1171 int maxNackFields =
1172 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - pos) / 4);
1173 int i = 0;
1174 while (i < nackSize && numOfNackFields < maxNackFields) {
1175 uint16_t nack = nackList[i++];
1176 uint16_t bitmask = 0;
1177 while (i < nackSize) {
1178 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1179 if (shift >= 0 && shift <= 15) {
1180 bitmask |= (1 << shift);
1181 ++i;
1182 } else {
1183 break;
1184 }
1185 }
1186 // Write the sequence number and the bitmask to the packet.
1187 assert(pos + 4 < IP_PACKET_SIZE);
1188 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + pos, nack);
1189 pos += 2;
1190 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + pos, bitmask);
1191 pos += 2;
1192 numOfNackFields++;
1193 }
1194 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
1195
1196 if (i != nackSize)
1197 LOG(LS_WARNING) << "Nack list too large for one packet.";
1198
1199 // Report stats.
1200 NACKStringBuilder stringBuilder;
1201 for (int idx = 0; idx < i; ++idx) {
1202 stringBuilder.PushNACK(nackList[idx]);
1203 nack_stats_.ReportRequest(nackList[idx]);
1204 }
1205 *nackString = stringBuilder.GetResult();
1206 packet_type_counter_.nack_requests = nack_stats_.requests();
1207 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
1208 return pos;
1209}
1210
1211int32_t RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int32_t pos) {
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001212 // sanity
1213 if (pos + 8 >= IP_PACKET_SIZE) {
1214 return -2;
1215 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001216
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001217 // Add a bye packet
1218 // Number of SSRC + CSRCs.
Erik Språng61be2a42015-04-27 13:32:52 +02001219 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + csrcs_.size());
1220 rtcpbuffer[pos++] = 203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001221
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001222 // length
Erik Språng61be2a42015-04-27 13:32:52 +02001223 rtcpbuffer[pos++] = 0;
1224 rtcpbuffer[pos++] = static_cast<uint8_t>(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001225
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001226 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001227 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001228 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001229
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001230 // add CSRCs
1231 for (size_t i = 0; i < csrcs_.size(); i++) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001232 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, csrcs_[i]);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001233 pos += 4;
1234 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001235
Erik Språng61be2a42015-04-27 13:32:52 +02001236 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001237}
1238
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001239int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
Erik Språng61be2a42015-04-27 13:32:52 +02001240 int32_t pos,
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001241 uint32_t ntp_sec,
1242 uint32_t ntp_frac) {
1243 const int kRrTimeBlockLength = 20;
Erik Språng61be2a42015-04-27 13:32:52 +02001244 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001245 return -2;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001246
Erik Språng61be2a42015-04-27 13:32:52 +02001247 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001248 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001249 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1250 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1251 Clock::NtpToMs(ntp_sec, ntp_frac)));
1252
1253 // Add XR header.
1254 buffer[pos++] = 0x80;
1255 buffer[pos++] = 207;
1256 buffer[pos++] = 0; // XR packet length.
1257 buffer[pos++] = 4; // XR packet length.
1258
1259 // Add our own SSRC.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001260 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001261 pos += 4;
1262
1263 // 0 1 2 3
1264 // 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
1265 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1266 // | BT=4 | reserved | block length = 2 |
1267 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1268 // | NTP timestamp, most significant word |
1269 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1270 // | NTP timestamp, least significant word |
1271 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1272
1273 // Add Receiver Reference Time Report block.
1274 buffer[pos++] = 4; // BT.
1275 buffer[pos++] = 0; // Reserved.
1276 buffer[pos++] = 0; // Block length.
1277 buffer[pos++] = 2; // Block length.
1278
1279 // NTP timestamp.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001280 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001281 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001282 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001283 pos += 4;
1284
Erik Språng61be2a42015-04-27 13:32:52 +02001285 return pos;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001286}
1287
1288int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
Erik Språng61be2a42015-04-27 13:32:52 +02001289 int32_t pos,
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001290 const RtcpReceiveTimeInfo& info) {
1291 const int kDlrrBlockLength = 24;
Erik Språng61be2a42015-04-27 13:32:52 +02001292 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001293 return -2;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001294
1295 // Add XR header.
1296 buffer[pos++] = 0x80;
1297 buffer[pos++] = 207;
1298 buffer[pos++] = 0; // XR packet length.
1299 buffer[pos++] = 5; // XR packet length.
1300
1301 // Add our own SSRC.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001302 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001303 pos += 4;
1304
1305 // 0 1 2 3
1306 // 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
1307 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1308 // | BT=5 | reserved | block length |
1309 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1310 // | SSRC_1 (SSRC of first receiver) | sub-
1311 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1312 // | last RR (LRR) | 1
1313 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1314 // | delay since last RR (DLRR) |
1315 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1316 // | SSRC_2 (SSRC of second receiver) | sub-
1317 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1318 // : ... : 2
1319
1320 // Add DLRR sub block.
1321 buffer[pos++] = 5; // BT.
1322 buffer[pos++] = 0; // Reserved.
1323 buffer[pos++] = 0; // Block length.
1324 buffer[pos++] = 3; // Block length.
1325
1326 // NTP timestamp.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001327 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001328 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001329 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001330 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001331 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001332 pos += 4;
1333
Erik Språng61be2a42015-04-27 13:32:52 +02001334 return pos;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001335}
1336
Erik Språng61be2a42015-04-27 13:32:52 +02001337int32_t RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int32_t pos) {
1338 // sanity
1339 if (pos + 44 >= IP_PACKET_SIZE)
1340 return -2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001341
Erik Språng61be2a42015-04-27 13:32:52 +02001342 // Add XR header
1343 rtcpbuffer[pos++] = 0x80;
1344 rtcpbuffer[pos++] = 207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001345
Erik Språng61be2a42015-04-27 13:32:52 +02001346 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001347
Erik Språng61be2a42015-04-27 13:32:52 +02001348 // handle length later on
1349 pos++;
1350 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001351
Erik Språng61be2a42015-04-27 13:32:52 +02001352 // Add our own SSRC
1353 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
1354 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001355
Erik Språng61be2a42015-04-27 13:32:52 +02001356 // Add a VoIP metrics block
1357 rtcpbuffer[pos++] = 7;
1358 rtcpbuffer[pos++] = 0;
1359 rtcpbuffer[pos++] = 0;
1360 rtcpbuffer[pos++] = 8;
niklase@google.com470e71d2011-07-07 08:21:25 +00001361
Erik Språng61be2a42015-04-27 13:32:52 +02001362 // Add the remote SSRC
1363 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
1364 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001365
Erik Språng61be2a42015-04-27 13:32:52 +02001366 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1367 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1368 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1369 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
niklase@google.com470e71d2011-07-07 08:21:25 +00001370
Erik Språng61be2a42015-04-27 13:32:52 +02001371 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.burstDuration >> 8);
1372 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.burstDuration);
1373 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.gapDuration >> 8);
1374 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001375
Erik Språng61be2a42015-04-27 13:32:52 +02001376 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.roundTripDelay >> 8);
1377 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.roundTripDelay);
1378 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.endSystemDelay >> 8);
1379 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001380
Erik Språng61be2a42015-04-27 13:32:52 +02001381 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1382 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1383 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1384 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
niklase@google.com470e71d2011-07-07 08:21:25 +00001385
Erik Språng61be2a42015-04-27 13:32:52 +02001386 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1387 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1388 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1389 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
niklase@google.com470e71d2011-07-07 08:21:25 +00001390
Erik Språng61be2a42015-04-27 13:32:52 +02001391 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1392 rtcpbuffer[pos++] = 0; // reserved
1393 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.JBnominal >> 8);
1394 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001395
Erik Språng61be2a42015-04-27 13:32:52 +02001396 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.JBmax >> 8);
1397 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.JBmax);
1398 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.JBabsMax >> 8);
1399 rtcpbuffer[pos++] = static_cast<uint8_t>(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001400
Erik Språng61be2a42015-04-27 13:32:52 +02001401 rtcpbuffer[XRLengthPos] = 0;
1402 rtcpbuffer[XRLengthPos + 1] = 10;
1403 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001404}
1405
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001406int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1407 uint32_t packetTypeFlags,
1408 int32_t nackSize,
1409 const uint16_t* nackList,
1410 bool repeat,
1411 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001412 {
Erik Språng61be2a42015-04-27 13:32:52 +02001413 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
1414 if (_method == kRtcpOff) {
1415 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1416 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001417 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001418 }
1419 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001420 int rtcp_length = PrepareRTCP(feedback_state,
1421 packetTypeFlags,
1422 nackSize,
1423 nackList,
1424 repeat,
1425 pictureID,
1426 rtcp_buffer,
1427 IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +02001428 if (rtcp_length < 0)
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001429 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001430
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001431 // Sanity don't send empty packets.
1432 if (rtcp_length == 0)
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001433 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001434
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001435 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001436}
1437
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001438int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1439 uint32_t packetTypeFlags,
1440 int32_t nackSize,
1441 const uint16_t* nackList,
1442 bool repeat,
1443 uint64_t pictureID,
1444 uint8_t* rtcp_buffer,
1445 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001446 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1447 // Collect the received information.
1448 uint32_t NTPsec = 0;
1449 uint32_t NTPfrac = 0;
1450 uint32_t jitterTransmissionOffset = 0;
1451 int position = 0;
1452
Erik Språng61be2a42015-04-27 13:32:52 +02001453 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001454
Erik Språng61be2a42015-04-27 13:32:52 +02001455 if (packet_type_counter_.first_packet_time_ms == -1)
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001456 packet_type_counter_.first_packet_time_ms = _clock->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +02001457
1458 // Attach TMMBR to send and receive reports.
1459 if (_TMMBR)
1460 rtcpPacketTypeFlags |= kRtcpTmmbr;
1461 if (_appSend) {
1462 rtcpPacketTypeFlags |= kRtcpApp;
1463 _appSend = false;
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001464 }
1465
Erik Språng61be2a42015-04-27 13:32:52 +02001466 if (_REMB && _sendREMB) {
1467 // Always attach REMB to SR if that is configured. Note that REMB is
1468 // only sent on one of the RTP modules in the REMB group.
1469 rtcpPacketTypeFlags |= kRtcpRemb;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001470 }
Erik Språng61be2a42015-04-27 13:32:52 +02001471 if (_xrSendVoIPMetric) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001472 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1473 _xrSendVoIPMetric = false;
1474 }
Erik Språng61be2a42015-04-27 13:32:52 +02001475 // Set when having received a TMMBR.
1476 if (_sendTMMBN) {
1477 rtcpPacketTypeFlags |= kRtcpTmmbn;
1478 _sendTMMBN = false;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001479 }
Erik Språng61be2a42015-04-27 13:32:52 +02001480 if (rtcpPacketTypeFlags & kRtcpReport) {
1481 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
1482 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1483 if (feedback_state.has_last_xr_rr)
1484 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001485 }
Erik Språng61be2a42015-04-27 13:32:52 +02001486 if (_method == kRtcpCompound) {
1487 if (_sending) {
1488 rtcpPacketTypeFlags |= kRtcpSr;
1489 } else {
1490 rtcpPacketTypeFlags |= kRtcpRr;
1491 }
1492 } else if (_method == kRtcpNonCompound) {
1493 if (rtcpPacketTypeFlags & kRtcpReport) {
1494 if (_sending) {
1495 rtcpPacketTypeFlags |= kRtcpSr;
1496 } else {
1497 rtcpPacketTypeFlags |= kRtcpRr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001498 }
Erik Språng61be2a42015-04-27 13:32:52 +02001499 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001500 }
Erik Språng61be2a42015-04-27 13:32:52 +02001501 if ((rtcpPacketTypeFlags & kRtcpRr) || (rtcpPacketTypeFlags & kRtcpSr)) {
1502 // generate next time to send a RTCP report
1503 // seeded from RTP constructor
1504 int32_t random = rand() % 1000;
1505 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001506
Erik Språng61be2a42015-04-27 13:32:52 +02001507 if (_audio) {
1508 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1509 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1510 } else {
1511 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1512 if (_sending) {
1513 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1514 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1515 if (send_bitrate_kbit != 0)
1516 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001517 }
Erik Språng61be2a42015-04-27 13:32:52 +02001518 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1519 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1520 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1521 }
1522 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001523 }
1524
1525 // If the data does not fit in the packet we fill it as much as possible.
1526 int32_t buildVal = 0;
1527
1528 // We need to send our NTP even if we haven't received any reports.
1529 _clock->CurrentNtp(NTPsec, NTPfrac);
1530 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1531 StatisticianMap statisticians =
1532 receive_statistics_->GetActiveStatisticians();
1533 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001534 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001535 RTCPReportBlock report_block;
Erik Språng61be2a42015-04-27 13:32:52 +02001536 if (PrepareReport(feedback_state, it->second, &report_block, &NTPsec,
1537 &NTPfrac)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001538 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001539 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001540 }
Erik Språng61be2a42015-04-27 13:32:52 +02001541 if (_IJ && !statisticians.empty())
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001542 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001543 }
1544 }
1545
Erik Språng61be2a42015-04-27 13:32:52 +02001546 if (rtcpPacketTypeFlags & kRtcpSr) {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001547 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
Erik Språng61be2a42015-04-27 13:32:52 +02001548 switch (buildVal) {
1549 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001550 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001551 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001552 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001553 default:
1554 position = buildVal;
1555 }
1556 buildVal = BuildSDEC(rtcp_buffer, position);
1557 switch (buildVal) {
1558 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001559 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001560 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001561 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001562 default:
1563 position = buildVal;
1564 }
1565 } else if (rtcpPacketTypeFlags & kRtcpRr) {
1566 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1567 switch (buildVal) {
1568 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001569 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001570 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001571 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001572 default:
1573 position = buildVal;
1574 }
1575 // only of set
1576 if (_CNAME[0] != 0) {
1577 if (BuildSDEC(rtcp_buffer, position) == -1)
1578 return -1;
1579 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001580 }
Erik Språng61be2a42015-04-27 13:32:52 +02001581 if (rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset) {
1582 // If present, this RTCP packet must be placed after a
1583 // receiver report.
1584 buildVal = BuildExtendedJitterReport(rtcp_buffer, position,
1585 jitterTransmissionOffset);
1586 switch (buildVal) {
1587 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001588 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001589 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001590 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001591 default:
1592 position = buildVal;
1593 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001594 }
Erik Språng61be2a42015-04-27 13:32:52 +02001595 if (rtcpPacketTypeFlags & kRtcpPli) {
1596 buildVal = BuildPLI(rtcp_buffer, position);
1597 switch (buildVal) {
1598 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001599 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001600 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001601 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001602 default:
1603 position = buildVal;
1604 }
1605 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1606 "RTCPSender::PLI");
1607 ++packet_type_counter_.pli_packets;
1608 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
1609 _SSRC, packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001610 }
Erik Språng61be2a42015-04-27 13:32:52 +02001611 if (rtcpPacketTypeFlags & kRtcpFir) {
1612 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1613 switch (buildVal) {
1614 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001615 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001616 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001617 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001618 default:
1619 position = buildVal;
1620 }
1621 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1622 "RTCPSender::FIR");
1623 ++packet_type_counter_.fir_packets;
1624 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
1625 _SSRC, packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001626 }
Erik Språng61be2a42015-04-27 13:32:52 +02001627 if (rtcpPacketTypeFlags & kRtcpSli) {
1628 buildVal = BuildSLI(rtcp_buffer, position, pictureID);
1629 switch (buildVal) {
1630 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001631 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001632 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001633 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001634 default:
1635 position = buildVal;
1636 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001637 }
Erik Språng61be2a42015-04-27 13:32:52 +02001638 if (rtcpPacketTypeFlags & kRtcpRpsi) {
1639 const int8_t payloadType = feedback_state.send_payload_type;
1640 if (payloadType == -1)
1641 return -1;
1642 buildVal = BuildRPSI(rtcp_buffer, position, pictureID, payloadType);
1643 switch (buildVal) {
1644 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001645 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001646 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001647 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001648 default:
1649 position = buildVal;
1650 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001651 }
Erik Språng61be2a42015-04-27 13:32:52 +02001652 if (rtcpPacketTypeFlags & kRtcpRemb) {
1653 buildVal = BuildREMB(rtcp_buffer, position);
1654 switch (buildVal) {
1655 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001656 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001657 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001658 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001659 default:
1660 position = buildVal;
1661 }
1662 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1663 "RTCPSender::REMB");
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001664 }
Erik Språng61be2a42015-04-27 13:32:52 +02001665 if (rtcpPacketTypeFlags & kRtcpBye) {
1666 buildVal = BuildBYE(rtcp_buffer, position);
1667 switch (buildVal) {
1668 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001669 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001670 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001671 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001672 default:
1673 position = buildVal;
1674 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001675 }
Erik Språng61be2a42015-04-27 13:32:52 +02001676 if (rtcpPacketTypeFlags & kRtcpApp) {
1677 buildVal = BuildAPP(rtcp_buffer, position);
1678 switch (buildVal) {
1679 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001680 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001681 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001682 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001683 default:
1684 position = buildVal;
1685 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001686 }
Erik Språng61be2a42015-04-27 13:32:52 +02001687 if (rtcpPacketTypeFlags & kRtcpTmmbr) {
1688 switch (buildVal =
1689 BuildTMMBR(feedback_state.module, rtcp_buffer, position)) {
1690 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001691 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001692 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001693 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001694 default:
1695 position = buildVal;
1696 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001697 }
Erik Språng61be2a42015-04-27 13:32:52 +02001698 if (rtcpPacketTypeFlags & kRtcpTmmbn) {
1699 buildVal = BuildTMMBN(rtcp_buffer, position);
1700 switch (buildVal) {
1701 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001702 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001703 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001704 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001705 default:
1706 position = buildVal;
1707 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001708 }
Erik Språng61be2a42015-04-27 13:32:52 +02001709 if (rtcpPacketTypeFlags & kRtcpNack) {
1710 std::string nackString;
1711 switch (buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1712 &nackString)) {
1713 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001714 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001715 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001716 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001717 default:
1718 position = buildVal;
1719 }
1720 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1721 "RTCPSender::NACK", "nacks",
1722 TRACE_STR_COPY(nackString.c_str()));
1723 ++packet_type_counter_.nack_packets;
1724 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
1725 _SSRC, packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001726 }
Erik Språng61be2a42015-04-27 13:32:52 +02001727 if (rtcpPacketTypeFlags & kRtcpXrVoipMetric) {
1728 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1729 switch (buildVal) {
1730 case -1:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001731 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001732 case -2:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001733 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001734 default:
1735 position = buildVal;
1736 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001737 }
Erik Språng61be2a42015-04-27 13:32:52 +02001738 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime) {
1739 buildVal =
1740 BuildReceiverReferenceTime(rtcp_buffer, position, NTPsec, NTPfrac);
1741 switch (buildVal) {
1742 case -1:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001743 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001744 case -2:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001745 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001746 default:
1747 position = buildVal;
1748 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001749 }
Erik Språng61be2a42015-04-27 13:32:52 +02001750 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock) {
1751 switch (buildVal =
1752 BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr)) {
1753 case -1:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001754 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001755 case -2:
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001756 return position;
Erik Språng61be2a42015-04-27 13:32:52 +02001757 default:
1758 position = buildVal;
1759 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001760 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001761
1762 if (packet_type_counter_observer_ != NULL) {
1763 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
1764 _remoteSSRC, packet_type_counter_);
1765 }
1766
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001767 return position;
1768}
1769
1770bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1771 return Status() == kRtcpCompound ||
1772 (rtcp_packet_type & kRtcpReport) ||
1773 (rtcp_packet_type & kRtcpSr) ||
1774 (rtcp_packet_type & kRtcpRr);
1775}
1776
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001777bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1778 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001779 RTCPReportBlock* report_block,
1780 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1781 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001782 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001783 if (!statistician->GetStatistics(&stats, true))
1784 return false;
1785 report_block->fractionLost = stats.fraction_lost;
1786 report_block->cumulativeLost = stats.cumulative_lost;
1787 report_block->extendedHighSeqNum =
1788 stats.extended_max_sequence_number;
1789 report_block->jitter = stats.jitter;
1790
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001791 // get our NTP as late as possible to avoid a race
1792 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1793
1794 // Delay since last received report
1795 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001796 if ((feedback_state.last_rr_ntp_secs != 0) ||
1797 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001798 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
Erik Språng61be2a42015-04-27 13:32:52 +02001799 uint32_t now = *ntp_secs & 0x0000FFFF;
1800 now <<= 16;
1801 now += (*ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001802
Erik Språng61be2a42015-04-27 13:32:52 +02001803 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1804 receiveTime <<= 16;
1805 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001806
1807 delaySinceLastReceivedSR = now-receiveTime;
1808 }
1809 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001810 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001811 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001812}
1813
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001814int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001815 CriticalSectionScoped lock(_criticalSectionTransport.get());
1816 if (_cbTransport) {
1817 if (_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1818 return 0;
1819 }
1820 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001821}
1822
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001823void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1824 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng61be2a42015-04-27 13:32:52 +02001825 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001826 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001827}
1828
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001829int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1830 uint32_t name,
1831 const uint8_t* data,
1832 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001833 if (length % 4 != 0) {
1834 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1835 return -1;
1836 }
1837 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001838
Erik Språng61be2a42015-04-27 13:32:52 +02001839 _appSend = true;
1840 _appSubType = subType;
1841 _appName = name;
1842 _appData.reset(new uint8_t[length]);
1843 _appLength = length;
1844 memcpy(_appData.get(), data, length);
1845 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001846}
1847
Erik Språng61be2a42015-04-27 13:32:52 +02001848int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
1849 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
1850 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001851
Erik Språng61be2a42015-04-27 13:32:52 +02001852 _xrSendVoIPMetric = true;
1853 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001854}
1855
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001856void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng61be2a42015-04-27 13:32:52 +02001857 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001858 xrSendReceiverReferenceTimeEnabled_ = enable;
1859}
1860
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001861bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng61be2a42015-04-27 13:32:52 +02001862 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001863 return xrSendReceiverReferenceTimeEnabled_;
1864}
1865
niklase@google.com470e71d2011-07-07 08:21:25 +00001866// called under critsect _criticalSectionRTCPSender
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001867int32_t RTCPSender::WriteAllReportBlocksToBuffer(uint8_t* rtcpbuffer,
1868 int pos,
Erik Språng61be2a42015-04-27 13:32:52 +02001869 uint8_t* numberOfReportBlocks,
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001870 uint32_t NTPsec,
1871 uint32_t NTPfrac) {
Erik Språng61be2a42015-04-27 13:32:52 +02001872 *numberOfReportBlocks = external_report_blocks_.size();
1873 *numberOfReportBlocks += internal_report_blocks_.size();
1874 if ((pos + *numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001875 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001876 return -1;
1877 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001878 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
1879 while (!internal_report_blocks_.empty()) {
1880 delete internal_report_blocks_.begin()->second;
1881 internal_report_blocks_.erase(internal_report_blocks_.begin());
1882 }
1883 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
1884 return pos;
1885}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001886
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001887int32_t RTCPSender::WriteReportBlocksToBuffer(
1888 uint8_t* rtcpbuffer,
1889 int32_t position,
1890 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
1891 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
1892 report_blocks.begin();
1893 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001894 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001895 RTCPReportBlock* reportBlock = it->second;
1896 if (reportBlock) {
1897 // Remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001898 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001899 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001900
1901 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001902 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001903
1904 // cumulative loss
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001905 ByteWriter<uint32_t, 3>::WriteBigEndian(rtcpbuffer + position,
1906 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001907 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001908
1909 // extended highest seq_no, contain the highest sequence number received
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001910 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
1911 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001912 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001913
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001914 // Jitter
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001915 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
1916 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001917 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001918
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001919 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
1920 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001921 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001922
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001923 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
1924 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001925 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001926 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001927 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001928 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00001929}
1930
1931// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001932int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1933 uint32_t maxBitrateKbit) {
Erik Språng61be2a42015-04-27 13:32:52 +02001934 CriticalSectionScoped lock(_criticalSectionRTCPSender.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001935
Erik Språng61be2a42015-04-27 13:32:52 +02001936 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1937 _sendTMMBN = true;
1938 return 0;
1939 }
1940 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001941}
Erik Språng61be2a42015-04-27 13:32:52 +02001942
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001943} // namespace webrtc