blob: 82b12035baee328261a82badb18820821ca11209 [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"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000020#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
22#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000023#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000024#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000025
niklase@google.com470e71d2011-07-07 08:21:25 +000026namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000027
28using RTCPUtility::RTCPCnameInformation;
29
edjee@google.com79b02892013-04-04 19:43:34 +000030NACKStringBuilder::NACKStringBuilder() :
31 _stream(""), _count(0), _consecutive(false)
32{
33 // Empty.
34}
35
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000036NACKStringBuilder::~NACKStringBuilder() {}
37
pbos@webrtc.org2f446732013-04-08 11:08:41 +000038void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000039{
40 if (_count == 0)
41 {
42 _stream << nack;
43 } else if (nack == _prevNack + 1)
44 {
45 _consecutive = true;
46 } else
47 {
48 if (_consecutive)
49 {
50 _stream << "-" << _prevNack;
51 _consecutive = false;
52 }
53 _stream << "," << nack;
54 }
55 _count++;
56 _prevNack = nack;
57}
58
59std::string NACKStringBuilder::GetResult()
60{
61 if (_consecutive)
62 {
63 _stream << "-" << _prevNack;
64 _consecutive = false;
65 }
66 return _stream.str();
67}
68
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000069RTCPSender::FeedbackState::FeedbackState()
70 : send_payload_type(0),
71 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000072 packets_sent(0),
73 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000074 send_bitrate(0),
75 last_rr_ntp_secs(0),
76 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000077 remote_sr(0),
78 has_last_xr_rr(false) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +000080RTCPSender::RTCPSender(
81 int32_t id,
82 bool audio,
83 Clock* clock,
84 ReceiveStatistics* receive_statistics,
85 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000086 : _id(id),
87 _audio(audio),
88 _clock(clock),
89 _method(kRtcpOff),
90 _criticalSectionTransport(
91 CriticalSectionWrapper::CreateCriticalSection()),
92 _cbTransport(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000093
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +000094 _criticalSectionRTCPSender(
95 CriticalSectionWrapper::CreateCriticalSection()),
96 _usingNack(false),
97 _sending(false),
98 _sendTMMBN(false),
99 _REMB(false),
100 _sendREMB(false),
101 _TMMBR(false),
102 _IJ(false),
103 _nextTimeToSendRTCP(0),
104 start_timestamp_(0),
105 last_rtp_timestamp_(0),
106 last_frame_capture_time_ms_(-1),
107 _SSRC(0),
108 _remoteSSRC(0),
109 _CNAME(),
110 receive_statistics_(receive_statistics),
111 internal_report_blocks_(),
112 external_report_blocks_(),
113 _csrcCNAMEs(),
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),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000135 _xrVoIPMetric(),
136 packet_type_counter_observer_(packet_type_counter_observer) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 memset(_CNAME, 0, sizeof(_CNAME));
138 memset(_lastSendReport, 0, sizeof(_lastSendReport));
139 memset(_lastRTCPTime, 0, sizeof(_lastRTCPTime));
niklase@google.com470e71d2011-07-07 08:21:25 +0000140}
141
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000142RTCPSender::~RTCPSender() {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000143 delete [] _appData;
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000145 while (!internal_report_blocks_.empty()) {
146 delete internal_report_blocks_.begin()->second;
147 internal_report_blocks_.erase(internal_report_blocks_.begin());
148 }
149 while (!external_report_blocks_.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000150 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000151 external_report_blocks_.begin();
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000152 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000153 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000154 }
155 while (!_csrcCNAMEs.empty()) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000156 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000157 _csrcCNAMEs.begin();
158 delete it->second;
159 _csrcCNAMEs.erase(it);
160 }
161 delete _criticalSectionTransport;
162 delete _criticalSectionRTCPSender;
niklase@google.com470e71d2011-07-07 08:21:25 +0000163}
164
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000165int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +0000166RTCPSender::RegisterSendTransport(Transport* outgoingTransport)
167{
168 CriticalSectionScoped lock(_criticalSectionTransport);
169 _cbTransport = outgoingTransport;
170 return 0;
171}
172
173RTCPMethod
174RTCPSender::Status() const
175{
176 CriticalSectionScoped lock(_criticalSectionRTCPSender);
177 return _method;
178}
179
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000180void RTCPSender::SetRTCPStatus(RTCPMethod method) {
181 CriticalSectionScoped lock(_criticalSectionRTCPSender);
182 _method = method;
183
184 if (method == kRtcpOff)
185 return;
186 _nextTimeToSendRTCP =
187 _clock->TimeInMilliseconds() +
188 (_audio ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
190
191bool
192RTCPSender::Sending() const
193{
194 CriticalSectionScoped lock(_criticalSectionRTCPSender);
195 return _sending;
196}
197
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000198int32_t
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000199RTCPSender::SetSendingStatus(const FeedbackState& feedback_state, bool sending)
niklase@google.com470e71d2011-07-07 08:21:25 +0000200{
201 bool sendRTCPBye = false;
202 {
203 CriticalSectionScoped lock(_criticalSectionRTCPSender);
204
205 if(_method != kRtcpOff)
206 {
207 if(sending == false && _sending == true)
208 {
209 // Trigger RTCP bye
210 sendRTCPBye = true;
211 }
212 }
213 _sending = sending;
214 }
215 if(sendRTCPBye)
216 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000217 return SendRTCP(feedback_state, kRtcpBye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000218 }
219 return 0;
220}
221
222bool
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000223RTCPSender::REMB() const
224{
225 CriticalSectionScoped lock(_criticalSectionRTCPSender);
226 return _REMB;
227}
228
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000229void RTCPSender::SetREMBStatus(bool enable) {
230 CriticalSectionScoped lock(_criticalSectionRTCPSender);
231 _REMB = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000232}
233
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000234void RTCPSender::SetREMBData(uint32_t bitrate,
235 const std::vector<uint32_t>& ssrcs) {
236 CriticalSectionScoped lock(_criticalSectionRTCPSender);
237 _rembBitrate = bitrate;
238 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000239
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000240 _sendREMB = true;
241 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
242 // throttled by the caller.
243 _nextTimeToSendRTCP = _clock->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000244}
245
246bool
niklase@google.com470e71d2011-07-07 08:21:25 +0000247RTCPSender::TMMBR() const
248{
249 CriticalSectionScoped lock(_criticalSectionRTCPSender);
250 return _TMMBR;
251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetTMMBRStatus(bool enable) {
254 CriticalSectionScoped lock(_criticalSectionRTCPSender);
255 _TMMBR = enable;
niklase@google.com470e71d2011-07-07 08:21:25 +0000256}
257
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000258bool
259RTCPSender::IJ() const
260{
261 CriticalSectionScoped lock(_criticalSectionRTCPSender);
262 return _IJ;
263}
264
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000265void RTCPSender::SetIJStatus(bool enable) {
266 CriticalSectionScoped lock(_criticalSectionRTCPSender);
267 _IJ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000268}
269
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000270void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000271 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000272 start_timestamp_ = start_timestamp;
273}
274
275void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
276 int64_t capture_time_ms) {
henrika@webrtc.org19da7192013-04-05 14:34:57 +0000277 CriticalSectionScoped lock(_criticalSectionRTCPSender);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278 last_rtp_timestamp_ = rtp_timestamp;
279 if (capture_time_ms < 0) {
280 // We don't currently get a capture time from VoiceEngine.
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000281 last_frame_capture_time_ms_ = _clock->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000282 } else {
283 last_frame_capture_time_ms_ = capture_time_ms;
284 }
285}
286
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000287void RTCPSender::SetSSRC(uint32_t ssrc) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000288 CriticalSectionScoped lock(_criticalSectionRTCPSender);
289
290 if(_SSRC != 0)
291 {
292 // not first SetSSRC, probably due to a collision
293 // schedule a new RTCP report
pwestin@webrtc.org0644b1d2011-12-01 15:42:31 +0000294 // make sure that we send a RTP packet
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000295 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000296 }
297 _SSRC = ssrc;
298}
299
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000300void RTCPSender::SetRemoteSSRC(uint32_t ssrc)
niklase@google.com470e71d2011-07-07 08:21:25 +0000301{
302 CriticalSectionScoped lock(_criticalSectionRTCPSender);
303 _remoteSSRC = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000304}
305
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000306int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000307 if (!cName)
308 return -1;
309
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000310 CriticalSectionScoped lock(_criticalSectionRTCPSender);
311 _CNAME[RTCP_CNAME_SIZE - 1] = 0;
312 strncpy(_CNAME, cName, RTCP_CNAME_SIZE - 1);
313 return 0;
314}
315
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000316int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000317 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000318 assert(cName);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000319 CriticalSectionScoped lock(_criticalSectionRTCPSender);
320 if (_csrcCNAMEs.size() >= kRtpCsrcSize) {
321 return -1;
322 }
323 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000324 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
325 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000326 _csrcCNAMEs[SSRC] = ptr;
327 return 0;
328}
329
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000330int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000331 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000332 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000333 _csrcCNAMEs.find(SSRC);
334
335 if (it == _csrcCNAMEs.end()) {
336 return -1;
337 }
338 delete it->second;
339 _csrcCNAMEs.erase(it);
340 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000344/*
345 For audio we use a fix 5 sec interval
346
347 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000348 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
349 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000350
351
352From RFC 3550
353
354 MAX RTCP BW is 5% if the session BW
355 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000356 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
358 The RECOMMENDED value for the reduced minimum in seconds is 360
359 divided by the session bandwidth in kilobits/second. This minimum
360 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
361
362 If the participant has not yet sent an RTCP packet (the variable
363 initial is true), the constant Tmin is set to 2.5 seconds, else it
364 is set to 5 seconds.
365
366 The interval between RTCP packets is varied randomly over the
367 range [0.5,1.5] times the calculated interval to avoid unintended
368 synchronization of all participants
369
370 if we send
371 If the participant is a sender (we_sent true), the constant C is
372 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
373 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
374 number of senders.
375
376 if we receive only
377 If we_sent is not true, the constant C is set
378 to the average RTCP packet size divided by 75% of the RTCP
379 bandwidth. The constant n is set to the number of receivers
380 (members - senders). If the number of senders is greater than
381 25%, senders and receivers are treated together.
382
383 reconsideration NOT required for peer-to-peer
384 "timer reconsideration" is
385 employed. This algorithm implements a simple back-off mechanism
386 which causes users to hold back RTCP packet transmission if the
387 group sizes are increasing.
388
389 n = number of members
390 C = avg_size/(rtcpBW/4)
391
392 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
393
394 4. The calculated interval T is set to a number uniformly distributed
395 between 0.5 and 1.5 times the deterministic calculated interval.
396
397 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
398 for the fact that the timer reconsideration algorithm converges to
399 a value of the RTCP bandwidth below the intended average
400*/
401
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000402 int64_t now = _clock->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000403
404 CriticalSectionScoped lock(_criticalSectionRTCPSender);
405
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 if(_method == kRtcpOff)
407 {
408 return false;
409 }
410
niklase@google.com470e71d2011-07-07 08:21:25 +0000411 if(!_audio && sendKeyframeBeforeRTP)
412 {
413 // for video key-frames we want to send the RTCP before the large key-frame
414 // if we have a 100 ms margin
415 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
416 }
417
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000418 if(now >= _nextTimeToSendRTCP)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 {
420 return true;
421
422 } else if(now < 0x0000ffff && _nextTimeToSendRTCP > 0xffff0000) // 65 sec margin
423 {
424 // wrap
425 return true;
426 }
427 return false;
428}
429
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000430uint32_t RTCPSender::LastSendReport(int64_t& lastRTCPTime)
niklase@google.com470e71d2011-07-07 08:21:25 +0000431{
432 CriticalSectionScoped lock(_criticalSectionRTCPSender);
433
434 lastRTCPTime = _lastRTCPTime[0];
435 return _lastSendReport[0];
436}
437
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000438int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000439 CriticalSectionScoped lock(_criticalSectionRTCPSender);
440
441 // This is only saved when we are the sender
442 if((_lastSendReport[0] == 0) || (sendReport == 0))
443 {
444 return 0; // will be ignored
445 } else
446 {
447 for(int i = 0; i < RTCP_NUMBER_OF_SR; ++i)
448 {
449 if( _lastSendReport[i] == sendReport)
450 {
451 return _lastRTCPTime[i];
452 }
453 }
454 }
455 return 0;
456}
457
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000458bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
459 int64_t* time_ms) const {
460 CriticalSectionScoped lock(_criticalSectionRTCPSender);
461
462 if (last_xr_rr_.empty()) {
463 return false;
464 }
465 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
466 if (it == last_xr_rr_.end()) {
467 return false;
468 }
469 *time_ms = it->second;
470 return true;
471}
472
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000473int32_t RTCPSender::AddExternalReportBlock(
474 uint32_t SSRC,
475 const RTCPReportBlock* reportBlock) {
476 CriticalSectionScoped lock(_criticalSectionRTCPSender);
477 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
478}
479
480int32_t RTCPSender::AddReportBlock(
481 uint32_t SSRC,
482 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
483 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000484 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000485
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000486 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000487 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000488 return -1;
489 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000490 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000491 report_blocks->find(SSRC);
492 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000493 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000494 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000495 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000496 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
497 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000498 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000499 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000500}
501
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000502int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000503 CriticalSectionScoped lock(_criticalSectionRTCPSender);
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000505 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000506 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000507
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000508 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000509 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000510 }
511 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000512 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000513 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000514}
515
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000516int32_t RTCPSender::BuildSR(const FeedbackState& feedback_state,
517 uint8_t* rtcpbuffer,
518 int& pos,
519 uint32_t NTPsec,
520 uint32_t NTPfrac)
niklase@google.com470e71d2011-07-07 08:21:25 +0000521{
522 // sanity
523 if(pos + 52 >= IP_PACKET_SIZE)
524 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000525 LOG(LS_WARNING) << "Failed to build Sender Report.";
niklase@google.com470e71d2011-07-07 08:21:25 +0000526 return -2;
527 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000528 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000529
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000530 uint32_t posNumberOfReportBlocks = pos;
531 rtcpbuffer[pos++]=(uint8_t)0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
533 // Sender report
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000534 rtcpbuffer[pos++]=(uint8_t)200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000535
536 for(int i = (RTCP_NUMBER_OF_SR-2); i >= 0; i--)
537 {
538 // shift old
539 _lastSendReport[i+1] = _lastSendReport[i];
540 _lastRTCPTime[i+1] =_lastRTCPTime[i];
541 }
542
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000543 _lastRTCPTime[0] = Clock::NtpToMs(NTPsec, NTPfrac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000544 _lastSendReport[0] = (NTPsec << 16) + (NTPfrac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000545
stefan@webrtc.org7da34592013-04-09 14:56:29 +0000546 // The timestamp of this RTCP packet should be estimated as the timestamp of
547 // the frame being captured at this moment. We are calculating that
548 // timestamp as the last frame's timestamp + the time since the last frame
549 // was captured.
pbos@webrtc.org180e5162014-07-11 15:36:26 +0000550 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
551 (_clock->TimeInMilliseconds() - last_frame_capture_time_ms_) *
552 (feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553
554 // Add sender data
555 // Save for our length field
556 pos++;
557 pos++;
558
559 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000560 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000561 pos += 4;
562 // NTP
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000563 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, NTPsec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000564 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000565 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000567 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000568 pos += 4;
569
570 //sender's packet count
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000571 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos,
572 feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000573 pos += 4;
574
575 //sender's octet count
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000576 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos,
577 feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000578 pos += 4;
579
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000580 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000581 int32_t retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
582 numberOfReportBlocks,
583 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000584 if(retVal < 0)
585 {
586 //
587 return retVal ;
588 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000589 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000590 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
591
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000592 uint16_t len = uint16_t((pos/4) -1);
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000593 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000594 return 0;
595}
596
597
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000598int32_t RTCPSender::BuildSDEC(uint8_t* rtcpbuffer, int& pos) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000599 size_t lengthCname = strlen(_CNAME);
600 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000602 // sanity
603 if(pos + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000604 LOG(LS_WARNING) << "Failed to build SDEC.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605 return -2;
606 }
607 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000608
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000609 // We always need to add SDES CNAME
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000610 rtcpbuffer[pos++] = static_cast<uint8_t>(0x80 + 1 + _csrcCNAMEs.size());
611 rtcpbuffer[pos++] = static_cast<uint8_t>(202);
niklase@google.com470e71d2011-07-07 08:21:25 +0000612
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000613 // handle SDES length later on
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000614 uint32_t SDESLengthPos = pos;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000615 pos++;
616 pos++;
niklase@google.com470e71d2011-07-07 08:21:25 +0000617
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000618 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000619 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000620 pos += 4;
621
622 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000623 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000624
625 //
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000626 rtcpbuffer[pos++] = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000627
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000628 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000629
630 memcpy(&rtcpbuffer[pos], _CNAME, lengthCname);
631 pos += lengthCname;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000632 SDESLength += (uint16_t)lengthCname;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000633
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000634 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000635 // We must have a zero field even if we have an even multiple of 4 bytes
636 if ((pos % 4) == 0) {
637 padding++;
638 rtcpbuffer[pos++]=0;
639 }
640 while ((pos % 4) != 0) {
641 padding++;
642 rtcpbuffer[pos++]=0;
643 }
644 SDESLength += padding;
645
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000646 std::map<uint32_t, RTCPUtility::RTCPCnameInformation*>::iterator it =
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000647 _csrcCNAMEs.begin();
648
649 for(; it != _csrcCNAMEs.end(); it++) {
650 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000651 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000652
653 // Add SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000654 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000655 pos += 4;
656
657 // CNAME = 1
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000658 rtcpbuffer[pos++] = static_cast<uint8_t>(1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000659
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000660 size_t length = strlen(cname->name);
661 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000662
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000663 rtcpbuffer[pos++]= static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000664 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000666 memcpy(&rtcpbuffer[pos],cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000668 pos += length;
669 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000670 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000671
672 // We must have a zero field even if we have an even multiple of 4 bytes
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000673 if((pos % 4) == 0){
674 padding++;
675 rtcpbuffer[pos++]=0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000676 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000677 while((pos % 4) != 0){
678 padding++;
679 rtcpbuffer[pos++] = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000680 }
681 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000682 }
683 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000684 uint16_t buffer_length = (SDESLength / 4) - 1;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000685 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + SDESLengthPos,
686 buffer_length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000687 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000688}
689
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000690int32_t RTCPSender::BuildRR(uint8_t* rtcpbuffer,
691 int& pos,
692 uint32_t NTPsec,
693 uint32_t NTPfrac) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000694 // sanity one block
695 if(pos + 32 >= IP_PACKET_SIZE)
696 {
697 return -2;
698 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000699 uint32_t posNumberOfReportBlocks = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000700
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000701 rtcpbuffer[pos++]=(uint8_t)0x80;
702 rtcpbuffer[pos++]=(uint8_t)201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000703
704 // Save for our length field
705 pos++;
706 pos++;
707
708 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000709 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000710 pos += 4;
711
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000712 uint8_t numberOfReportBlocks = 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000713 int retVal = WriteAllReportBlocksToBuffer(rtcpbuffer, pos,
714 numberOfReportBlocks,
715 NTPsec, NTPfrac);
niklase@google.com470e71d2011-07-07 08:21:25 +0000716 if(retVal < 0)
717 {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000718 return pos;
niklase@google.com470e71d2011-07-07 08:21:25 +0000719 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000720 pos = retVal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000721 rtcpbuffer[posNumberOfReportBlocks] += numberOfReportBlocks;
722
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000723 uint16_t len = uint16_t((pos)/4 -1);
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000724 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + 2, len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000725 return 0;
726}
727
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000728// From RFC 5450: Transmission Time Offsets in RTP Streams.
729// 0 1 2 3
730// 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
731// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
732// hdr |V=2|P| RC | PT=IJ=195 | length |
733// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
734// | inter-arrival jitter |
735// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
736// . .
737// . .
738// . .
739// | inter-arrival jitter |
740// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
741//
742// If present, this RTCP packet must be placed after a receiver report
743// (inside a compound RTCP packet), and MUST have the same value for RC
744// (reception report count) as the receiver report.
745
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000746int32_t
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000747RTCPSender::BuildExtendedJitterReport(
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000748 uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000749 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000750 const uint32_t jitterTransmissionTimeOffset)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000751{
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000752 if (external_report_blocks_.size() > 0)
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000753 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000754 // TODO(andresp): Remove external report blocks since they are not
755 // supported.
756 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000757 return 0;
758 }
759
760 // sanity
761 if(pos + 8 >= IP_PACKET_SIZE)
762 {
763 return -2;
764 }
765 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000766 uint8_t RC = 1;
767 rtcpbuffer[pos++]=(uint8_t)0x80 + RC;
768 rtcpbuffer[pos++]=(uint8_t)195;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000769
770 // Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000771 rtcpbuffer[pos++]=(uint8_t)0;
772 rtcpbuffer[pos++]=(uint8_t)(1);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000773
774 // Add inter-arrival jitter
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000775 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos,
776 jitterTransmissionTimeOffset);
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000777 pos += 4;
778 return 0;
779}
780
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000781int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000782RTCPSender::BuildPLI(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +0000783{
784 // sanity
785 if(pos + 12 >= IP_PACKET_SIZE)
786 {
787 return -2;
788 }
789 // add picture loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000790 uint8_t FMT = 1;
791 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
792 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000793
794 //Used fixed length of 2
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000795 rtcpbuffer[pos++]=(uint8_t)0;
796 rtcpbuffer[pos++]=(uint8_t)(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000797
798 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000799 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000800 pos += 4;
801
802 // Add the remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000803 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000804 pos += 4;
805 return 0;
806}
807
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000808int32_t RTCPSender::BuildFIR(uint8_t* rtcpbuffer,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000809 int& pos,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000810 bool repeat) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000811 // sanity
812 if(pos + 20 >= IP_PACKET_SIZE) {
813 return -2;
814 }
815 if (!repeat) {
816 _sequenceNumberFIR++; // do not increase if repetition
817 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000818
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000819 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000820 uint8_t FMT = 4;
821 rtcpbuffer[pos++] = (uint8_t)0x80 + FMT;
822 rtcpbuffer[pos++] = (uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000823
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000824 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000825 rtcpbuffer[pos++] = (uint8_t)0;
826 rtcpbuffer[pos++] = (uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000827
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000828 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000829 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000830 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000832 // RFC 5104 4.3.1.2. Semantics
833 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000834 rtcpbuffer[pos++] = (uint8_t)0;
835 rtcpbuffer[pos++] = (uint8_t)0;
836 rtcpbuffer[pos++] = (uint8_t)0;
837 rtcpbuffer[pos++] = (uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000838
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000839 // Additional Feedback Control Information (FCI)
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000840 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000841 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000842
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000843 rtcpbuffer[pos++] = (uint8_t)(_sequenceNumberFIR);
844 rtcpbuffer[pos++] = (uint8_t)0;
845 rtcpbuffer[pos++] = (uint8_t)0;
846 rtcpbuffer[pos++] = (uint8_t)0;
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000847 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000848}
849
850/*
851 0 1 2 3
852 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
853 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
854 | First | Number | PictureID |
855 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
856*/
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000857int32_t RTCPSender::BuildSLI(uint8_t* rtcpbuffer, int& pos, uint8_t pictureID) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000858 // sanity
859 if(pos + 16 >= IP_PACKET_SIZE)
860 {
861 return -2;
862 }
863 // add slice loss indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000864 uint8_t FMT = 2;
865 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
866 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000867
868 //Used fixed length of 3
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000869 rtcpbuffer[pos++]=(uint8_t)0;
870 rtcpbuffer[pos++]=(uint8_t)(3);
niklase@google.com470e71d2011-07-07 08:21:25 +0000871
872 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000873 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000874 pos += 4;
875
876 // Add the remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000877 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000878 pos += 4;
879
880 // Add first, number & picture ID 6 bits
881 // first = 0, 13 - bits
882 // number = 0x1fff, 13 - bits only ones for now
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000883 uint32_t sliField = (0x1fff << 6)+ (0x3f & pictureID);
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000884 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, sliField);
niklase@google.com470e71d2011-07-07 08:21:25 +0000885 pos += 4;
886 return 0;
887}
888
889/*
890 0 1 2 3
891 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
892 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
893 | PB |0| Payload Type| Native RPSI bit string |
894 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
895 | defined per codec ... | Padding (0) |
896 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
897*/
898/*
899* Note: not generic made for VP8
900*/
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000901int32_t RTCPSender::BuildRPSI(uint8_t* rtcpbuffer,
902 int& pos,
903 uint64_t pictureID,
904 uint8_t payloadType) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000905 // sanity
906 if(pos + 24 >= IP_PACKET_SIZE)
907 {
908 return -2;
909 }
910 // add Reference Picture Selection Indication
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000911 uint8_t FMT = 3;
912 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
913 rtcpbuffer[pos++]=(uint8_t)206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000914
915 // calc length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000916 uint32_t bitsRequired = 7;
917 uint8_t bytesRequired = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000918 while((pictureID>>bitsRequired) > 0)
919 {
920 bitsRequired += 7;
921 bytesRequired++;
922 }
923
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000924 uint8_t size = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000925 if(bytesRequired > 6)
926 {
927 size = 5;
928 } else if(bytesRequired > 2)
929 {
930 size = 4;
931 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000932 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000933 rtcpbuffer[pos++]=size;
934
935 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000936 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000937 pos += 4;
938
939 // Add the remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000940 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000941 pos += 4;
942
943 // calc padding length
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000944 uint8_t paddingBytes = 4-((2+bytesRequired)%4);
niklase@google.com470e71d2011-07-07 08:21:25 +0000945 if(paddingBytes == 4)
946 {
947 paddingBytes = 0;
948 }
949 // add padding length in bits
950 rtcpbuffer[pos] = paddingBytes*8; // padding can be 0, 8, 16 or 24
951 pos++;
952
953 // add payload type
954 rtcpbuffer[pos] = payloadType;
955 pos++;
956
957 // add picture ID
958 for(int i = bytesRequired-1; i > 0; i--)
959 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000960 rtcpbuffer[pos] = 0x80 | uint8_t(pictureID >> (i*7));
niklase@google.com470e71d2011-07-07 08:21:25 +0000961 pos++;
962 }
963 // add last byte of picture ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000964 rtcpbuffer[pos] = uint8_t(pictureID & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000965 pos++;
966
967 // add padding
968 for(int j = 0; j <paddingBytes; j++)
969 {
970 rtcpbuffer[pos] = 0;
971 pos++;
972 }
973 return 0;
974}
975
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000976int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000977RTCPSender::BuildREMB(uint8_t* rtcpbuffer, int& pos)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000978{
979 // sanity
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000980 if(pos + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000981 {
982 return -2;
983 }
984 // add application layer feedback
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000985 uint8_t FMT = 15;
986 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
987 rtcpbuffer[pos++]=(uint8_t)206;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000988
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000989 rtcpbuffer[pos++]=(uint8_t)0;
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +0000990 rtcpbuffer[pos++]=remb_ssrcs_.size() + 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000991
992 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000993 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000994 pos += 4;
995
996 // Remote SSRC must be 0
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000997 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, 0);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000998 pos += 4;
999
1000 rtcpbuffer[pos++]='R';
1001 rtcpbuffer[pos++]='E';
1002 rtcpbuffer[pos++]='M';
1003 rtcpbuffer[pos++]='B';
1004
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001005 rtcpbuffer[pos++] = remb_ssrcs_.size();
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001006 // 6 bit Exp
1007 // 18 bit mantissa
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001008 uint8_t brExp = 0;
1009 for(uint32_t i=0; i<64; i++)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001010 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001011 if(_rembBitrate <= ((uint32_t)262143 << i))
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001012 {
1013 brExp = i;
1014 break;
1015 }
1016 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001017 const uint32_t brMantissa = (_rembBitrate >> brExp);
1018 rtcpbuffer[pos++]=(uint8_t)((brExp << 2) + ((brMantissa >> 16) & 0x03));
1019 rtcpbuffer[pos++]=(uint8_t)(brMantissa >> 8);
1020 rtcpbuffer[pos++]=(uint8_t)(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001021
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001022 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001023 {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001024 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, remb_ssrcs_[i]);
pbos@webrtc.org49ff40e2014-11-13 14:42:37 +00001025 pos += 4;
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001026 }
1027 return 0;
1028}
1029
stefan@webrtc.org9354cc92012-06-07 08:10:14 +00001030void
1031RTCPSender::SetTargetBitrate(unsigned int target_bitrate)
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001032{
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001033 CriticalSectionScoped lock(_criticalSectionRTCPSender);
pwestin@webrtc.org741da942011-09-20 13:52:04 +00001034 _tmmbr_Send = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +00001035}
1036
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001037int32_t RTCPSender::BuildTMMBR(ModuleRtpRtcpImpl* rtp_rtcp_module,
1038 uint8_t* rtcpbuffer,
1039 int& pos) {
1040 if (rtp_rtcp_module == NULL)
1041 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001042 // Before sending the TMMBR check the received TMMBN, only an owner is allowed to raise the bitrate
1043 // If the sender is an owner of the TMMBN -> send TMMBR
1044 // If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
1045
niklase@google.com470e71d2011-07-07 08:21:25 +00001046 // get current bounding set from RTCP receiver
1047 bool tmmbrOwner = false;
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001048 // store in candidateSet, allocates one extra slot
1049 TMMBRSet* candidateSet = _tmmbrHelp.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +00001050
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001051 // holding _criticalSectionRTCPSender while calling RTCPreceiver which
1052 // will accuire _criticalSectionRTCPReceiver is a potental deadlock but
1053 // since RTCPreceiver is not doing the reverse we should be fine
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001054 int32_t lengthOfBoundingSet =
1055 rtp_rtcp_module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +00001056
1057 if(lengthOfBoundingSet > 0)
1058 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001059 for (int32_t i = 0; i < lengthOfBoundingSet; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001060 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001061 if( candidateSet->Tmmbr(i) == _tmmbr_Send &&
1062 candidateSet->PacketOH(i) == _packetOH_Send)
niklase@google.com470e71d2011-07-07 08:21:25 +00001063 {
1064 // do not send the same tuple
1065 return 0;
1066 }
1067 }
1068 if(!tmmbrOwner)
1069 {
1070 // use received bounding set as candidate set
1071 // add current tuple
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001072 candidateSet->SetEntry(lengthOfBoundingSet,
1073 _tmmbr_Send,
1074 _packetOH_Send,
1075 _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001076 int numCandidates = lengthOfBoundingSet+ 1;
1077
1078 // find bounding set
1079 TMMBRSet* boundingSet = NULL;
1080 int numBoundingSet = _tmmbrHelp.FindTMMBRBoundingSet(boundingSet);
1081 if(numBoundingSet > 0 || numBoundingSet <= numCandidates)
1082 {
1083 tmmbrOwner = _tmmbrHelp.IsOwner(_SSRC, numBoundingSet);
1084 }
1085 if(!tmmbrOwner)
1086 {
1087 // did not enter bounding set, no meaning to send this request
1088 return 0;
1089 }
1090 }
1091 }
1092
1093 if(_tmmbr_Send)
1094 {
1095 // sanity
1096 if(pos + 20 >= IP_PACKET_SIZE)
1097 {
1098 return -2;
1099 }
1100 // add TMMBR indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001101 uint8_t FMT = 3;
1102 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1103 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001104
1105 //Length of 4
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001106 rtcpbuffer[pos++]=(uint8_t)0;
1107 rtcpbuffer[pos++]=(uint8_t)(4);
niklase@google.com470e71d2011-07-07 08:21:25 +00001108
1109 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001110 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 pos += 4;
1112
1113 // RFC 5104 4.2.1.2. Semantics
1114
1115 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001116 rtcpbuffer[pos++]=(uint8_t)0;
1117 rtcpbuffer[pos++]=(uint8_t)0;
1118 rtcpbuffer[pos++]=(uint8_t)0;
1119 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001120
1121 // Additional Feedback Control Information (FCI)
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001122 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001123 pos += 4;
1124
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001125 uint32_t bitRate = _tmmbr_Send*1000;
1126 uint32_t mmbrExp = 0;
1127 for(uint32_t i=0;i<64;i++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001128 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001129 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001130 {
1131 mmbrExp = i;
1132 break;
1133 }
1134 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001135 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
niklase@google.com470e71d2011-07-07 08:21:25 +00001136
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001137 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1138 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1139 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((_packetOH_Send >> 8)& 0x01));
1140 rtcpbuffer[pos++]=(uint8_t)(_packetOH_Send);
niklase@google.com470e71d2011-07-07 08:21:25 +00001141 }
1142 return 0;
1143}
1144
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001145int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001146RTCPSender::BuildTMMBN(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001147{
1148 TMMBRSet* boundingSet = _tmmbrHelp.BoundingSetToSend();
1149 if(boundingSet == NULL)
1150 {
1151 return -1;
1152 }
1153 // sanity
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001154 if(pos + 12 + boundingSet->lengthOfSet()*8 >= IP_PACKET_SIZE)
niklase@google.com470e71d2011-07-07 08:21:25 +00001155 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001156 LOG(LS_WARNING) << "Failed to build TMMBN.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001157 return -2;
1158 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001159 uint8_t FMT = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001160 // add TMMBN indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001161 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1162 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001163
1164 //Add length later
1165 int posLength = pos;
1166 pos++;
1167 pos++;
1168
1169 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001170 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001171 pos += 4;
1172
1173 // RFC 5104 4.2.2.2. Semantics
1174
1175 // SSRC of media source
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001176 rtcpbuffer[pos++]=(uint8_t)0;
1177 rtcpbuffer[pos++]=(uint8_t)0;
1178 rtcpbuffer[pos++]=(uint8_t)0;
1179 rtcpbuffer[pos++]=(uint8_t)0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001180
1181 // Additional Feedback Control Information (FCI)
1182 int numBoundingSet = 0;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001183 for(uint32_t n=0; n< boundingSet->lengthOfSet(); n++)
niklase@google.com470e71d2011-07-07 08:21:25 +00001184 {
hta@webrtc.org54536bb2012-05-03 14:07:23 +00001185 if (boundingSet->Tmmbr(n) > 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001186 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001187 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001188 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, tmmbrSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001189 pos += 4;
1190
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001191 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1192 uint32_t mmbrExp = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001193 for(int i=0; i<64; i++)
1194 {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001195 if(bitRate <= ((uint32_t)131071 << i))
niklase@google.com470e71d2011-07-07 08:21:25 +00001196 {
1197 mmbrExp = i;
1198 break;
1199 }
1200 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001201 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1202 uint32_t measuredOH = boundingSet->PacketOH(n);
niklase@google.com470e71d2011-07-07 08:21:25 +00001203
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001204 rtcpbuffer[pos++]=(uint8_t)((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
1205 rtcpbuffer[pos++]=(uint8_t)(mmbrMantissa >> 7);
1206 rtcpbuffer[pos++]=(uint8_t)((mmbrMantissa << 1) + ((measuredOH >> 8)& 0x01));
1207 rtcpbuffer[pos++]=(uint8_t)(measuredOH);
niklase@google.com470e71d2011-07-07 08:21:25 +00001208 numBoundingSet++;
1209 }
1210 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001211 uint16_t length= (uint16_t)(2+2*numBoundingSet);
1212 rtcpbuffer[posLength++]=(uint8_t)(length>>8);
1213 rtcpbuffer[posLength]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001214 return 0;
1215}
1216
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001217int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001218RTCPSender::BuildAPP(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001219{
1220 // sanity
1221 if(_appData == NULL)
1222 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001223 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 return -1;
1225 }
1226 if(pos + 12 + _appLength >= IP_PACKET_SIZE)
1227 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001228 LOG(LS_WARNING) << "Failed to build app specific.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001229 return -2;
1230 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001231 rtcpbuffer[pos++]=(uint8_t)0x80 + _appSubType;
niklase@google.com470e71d2011-07-07 08:21:25 +00001232
1233 // Add APP ID
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001234 rtcpbuffer[pos++]=(uint8_t)204;
niklase@google.com470e71d2011-07-07 08:21:25 +00001235
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001236 uint16_t length = (_appLength>>2) + 2; // include SSRC and name
1237 rtcpbuffer[pos++]=(uint8_t)(length>>8);
1238 rtcpbuffer[pos++]=(uint8_t)(length);
niklase@google.com470e71d2011-07-07 08:21:25 +00001239
1240 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001241 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001242 pos += 4;
1243
1244 // Add our application name
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001245 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _appName);
niklase@google.com470e71d2011-07-07 08:21:25 +00001246 pos += 4;
1247
1248 // Add the data
1249 memcpy(rtcpbuffer +pos, _appData,_appLength);
1250 pos += _appLength;
1251 return 0;
1252}
1253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001254int32_t RTCPSender::BuildNACK(uint8_t* rtcpbuffer,
1255 int& pos,
1256 int32_t nackSize,
1257 const uint16_t* nackList,
1258 std::string* nackString) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001259 // sanity
1260 if(pos + 16 >= IP_PACKET_SIZE)
1261 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001262 LOG(LS_WARNING) << "Failed to build NACK.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001263 return -2;
1264 }
1265
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001266 // int size, uint16_t* nackList
niklase@google.com470e71d2011-07-07 08:21:25 +00001267 // add nack list
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001268 uint8_t FMT = 1;
1269 rtcpbuffer[pos++]=(uint8_t)0x80 + FMT;
1270 rtcpbuffer[pos++]=(uint8_t)205;
niklase@google.com470e71d2011-07-07 08:21:25 +00001271
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001272 rtcpbuffer[pos++]=(uint8_t) 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001273 int nackSizePos = pos;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001274 rtcpbuffer[pos++]=(uint8_t)(3); //setting it to one kNACK signal as default
niklase@google.com470e71d2011-07-07 08:21:25 +00001275
1276 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001277 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001278 pos += 4;
1279
1280 // Add the remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001281 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001282 pos += 4;
1283
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001284 // Build NACK bitmasks and write them to the RTCP message.
1285 // The nack list should be sorted and not contain duplicates if one
1286 // wants to build the smallest rtcp nack packet.
1287 int numOfNackFields = 0;
1288 int maxNackFields = std::min<int>(kRtcpMaxNackFields,
1289 (IP_PACKET_SIZE - pos) / 4);
1290 int i = 0;
1291 while (i < nackSize && numOfNackFields < maxNackFields) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001292 uint16_t nack = nackList[i++];
1293 uint16_t bitmask = 0;
1294 while (i < nackSize) {
1295 int shift = static_cast<uint16_t>(nackList[i] - nack) - 1;
1296 if (shift >= 0 && shift <= 15) {
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001297 bitmask |= (1 << shift);
1298 ++i;
1299 } else {
1300 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001301 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001302 }
1303 // Write the sequence number and the bitmask to the packet.
1304 assert(pos + 4 < IP_PACKET_SIZE);
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001305 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + pos, nack);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001306 pos += 2;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001307 ByteWriter<uint16_t>::WriteBigEndian(rtcpbuffer + pos, bitmask);
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001308 pos += 2;
1309 numOfNackFields++;
niklase@google.com470e71d2011-07-07 08:21:25 +00001310 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001311 rtcpbuffer[nackSizePos] = static_cast<uint8_t>(2 + numOfNackFields);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001312
1313 if (i != nackSize) {
1314 LOG(LS_WARNING) << "Nack list too large for one packet.";
1315 }
1316
1317 // Report stats.
1318 NACKStringBuilder stringBuilder;
1319 for (int idx = 0; idx < i; ++idx) {
1320 stringBuilder.PushNACK(nackList[idx]);
1321 nack_stats_.ReportRequest(nackList[idx]);
1322 }
edjee@google.com79b02892013-04-04 19:43:34 +00001323 *nackString = stringBuilder.GetResult();
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001324 packet_type_counter_.nack_requests = nack_stats_.requests();
1325 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
niklase@google.com470e71d2011-07-07 08:21:25 +00001326 return 0;
1327}
1328
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001329int32_t RTCPSender::BuildBYE(uint8_t* rtcpbuffer, int& pos) {
1330 // sanity
1331 if (pos + 8 >= IP_PACKET_SIZE) {
1332 return -2;
1333 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001334
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001335 // Add a bye packet
1336 // Number of SSRC + CSRCs.
1337 rtcpbuffer[pos++] = (uint8_t)0x80 + 1 + csrcs_.size();
1338 rtcpbuffer[pos++] = (uint8_t)203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001339
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001340 // length
1341 rtcpbuffer[pos++] = (uint8_t)0;
1342 rtcpbuffer[pos++] = (uint8_t)(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001343
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001344 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001345 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001346 pos += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001347
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001348 // add CSRCs
1349 for (size_t i = 0; i < csrcs_.size(); i++) {
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001350 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, csrcs_[i]);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001351 pos += 4;
1352 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001353
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001354 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001355}
1356
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001357int32_t RTCPSender::BuildReceiverReferenceTime(uint8_t* buffer,
1358 int& pos,
1359 uint32_t ntp_sec,
1360 uint32_t ntp_frac) {
1361 const int kRrTimeBlockLength = 20;
1362 if (pos + kRrTimeBlockLength >= IP_PACKET_SIZE) {
1363 return -2;
1364 }
1365
1366 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR) {
1367 last_xr_rr_.erase(last_xr_rr_.begin());
1368 }
1369 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
1370 RTCPUtility::MidNtp(ntp_sec, ntp_frac),
1371 Clock::NtpToMs(ntp_sec, ntp_frac)));
1372
1373 // Add XR header.
1374 buffer[pos++] = 0x80;
1375 buffer[pos++] = 207;
1376 buffer[pos++] = 0; // XR packet length.
1377 buffer[pos++] = 4; // XR packet length.
1378
1379 // Add our own SSRC.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001380 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001381 pos += 4;
1382
1383 // 0 1 2 3
1384 // 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
1385 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1386 // | BT=4 | reserved | block length = 2 |
1387 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1388 // | NTP timestamp, most significant word |
1389 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1390 // | NTP timestamp, least significant word |
1391 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1392
1393 // Add Receiver Reference Time Report block.
1394 buffer[pos++] = 4; // BT.
1395 buffer[pos++] = 0; // Reserved.
1396 buffer[pos++] = 0; // Block length.
1397 buffer[pos++] = 2; // Block length.
1398
1399 // NTP timestamp.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001400 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, ntp_sec);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001401 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001402 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001403 pos += 4;
1404
1405 return 0;
1406}
1407
1408int32_t RTCPSender::BuildDlrr(uint8_t* buffer,
1409 int& pos,
1410 const RtcpReceiveTimeInfo& info) {
1411 const int kDlrrBlockLength = 24;
1412 if (pos + kDlrrBlockLength >= IP_PACKET_SIZE) {
1413 return -2;
1414 }
1415
1416 // Add XR header.
1417 buffer[pos++] = 0x80;
1418 buffer[pos++] = 207;
1419 buffer[pos++] = 0; // XR packet length.
1420 buffer[pos++] = 5; // XR packet length.
1421
1422 // Add our own SSRC.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001423 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, _SSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001424 pos += 4;
1425
1426 // 0 1 2 3
1427 // 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
1428 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1429 // | BT=5 | reserved | block length |
1430 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1431 // | SSRC_1 (SSRC of first receiver) | sub-
1432 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1433 // | last RR (LRR) | 1
1434 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1435 // | delay since last RR (DLRR) |
1436 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1437 // | SSRC_2 (SSRC of second receiver) | sub-
1438 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1439 // : ... : 2
1440
1441 // Add DLRR sub block.
1442 buffer[pos++] = 5; // BT.
1443 buffer[pos++] = 0; // Reserved.
1444 buffer[pos++] = 0; // Block length.
1445 buffer[pos++] = 3; // Block length.
1446
1447 // NTP timestamp.
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001448 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, info.sourceSSRC);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001449 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001450 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, info.lastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001451 pos += 4;
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001452 ByteWriter<uint32_t>::WriteBigEndian(buffer + pos, info.delaySinceLastRR);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001453 pos += 4;
1454
1455 return 0;
1456}
1457
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001458int32_t
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001459RTCPSender::BuildVoIPMetric(uint8_t* rtcpbuffer, int& pos)
niklase@google.com470e71d2011-07-07 08:21:25 +00001460{
1461 // sanity
1462 if(pos + 44 >= IP_PACKET_SIZE)
1463 {
1464 return -2;
1465 }
1466
1467 // Add XR header
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001468 rtcpbuffer[pos++]=(uint8_t)0x80;
1469 rtcpbuffer[pos++]=(uint8_t)207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001470
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001471 uint32_t XRLengthPos = pos;
niklase@google.com470e71d2011-07-07 08:21:25 +00001472
1473 // handle length later on
1474 pos++;
1475 pos++;
1476
1477 // Add our own SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001478 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001479 pos += 4;
1480
1481 // Add a VoIP metrics block
1482 rtcpbuffer[pos++]=7;
1483 rtcpbuffer[pos++]=0;
1484 rtcpbuffer[pos++]=0;
1485 rtcpbuffer[pos++]=8;
1486
1487 // Add the remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001488 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + pos, _remoteSSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +00001489 pos += 4;
1490
1491 rtcpbuffer[pos++] = _xrVoIPMetric.lossRate;
1492 rtcpbuffer[pos++] = _xrVoIPMetric.discardRate;
1493 rtcpbuffer[pos++] = _xrVoIPMetric.burstDensity;
1494 rtcpbuffer[pos++] = _xrVoIPMetric.gapDensity;
1495
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001496 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration >> 8);
1497 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.burstDuration);
1498 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration >> 8);
1499 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001500
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001501 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay >> 8);
1502 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.roundTripDelay);
1503 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay >> 8);
1504 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001505
1506 rtcpbuffer[pos++] = _xrVoIPMetric.signalLevel;
1507 rtcpbuffer[pos++] = _xrVoIPMetric.noiseLevel;
1508 rtcpbuffer[pos++] = _xrVoIPMetric.RERL;
1509 rtcpbuffer[pos++] = _xrVoIPMetric.Gmin;
1510
1511 rtcpbuffer[pos++] = _xrVoIPMetric.Rfactor;
1512 rtcpbuffer[pos++] = _xrVoIPMetric.extRfactor;
1513 rtcpbuffer[pos++] = _xrVoIPMetric.MOSLQ;
1514 rtcpbuffer[pos++] = _xrVoIPMetric.MOSCQ;
1515
1516 rtcpbuffer[pos++] = _xrVoIPMetric.RXconfig;
1517 rtcpbuffer[pos++] = 0; // reserved
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001518 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal >> 8);
1519 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBnominal);
niklase@google.com470e71d2011-07-07 08:21:25 +00001520
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001521 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax >> 8);
1522 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBmax);
1523 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax >> 8);
1524 rtcpbuffer[pos++] = (uint8_t)(_xrVoIPMetric.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001525
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001526 rtcpbuffer[XRLengthPos]=(uint8_t)(0);
1527 rtcpbuffer[XRLengthPos+1]=(uint8_t)(10);
niklase@google.com470e71d2011-07-07 08:21:25 +00001528 return 0;
1529}
1530
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001531int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
1532 uint32_t packetTypeFlags,
1533 int32_t nackSize,
1534 const uint16_t* nackList,
1535 bool repeat,
1536 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001537 {
1538 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1539 if(_method == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +00001540 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001541 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001542 return -1;
1543 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001544 }
1545 uint8_t rtcp_buffer[IP_PACKET_SIZE];
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001546 int rtcp_length = PrepareRTCP(feedback_state,
1547 packetTypeFlags,
1548 nackSize,
1549 nackList,
1550 repeat,
1551 pictureID,
1552 rtcp_buffer,
1553 IP_PACKET_SIZE);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001554 if (rtcp_length < 0) {
1555 return -1;
1556 }
1557 // Sanity don't send empty packets.
1558 if (rtcp_length == 0)
1559 {
1560 return -1;
1561 }
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001562 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001563}
1564
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001565int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
1566 uint32_t packetTypeFlags,
1567 int32_t nackSize,
1568 const uint16_t* nackList,
1569 bool repeat,
1570 uint64_t pictureID,
1571 uint8_t* rtcp_buffer,
1572 int buffer_size) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001573 uint32_t rtcpPacketTypeFlags = packetTypeFlags;
1574 // Collect the received information.
1575 uint32_t NTPsec = 0;
1576 uint32_t NTPfrac = 0;
1577 uint32_t jitterTransmissionOffset = 0;
1578 int position = 0;
1579
1580 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1581
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001582 if (packet_type_counter_.first_packet_time_ms == -1) {
1583 packet_type_counter_.first_packet_time_ms = _clock->TimeInMilliseconds();
1584 }
1585
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001586 if(_TMMBR ) // Attach TMMBR to send and receive reports.
1587 {
1588 rtcpPacketTypeFlags |= kRtcpTmmbr;
1589 }
1590 if(_appSend)
1591 {
1592 rtcpPacketTypeFlags |= kRtcpApp;
1593 _appSend = false;
1594 }
1595 if(_REMB && _sendREMB)
1596 {
1597 // Always attach REMB to SR if that is configured. Note that REMB is
1598 // only sent on one of the RTP modules in the REMB group.
1599 rtcpPacketTypeFlags |= kRtcpRemb;
1600 }
1601 if(_xrSendVoIPMetric)
1602 {
1603 rtcpPacketTypeFlags |= kRtcpXrVoipMetric;
1604 _xrSendVoIPMetric = false;
1605 }
1606 if(_sendTMMBN) // Set when having received a TMMBR.
1607 {
1608 rtcpPacketTypeFlags |= kRtcpTmmbn;
1609 _sendTMMBN = false;
1610 }
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001611 if (rtcpPacketTypeFlags & kRtcpReport)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001612 {
asapersson@webrtc.orgefaeda02014-01-20 08:34:49 +00001613 if (xrSendReceiverReferenceTimeEnabled_ && !_sending)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001614 {
1615 rtcpPacketTypeFlags |= kRtcpXrReceiverReferenceTime;
1616 }
1617 if (feedback_state.has_last_xr_rr)
1618 {
1619 rtcpPacketTypeFlags |= kRtcpXrDlrrReportBlock;
1620 }
1621 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001622 if(_method == kRtcpCompound)
1623 {
1624 if(_sending)
1625 {
1626 rtcpPacketTypeFlags |= kRtcpSr;
1627 } else
1628 {
1629 rtcpPacketTypeFlags |= kRtcpRr;
1630 }
1631 } else if(_method == kRtcpNonCompound)
1632 {
1633 if(rtcpPacketTypeFlags & kRtcpReport)
1634 {
1635 if(_sending)
1636 {
1637 rtcpPacketTypeFlags |= kRtcpSr;
1638 } else
1639 {
1640 rtcpPacketTypeFlags |= kRtcpRr;
1641 }
1642 }
1643 }
1644 if( rtcpPacketTypeFlags & kRtcpRr ||
1645 rtcpPacketTypeFlags & kRtcpSr)
1646 {
1647 // generate next time to send a RTCP report
1648 // seeded from RTP constructor
1649 int32_t random = rand() % 1000;
1650 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
1651
1652 if(_audio)
1653 {
1654 timeToNext = (RTCP_INTERVAL_AUDIO_MS/2) +
1655 (RTCP_INTERVAL_AUDIO_MS*random/1000);
1656 }else
1657 {
1658 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
1659 if(_sending)
1660 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001661 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1662 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1663 if (send_bitrate_kbit != 0)
1664 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001665 }
1666 if(minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1667 {
1668 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1669 }
1670 timeToNext = (minIntervalMs/2) + (minIntervalMs*random/1000);
1671 }
1672 _nextTimeToSendRTCP = _clock->TimeInMilliseconds() + timeToNext;
1673 }
1674
1675 // If the data does not fit in the packet we fill it as much as possible.
1676 int32_t buildVal = 0;
1677
1678 // We need to send our NTP even if we haven't received any reports.
1679 _clock->CurrentNtp(NTPsec, NTPfrac);
1680 if (ShouldSendReportBlocks(rtcpPacketTypeFlags)) {
1681 StatisticianMap statisticians =
1682 receive_statistics_->GetActiveStatisticians();
1683 if (!statisticians.empty()) {
1684 StatisticianMap::const_iterator it;
1685 int i;
1686 for (it = statisticians.begin(), i = 0; it != statisticians.end();
1687 ++it, ++i) {
1688 RTCPReportBlock report_block;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001689 if (PrepareReport(
1690 feedback_state, it->second, &report_block, &NTPsec, &NTPfrac))
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001691 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
1692 }
1693 if (_IJ && !statisticians.empty()) {
1694 rtcpPacketTypeFlags |= kRtcpTransmissionTimeOffset;
1695 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001696 }
1697 }
1698
1699 if(rtcpPacketTypeFlags & kRtcpSr)
1700 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001701 buildVal = BuildSR(feedback_state, rtcp_buffer, position, NTPsec, NTPfrac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001702 if (buildVal == -1) {
1703 return -1;
1704 } else if (buildVal == -2) {
1705 return position;
1706 }
1707 buildVal = BuildSDEC(rtcp_buffer, position);
1708 if (buildVal == -1) {
1709 return -1;
1710 } else if (buildVal == -2) {
1711 return position;
1712 }
1713 }else if(rtcpPacketTypeFlags & kRtcpRr)
1714 {
1715 buildVal = BuildRR(rtcp_buffer, position, NTPsec, NTPfrac);
1716 if (buildVal == -1) {
1717 return -1;
1718 } else if (buildVal == -2) {
1719 return position;
1720 }
1721 // only of set
1722 if(_CNAME[0] != 0)
1723 {
1724 buildVal = BuildSDEC(rtcp_buffer, position);
1725 if (buildVal == -1) {
1726 return -1;
1727 }
1728 }
1729 }
1730 if(rtcpPacketTypeFlags & kRtcpTransmissionTimeOffset)
1731 {
1732 // If present, this RTCP packet must be placed after a
1733 // receiver report.
1734 buildVal = BuildExtendedJitterReport(rtcp_buffer,
1735 position,
1736 jitterTransmissionOffset);
1737 if (buildVal == -1) {
1738 return -1;
1739 } else if (buildVal == -2) {
1740 return position;
1741 }
1742 }
1743 if(rtcpPacketTypeFlags & kRtcpPli)
1744 {
1745 buildVal = BuildPLI(rtcp_buffer, position);
1746 if (buildVal == -1) {
1747 return -1;
1748 } else if (buildVal == -2) {
1749 return position;
1750 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001751 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1752 "RTCPSender::PLI");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001753 ++packet_type_counter_.pli_packets;
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001754 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1755 "RTCP_PLICount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001756 packet_type_counter_.pli_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001757 }
1758 if(rtcpPacketTypeFlags & kRtcpFir)
1759 {
1760 buildVal = BuildFIR(rtcp_buffer, position, repeat);
1761 if (buildVal == -1) {
1762 return -1;
1763 } else if (buildVal == -2) {
1764 return position;
1765 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001766 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1767 "RTCPSender::FIR");
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001768 ++packet_type_counter_.fir_packets;
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001769 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1770 "RTCP_FIRCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001771 packet_type_counter_.fir_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001772 }
1773 if(rtcpPacketTypeFlags & kRtcpSli)
1774 {
1775 buildVal = BuildSLI(rtcp_buffer, position, (uint8_t)pictureID);
1776 if (buildVal == -1) {
1777 return -1;
1778 } else if (buildVal == -2) {
1779 return position;
1780 }
1781 }
1782 if(rtcpPacketTypeFlags & kRtcpRpsi)
1783 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001784 const int8_t payloadType = feedback_state.send_payload_type;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001785 if (payloadType == -1) {
1786 return -1;
1787 }
1788 buildVal = BuildRPSI(rtcp_buffer, position, pictureID,
1789 (uint8_t)payloadType);
1790 if (buildVal == -1) {
1791 return -1;
1792 } else if (buildVal == -2) {
1793 return position;
1794 }
1795 }
1796 if(rtcpPacketTypeFlags & kRtcpRemb)
1797 {
1798 buildVal = BuildREMB(rtcp_buffer, position);
1799 if (buildVal == -1) {
1800 return -1;
1801 } else if (buildVal == -2) {
1802 return position;
1803 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001804 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1805 "RTCPSender::REMB");
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001806 }
1807 if(rtcpPacketTypeFlags & kRtcpBye)
1808 {
1809 buildVal = BuildBYE(rtcp_buffer, position);
1810 if (buildVal == -1) {
1811 return -1;
1812 } else if (buildVal == -2) {
1813 return position;
1814 }
1815 }
1816 if(rtcpPacketTypeFlags & kRtcpApp)
1817 {
1818 buildVal = BuildAPP(rtcp_buffer, position);
1819 if (buildVal == -1) {
1820 return -1;
1821 } else if (buildVal == -2) {
1822 return position;
1823 }
1824 }
1825 if(rtcpPacketTypeFlags & kRtcpTmmbr)
1826 {
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001827 buildVal = BuildTMMBR(feedback_state.module, rtcp_buffer, position);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001828 if (buildVal == -1) {
1829 return -1;
1830 } else if (buildVal == -2) {
1831 return position;
1832 }
1833 }
1834 if(rtcpPacketTypeFlags & kRtcpTmmbn)
1835 {
1836 buildVal = BuildTMMBN(rtcp_buffer, position);
1837 if (buildVal == -1) {
1838 return -1;
1839 } else if (buildVal == -2) {
1840 return position;
1841 }
1842 }
1843 if(rtcpPacketTypeFlags & kRtcpNack)
1844 {
1845 std::string nackString;
1846 buildVal = BuildNACK(rtcp_buffer, position, nackSize, nackList,
1847 &nackString);
1848 if (buildVal == -1) {
1849 return -1;
1850 } else if (buildVal == -2) {
1851 return position;
1852 }
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001853 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1854 "RTCPSender::NACK", "nacks",
1855 TRACE_STR_COPY(nackString.c_str()));
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001856 ++packet_type_counter_.nack_packets;
sprang@webrtc.org0200f702015-02-16 12:06:00 +00001857 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1858 "RTCP_NACKCount", _SSRC,
asapersson@webrtc.org8098e072014-02-19 11:59:02 +00001859 packet_type_counter_.nack_packets);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001860 }
1861 if(rtcpPacketTypeFlags & kRtcpXrVoipMetric)
1862 {
1863 buildVal = BuildVoIPMetric(rtcp_buffer, position);
1864 if (buildVal == -1) {
1865 return -1;
1866 } else if (buildVal == -2) {
1867 return position;
1868 }
1869 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001870 if (rtcpPacketTypeFlags & kRtcpXrReceiverReferenceTime)
1871 {
1872 buildVal = BuildReceiverReferenceTime(rtcp_buffer,
1873 position,
1874 NTPsec,
1875 NTPfrac);
1876 if (buildVal == -1) {
1877 return -1;
1878 } else if (buildVal == -2) {
1879 return position;
1880 }
1881 }
1882 if (rtcpPacketTypeFlags & kRtcpXrDlrrReportBlock)
1883 {
1884 buildVal = BuildDlrr(rtcp_buffer, position, feedback_state.last_xr_rr);
1885 if (buildVal == -1) {
1886 return -1;
1887 } else if (buildVal == -2) {
1888 return position;
1889 }
1890 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001891
1892 if (packet_type_counter_observer_ != NULL) {
1893 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
1894 _remoteSSRC, packet_type_counter_);
1895 }
1896
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001897 return position;
1898}
1899
1900bool RTCPSender::ShouldSendReportBlocks(uint32_t rtcp_packet_type) const {
1901 return Status() == kRtcpCompound ||
1902 (rtcp_packet_type & kRtcpReport) ||
1903 (rtcp_packet_type & kRtcpSr) ||
1904 (rtcp_packet_type & kRtcpRr);
1905}
1906
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001907bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1908 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001909 RTCPReportBlock* report_block,
1910 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1911 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001912 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001913 if (!statistician->GetStatistics(&stats, true))
1914 return false;
1915 report_block->fractionLost = stats.fraction_lost;
1916 report_block->cumulativeLost = stats.cumulative_lost;
1917 report_block->extendedHighSeqNum =
1918 stats.extended_max_sequence_number;
1919 report_block->jitter = stats.jitter;
1920
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001921 // get our NTP as late as possible to avoid a race
1922 _clock->CurrentNtp(*ntp_secs, *ntp_frac);
1923
1924 // Delay since last received report
1925 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001926 if ((feedback_state.last_rr_ntp_secs != 0) ||
1927 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001928 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
1929 uint32_t now=*ntp_secs&0x0000FFFF;
1930 now <<=16;
1931 now += (*ntp_frac&0xffff0000)>>16;
1932
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001933 uint32_t receiveTime = feedback_state.last_rr_ntp_secs&0x0000FFFF;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001934 receiveTime <<=16;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001935 receiveTime += (feedback_state.last_rr_ntp_frac&0xffff0000)>>16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001936
1937 delaySinceLastReceivedSR = now-receiveTime;
1938 }
1939 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001940 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001941 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001942}
1943
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001944int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001945 CriticalSectionScoped lock(_criticalSectionTransport);
1946 if(_cbTransport)
1947 {
1948 if(_cbTransport->SendRTCPPacket(_id, dataBuffer, length) > 0)
1949 {
1950 return 0;
1951 }
1952 }
1953 return -1;
1954}
1955
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001956void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1957 assert(csrcs.size() <= kRtpCsrcSize);
1958 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1959 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001960}
1961
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001962int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1963 uint32_t name,
1964 const uint8_t* data,
1965 uint16_t length) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001966 if(length %4 != 0)
1967 {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001968 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
niklase@google.com470e71d2011-07-07 08:21:25 +00001969 return -1;
1970 }
1971 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1972
1973 if(_appData)
1974 {
1975 delete [] _appData;
1976 }
1977
1978 _appSend = true;
1979 _appSubType = subType;
1980 _appName = name;
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001981 _appData = new uint8_t[length];
niklase@google.com470e71d2011-07-07 08:21:25 +00001982 _appLength = length;
1983 memcpy(_appData, data, length);
1984 return 0;
1985}
1986
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001987int32_t
niklase@google.com470e71d2011-07-07 08:21:25 +00001988RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric)
1989{
1990 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1991 memcpy(&_xrVoIPMetric, VoIPMetric, sizeof(RTCPVoIPMetric));
1992
1993 _xrSendVoIPMetric = true;
1994 return 0;
1995}
1996
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001997void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
1998 CriticalSectionScoped lock(_criticalSectionRTCPSender);
1999 xrSendReceiverReferenceTimeEnabled_ = enable;
2000}
2001
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00002002bool RTCPSender::RtcpXrReceiverReferenceTime() const {
2003 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2004 return xrSendReceiverReferenceTimeEnabled_;
2005}
2006
niklase@google.com470e71d2011-07-07 08:21:25 +00002007// called under critsect _criticalSectionRTCPSender
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002008int32_t RTCPSender::WriteAllReportBlocksToBuffer(uint8_t* rtcpbuffer,
2009 int pos,
2010 uint8_t& numberOfReportBlocks,
2011 uint32_t NTPsec,
2012 uint32_t NTPfrac) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002013 numberOfReportBlocks = external_report_blocks_.size();
2014 numberOfReportBlocks += internal_report_blocks_.size();
2015 if ((pos + numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00002016 LOG(LS_WARNING) << "Can't fit all report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002017 return -1;
2018 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002019 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, internal_report_blocks_);
2020 while (!internal_report_blocks_.empty()) {
2021 delete internal_report_blocks_.begin()->second;
2022 internal_report_blocks_.erase(internal_report_blocks_.begin());
2023 }
2024 pos = WriteReportBlocksToBuffer(rtcpbuffer, pos, external_report_blocks_);
2025 return pos;
2026}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002027
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002028int32_t RTCPSender::WriteReportBlocksToBuffer(
2029 uint8_t* rtcpbuffer,
2030 int32_t position,
2031 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
2032 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
2033 report_blocks.begin();
2034 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00002035 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002036 RTCPReportBlock* reportBlock = it->second;
2037 if (reportBlock) {
2038 // Remote SSRC
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00002039 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position, remoteSSRC);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002040 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002041
2042 // fraction lost
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002043 rtcpbuffer[position++] = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002044
2045 // cumulative loss
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00002046 ByteWriter<uint32_t, 3>::WriteBigEndian(rtcpbuffer + position,
2047 reportBlock->cumulativeLost);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002048 position += 3;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002049
2050 // extended highest seq_no, contain the highest sequence number received
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00002051 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
2052 reportBlock->extendedHighSeqNum);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002053 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002054
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002055 // Jitter
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00002056 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
2057 reportBlock->jitter);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002058 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002059
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00002060 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
2061 reportBlock->lastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002062 position += 4;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002063
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00002064 ByteWriter<uint32_t>::WriteBigEndian(rtcpbuffer + position,
2065 reportBlock->delaySinceLastSR);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002066 position += 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00002067 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00002068 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00002069 return position;
niklase@google.com470e71d2011-07-07 08:21:25 +00002070}
2071
2072// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002073int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
2074 uint32_t maxBitrateKbit) {
niklase@google.com470e71d2011-07-07 08:21:25 +00002075 CriticalSectionScoped lock(_criticalSectionRTCPSender);
2076
2077 if (0 == _tmmbrHelp.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit))
2078 {
2079 _sendTMMBN = true;
2080 return 0;
2081 }
2082 return -1;
2083}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00002084} // namespace webrtc