blob: 7bf38a6f9ea076df600f7989091f48479e106629 [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
18
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000019#include "webrtc/common_types.h"
20#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
21#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000022#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000024
niklase@google.com470e71d2011-07-07 08:21:25 +000025namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000026
27using RTCPUtility::RTCPCnameInformation;
28
edjee@google.com79b02892013-04-04 19:43:34 +000029NACKStringBuilder::NACKStringBuilder() :
30 _stream(""), _count(0), _consecutive(false)
31{
32 // Empty.
33}
34
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000035NACKStringBuilder::~NACKStringBuilder() {}
36
pbos@webrtc.org2f446732013-04-08 11:08:41 +000037void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000038{
39 if (_count == 0)
40 {
41 _stream << nack;
42 } else if (nack == _prevNack + 1)
43 {
44 _consecutive = true;
45 } else
46 {
47 if (_consecutive)
48 {
49 _stream << "-" << _prevNack;
50 _consecutive = false;
51 }
52 _stream << "," << nack;
53 }
54 _count++;
55 _prevNack = nack;
56}
57
58std::string NACKStringBuilder::GetResult()
59{
60 if (_consecutive)
61 {
62 _stream << "-" << _prevNack;
63 _consecutive = false;
64 }
65 return _stream.str();
66}
67
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068RTCPSender::FeedbackState::FeedbackState()
69 : send_payload_type(0),
70 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000071 packets_sent(0),
72 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000073 send_bitrate(0),
74 last_rr_ntp_secs(0),
75 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000076 remote_sr(0),
77 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000079RTCPSender::RTCPSender(int32_t id,
80 bool audio,
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000081 Clock* clock,
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000082 ReceiveStatistics* receive_statistics)
83 : _id(id),
84 _audio(audio),
85 _clock(clock),
86 _method(kRtcpOff),
87 _criticalSectionTransport(
88 CriticalSectionWrapper::CreateCriticalSection()),
89 _cbTransport(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000090
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000091 _criticalSectionRTCPSender(
92 CriticalSectionWrapper::CreateCriticalSection()),
93 _usingNack(false),
94 _sending(false),
95 _sendTMMBN(false),
96 _REMB(false),
97 _sendREMB(false),
98 _TMMBR(false),
99 _IJ(false),
100 _nextTimeToSendRTCP(0),
101 start_timestamp_(0),
102 last_rtp_timestamp_(0),
103 last_frame_capture_time_ms_(-1),
104 _SSRC(0),
105 _remoteSSRC(0),
106 _CNAME(),
107 receive_statistics_(receive_statistics),
108 internal_report_blocks_(),
109 external_report_blocks_(),
110 _csrcCNAMEs(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000111
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000112 _cameraDelayMS(0),
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000113
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000114 _lastSendReport(),
115 _lastRTCPTime(),
niklase@google.com470e71d2011-07-07 08:21:25 +0000116
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000117 last_xr_rr_(),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000118
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000119 _sequenceNumberFIR(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000120
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000121 _rembBitrate(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000122
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000123 _tmmbrHelp(),
124 _tmmbr_Send(0),
125 _packetOH_Send(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000126
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000127 _appSend(false),
128 _appSubType(0),
129 _appName(),
130 _appData(NULL),
131 _appLength(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000132
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000133 xrSendReceiverReferenceTimeEnabled_(false),
134 _xrSendVoIPMetric(false),
135 _xrVoIPMetric() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000136 memset(_CNAME, 0, sizeof(_CNAME));
137 memset(_lastSendReport, 0, sizeof(_lastSendReport));
138 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000139}
140
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000141RTCPSender::~RTCPSender() {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000142 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000143
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000144 while (!internal_report_blocks_.empty()) {
145 delete internal_report_blocks_.begin()->second;
146 internal_report_blocks_.erase(internal_report_blocks_.begin());
147 }
148 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000149 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000150 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000151 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000152 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000153 }
154 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000155 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000156 _csrcCNAMEs.begin();
157 delete it->second;
158 _csrcCNAMEs.erase(it);
159 }
160 delete _criticalSectionTransport;
161 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000162}
163
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000164int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000165RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
166{
167 CriticalSectionScoped lock(_criticalSectionTransport);
168 _cbTransport = outgoingTransport;
169 return 0;
170}
171
172RTCPMethod
173RTCPSender::Status() const
174{
175 CriticalSectionScoped lock(_criticalSectionRTCPSender);
176 return _method;
177}
178
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000179void RTCPSender::SetRTCPStatus(RTCPMethod method) {
180 CriticalSectionScoped lock(_criticalSectionRTCPSender);
181 _method = method;
182
183 if (method == kRtcpOff)
184 return;
185 _nextTimeToSendRTCP =
186 _clock->TimeInMilliseconds() +
187 (_audio ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
190bool
191RTCPSender::Sending() const
192{
193 CriticalSectionScoped lock(_criticalSectionRTCPSender);
194 return _sending;
195}
196
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000197int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000198RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000199{
200 bool sendRTCPBye = false;
201 {
202 CriticalSectionScoped lock(_criticalSectionRTCPSender);
203
204 if(_method != kRtcpOff)
205 {
206 if(sending == false && _sending == true)
207 {
208 // Trigger RTCP bye
209 sendRTCPBye = true;
210 }
211 }
212 _sending = sending;
213 }
214 if(sendRTCPBye)
215 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000216 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000217 }
218 return 0;
219}
220
221bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000222RTCPSender::REMB() const
223{
224 CriticalSectionScoped lock(_criticalSectionRTCPSender);
225 return _REMB;
226}
227
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000228void RTCPSender::SetREMBStatus(bool enable) {
229 CriticalSectionScoped lock(_criticalSectionRTCPSender);
230 _REMB = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000231}
232
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000233void RTCPSender::SetREMBData(uint32_t bitrate,
234 const std::vector<uint32_t>& ssrcs) {
235 CriticalSectionScoped lock(_criticalSectionRTCPSender);
236 _rembBitrate = bitrate;
237 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000238
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000239 _sendREMB = true;
240 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
241 // throttled by the caller.
242 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
245bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000246RTCPSender::TMMBR() const
247{
248 CriticalSectionScoped lock(_criticalSectionRTCPSender);
249 return _TMMBR;
250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetTMMBRStatus(bool enable) {
253 CriticalSectionScoped lock(_criticalSectionRTCPSender);
254 _TMMBR = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000255}
256
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000257bool
258RTCPSender::IJ() const
259{
260 CriticalSectionScoped lock(_criticalSectionRTCPSender);
261 return _IJ;
262}
263
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000264void RTCPSender::SetIJStatus(bool enable) {
265 CriticalSectionScoped lock(_criticalSectionRTCPSender);
266 _IJ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000267}
268
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000269void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000270 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000271 start_timestamp_ = start_timestamp;
272}
273
274void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
275 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000276 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000277 last_rtp_timestamp_ = rtp_timestamp;
278 if (capture_time_ms < 0) {
279 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000280 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000281 } else {
282 last_frame_capture_time_ms_ = capture_time_ms;
283 }
284}
285
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000286void RTCPSender::SetSSRC(uint32_t ssrc) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000287 CriticalSectionScoped lock(_criticalSectionRTCPSender);
288
289 if(_SSRC != 0)
290 {
291 // not first SetSSRC, probably due to a collision
292 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000293 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000294 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000295 }
296 _SSRC = ssrc;
297}
298
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000299void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000300{
301 CriticalSectionScoped lock(_criticalSectionRTCPSender);
302 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000305int32_t RTCPSender::SetCameraDelay(int32_t delayMS) {
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000306 CriticalSectionScoped lock(_criticalSectionRTCPSender);
307 if(delayMS > 1000 || delayMS < -1000)
308 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000309 LOG(LS_WARNING) << "Delay can't be larger than 1 second: "
310 << delayMS << " ms";
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000311 return -1;
312 }
313 _cameraDelayMS = delayMS;
314 return 0;
315}
316
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000317int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000318 if (!cName)
319 return -1;
320
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000321 CriticalSectionScoped lock(_criticalSectionRTCPSender);
322 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
323 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
324 return 0;
325}
326
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000327int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000328 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000329 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000330 CriticalSectionScoped lock(_criticalSectionRTCPSender);
331 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
332 return -1;
333 }
334 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000335 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
336 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 _csrcCNAMEs[SSRC] = ptr;
338 return 0;
339}
340
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000341int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000343 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 _csrcCNAMEs.find(SSRC);
345
346 if (it == _csrcCNAMEs.end()) {
347 return -1;
348 }
349 delete it->second;
350 _csrcCNAMEs.erase(it);
351 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000352}
353
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000354bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000355/*
356 For audio we use a fix 5 sec interval
357
358 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000359 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
360 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
362
363From RFC 3550
364
365 MAX RTCP BW is 5% if the session BW
366 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000367 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
369 The RECOMMENDED value for the reduced minimum in seconds is 360
370 divided by the session bandwidth in kilobits/second. This minimum
371 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
372
373 If the participant has not yet sent an RTCP packet (the variable
374 initial is true), the constant Tmin is set to 2.5 seconds, else it
375 is set to 5 seconds.
376
377 The interval between RTCP packets is varied randomly over the
378 range [0.5,1.5] times the calculated interval to avoid unintended
379 synchronization of all participants
380
381 if we send
382 If the participant is a sender (we_sent true), the constant C is
383 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
384 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
385 number of senders.
386
387 if we receive only
388 If we_sent is not true, the constant C is set
389 to the average RTCP packet size divided by 75% of the RTCP
390 bandwidth. The constant n is set to the number of receivers
391 (members - senders). If the number of senders is greater than
392 25%, senders and receivers are treated together.
393
394 reconsideration NOT required for peer-to-peer
395 "timer reconsideration" is
396 employed. This algorithm implements a simple back-off mechanism
397 which causes users to hold back RTCP packet transmission if the
398 group sizes are increasing.
399
400 n = number of members
401 C = avg_size/(rtcpBW/4)
402
403 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
404
405 4. The calculated interval T is set to a number uniformly distributed
406 between 0.5 and 1.5 times the deterministic calculated interval.
407
408 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
409 for the fact that the timer reconsideration algorithm converges to
410 a value of the RTCP bandwidth below the intended average
411*/
412
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000413 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000414
415 CriticalSectionScoped lock(_criticalSectionRTCPSender);
416
niklase@google.com470e71d2011-07-07 08:21:25 +0000417 if(_method == kRtcpOff)
418 {
419 return false;
420 }
421
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 if(!_audio && sendKeyframeBeforeRTP)
423 {
424 // for video key-frames we want to send the RTCP before the large key-frame
425 // if we have a 100 ms margin
426 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
427 }
428
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000429 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000430 {
431 return true;
432
433 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
434 {
435 // wrap
436 return true;
437 }
438 return false;
439}
440
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000441uint32_t RTCPSender::LastSendReport(int64_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000442{
443 CriticalSectionScoped lock(_criticalSectionRTCPSender);
444
445 lastRTCPTime = _lastRTCPTime[0];
446 return _lastSendReport[0];
447}
448
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000449int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000450 CriticalSectionScoped lock(_criticalSectionRTCPSender);
451
452 // This is only saved when we are the sender
453 if((_lastSendReport[0] == 0) || (sendReport == 0))
454 {
455 return 0; // will be ignored
456 } else
457 {
458 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
459 {
460 if( _lastSendReport[i] == sendReport)
461 {
462 return _lastRTCPTime[i];
463 }
464 }
465 }
466 return 0;
467}
468
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000469bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
470 int64_t* time_ms) const {
471 CriticalSectionScoped lock(_criticalSectionRTCPSender);
472
473 if (last_xr_rr_.empty()) {
474 return false;
475 }
476 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
477 if (it == last_xr_rr_.end()) {
478 return false;
479 }
480 *time_ms = it->second;
481 return true;
482}
483
asapersson@webrtc.org8098e072014-02-19 11:59:02 +0000484void RTCPSender::GetPacketTypeCounter(
485 RtcpPacketTypeCounter* packet_counter) const {
486 CriticalSectionScoped lock(_criticalSectionRTCPSender);
487 *packet_counter = packet_type_counter_;
488}
489
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000490int32_t RTCPSender::AddExternalReportBlock(
491 uint32_t SSRC,
492 const RTCPReportBlock* reportBlock) {
493 CriticalSectionScoped lock(_criticalSectionRTCPSender);
494 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
495}
496
497int32_t RTCPSender::AddReportBlock(
498 uint32_t SSRC,
499 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
500 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000501 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000503 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000504 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000505 return -1;
506 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000507 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000508 report_blocks->find(SSRC);
509 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000510 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000511 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000512 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000513 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
514 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000515 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000516 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000517}
518
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000519int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000520 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000521
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000522 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000523 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000524
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000525 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000527 }
528 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000529 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000530 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000533int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
534 uint8_t* rtcpbuffer,
535 int& pos,
536 uint32_t NTPsec,
537 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000538{
539 // sanity
540 if(pos + 52 >= IP_PACKET_SIZE)
541 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000542 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000543 return -2;
544 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000545 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000546
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000547 uint32_t posNumberOfReportBlocks = pos;
548 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000549
550 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000551 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000552
553 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
554 {
555 // shift old
556 _lastSendReport[i+1] = _lastSendReport[i];
557 _lastRTCPTime[i+1] =_lastRTCPTime[i];
558 }
559
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000560 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000561 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000563 // The timestamp of this RTCP packet should be estimated as the timestamp of
564 // the frame being captured at this moment. We are calculating that
565 // timestamp as the last frame's timestamp + the time since the last frame
566 // was captured.
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000567 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
568 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
569 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
571 // Add sender data
572 // Save for our length field
573 pos++;
574 pos++;
575
576 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000577 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000578 pos += 4;
579 // NTP
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000580 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000581 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000582 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000583 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000584 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000585 pos += 4;
586
587 //sender's packet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000588 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000589 feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000590 pos += 4;
591
592 //sender's octet count
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000593 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +0000594 feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000595 pos += 4;
596
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000597 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000598 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
599 numberOfReportBlocks,
600 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601 if(retVal < 0)
602 {
603 //
604 return retVal ;
605 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000606 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000607 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
608
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000609 uint16_t len = uint16_t((pos/4) -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000610 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 return 0;
612}
613
614
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000615int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000616 size_t lengthCname = strlen(_CNAME);
617 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 // sanity
620 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000621 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000622 return -2;
623 }
624 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000625
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000626 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000627 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
628 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000629
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000631 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000632 pos++;
633 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000636 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000637 pos += 4;
638
639 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000640 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000641
642 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000643 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000644
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000645 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000646
647 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
648 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000649 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000650
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000651 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000652 // We must have a zero field even if we have an even multiple of 4 bytes
653 if ((pos % 4) == 0) {
654 padding++;
655 rtcpbuffer[pos++]=0;
656 }
657 while ((pos % 4) != 0) {
658 padding++;
659 rtcpbuffer[pos++]=0;
660 }
661 SDESLength += padding;
662
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000663 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 _csrcCNAMEs.begin();
665
666 for(; it != _csrcCNAMEs.end(); it++) {
667 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000668 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000669
670 // Add SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000671 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000672 pos += 4;
673
674 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000675 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000676
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000677 size_t length = strlen(cname->name);
678 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000679
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000680 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000681 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000682
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000683 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000684
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000685 pos += length;
686 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000687 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000688
689 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000690 if((pos % 4) == 0){
691 padding++;
692 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000693 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000694 while((pos % 4) != 0){
695 padding++;
696 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000697 }
698 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000699 }
700 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000701 uint16_t buffer_length = (SDESLength / 4) - 1;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000702 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + SDESLengthPos, buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000703 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000704}
705
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000706int32_t RTCPSender::BuildRR(uint8_t* rtcpbuffer,
707 int& pos,
708 uint32_t NTPsec,
709 uint32_t NTPfrac) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000710 // sanity one block
711 if(pos + 32 >= IP_PACKET_SIZE)
712 {
713 return -2;
714 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000715 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000716
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000717 rtcpbuffer[pos++]=(uint8_t)0x80;
718 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000719
720 // Save for our length field
721 pos++;
722 pos++;
723
724 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000725 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000726 pos += 4;
727
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000728 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000729 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
730 numberOfReportBlocks,
731 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000732 if(retVal < 0)
733 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000734 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000735 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000736 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000737 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
738
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000739 uint16_t len = uint16_t((pos)/4 -1);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000740 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000741 return 0;
742}
743
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000744// From RFC 5450: Transmission Time Offsets in RTP Streams.
745// 0 1 2 3
746// 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
747// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
748// hdr |V=2|P| RC | PT=IJ=195 | length |
749// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
750// | inter-arrival jitter |
751// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
752// . .
753// . .
754// . .
755// | inter-arrival jitter |
756// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
757//
758// If present, this RTCP packet must be placed after a receiver report
759// (inside a compound RTCP packet), and MUST have the same value for RC
760// (reception report count) as the receiver report.
761
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000762int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000763RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000764 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000765 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000766 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000767{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000768 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000769 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000770 // TODO(andresp): Remove external report blocks since they are not
771 // supported.
772 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000773 return 0;
774 }
775
776 // sanity
777 if(pos + 8 >= IP_PACKET_SIZE)
778 {
779 return -2;
780 }
781 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000782 uint8_t RC = 1;
783 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
784 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000785
786 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000787 rtcpbuffer[pos++]=(uint8_t)0;
788 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000789
790 // Add inter-arrival jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000791 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos,
792 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000793 pos += 4;
794 return 0;
795}
796
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000797int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000798RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000799{
800 // sanity
801 if(pos + 12 >= IP_PACKET_SIZE)
802 {
803 return -2;
804 }
805 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000806 uint8_t FMT = 1;
807 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
808 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000809
810 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000811 rtcpbuffer[pos++]=(uint8_t)0;
812 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000813
814 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000815 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000816 pos += 4;
817
818 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000819 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000820 pos += 4;
821 return 0;
822}
823
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000824int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000825 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000826 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000827 // sanity
828 if(pos + 20 >= IP_PACKET_SIZE) {
829 return -2;
830 }
831 if (!repeat) {
832 _sequenceNumberFIR++; // do not increase if repetition
833 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000834
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000835 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000836 uint8_t FMT = 4;
837 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
838 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000839
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000840 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000841 rtcpbuffer[pos++] = (uint8_t)0;
842 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000843
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000844 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000845 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000846 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000847
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000848 // RFC 5104 4.3.1.2. Semantics
849 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000850 rtcpbuffer[pos++] = (uint8_t)0;
851 rtcpbuffer[pos++] = (uint8_t)0;
852 rtcpbuffer[pos++] = (uint8_t)0;
853 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000854
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000855 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000856 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000857 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000858
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000859 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
860 rtcpbuffer[pos++] = (uint8_t)0;
861 rtcpbuffer[pos++] = (uint8_t)0;
862 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000863 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000864}
865
866/*
867 0 1 2 3
868 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
869 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
870 | First | Number | PictureID |
871 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
872*/
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000873int32_t RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, uint8_t pictureID) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000874 // sanity
875 if(pos + 16 >= IP_PACKET_SIZE)
876 {
877 return -2;
878 }
879 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000880 uint8_t FMT = 2;
881 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
882 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
884 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000885 rtcpbuffer[pos++]=(uint8_t)0;
886 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000887
888 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000889 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000890 pos += 4;
891
892 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000893 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000894 pos += 4;
895
896 // Add first, number & picture ID 6 bits
897 // first = 0, 13 - bits
898 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000899 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000900 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +0000901 pos += 4;
902 return 0;
903}
904
905/*
906 0 1 2 3
907 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
908 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
909 | PB |0| Payload Type| Native RPSI bit string |
910 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
911 | defined per codec ... | Padding (0) |
912 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
913*/
914/*
915* Note: not generic made for VP8
916*/
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000917int32_t RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
918 int& pos,
919 uint64_t pictureID,
920 uint8_t payloadType) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000921 // sanity
922 if(pos + 24 >= IP_PACKET_SIZE)
923 {
924 return -2;
925 }
926 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000927 uint8_t FMT = 3;
928 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
929 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000930
931 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000932 uint32_t bitsRequired = 7;
933 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934 while((pictureID>>bitsRequired) > 0)
935 {
936 bitsRequired += 7;
937 bytesRequired++;
938 }
939
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000940 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000941 if(bytesRequired > 6)
942 {
943 size = 5;
944 } else if(bytesRequired > 2)
945 {
946 size = 4;
947 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000948 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000949 rtcpbuffer[pos++]=size;
950
951 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000952 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000953 pos += 4;
954
955 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000956 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000957 pos += 4;
958
959 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000960 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000961 if(paddingBytes == 4)
962 {
963 paddingBytes = 0;
964 }
965 // add padding length in bits
966 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
967 pos++;
968
969 // add payload type
970 rtcpbuffer[pos] = payloadType;
971 pos++;
972
973 // add picture ID
974 for(int i = bytesRequired-1; i > 0; i--)
975 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000976 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +0000977 pos++;
978 }
979 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000980 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000981 pos++;
982
983 // add padding
984 for(int j = 0; j <paddingBytes; j++)
985 {
986 rtcpbuffer[pos] = 0;
987 pos++;
988 }
989 return 0;
990}
991
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000992int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000993RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000994{
995 // sanity
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000996 if(pos + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000997 {
998 return -2;
999 }
1000 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001001 uint8_t FMT = 15;
1002 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1003 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001004
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001005 rtcpbuffer[pos++]=(uint8_t)0;
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001006 rtcpbuffer[pos++]=remb_ssrcs_.size() + 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001007
1008 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001009 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001010 pos += 4;
1011
1012 // Remote SSRC must be 0
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001013 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001014 pos += 4;
1015
1016 rtcpbuffer[pos++]='R';
1017 rtcpbuffer[pos++]='E';
1018 rtcpbuffer[pos++]='M';
1019 rtcpbuffer[pos++]='B';
1020
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001021 rtcpbuffer[pos++] = remb_ssrcs_.size();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001022 // 6 bit Exp
1023 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001024 uint8_t brExp = 0;
1025 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001026 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001027 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001028 {
1029 brExp = i;
1030 break;
1031 }
1032 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001033 const uint32_t brMantissa = (_rembBitrate >> brExp);
1034 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1035 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1036 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001037
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001038 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001039 {
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001040 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, remb_ssrcs_[i]);
1041 pos += 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001042 }
1043 return 0;
1044}
1045
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001046void
1047RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001048{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001049 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001050 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001051}
1052
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001053int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1054 uint8_t* rtcpbuffer,
1055 int& pos) {
1056 if (rtp_rtcp_module == NULL)
1057 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001058 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1059 // If the sender is an owner of the TMMBN -> send TMMBR
1060 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1061
niklase@google.com470e71d2011-07-07 08:21:25 +00001062 // get current bounding set from RTCP receiver
1063 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001064 // store in candidateSet, allocates one extra slot
1065 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001066
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001067 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1068 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1069 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001070 int32_t lengthOfBoundingSet =
1071 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001072
1073 if(lengthOfBoundingSet > 0)
1074 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001075 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001076 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001077 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1078 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001079 {
1080 // do not send the same tuple
1081 return 0;
1082 }
1083 }
1084 if(!tmmbrOwner)
1085 {
1086 // use received bounding set as candidate set
1087 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001088 candidateSet->SetEntry(lengthOfBoundingSet,
1089 _tmmbr_Send,
1090 _packetOH_Send,
1091 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001092 int numCandidates = lengthOfBoundingSet+ 1;
1093
1094 // find bounding set
1095 TMMBRSet* boundingSet = NULL;
1096 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1097 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1098 {
1099 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1100 }
1101 if(!tmmbrOwner)
1102 {
1103 // did not enter bounding set, no meaning to send this request
1104 return 0;
1105 }
1106 }
1107 }
1108
1109 if(_tmmbr_Send)
1110 {
1111 // sanity
1112 if(pos + 20 >= IP_PACKET_SIZE)
1113 {
1114 return -2;
1115 }
1116 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001117 uint8_t FMT = 3;
1118 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1119 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001120
1121 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001122 rtcpbuffer[pos++]=(uint8_t)0;
1123 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001124
1125 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001126 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001127 pos += 4;
1128
1129 // RFC 5104 4.2.1.2. Semantics
1130
1131 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001132 rtcpbuffer[pos++]=(uint8_t)0;
1133 rtcpbuffer[pos++]=(uint8_t)0;
1134 rtcpbuffer[pos++]=(uint8_t)0;
1135 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001136
1137 // Additional Feedback Control Information (FCI)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001138 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001139 pos += 4;
1140
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001141 uint32_t bitRate = _tmmbr_Send*1000;
1142 uint32_t mmbrExp = 0;
1143 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001144 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001145 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001146 {
1147 mmbrExp = i;
1148 break;
1149 }
1150 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001151 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001152
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001153 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1154 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1155 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1156 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001157 }
1158 return 0;
1159}
1160
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001161int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001162RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001163{
1164 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1165 if(boundingSet == NULL)
1166 {
1167 return -1;
1168 }
1169 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001170 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001171 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001172 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001173 return -2;
1174 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001175 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001176 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001177 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1178 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001179
1180 //Add length later
1181 int posLength = pos;
1182 pos++;
1183 pos++;
1184
1185 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001186 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001187 pos += 4;
1188
1189 // RFC 5104 4.2.2.2. Semantics
1190
1191 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001192 rtcpbuffer[pos++]=(uint8_t)0;
1193 rtcpbuffer[pos++]=(uint8_t)0;
1194 rtcpbuffer[pos++]=(uint8_t)0;
1195 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001196
1197 // Additional Feedback Control Information (FCI)
1198 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001199 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001200 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001201 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001202 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001203 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001204 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001205 pos += 4;
1206
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001207 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1208 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001209 for(int i=0; i<64; i++)
1210 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001211 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001212 {
1213 mmbrExp = i;
1214 break;
1215 }
1216 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001217 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1218 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001219
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001220 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1221 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1222 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1223 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 numBoundingSet++;
1225 }
1226 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001227 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1228 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1229 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001230 return 0;
1231}
1232
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001233int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001234RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001235{
1236 // sanity
1237 if(_appData == NULL)
1238 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001239 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001240 return -1;
1241 }
1242 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1243 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001244 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001245 return -2;
1246 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001247 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001248
1249 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001250 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001251
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001252 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1253 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1254 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
1256 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001257 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001258 pos += 4;
1259
1260 // Add our application name
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001261 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001262 pos += 4;
1263
1264 // Add the data
1265 memcpy(rtcpbuffer +pos, _appData,_appLength);
1266 pos += _appLength;
1267 return 0;
1268}
1269
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001270int32_t RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1271 int& pos,
1272 int32_t nackSize,
1273 const uint16_t* nackList,
1274 std::string* nackString) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001275 // sanity
1276 if(pos + 16 >= IP_PACKET_SIZE)
1277 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001278 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001279 return -2;
1280 }
1281
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001282 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001283 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001284 uint8_t FMT = 1;
1285 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1286 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001287
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001288 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001289 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001290 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001291
1292 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001293 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001294 pos += 4;
1295
1296 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001297 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298 pos += 4;
1299
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001300 // Build NACK bitmasks and write them to the RTCP message.
1301 // The nack list should be sorted and not contain duplicates if one
1302 // wants to build the smallest rtcp nack packet.
1303 int numOfNackFields = 0;
1304 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1305 (IP_PACKET_SIZE - pos) / 4);
1306 int i = 0;
1307 while (i < nackSize && numOfNackFields < maxNackFields) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001308 uint16_t nack = nackList[i++];
1309 uint16_t bitmask = 0;
1310 while (i < nackSize) {
1311 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1312 if (shift >= 0 && shift <= 15) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001313 bitmask |= (1 << shift);
1314 ++i;
1315 } else {
1316 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001317 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001318 }
1319 // Write the sequence number and the bitmask to the packet.
1320 assert(pos + 4 < IP_PACKET_SIZE);
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001321 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001322 pos += 2;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001323 RtpUtility::AssignUWord16ToBuffer(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001324 pos += 2;
1325 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001327 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001328
1329 if (i != nackSize) {
1330 LOG(LS_WARNING) << "Nack list too large for one packet.";
1331 }
1332
1333 // Report stats.
1334 NACKStringBuilder stringBuilder;
1335 for (int idx = 0; idx < i; ++idx) {
1336 stringBuilder.PushNACK(nackList[idx]);
1337 nack_stats_.ReportRequest(nackList[idx]);
1338 }
edjee@google.com79b02892013-04-04 19:43:34 +00001339 *nackString = stringBuilder.GetResult();
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001340 packet_type_counter_.nack_requests = nack_stats_.requests();
1341 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
niklase@google.com470e71d2011-07-07 08:21:25 +00001342 return 0;
1343}
1344
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001345int32_t RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos) {
1346 // sanity
1347 if (pos + 8 >= IP_PACKET_SIZE) {
1348 return -2;
1349 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001350
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001351 // Add a bye packet
1352 // Number of SSRC + CSRCs.
1353 rtcpbuffer[pos++] = (uint8_t)0x80 + 1 + csrcs_.size();
1354 rtcpbuffer[pos++] = (uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001355
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001356 // length
1357 rtcpbuffer[pos++] = (uint8_t)0;
1358 rtcpbuffer[pos++] = (uint8_t)(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001359
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001360 // Add our own SSRC
1361 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
1362 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001363
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001364 // add CSRCs
1365 for (size_t i = 0; i < csrcs_.size(); i++) {
1366 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, csrcs_[i]);
1367 pos += 4;
1368 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001369
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001370 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001371}
1372
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001373int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1374 int& pos,
1375 uint32_t ntp_sec,
1376 uint32_t ntp_frac) {
1377 const int kRrTimeBlockLength = 20;
1378 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1379 return -2;
1380 }
1381
1382 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1383 last_xr_rr_.erase(last_xr_rr_.begin());
1384 }
1385 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1386 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1387 Clock::NtpToMs(ntp_sec, ntp_frac)));
1388
1389 // Add XR header.
1390 buffer[pos++] = 0x80;
1391 buffer[pos++] = 207;
1392 buffer[pos++] = 0; // XR packet length.
1393 buffer[pos++] = 4; // XR packet length.
1394
1395 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001396 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001397 pos += 4;
1398
1399 // 0 1 2 3
1400 // 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
1401 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1402 // | BT=4 | reserved | block length = 2 |
1403 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1404 // | NTP timestamp, most significant word |
1405 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1406 // | NTP timestamp, least significant word |
1407 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1408
1409 // Add Receiver Reference Time Report block.
1410 buffer[pos++] = 4; // BT.
1411 buffer[pos++] = 0; // Reserved.
1412 buffer[pos++] = 0; // Block length.
1413 buffer[pos++] = 2; // Block length.
1414
1415 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001416 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001417 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001418 RtpUtility::AssignUWord32ToBuffer(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001419 pos += 4;
1420
1421 return 0;
1422}
1423
1424int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1425 int& pos,
1426 const RtcpReceiveTimeInfo& info) {
1427 const int kDlrrBlockLength = 24;
1428 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1429 return -2;
1430 }
1431
1432 // Add XR header.
1433 buffer[pos++] = 0x80;
1434 buffer[pos++] = 207;
1435 buffer[pos++] = 0; // XR packet length.
1436 buffer[pos++] = 5; // XR packet length.
1437
1438 // Add our own SSRC.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001439 RtpUtility::AssignUWord32ToBuffer(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001440 pos += 4;
1441
1442 // 0 1 2 3
1443 // 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
1444 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1445 // | BT=5 | reserved | block length |
1446 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1447 // | SSRC_1 (SSRC of first receiver) | sub-
1448 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1449 // | last RR (LRR) | 1
1450 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1451 // | delay since last RR (DLRR) |
1452 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1453 // | SSRC_2 (SSRC of second receiver) | sub-
1454 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1455 // : ... : 2
1456
1457 // Add DLRR sub block.
1458 buffer[pos++] = 5; // BT.
1459 buffer[pos++] = 0; // Reserved.
1460 buffer[pos++] = 0; // Block length.
1461 buffer[pos++] = 3; // Block length.
1462
1463 // NTP timestamp.
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001464 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001465 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001466 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001467 pos += 4;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001468 RtpUtility::AssignUWord32ToBuffer(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001469 pos += 4;
1470
1471 return 0;
1472}
1473
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001474int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001475RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001476{
1477 // sanity
1478 if(pos + 44 >= IP_PACKET_SIZE)
1479 {
1480 return -2;
1481 }
1482
1483 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001484 rtcpbuffer[pos++]=(uint8_t)0x80;
1485 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001486
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001487 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001488
1489 // handle length later on
1490 pos++;
1491 pos++;
1492
1493 // Add our own SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001494 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001495 pos += 4;
1496
1497 // Add a VoIP metrics block
1498 rtcpbuffer[pos++]=7;
1499 rtcpbuffer[pos++]=0;
1500 rtcpbuffer[pos++]=0;
1501 rtcpbuffer[pos++]=8;
1502
1503 // Add the remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001504 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001505 pos += 4;
1506
1507 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1508 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1509 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1510 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1511
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001512 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1513 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1514 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1515 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001516
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001517 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1518 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1519 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1520 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001521
1522 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1523 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1524 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1525 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1526
1527 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1528 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1529 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1530 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1531
1532 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1533 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001534 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1535 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001536
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001537 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1538 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1539 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1540 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001541
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001542 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1543 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001544 return 0;
1545}
1546
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001547int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1548 uint32_t packetTypeFlags,
1549 int32_t nackSize,
1550 const uint16_t* nackList,
1551 bool repeat,
1552 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001553 {
1554 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1555 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001556 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001557 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001558 return -1;
1559 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001560 }
1561 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001562 int rtcp_length = PrepareRTCP(feedback_state,
1563 packetTypeFlags,
1564 nackSize,
1565 nackList,
1566 repeat,
1567 pictureID,
1568 rtcp_buffer,
1569 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001570 if (rtcp_length < 0) {
1571 return -1;
1572 }
1573 // Sanity don't send empty packets.
1574 if (rtcp_length == 0)
1575 {
1576 return -1;
1577 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001578 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001579}
1580
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001581int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1582 uint32_t packetTypeFlags,
1583 int32_t nackSize,
1584 const uint16_t* nackList,
1585 bool repeat,
1586 uint64_t pictureID,
1587 uint8_t* rtcp_buffer,
1588 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001589 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1590 // Collect the received information.
1591 uint32_t NTPsec = 0;
1592 uint32_t NTPfrac = 0;
1593 uint32_t jitterTransmissionOffset = 0;
1594 int position = 0;
1595
1596 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1597
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001598 if (packet_type_counter_.first_packet_time_ms == -1) {
1599 packet_type_counter_.first_packet_time_ms = _clock->TimeInMilliseconds();
1600 }
1601
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001602 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1603 {
1604 rtcpPacketTypeFlags |= kRtcpTmmbr;
1605 }
1606 if(_appSend)
1607 {
1608 rtcpPacketTypeFlags |= kRtcpApp;
1609 _appSend = false;
1610 }
1611 if(_REMB && _sendREMB)
1612 {
1613 // Always attach REMB to SR if that is configured. Note that REMB is
1614 // only sent on one of the RTP modules in the REMB group.
1615 rtcpPacketTypeFlags |= kRtcpRemb;
1616 }
1617 if(_xrSendVoIPMetric)
1618 {
1619 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1620 _xrSendVoIPMetric = false;
1621 }
1622 if(_sendTMMBN) // Set when having received a TMMBR.
1623 {
1624 rtcpPacketTypeFlags |= kRtcpTmmbn;
1625 _sendTMMBN = false;
1626 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001627 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001628 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001629 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001630 {
1631 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1632 }
1633 if (feedback_state.has_last_xr_rr)
1634 {
1635 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1636 }
1637 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001638 if(_method == kRtcpCompound)
1639 {
1640 if(_sending)
1641 {
1642 rtcpPacketTypeFlags |= kRtcpSr;
1643 } else
1644 {
1645 rtcpPacketTypeFlags |= kRtcpRr;
1646 }
1647 } else if(_method == kRtcpNonCompound)
1648 {
1649 if(rtcpPacketTypeFlags & kRtcpReport)
1650 {
1651 if(_sending)
1652 {
1653 rtcpPacketTypeFlags |= kRtcpSr;
1654 } else
1655 {
1656 rtcpPacketTypeFlags |= kRtcpRr;
1657 }
1658 }
1659 }
1660 if( rtcpPacketTypeFlags & kRtcpRr ||
1661 rtcpPacketTypeFlags & kRtcpSr)
1662 {
1663 // generate next time to send a RTCP report
1664 // seeded from RTP constructor
1665 int32_t random = rand() % 1000;
1666 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1667
1668 if(_audio)
1669 {
1670 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1671 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1672 }else
1673 {
1674 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1675 if(_sending)
1676 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001677 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1678 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1679 if (send_bitrate_kbit != 0)
1680 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001681 }
1682 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1683 {
1684 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1685 }
1686 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1687 }
1688 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1689 }
1690
1691 // If the data does not fit in the packet we fill it as much as possible.
1692 int32_t buildVal = 0;
1693
1694 // We need to send our NTP even if we haven't received any reports.
1695 _clock->CurrentNtp(NTPsec, NTPfrac);
1696 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1697 StatisticianMap statisticians =
1698 receive_statistics_->GetActiveStatisticians();
1699 if (!statisticians.empty()) {
1700 StatisticianMap::const_iterator it;
1701 int i;
1702 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1703 ++it, ++i) {
1704 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001705 if (PrepareReport(
1706 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001707 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1708 }
1709 if (_IJ && !statisticians.empty()) {
1710 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1711 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001712 }
1713 }
1714
1715 if(rtcpPacketTypeFlags & kRtcpSr)
1716 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001717 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001718 if (buildVal == -1) {
1719 return -1;
1720 } else if (buildVal == -2) {
1721 return position;
1722 }
1723 buildVal = BuildSDEC(rtcp_buffer, position);
1724 if (buildVal == -1) {
1725 return -1;
1726 } else if (buildVal == -2) {
1727 return position;
1728 }
1729 }else if(rtcpPacketTypeFlags & kRtcpRr)
1730 {
1731 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1732 if (buildVal == -1) {
1733 return -1;
1734 } else if (buildVal == -2) {
1735 return position;
1736 }
1737 // only of set
1738 if(_CNAME[0] != 0)
1739 {
1740 buildVal = BuildSDEC(rtcp_buffer, position);
1741 if (buildVal == -1) {
1742 return -1;
1743 }
1744 }
1745 }
1746 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1747 {
1748 // If present, this RTCP packet must be placed after a
1749 // receiver report.
1750 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1751 position,
1752 jitterTransmissionOffset);
1753 if (buildVal == -1) {
1754 return -1;
1755 } else if (buildVal == -2) {
1756 return position;
1757 }
1758 }
1759 if(rtcpPacketTypeFlags & kRtcpPli)
1760 {
1761 buildVal = BuildPLI(rtcp_buffer, position);
1762 if (buildVal == -1) {
1763 return -1;
1764 } else if (buildVal == -2) {
1765 return position;
1766 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001767 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1768 "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001769 ++packet_type_counter_.pli_packets;
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001770 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1771 "RTCP_PLICount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001772 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001773 }
1774 if(rtcpPacketTypeFlags & kRtcpFir)
1775 {
1776 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1777 if (buildVal == -1) {
1778 return -1;
1779 } else if (buildVal == -2) {
1780 return position;
1781 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001782 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1783 "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001784 ++packet_type_counter_.fir_packets;
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001785 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1786 "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001787 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001788 }
1789 if(rtcpPacketTypeFlags & kRtcpSli)
1790 {
1791 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1792 if (buildVal == -1) {
1793 return -1;
1794 } else if (buildVal == -2) {
1795 return position;
1796 }
1797 }
1798 if(rtcpPacketTypeFlags & kRtcpRpsi)
1799 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001800 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001801 if (payloadType == -1) {
1802 return -1;
1803 }
1804 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1805 (uint8_t)payloadType);
1806 if (buildVal == -1) {
1807 return -1;
1808 } else if (buildVal == -2) {
1809 return position;
1810 }
1811 }
1812 if(rtcpPacketTypeFlags & kRtcpRemb)
1813 {
1814 buildVal = BuildREMB(rtcp_buffer, position);
1815 if (buildVal == -1) {
1816 return -1;
1817 } else if (buildVal == -2) {
1818 return position;
1819 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001820 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1821 "RTCPSender::REMB");
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001822 }
1823 if(rtcpPacketTypeFlags & kRtcpBye)
1824 {
1825 buildVal = BuildBYE(rtcp_buffer, position);
1826 if (buildVal == -1) {
1827 return -1;
1828 } else if (buildVal == -2) {
1829 return position;
1830 }
1831 }
1832 if(rtcpPacketTypeFlags & kRtcpApp)
1833 {
1834 buildVal = BuildAPP(rtcp_buffer, position);
1835 if (buildVal == -1) {
1836 return -1;
1837 } else if (buildVal == -2) {
1838 return position;
1839 }
1840 }
1841 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1842 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001843 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001844 if (buildVal == -1) {
1845 return -1;
1846 } else if (buildVal == -2) {
1847 return position;
1848 }
1849 }
1850 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1851 {
1852 buildVal = BuildTMMBN(rtcp_buffer, position);
1853 if (buildVal == -1) {
1854 return -1;
1855 } else if (buildVal == -2) {
1856 return position;
1857 }
1858 }
1859 if(rtcpPacketTypeFlags & kRtcpNack)
1860 {
1861 std::string nackString;
1862 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1863 &nackString);
1864 if (buildVal == -1) {
1865 return -1;
1866 } else if (buildVal == -2) {
1867 return position;
1868 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001869 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1870 "RTCPSender::NACK", "nacks",
1871 TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001872 ++packet_type_counter_.nack_packets;
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001873 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1874 "RTCP_NACKCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001875 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001876 }
1877 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1878 {
1879 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1880 if (buildVal == -1) {
1881 return -1;
1882 } else if (buildVal == -2) {
1883 return position;
1884 }
1885 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001886 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1887 {
1888 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1889 position,
1890 NTPsec,
1891 NTPfrac);
1892 if (buildVal == -1) {
1893 return -1;
1894 } else if (buildVal == -2) {
1895 return position;
1896 }
1897 }
1898 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1899 {
1900 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1901 if (buildVal == -1) {
1902 return -1;
1903 } else if (buildVal == -2) {
1904 return position;
1905 }
1906 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001907 return position;
1908}
1909
1910bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1911 return Status() == kRtcpCompound ||
1912 (rtcp_packet_type & kRtcpReport) ||
1913 (rtcp_packet_type & kRtcpSr) ||
1914 (rtcp_packet_type & kRtcpRr);
1915}
1916
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001917bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1918 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001919 RTCPReportBlock* report_block,
1920 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1921 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001922 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001923 if (!statistician->GetStatistics(&stats, true))
1924 return false;
1925 report_block->fractionLost = stats.fraction_lost;
1926 report_block->cumulativeLost = stats.cumulative_lost;
1927 report_block->extendedHighSeqNum =
1928 stats.extended_max_sequence_number;
1929 report_block->jitter = stats.jitter;
1930
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001931 // get our NTP as late as possible to avoid a race
1932 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1933
1934 // Delay since last received report
1935 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001936 if ((feedback_state.last_rr_ntp_secs != 0) ||
1937 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001938 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1939 uint32_t now=*ntp_secs&0x0000FFFF;
1940 now <<=16;
1941 now += (*ntp_frac&0xffff0000)>>16;
1942
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001943 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001944 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001945 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001946
1947 delaySinceLastReceivedSR = now-receiveTime;
1948 }
1949 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001950 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001951 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001952}
1953
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001954int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001955 CriticalSectionScoped lock(_criticalSectionTransport);
1956 if(_cbTransport)
1957 {
1958 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1959 {
1960 return 0;
1961 }
1962 }
1963 return -1;
1964}
1965
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001966void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1967 assert(csrcs.size() <= kRtpCsrcSize);
1968 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1969 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001970}
1971
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001972int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1973 uint32_t name,
1974 const uint8_t* data,
1975 uint16_t length) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001976 if(length %4 != 0)
1977 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001978 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001979 return -1;
1980 }
1981 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1982
1983 if(_appData)
1984 {
1985 delete [] _appData;
1986 }
1987
1988 _appSend = true;
1989 _appSubType = subType;
1990 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001991 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00001992 _appLength = length;
1993 memcpy(_appData, data, length);
1994 return 0;
1995}
1996
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001997int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001998RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
1999{
2000 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2001 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
2002
2003 _xrSendVoIPMetric = true;
2004 return 0;
2005}
2006
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00002007void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
2008 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2009 xrSendReceiverReferenceTimeEnabled_ = enable;
2010}
2011
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002012bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2013 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2014 return xrSendReceiverReferenceTimeEnabled_;
2015}
2016
niklase@google.com470e71d2011-07-07 08:21:25 +00002017// called under critsect _criticalSectionRTCPSender
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002018int32_t RTCPSender::WriteAllReportBlocksToBuffer(uint8_t* rtcpbuffer,
2019 int pos,
2020 uint8_t& numberOfReportBlocks,
2021 uint32_t NTPsec,
2022 uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002023 numberOfReportBlocks = external_report_blocks_.size();
2024 numberOfReportBlocks += internal_report_blocks_.size();
2025 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002026 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002027 return -1;
2028 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002029 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2030 while (!internal_report_blocks_.empty()) {
2031 delete internal_report_blocks_.begin()->second;
2032 internal_report_blocks_.erase(internal_report_blocks_.begin());
2033 }
2034 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2035 return pos;
2036}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002037
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002038int32_t RTCPSender::WriteReportBlocksToBuffer(
2039 uint8_t* rtcpbuffer,
2040 int32_t position,
2041 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2042 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2043 report_blocks.begin();
2044 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002045 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002046 RTCPReportBlock* reportBlock = it->second;
2047 if (reportBlock) {
2048 // Remote SSRC
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002049 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002050 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002051
2052 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002053 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002054
2055 // cumulative loss
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002056 RtpUtility::AssignUWord24ToBuffer(rtcpbuffer + position,
2057 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002058 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002059
2060 // extended highest seq_no, contain the highest sequence number received
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002061 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2062 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002063 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002064
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002065 // Jitter
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002066 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2067 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002068 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002069
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002070 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2071 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002072 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002073
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002074 RtpUtility::AssignUWord32ToBuffer(rtcpbuffer + position,
2075 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002076 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002077 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002078 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002079 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002080}
2081
2082// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002083int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2084 uint32_t maxBitrateKbit) {
niklase@google.com470e71d2011-07-07 08:21:25 +00002085 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2086
2087 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2088 {
2089 _sendTMMBN = true;
2090 return 0;
2091 }
2092 return -1;
2093}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002094} // namespace webrtc