blob: e2ad3f0cc392b506dc604e13bcb259e01b2d810e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000013#include <assert.h> // assert
14#include <stdlib.h> // rand
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000015#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000016
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000017#include <algorithm> // min
Erik Språng61be2a42015-04-27 13:32:52 +020018#include <limits> // max
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000019
Erik Språng61be2a42015-04-27 13:32:52 +020020#include "webrtc/base/checks.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000021#include "webrtc/common_types.h"
sprang@webrtc.org779c3d12015-03-17 16:42:49 +000022#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000023#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
24#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000025#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000026#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000027
niklase@google.com470e71d2011-07-07 08:21:25 +000028namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000029
30using RTCPUtility::RTCPCnameInformation;
31
Erik Språng61be2a42015-04-27 13:32:52 +020032NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020033 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000034}
35
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000036NACKStringBuilder::~NACKStringBuilder() {}
37
pbos@webrtc.org2f446732013-04-08 11:08:41 +000038void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000039{
Erik Språng242e22b2015-05-11 10:17:43 +020040 if (count_ == 0) {
41 stream_ << nack;
42 } else if (nack == prevNack_ + 1) {
43 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020044 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020045 if (consecutive_) {
46 stream_ << "-" << prevNack_;
47 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000048 }
Erik Språng242e22b2015-05-11 10:17:43 +020049 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020050 }
Erik Språng242e22b2015-05-11 10:17:43 +020051 count_++;
52 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000053}
54
Erik Språng61be2a42015-04-27 13:32:52 +020055std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (consecutive_) {
57 stream_ << "-" << prevNack_;
58 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020059 }
Erik Språng242e22b2015-05-11 10:17:43 +020060 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000061}
62
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000063RTCPSender::FeedbackState::FeedbackState()
64 : send_payload_type(0),
65 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000066 packets_sent(0),
67 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000068 send_bitrate(0),
69 last_rr_ntp_secs(0),
70 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000071 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020072 has_last_xr_rr(false),
73 module(nullptr) {
74}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000075
Erik Språng242e22b2015-05-11 10:17:43 +020076struct RTCPSender::RtcpContext {
77 RtcpContext(const FeedbackState& feedback_state,
78 int32_t nack_size,
79 const uint16_t* nack_list,
80 bool repeat,
81 uint64_t picture_id,
82 uint8_t* buffer,
83 uint32_t buffer_size)
84 : feedback_state(feedback_state),
85 nack_size(nack_size),
86 nack_list(nack_list),
87 repeat(repeat),
88 picture_id(picture_id),
89 buffer(buffer),
90 buffer_size(buffer_size),
91 ntp_sec(0),
92 ntp_frac(0),
93 jitter_transmission_offset(0),
94 position(0) {}
95
96 uint8_t* AllocateData(uint32_t bytes) {
97 DCHECK_LE(position + bytes, buffer_size);
98 uint8_t* ptr = &buffer[position];
99 position += bytes;
100 return ptr;
101 }
102
103 const FeedbackState& feedback_state;
104 int32_t nack_size;
105 const uint16_t* nack_list;
106 bool repeat;
107 uint64_t picture_id;
108 uint8_t* buffer;
109 uint32_t buffer_size;
110 uint32_t ntp_sec;
111 uint32_t ntp_frac;
112 uint32_t jitter_transmission_offset;
113 uint32_t position;
114};
115
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000116RTCPSender::RTCPSender(
117 int32_t id,
118 bool audio,
119 Clock* clock,
120 ReceiveStatistics* receive_statistics,
121 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Erik Språng242e22b2015-05-11 10:17:43 +0200122 : id_(id),
123 audio_(audio),
124 clock_(clock),
125 method_(kRtcpOff),
126 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000127 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200128 cbTransport_(nullptr),
niklase@google.com470e71d2011-07-07 08:21:25 +0000129
Erik Språng242e22b2015-05-11 10:17:43 +0200130 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000131 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200132 using_nack_(false),
133 sending_(false),
134 remb_enabled_(false),
135 extended_jitter_report_enabled_(false),
136 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000137 start_timestamp_(0),
138 last_rtp_timestamp_(0),
139 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200140 ssrc_(0),
141 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000142 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000143
Erik Språng242e22b2015-05-11 10:17:43 +0200144 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000145
Erik Språng242e22b2015-05-11 10:17:43 +0200146 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000147
Erik Språng242e22b2015-05-11 10:17:43 +0200148 tmmbr_help_(),
149 tmmbr_send_(0),
150 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000151
Erik Språng242e22b2015-05-11 10:17:43 +0200152 app_sub_type_(0),
153 app_data_(nullptr),
154 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000155
Erik Språng242e22b2015-05-11 10:17:43 +0200156 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000157 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200158 memset(cname_, 0, sizeof(cname_));
159 memset(last_send_report_, 0, sizeof(last_send_report_));
160 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
161
162 builders_[kRtcpSr] = &RTCPSender::BuildSR;
163 builders_[kRtcpRr] = &RTCPSender::BuildRR;
164 builders_[kRtcpSdes] = &RTCPSender::BuildSDEC;
165 builders_[kRtcpTransmissionTimeOffset] =
166 &RTCPSender::BuildExtendedJitterReport;
167 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
168 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
169 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
170 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
171 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
172 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
173 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
174 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
175 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
176 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
177 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
178 builders_[kRtcpXrReceiverReferenceTime] =
179 &RTCPSender::BuildReceiverReferenceTime;
180 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000181}
182
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000183RTCPSender::~RTCPSender() {
Erik Språng61be2a42015-04-27 13:32:52 +0200184 for (auto it : internal_report_blocks_)
185 delete it.second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000186
Erik Språng61be2a42015-04-27 13:32:52 +0200187 for (auto it : external_report_blocks_)
188 delete it.second;
189
Erik Språng242e22b2015-05-11 10:17:43 +0200190 for (auto it : csrc_cnames_)
Erik Språng61be2a42015-04-27 13:32:52 +0200191 delete it.second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
Erik Språng61be2a42015-04-27 13:32:52 +0200194int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200195 CriticalSectionScoped lock(critical_section_transport_.get());
196 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200197 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000198}
199
Erik Språng61be2a42015-04-27 13:32:52 +0200200RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200201 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
202 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203}
204
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000205void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200206 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
207 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000208
209 if (method == kRtcpOff)
210 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200211 next_time_to_send_rtcp_ =
212 clock_->TimeInMilliseconds() +
213 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200217 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
Erik Språng242e22b2015-05-11 10:17:43 +0200225 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
Erik Språng242e22b2015-05-11 10:17:43 +0200227 if (method_ != kRtcpOff) {
228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200241 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200246 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
247 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000250void RTCPSender::SetREMBData(uint32_t bitrate,
251 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200252 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
253 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000255
Erik Språng242e22b2015-05-11 10:17:43 +0200256 if (remb_enabled_)
257 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
259 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200260 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000261}
262
Erik Språng61be2a42015-04-27 13:32:52 +0200263bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200264 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
265 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000266}
267
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000268void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200269 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
270 if (enable) {
271 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
272 } else {
273 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
274 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
Erik Språng61be2a42015-04-27 13:32:52 +0200277bool RTCPSender::IJ() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200278 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
279 return extended_jitter_report_enabled_;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000280}
281
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000282void RTCPSender::SetIJStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200283 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
284 extended_jitter_report_enabled_ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000285}
286
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200288 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 start_timestamp_ = start_timestamp;
290}
291
292void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
293 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200294 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 last_rtp_timestamp_ = rtp_timestamp;
296 if (capture_time_ms < 0) {
297 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200298 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000299 } else {
300 last_frame_capture_time_ms_ = capture_time_ms;
301 }
302}
303
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000304void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200305 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000306
Erik Språng242e22b2015-05-11 10:17:43 +0200307 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200308 // not first SetSSRC, probably due to a collision
309 // schedule a new RTCP report
310 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200311 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200312 }
Erik Språng242e22b2015-05-11 10:17:43 +0200313 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000314}
315
Erik Språng61be2a42015-04-27 13:32:52 +0200316void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200317 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
318 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000319}
320
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000321int32_t RTCPSender::SetCNAME(const char cName[RTCP_CNAME_SIZE]) {
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000322 if (!cName)
323 return -1;
324
Erik Språng242e22b2015-05-11 10:17:43 +0200325 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
326 cname_[RTCP_CNAME_SIZE - 1] = 0;
327 strncpy(cname_, cName, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000328 return 0;
329}
330
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000331int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000332 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000333 assert(cName);
Erik Språng242e22b2015-05-11 10:17:43 +0200334 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
335 if (csrc_cnames_.size() >= kRtpCsrcSize) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return -1;
337 }
338 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000339 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
340 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
Erik Språng242e22b2015-05-11 10:17:43 +0200341 csrc_cnames_[SSRC] = ptr;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return 0;
343}
344
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000345int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200346 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000347 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
Erik Språng242e22b2015-05-11 10:17:43 +0200348 csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349
Erik Språng242e22b2015-05-11 10:17:43 +0200350 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200352
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000353 delete it->second;
Erik Språng242e22b2015-05-11 10:17:43 +0200354 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000355 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356}
357
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000358bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000359/*
360 For audio we use a fix 5 sec interval
361
362 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000363 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
364 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
366
367From RFC 3550
368
369 MAX RTCP BW is 5% if the session BW
370 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000371 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
373 The RECOMMENDED value for the reduced minimum in seconds is 360
374 divided by the session bandwidth in kilobits/second. This minimum
375 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
376
377 If the participant has not yet sent an RTCP packet (the variable
378 initial is true), the constant Tmin is set to 2.5 seconds, else it
379 is set to 5 seconds.
380
381 The interval between RTCP packets is varied randomly over the
382 range [0.5,1.5] times the calculated interval to avoid unintended
383 synchronization of all participants
384
385 if we send
386 If the participant is a sender (we_sent true), the constant C is
387 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
388 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
389 number of senders.
390
391 if we receive only
392 If we_sent is not true, the constant C is set
393 to the average RTCP packet size divided by 75% of the RTCP
394 bandwidth. The constant n is set to the number of receivers
395 (members - senders). If the number of senders is greater than
396 25%, senders and receivers are treated together.
397
398 reconsideration NOT required for peer-to-peer
399 "timer reconsideration" is
400 employed. This algorithm implements a simple back-off mechanism
401 which causes users to hold back RTCP packet transmission if the
402 group sizes are increasing.
403
404 n = number of members
405 C = avg_size/(rtcpBW/4)
406
407 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
408
409 4. The calculated interval T is set to a number uniformly distributed
410 between 0.5 and 1.5 times the deterministic calculated interval.
411
412 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
413 for the fact that the timer reconsideration algorithm converges to
414 a value of the RTCP bandwidth below the intended average
415*/
416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000418
Erik Språng242e22b2015-05-11 10:17:43 +0200419 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
Erik Språng242e22b2015-05-11 10:17:43 +0200424 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // for video key-frames we want to send the RTCP before the large key-frame
426 // if we have a 100 ms margin
427 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
428 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
Erik Språng242e22b2015-05-11 10:17:43 +0200430 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200431 return true;
432 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200433 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // wrap
435 return true;
436 }
437 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000440int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200441 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000442
Erik Språng61be2a42015-04-27 13:32:52 +0200443 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200444 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200445 return 0; // will be ignored
446 } else {
447 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200448 if (last_send_report_[i] == sendReport)
449 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000450 }
Erik Språng61be2a42015-04-27 13:32:52 +0200451 }
452 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000453}
454
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000455bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
456 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200457 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000458
459 if (last_xr_rr_.empty()) {
460 return false;
461 }
462 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
463 if (it == last_xr_rr_.end()) {
464 return false;
465 }
466 *time_ms = it->second;
467 return true;
468}
469
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000470int32_t RTCPSender::AddExternalReportBlock(
471 uint32_t SSRC,
472 const RTCPReportBlock* reportBlock) {
Erik Språng242e22b2015-05-11 10:17:43 +0200473 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000474 return AddReportBlock(SSRC, &external_report_blocks_, reportBlock);
475}
476
477int32_t RTCPSender::AddReportBlock(
478 uint32_t SSRC,
479 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
480 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000481 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000482
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000483 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000484 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000485 return -1;
486 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000487 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000488 report_blocks->find(SSRC);
489 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000490 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000491 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000492 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000493 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
494 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000495 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000496 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000497}
498
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000499int32_t RTCPSender::RemoveExternalReportBlock(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200500 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000502 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000503 external_report_blocks_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000504
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000505 if (it == external_report_blocks_.end()) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000506 return -1;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000507 }
508 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000509 external_report_blocks_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000510 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000511}
512
Erik Språng242e22b2015-05-11 10:17:43 +0200513RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200514 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200515 if (ctx->position + 52 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200516 LOG(LS_WARNING) << "Failed to build Sender Report.";
Erik Språng242e22b2015-05-11 10:17:43 +0200517 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200518 }
519 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000520
Erik Språng242e22b2015-05-11 10:17:43 +0200521 uint32_t posNumberOfReportBlocks = ctx->position;
522 *ctx->AllocateData(1) = 0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523
Erik Språng61be2a42015-04-27 13:32:52 +0200524 // Sender report
Erik Språng242e22b2015-05-11 10:17:43 +0200525 *ctx->AllocateData(1) = 200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
Erik Språng61be2a42015-04-27 13:32:52 +0200527 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
528 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200529 last_send_report_[i + 1] = last_send_report_[i];
530 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200531 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000532
Erik Språng242e22b2015-05-11 10:17:43 +0200533 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
534 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000535
Erik Språng61be2a42015-04-27 13:32:52 +0200536 // The timestamp of this RTCP packet should be estimated as the timestamp of
537 // the frame being captured at this moment. We are calculating that
538 // timestamp as the last frame's timestamp + the time since the last frame
539 // was captured.
540 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
Erik Språng242e22b2015-05-11 10:17:43 +0200541 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
542 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000543
Erik Språng61be2a42015-04-27 13:32:52 +0200544 // Add sender data
545 // Save for our length field
Erik Språng242e22b2015-05-11 10:17:43 +0200546 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
Erik Språng61be2a42015-04-27 13:32:52 +0200548 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200549 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200550 // NTP
Erik Språng242e22b2015-05-11 10:17:43 +0200551 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
552 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
553 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
Erik Språng61be2a42015-04-27 13:32:52 +0200555 // sender's packet count
Erik Språng242e22b2015-05-11 10:17:43 +0200556 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
557 ctx->feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558
Erik Språng61be2a42015-04-27 13:32:52 +0200559 // sender's octet count
Erik Språng242e22b2015-05-11 10:17:43 +0200560 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
561 ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
Erik Språng61be2a42015-04-27 13:32:52 +0200563 uint8_t numberOfReportBlocks = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200564 BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
565 switch (result) {
566 case BuildResult::kError:
567 case BuildResult::kTruncated:
568 case BuildResult::kAborted:
569 return result;
570 case BuildResult::kSuccess:
571 break;
572 default:
573 abort();
574 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
Erik Språng242e22b2015-05-11 10:17:43 +0200576 ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
Erik Språng61be2a42015-04-27 13:32:52 +0200577
Erik Språng242e22b2015-05-11 10:17:43 +0200578 uint16_t len = static_cast<uint16_t>((ctx->position / 4) - 1);
579 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[2], len);
580
581 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000582}
583
Erik Språng242e22b2015-05-11 10:17:43 +0200584RTCPSender::BuildResult RTCPSender::BuildSDEC(RtcpContext* ctx) {
585 size_t lengthCname = strlen(cname_);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000586 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000587
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000588 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200589 if (ctx->position + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000590 LOG(LS_WARNING) << "Failed to build SDEC.";
Erik Språng242e22b2015-05-11 10:17:43 +0200591 return BuildResult::kTruncated;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000592 }
593 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000594
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000595 // We always need to add SDES CNAME
Erik Språng242e22b2015-05-11 10:17:43 +0200596 size_t size = 0x80 + 1 + csrc_cnames_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200597 DCHECK_LE(size, std::numeric_limits<uint8_t>::max());
Erik Språng242e22b2015-05-11 10:17:43 +0200598 *ctx->AllocateData(1) = static_cast<uint8_t>(size);
599 *ctx->AllocateData(1) = 202;
niklase@google.com470e71d2011-07-07 08:21:25 +0000600
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 // handle SDES length later on
Erik Språng242e22b2015-05-11 10:17:43 +0200602 uint32_t SDESLengthPos = ctx->position;
603 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000604
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000605 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200606 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000607
608 // CNAME = 1
Erik Språng242e22b2015-05-11 10:17:43 +0200609 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200610 DCHECK_LE(lengthCname, std::numeric_limits<uint8_t>::max());
Erik Språng242e22b2015-05-11 10:17:43 +0200611 *ctx->AllocateData(1) = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000612
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000613 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000614
Erik Språng242e22b2015-05-11 10:17:43 +0200615 memcpy(ctx->AllocateData(lengthCname), cname_, lengthCname);
Erik Språng61be2a42015-04-27 13:32:52 +0200616 SDESLength += static_cast<uint16_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000617
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000618 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000619 // We must have a zero field even if we have an even multiple of 4 bytes
Erik Språng242e22b2015-05-11 10:17:43 +0200620 do {
621 ++padding;
622 *ctx->AllocateData(1) = 0;
623 } while ((ctx->position % 4) != 0);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000624 SDESLength += padding;
625
Erik Språng242e22b2015-05-11 10:17:43 +0200626 for (auto it = csrc_cnames_.begin(); it != csrc_cnames_.end(); ++it) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000627 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000628 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000629
630 // Add SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200631 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000632
633 // CNAME = 1
Erik Språng242e22b2015-05-11 10:17:43 +0200634 *ctx->AllocateData(1) = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000635
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000636 size_t length = strlen(cname->name);
637 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000638
Erik Språng242e22b2015-05-11 10:17:43 +0200639 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000640 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000641
Erik Språng242e22b2015-05-11 10:17:43 +0200642 memcpy(ctx->AllocateData(length), cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000644 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000645 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
647 // We must have a zero field even if we have an even multiple of 4 bytes
Erik Språng242e22b2015-05-11 10:17:43 +0200648 do {
649 ++padding;
650 *ctx->AllocateData(1) = 0;
651 } while ((ctx->position % 4) != 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000652 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000653 }
654 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000655 uint16_t buffer_length = (SDESLength / 4) - 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200656 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[SDESLengthPos],
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000657 buffer_length);
Erik Språng242e22b2015-05-11 10:17:43 +0200658 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000659}
660
Erik Språng242e22b2015-05-11 10:17:43 +0200661RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200662 // sanity one block
Erik Språng242e22b2015-05-11 10:17:43 +0200663 if (ctx->position + 32 >= IP_PACKET_SIZE)
664 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000665
Erik Språng242e22b2015-05-11 10:17:43 +0200666 uint32_t posNumberOfReportBlocks = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
Erik Språng242e22b2015-05-11 10:17:43 +0200668 *ctx->AllocateData(1) = 0x80;
669 *ctx->AllocateData(1) = 201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000670
Erik Språng61be2a42015-04-27 13:32:52 +0200671 // Save for our length field
Erik Språng242e22b2015-05-11 10:17:43 +0200672 uint32_t len_pos = ctx->position;
673 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000674
Erik Språng61be2a42015-04-27 13:32:52 +0200675 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200676 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677
Erik Språng61be2a42015-04-27 13:32:52 +0200678 uint8_t numberOfReportBlocks = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200679 BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
680 switch (result) {
681 case BuildResult::kError:
682 case BuildResult::kTruncated:
683 case BuildResult::kAborted:
684 return result;
685 case BuildResult::kSuccess:
686 break;
687 default:
688 abort();
689 }
Erik Språng61be2a42015-04-27 13:32:52 +0200690
Erik Språng242e22b2015-05-11 10:17:43 +0200691 ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
Erik Språng61be2a42015-04-27 13:32:52 +0200692
Erik Språng242e22b2015-05-11 10:17:43 +0200693 uint16_t len = uint16_t((ctx->position) / 4 - 1);
694 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[len_pos], len);
695
696 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000697}
698
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000699// From RFC 5450: Transmission Time Offsets in RTP Streams.
700// 0 1 2 3
701// 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
702// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
703// hdr |V=2|P| RC | PT=IJ=195 | length |
704// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
705// | inter-arrival jitter |
706// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
707// . .
708// . .
709// . .
710// | inter-arrival jitter |
711// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
712//
713// If present, this RTCP packet must be placed after a receiver report
714// (inside a compound RTCP packet), and MUST have the same value for RC
715// (reception report count) as the receiver report.
716
Erik Språng242e22b2015-05-11 10:17:43 +0200717RTCPSender::BuildResult RTCPSender::BuildExtendedJitterReport(
718 RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200719 if (external_report_blocks_.size() > 0) {
720 // TODO(andresp): Remove external report blocks since they are not
721 // supported.
722 LOG(LS_ERROR) << "Handling of external report blocks not implemented.";
Erik Språng242e22b2015-05-11 10:17:43 +0200723 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200724 }
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000725
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000726 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200727 if (ctx->position + 8 >= IP_PACKET_SIZE)
728 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200729
730 // add picture loss indicator
731 uint8_t RC = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200732 *ctx->AllocateData(1) = 0x80 + RC;
733 *ctx->AllocateData(1) = 195;
Erik Språng61be2a42015-04-27 13:32:52 +0200734
735 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200736 *ctx->AllocateData(1) = 0;
737 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200738
739 // Add inter-arrival jitter
Erik Språng242e22b2015-05-11 10:17:43 +0200740 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
741 ctx->jitter_transmission_offset);
742 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200743}
744
Erik Språng242e22b2015-05-11 10:17:43 +0200745RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200746 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200747 if (ctx->position + 12 >= IP_PACKET_SIZE)
748 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200749
750 // add picture loss indicator
751 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200752 *ctx->AllocateData(1) = 0x80 + FMT;
753 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200754
755 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200756 *ctx->AllocateData(1) = 0;
757 *ctx->AllocateData(1) = 2;
Erik Språng61be2a42015-04-27 13:32:52 +0200758
759 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200760 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200761
762 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200763 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
764
765 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
766 "RTCPSender::PLI");
767 ++packet_type_counter_.pli_packets;
768 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
769 ssrc_, packet_type_counter_.pli_packets);
770
771 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200772}
773
Erik Språng242e22b2015-05-11 10:17:43 +0200774RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200775 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200776 if (ctx->position + 20 >= IP_PACKET_SIZE)
777 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200778
Erik Språng242e22b2015-05-11 10:17:43 +0200779 if (!ctx->repeat)
780 sequence_number_fir_++; // do not increase if repetition
niklase@google.com470e71d2011-07-07 08:21:25 +0000781
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000782 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000783 uint8_t FMT = 4;
Erik Språng242e22b2015-05-11 10:17:43 +0200784 *ctx->AllocateData(1) = 0x80 + FMT;
785 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000786
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000787 //Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200788 *ctx->AllocateData(1) = 0;
789 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000790
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000791 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200792 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000793
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000794 // RFC 5104 4.3.1.2. Semantics
795 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200796 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000797
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000798 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200799 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000800
Erik Språng242e22b2015-05-11 10:17:43 +0200801 *ctx->AllocateData(1) = sequence_number_fir_;
802 *ctx->AllocateData(1) = 0;
803 *ctx->AllocateData(1) = 0;
804 *ctx->AllocateData(1) = 0;
805
806 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
807 "RTCPSender::FIR");
808 ++packet_type_counter_.fir_packets;
809 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
810 ssrc_, packet_type_counter_.fir_packets);
811
812 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000813}
814
815/*
816 0 1 2 3
817 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
818 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
819 | First | Number | PictureID |
820 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
821*/
Erik Språng242e22b2015-05-11 10:17:43 +0200822RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200823 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200824 if (ctx->position + 16 >= IP_PACKET_SIZE)
825 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000826
Erik Språng61be2a42015-04-27 13:32:52 +0200827 // add slice loss indicator
828 uint8_t FMT = 2;
Erik Språng242e22b2015-05-11 10:17:43 +0200829 *ctx->AllocateData(1) = 0x80 + FMT;
830 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
Erik Språng61be2a42015-04-27 13:32:52 +0200832 // Used fixed length of 3
Erik Språng242e22b2015-05-11 10:17:43 +0200833 *ctx->AllocateData(1) = 0;
834 *ctx->AllocateData(1) = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000835
Erik Språng61be2a42015-04-27 13:32:52 +0200836 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200837 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000838
Erik Språng61be2a42015-04-27 13:32:52 +0200839 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200840 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200841
842 // Add first, number & picture ID 6 bits
843 // first = 0, 13 - bits
844 // number = 0x1fff, 13 - bits only ones for now
Erik Språng242e22b2015-05-11 10:17:43 +0200845 uint32_t sliField = (0x1fff << 6) + (0x3f & ctx->picture_id);
846 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), sliField);
847
848 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000849}
850
851/*
852 0 1 2 3
853 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
854 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
855 | PB |0| Payload Type| Native RPSI bit string |
856 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
857 | defined per codec ... | Padding (0) |
858 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
859*/
860/*
861* Note: not generic made for VP8
862*/
Erik Språng242e22b2015-05-11 10:17:43 +0200863RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
864 if (ctx->feedback_state.send_payload_type == 0xFF)
865 return BuildResult::kError;
866
Erik Språng61be2a42015-04-27 13:32:52 +0200867 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200868 if (ctx->position + 24 >= IP_PACKET_SIZE)
869 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000870
Erik Språng61be2a42015-04-27 13:32:52 +0200871 // add Reference Picture Selection Indication
872 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200873 *ctx->AllocateData(1) = 0x80 + FMT;
874 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000875
Erik Språng61be2a42015-04-27 13:32:52 +0200876 // calc length
877 uint32_t bitsRequired = 7;
878 uint8_t bytesRequired = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200879 while ((ctx->picture_id >> bitsRequired) > 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200880 bitsRequired += 7;
881 bytesRequired++;
882 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
Erik Språng61be2a42015-04-27 13:32:52 +0200884 uint8_t size = 3;
885 if (bytesRequired > 6) {
886 size = 5;
887 } else if (bytesRequired > 2) {
888 size = 4;
889 }
Erik Språng242e22b2015-05-11 10:17:43 +0200890 *ctx->AllocateData(1) = 0;
891 *ctx->AllocateData(1) = size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000892
Erik Språng61be2a42015-04-27 13:32:52 +0200893 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200894 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000895
Erik Språng61be2a42015-04-27 13:32:52 +0200896 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200897 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200898
899 // calc padding length
900 uint8_t paddingBytes = 4 - ((2 + bytesRequired) % 4);
901 if (paddingBytes == 4)
902 paddingBytes = 0;
903 // add padding length in bits
Erik Språng242e22b2015-05-11 10:17:43 +0200904 *ctx->AllocateData(1) = paddingBytes * 8; // padding can be 0, 8, 16 or 24
Erik Språng61be2a42015-04-27 13:32:52 +0200905
906 // add payload type
Erik Språng242e22b2015-05-11 10:17:43 +0200907 *ctx->AllocateData(1) = ctx->feedback_state.send_payload_type;
Erik Språng61be2a42015-04-27 13:32:52 +0200908
909 // add picture ID
910 for (int i = bytesRequired - 1; i > 0; --i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200911 *ctx->AllocateData(1) =
912 0x80 | static_cast<uint8_t>(ctx->picture_id >> (i * 7));
Erik Språng61be2a42015-04-27 13:32:52 +0200913 }
914 // add last byte of picture ID
Erik Språng242e22b2015-05-11 10:17:43 +0200915 *ctx->AllocateData(1) = static_cast<uint8_t>(ctx->picture_id & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000916
Erik Språng61be2a42015-04-27 13:32:52 +0200917 // add padding
918 for (int j = 0; j < paddingBytes; j++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200919 *ctx->AllocateData(1) = 0;
Erik Språng61be2a42015-04-27 13:32:52 +0200920 }
Erik Språng242e22b2015-05-11 10:17:43 +0200921
922 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000923}
924
Erik Språng242e22b2015-05-11 10:17:43 +0200925RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200926 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200927 if (ctx->position + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
928 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200929
930 // add application layer feedback
931 uint8_t FMT = 15;
Erik Språng242e22b2015-05-11 10:17:43 +0200932 *ctx->AllocateData(1) = 0x80 + FMT;
933 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200934
Erik Språng242e22b2015-05-11 10:17:43 +0200935 *ctx->AllocateData(1) = 0;
936 *ctx->AllocateData(1) = static_cast<uint8_t>(remb_ssrcs_.size() + 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200937
938 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200939 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200940
941 // Remote SSRC must be 0
Erik Språng242e22b2015-05-11 10:17:43 +0200942 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200943
Erik Språng242e22b2015-05-11 10:17:43 +0200944 *ctx->AllocateData(1) = 'R';
945 *ctx->AllocateData(1) = 'E';
946 *ctx->AllocateData(1) = 'M';
947 *ctx->AllocateData(1) = 'B';
Erik Språng61be2a42015-04-27 13:32:52 +0200948
Erik Språng242e22b2015-05-11 10:17:43 +0200949 *ctx->AllocateData(1) = remb_ssrcs_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200950 // 6 bit Exp
951 // 18 bit mantissa
952 uint8_t brExp = 0;
953 for (uint32_t i = 0; i < 64; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200954 if (remb_bitrate_ <= (0x3FFFFu << i)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200955 brExp = i;
956 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000957 }
Erik Språng61be2a42015-04-27 13:32:52 +0200958 }
Erik Språng242e22b2015-05-11 10:17:43 +0200959 const uint32_t brMantissa = (remb_bitrate_ >> brExp);
960 *ctx->AllocateData(1) =
961 static_cast<uint8_t>((brExp << 2) + ((brMantissa >> 16) & 0x03));
962 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa >> 8);
963 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000964
Erik Språng242e22b2015-05-11 10:17:43 +0200965 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
966 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remb_ssrcs_[i]);
967
968 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
969 "RTCPSender::REMB");
970
971 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000972}
973
Erik Språng61be2a42015-04-27 13:32:52 +0200974void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200975 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
976 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000977}
978
Erik Språng242e22b2015-05-11 10:17:43 +0200979RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
980 if (ctx->feedback_state.module == NULL)
981 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200982 // Before sending the TMMBR check the received TMMBN, only an owner is
983 // allowed to raise the bitrate:
984 // * If the sender is an owner of the TMMBN -> send TMMBR
985 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000986
Erik Språng61be2a42015-04-27 13:32:52 +0200987 // get current bounding set from RTCP receiver
988 bool tmmbrOwner = false;
989 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200990 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000991
Erik Språng242e22b2015-05-11 10:17:43 +0200992 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
993 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200994 // since RTCPreceiver is not doing the reverse we should be fine
995 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200996 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000997
Erik Språng61be2a42015-04-27 13:32:52 +0200998 if (lengthOfBoundingSet > 0) {
999 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +02001000 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
1001 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001002 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +02001003 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +02001004 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001005 }
Erik Språng61be2a42015-04-27 13:32:52 +02001006 if (!tmmbrOwner) {
1007 // use received bounding set as candidate set
1008 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +02001009 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
1010 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001011 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001012
Erik Språng61be2a42015-04-27 13:32:52 +02001013 // find bounding set
1014 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +02001015 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +02001016 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +02001017 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +02001018 if (!tmmbrOwner) {
1019 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +02001020 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +02001021 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001022 }
Erik Språng61be2a42015-04-27 13:32:52 +02001023 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001024
Erik Språng242e22b2015-05-11 10:17:43 +02001025 if (tmmbr_send_) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001026 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001027 if (ctx->position + 20 >= IP_PACKET_SIZE)
1028 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001029
Erik Språng61be2a42015-04-27 13:32:52 +02001030 // add TMMBR indicator
1031 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +02001032 *ctx->AllocateData(1) = 0x80 + FMT;
1033 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001034
1035 // Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +02001036 *ctx->AllocateData(1) = 0;
1037 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001038
1039 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001040 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001041
Erik Språng61be2a42015-04-27 13:32:52 +02001042 // RFC 5104 4.2.1.2. Semantics
niklase@google.com470e71d2011-07-07 08:21:25 +00001043
1044 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +02001045 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +00001046
1047 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +02001048 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001049
Erik Språng242e22b2015-05-11 10:17:43 +02001050 uint32_t bitRate = tmmbr_send_ * 1000;
Erik Språng61be2a42015-04-27 13:32:52 +02001051 uint32_t mmbrExp = 0;
1052 for (uint32_t i = 0; i < 64; i++) {
1053 if (bitRate <= (0x1FFFFu << i)) {
1054 mmbrExp = i;
1055 break;
1056 }
1057 }
1058 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1059
Erik Språng242e22b2015-05-11 10:17:43 +02001060 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +02001061 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +02001062 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
1063 *ctx->AllocateData(1) = static_cast<uint8_t>(
1064 (mmbrMantissa << 1) + ((packet_oh_send_ >> 8) & 0x01));
1065 *ctx->AllocateData(1) = static_cast<uint8_t>(packet_oh_send_);
Erik Språng61be2a42015-04-27 13:32:52 +02001066 }
Erik Språng242e22b2015-05-11 10:17:43 +02001067 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001068}
1069
Erik Språng242e22b2015-05-11 10:17:43 +02001070RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
1071 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +02001072 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +02001073 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +02001074
1075 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001076 if (ctx->position + 12 + boundingSet->lengthOfSet() * 8 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001077 LOG(LS_WARNING) << "Failed to build TMMBN.";
Erik Språng242e22b2015-05-11 10:17:43 +02001078 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001079 }
1080
1081 uint8_t FMT = 4;
1082 // add TMMBN indicator
Erik Språng242e22b2015-05-11 10:17:43 +02001083 *ctx->AllocateData(1) = 0x80 + FMT;
1084 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001085
1086 // Add length later
Erik Språng242e22b2015-05-11 10:17:43 +02001087 int posLength = ctx->position;
1088 ctx->AllocateData(2);
Erik Språng61be2a42015-04-27 13:32:52 +02001089
1090 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001091 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001092
1093 // RFC 5104 4.2.2.2. Semantics
1094
1095 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +02001096 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +02001097
1098 // Additional Feedback Control Information (FCI)
1099 int numBoundingSet = 0;
1100 for (uint32_t n = 0; n < boundingSet->lengthOfSet(); n++) {
1101 if (boundingSet->Tmmbr(n) > 0) {
1102 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
Erik Språng242e22b2015-05-11 10:17:43 +02001103 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), tmmbrSSRC);
Erik Språng61be2a42015-04-27 13:32:52 +02001104
1105 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1106 uint32_t mmbrExp = 0;
1107 for (int i = 0; i < 64; i++) {
1108 if (bitRate <= (0x1FFFFu << i)) {
1109 mmbrExp = i;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001110 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001112 }
Erik Språng61be2a42015-04-27 13:32:52 +02001113 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1114 uint32_t measuredOH = boundingSet->PacketOH(n);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001115
Erik Språng242e22b2015-05-11 10:17:43 +02001116 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +02001117 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +02001118 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
1119 *ctx->AllocateData(1) = static_cast<uint8_t>((mmbrMantissa << 1) +
1120 ((measuredOH >> 8) & 0x01));
1121 *ctx->AllocateData(1) = static_cast<uint8_t>(measuredOH);
Erik Språng61be2a42015-04-27 13:32:52 +02001122 numBoundingSet++;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001123 }
Erik Språng61be2a42015-04-27 13:32:52 +02001124 }
1125 uint16_t length = static_cast<uint16_t>(2 + 2 * numBoundingSet);
Erik Språng242e22b2015-05-11 10:17:43 +02001126 ctx->buffer[posLength++] = static_cast<uint8_t>(length >> 8);
1127 ctx->buffer[posLength] = static_cast<uint8_t>(length);
1128
1129 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001130}
1131
Erik Språng242e22b2015-05-11 10:17:43 +02001132RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001133 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001134 if (app_data_ == NULL) {
Erik Språng61be2a42015-04-27 13:32:52 +02001135 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001136 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +02001137 }
Erik Språng242e22b2015-05-11 10:17:43 +02001138 if (ctx->position + 12 + app_length_ >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001139 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001140 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001141 }
Erik Språng242e22b2015-05-11 10:17:43 +02001142 *ctx->AllocateData(1) = 0x80 + app_sub_type_;
Erik Språng61be2a42015-04-27 13:32:52 +02001143
1144 // Add APP ID
Erik Språng242e22b2015-05-11 10:17:43 +02001145 *ctx->AllocateData(1) = 204;
Erik Språng61be2a42015-04-27 13:32:52 +02001146
Erik Språng242e22b2015-05-11 10:17:43 +02001147 uint16_t length = (app_length_ >> 2) + 2; // include SSRC and name
1148 *ctx->AllocateData(1) = static_cast<uint8_t>(length >> 8);
1149 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
Erik Språng61be2a42015-04-27 13:32:52 +02001150
1151 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001152 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001153
1154 // Add our application name
Erik Språng242e22b2015-05-11 10:17:43 +02001155 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), app_name_);
Erik Språng61be2a42015-04-27 13:32:52 +02001156
1157 // Add the data
Erik Språng242e22b2015-05-11 10:17:43 +02001158 memcpy(ctx->AllocateData(app_length_), app_data_.get(), app_length_);
1159
1160 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001161}
1162
Erik Språng242e22b2015-05-11 10:17:43 +02001163RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001164 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001165 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001166 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +02001167 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001168 }
1169
Erik Språng242e22b2015-05-11 10:17:43 +02001170 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +02001171 // add nack list
1172 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +02001173 *ctx->AllocateData(1) = 0x80 + FMT;
1174 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001175
Erik Språng242e22b2015-05-11 10:17:43 +02001176 *ctx->AllocateData(1) = 0;
1177 int nack_size_pos_ = ctx->position;
1178 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +02001179
1180 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001181 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001182
1183 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001184 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001185
1186 // Build NACK bitmasks and write them to the RTCP message.
1187 // The nack list should be sorted and not contain duplicates if one
1188 // wants to build the smallest rtcp nack packet.
1189 int numOfNackFields = 0;
1190 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +02001191 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +02001192 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001193 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
1194 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +02001195 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001196 while (i < ctx->nack_size) {
1197 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +02001198 if (shift >= 0 && shift <= 15) {
1199 bitmask |= (1 << shift);
1200 ++i;
1201 } else {
1202 break;
1203 }
1204 }
1205 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +02001206 assert(ctx->position + 4 < IP_PACKET_SIZE);
1207 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
1208 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +02001209 numOfNackFields++;
1210 }
Erik Språng242e22b2015-05-11 10:17:43 +02001211 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +02001212
Erik Språng242e22b2015-05-11 10:17:43 +02001213 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +02001214 LOG(LS_WARNING) << "Nack list too large for one packet.";
1215
1216 // Report stats.
1217 NACKStringBuilder stringBuilder;
1218 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +02001219 stringBuilder.PushNACK(ctx->nack_list[idx]);
1220 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +02001221 }
Erik Språng61be2a42015-04-27 13:32:52 +02001222 packet_type_counter_.nack_requests = nack_stats_.requests();
1223 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +02001224
1225 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1226 "RTCPSender::NACK", "nacks",
1227 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
1228 ++packet_type_counter_.nack_packets;
1229 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
1230 ssrc_, packet_type_counter_.nack_packets);
1231
1232 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001233}
1234
Erik Språng242e22b2015-05-11 10:17:43 +02001235RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001236 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001237 if (ctx->position + 8 >= IP_PACKET_SIZE)
1238 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001239
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001240 // Add a bye packet
1241 // Number of SSRC + CSRCs.
Erik Språng242e22b2015-05-11 10:17:43 +02001242 *ctx->AllocateData(1) = static_cast<uint8_t>(0x80 + 1 + csrcs_.size());
1243 *ctx->AllocateData(1) = 203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001244
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001245 // length
Erik Språng242e22b2015-05-11 10:17:43 +02001246 *ctx->AllocateData(1) = 0;
1247 *ctx->AllocateData(1) = static_cast<uint8_t>(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001248
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001249 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001250 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001251
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001252 // add CSRCs
Erik Språng242e22b2015-05-11 10:17:43 +02001253 for (size_t i = 0; i < csrcs_.size(); i++)
1254 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), csrcs_[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001255
Erik Språng242e22b2015-05-11 10:17:43 +02001256 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001257}
1258
Erik Språng242e22b2015-05-11 10:17:43 +02001259RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
1260 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001261 const int kRrTimeBlockLength = 20;
Erik Språng242e22b2015-05-11 10:17:43 +02001262 if (ctx->position + kRrTimeBlockLength >= IP_PACKET_SIZE)
1263 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001264
Erik Språng61be2a42015-04-27 13:32:52 +02001265 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001266 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001267 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +02001268 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
1269 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001270
1271 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001272 *ctx->AllocateData(1) = 0x80;
1273 *ctx->AllocateData(1) = 207;
1274 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1275 4); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001276
1277 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001278 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001279
1280 // 0 1 2 3
1281 // 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
1282 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1283 // | BT=4 | reserved | block length = 2 |
1284 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1285 // | NTP timestamp, most significant word |
1286 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1287 // | NTP timestamp, least significant word |
1288 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1289
1290 // Add Receiver Reference Time Report block.
Erik Språng242e22b2015-05-11 10:17:43 +02001291 *ctx->AllocateData(1) = 4; // BT.
1292 *ctx->AllocateData(1) = 0; // Reserved.
1293 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1294 2); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001295
1296 // NTP timestamp.
Erik Språng242e22b2015-05-11 10:17:43 +02001297 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
1298 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001299
Erik Språng242e22b2015-05-11 10:17:43 +02001300 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001301}
1302
Erik Språng242e22b2015-05-11 10:17:43 +02001303RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001304 const int kDlrrBlockLength = 24;
Erik Språng242e22b2015-05-11 10:17:43 +02001305 if (ctx->position + kDlrrBlockLength >= IP_PACKET_SIZE)
1306 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001307
1308 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001309 *ctx->AllocateData(1) = 0x80;
1310 *ctx->AllocateData(1) = 207;
1311 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1312 5); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001313
1314 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001315 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001316
1317 // 0 1 2 3
1318 // 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
1319 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1320 // | BT=5 | reserved | block length |
1321 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1322 // | SSRC_1 (SSRC of first receiver) | sub-
1323 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1324 // | last RR (LRR) | 1
1325 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1326 // | delay since last RR (DLRR) |
1327 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1328 // | SSRC_2 (SSRC of second receiver) | sub-
1329 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1330 // : ... : 2
1331
1332 // Add DLRR sub block.
Erik Språng242e22b2015-05-11 10:17:43 +02001333 *ctx->AllocateData(1) = 5; // BT.
1334 *ctx->AllocateData(1) = 0; // Reserved.
1335 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1336 3); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001337
1338 // NTP timestamp.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001339
Erik Språng242e22b2015-05-11 10:17:43 +02001340 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
1341 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.sourceSSRC);
1342 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.lastRR);
1343 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
1344 info.delaySinceLastRR);
1345
1346 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001347}
1348
Erik Språng242e22b2015-05-11 10:17:43 +02001349// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
1350RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001351 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001352 if (ctx->position + 44 >= IP_PACKET_SIZE)
1353 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001354
Erik Språng61be2a42015-04-27 13:32:52 +02001355 // Add XR header
Erik Språng242e22b2015-05-11 10:17:43 +02001356 *ctx->AllocateData(1) = 0x80;
1357 *ctx->AllocateData(1) = 207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001358
Erik Språng242e22b2015-05-11 10:17:43 +02001359 uint32_t XRLengthPos = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +00001360
Erik Språng61be2a42015-04-27 13:32:52 +02001361 // handle length later on
Erik Språng242e22b2015-05-11 10:17:43 +02001362 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +00001363
Erik Språng61be2a42015-04-27 13:32:52 +02001364 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001365 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001366
Erik Språng61be2a42015-04-27 13:32:52 +02001367 // Add a VoIP metrics block
Erik Språng242e22b2015-05-11 10:17:43 +02001368 *ctx->AllocateData(1) = 7;
1369 *ctx->AllocateData(1) = 0;
1370 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), 8);
niklase@google.com470e71d2011-07-07 08:21:25 +00001371
Erik Språng61be2a42015-04-27 13:32:52 +02001372 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001373 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001374
Erik Språng242e22b2015-05-11 10:17:43 +02001375 *ctx->AllocateData(1) = xr_voip_metric_.lossRate;
1376 *ctx->AllocateData(1) = xr_voip_metric_.discardRate;
1377 *ctx->AllocateData(1) = xr_voip_metric_.burstDensity;
1378 *ctx->AllocateData(1) = xr_voip_metric_.gapDensity;
niklase@google.com470e71d2011-07-07 08:21:25 +00001379
Erik Språng242e22b2015-05-11 10:17:43 +02001380 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1381 xr_voip_metric_.burstDuration);
1382 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1383 xr_voip_metric_.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001384
Erik Språng242e22b2015-05-11 10:17:43 +02001385 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1386 xr_voip_metric_.roundTripDelay);
1387 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1388 xr_voip_metric_.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001389
Erik Språng242e22b2015-05-11 10:17:43 +02001390 *ctx->AllocateData(1) = xr_voip_metric_.signalLevel;
1391 *ctx->AllocateData(1) = xr_voip_metric_.noiseLevel;
1392 *ctx->AllocateData(1) = xr_voip_metric_.RERL;
1393 *ctx->AllocateData(1) = xr_voip_metric_.Gmin;
niklase@google.com470e71d2011-07-07 08:21:25 +00001394
Erik Språng242e22b2015-05-11 10:17:43 +02001395 *ctx->AllocateData(1) = xr_voip_metric_.Rfactor;
1396 *ctx->AllocateData(1) = xr_voip_metric_.extRfactor;
1397 *ctx->AllocateData(1) = xr_voip_metric_.MOSLQ;
1398 *ctx->AllocateData(1) = xr_voip_metric_.MOSCQ;
niklase@google.com470e71d2011-07-07 08:21:25 +00001399
Erik Språng242e22b2015-05-11 10:17:43 +02001400 *ctx->AllocateData(1) = xr_voip_metric_.RXconfig;
1401 *ctx->AllocateData(1) = 0; // reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001402
Erik Språng242e22b2015-05-11 10:17:43 +02001403 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1404 xr_voip_metric_.JBnominal);
1405 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1406 xr_voip_metric_.JBmax);
1407 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1408 xr_voip_metric_.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001409
Erik Språng242e22b2015-05-11 10:17:43 +02001410 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[XRLengthPos], 10);
1411
1412 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001413}
1414
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001415int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001416 RTCPPacketType packetType,
1417 int32_t nack_size,
1418 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001419 bool repeat,
1420 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +02001421 return SendCompoundRTCP(
1422 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
1423 nack_size, nack_list, repeat, pictureID);
1424}
1425
1426int32_t RTCPSender::SendCompoundRTCP(
1427 const FeedbackState& feedback_state,
1428 const std::set<RTCPPacketType>& packetTypes,
1429 int32_t nack_size,
1430 const uint16_t* nack_list,
1431 bool repeat,
1432 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001433 {
Erik Språng242e22b2015-05-11 10:17:43 +02001434 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1435 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +02001436 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1437 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001438 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001439 }
1440 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +02001441 int rtcp_length =
1442 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
1443 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +02001444
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001445 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +02001446 if (rtcp_length <= 0)
1447 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001448
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001449 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001450}
1451
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001452int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001453 const std::set<RTCPPacketType>& packetTypes,
1454 int32_t nack_size,
1455 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001456 bool repeat,
1457 uint64_t pictureID,
1458 uint8_t* rtcp_buffer,
1459 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +02001460 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001461
Erik Språng242e22b2015-05-11 10:17:43 +02001462 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
1463 rtcp_buffer, buffer_size);
1464
1465 // Add all flags as volatile. Non volatile entries will not be overwritten
1466 // and all new volatile flags added will be consumed by the end of this call.
1467 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001468
Erik Språng61be2a42015-04-27 13:32:52 +02001469 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +02001470 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +02001471
Erik Språng242e22b2015-05-11 10:17:43 +02001472 bool generate_report;
1473 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
1474 // Report type already explicitly set, don't automatically populate.
1475 generate_report = true;
1476 DCHECK(ConsumeFlag(kRtcpReport) == false);
1477 } else {
1478 generate_report =
1479 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
1480 method_ == kRtcpCompound;
1481 if (generate_report)
1482 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001483 }
1484
Erik Språng242e22b2015-05-11 10:17:43 +02001485 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && cname_[0] != 0))
1486 SetFlag(kRtcpSdes, true);
1487
1488 // We need to send our NTP even if we haven't received any reports.
1489 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
1490
1491 if (generate_report) {
1492 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1493 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001494 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001495 SetFlag(kRtcpXrDlrrReportBlock, true);
1496
1497 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001498 // seeded from RTP constructor
1499 int32_t random = rand() % 1000;
1500 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001501
Erik Språng242e22b2015-05-11 10:17:43 +02001502 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001503 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1504 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1505 } else {
1506 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001507 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001508 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1509 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1510 if (send_bitrate_kbit != 0)
1511 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001512 }
Erik Språng61be2a42015-04-27 13:32:52 +02001513 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1514 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1515 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1516 }
Erik Språng242e22b2015-05-11 10:17:43 +02001517 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001518
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001519 StatisticianMap statisticians =
1520 receive_statistics_->GetActiveStatisticians();
1521 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001522 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001523 RTCPReportBlock report_block;
Erik Språng242e22b2015-05-11 10:17:43 +02001524 if (PrepareReport(feedback_state, it->second, &report_block,
1525 &context.ntp_sec, &context.ntp_frac)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001526 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001527 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001528 }
Erik Språng242e22b2015-05-11 10:17:43 +02001529 if (extended_jitter_report_enabled_)
1530 SetFlag(kRtcpTransmissionTimeOffset, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001531 }
1532 }
1533
Erik Språng242e22b2015-05-11 10:17:43 +02001534 auto it = report_flags_.begin();
1535 while (it != report_flags_.end()) {
1536 auto builder = builders_.find(it->type);
1537 DCHECK(builder != builders_.end());
1538 if (it->is_volatile) {
1539 report_flags_.erase(it++);
1540 } else {
1541 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001542 }
Erik Språng242e22b2015-05-11 10:17:43 +02001543
1544 uint32_t start_position = context.position;
1545 BuildResult result = (*this.*(builder->second))(&context);
1546 switch (result) {
1547 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001548 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001549 case BuildResult::kTruncated:
1550 return context.position;
1551 case BuildResult::kAborted:
1552 context.position = start_position;
1553 FALLTHROUGH();
1554 case BuildResult::kSuccess:
1555 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001556 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001557 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001558 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001559 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001560
1561 if (packet_type_counter_observer_ != NULL) {
1562 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001563 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001564 }
1565
Erik Språng242e22b2015-05-11 10:17:43 +02001566 DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001567
Erik Språng242e22b2015-05-11 10:17:43 +02001568 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001569}
1570
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001571bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1572 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001573 RTCPReportBlock* report_block,
1574 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1575 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001576 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001577 if (!statistician->GetStatistics(&stats, true))
1578 return false;
1579 report_block->fractionLost = stats.fraction_lost;
1580 report_block->cumulativeLost = stats.cumulative_lost;
1581 report_block->extendedHighSeqNum =
1582 stats.extended_max_sequence_number;
1583 report_block->jitter = stats.jitter;
1584
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001585 // get our NTP as late as possible to avoid a race
Erik Språng242e22b2015-05-11 10:17:43 +02001586 clock_->CurrentNtp(*ntp_secs, *ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001587
1588 // Delay since last received report
1589 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001590 if ((feedback_state.last_rr_ntp_secs != 0) ||
1591 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001592 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
Erik Språng61be2a42015-04-27 13:32:52 +02001593 uint32_t now = *ntp_secs & 0x0000FFFF;
1594 now <<= 16;
1595 now += (*ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001596
Erik Språng61be2a42015-04-27 13:32:52 +02001597 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1598 receiveTime <<= 16;
1599 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001600
1601 delaySinceLastReceivedSR = now-receiveTime;
1602 }
1603 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001604 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001605 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001606}
1607
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001608int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001609 CriticalSectionScoped lock(critical_section_transport_.get());
1610 if (cbTransport_) {
1611 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001612 return 0;
1613 }
1614 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001615}
1616
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001617void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1618 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001619 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001620 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001621}
1622
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001623int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1624 uint32_t name,
1625 const uint8_t* data,
1626 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001627 if (length % 4 != 0) {
1628 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1629 return -1;
1630 }
Erik Språng242e22b2015-05-11 10:17:43 +02001631 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001632
Erik Språng242e22b2015-05-11 10:17:43 +02001633 SetFlag(kRtcpApp, true);
1634 app_sub_type_ = subType;
1635 app_name_ = name;
1636 app_data_.reset(new uint8_t[length]);
1637 app_length_ = length;
1638 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001639 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001640}
1641
Erik Språng61be2a42015-04-27 13:32:52 +02001642int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001643 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1644 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001645
Erik Språng242e22b2015-05-11 10:17:43 +02001646 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001647 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001648}
1649
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001650void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001651 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1652 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001653}
1654
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001655bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001656 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1657 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001658}
1659
Erik Språng242e22b2015-05-11 10:17:43 +02001660// called under critsect critical_section_rtcp_sender_
1661RTCPSender::BuildResult RTCPSender::WriteAllReportBlocksToBuffer(
1662 RtcpContext* ctx,
1663 uint8_t* numberOfReportBlocks) {
Erik Språng61be2a42015-04-27 13:32:52 +02001664 *numberOfReportBlocks = external_report_blocks_.size();
1665 *numberOfReportBlocks += internal_report_blocks_.size();
Erik Språng242e22b2015-05-11 10:17:43 +02001666 if ((ctx->position + *numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001667 LOG(LS_WARNING) << "Can't fit all report blocks.";
Erik Språng242e22b2015-05-11 10:17:43 +02001668 return BuildResult::kError;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001669 }
Erik Språng242e22b2015-05-11 10:17:43 +02001670 WriteReportBlocksToBuffer(ctx, internal_report_blocks_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001671 while (!internal_report_blocks_.empty()) {
1672 delete internal_report_blocks_.begin()->second;
1673 internal_report_blocks_.erase(internal_report_blocks_.begin());
1674 }
Erik Språng242e22b2015-05-11 10:17:43 +02001675 WriteReportBlocksToBuffer(ctx, external_report_blocks_);
1676 return BuildResult::kSuccess;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001677}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001678
Erik Språng242e22b2015-05-11 10:17:43 +02001679void RTCPSender::WriteReportBlocksToBuffer(
1680 RtcpContext* ctx,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001681 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
1682 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
1683 report_blocks.begin();
1684 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001685 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001686 RTCPReportBlock* reportBlock = it->second;
1687 if (reportBlock) {
1688 // Remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001689 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remoteSSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001690
1691 // fraction lost
Erik Språng242e22b2015-05-11 10:17:43 +02001692 *ctx->AllocateData(1) = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001693
1694 // cumulative loss
Erik Språng242e22b2015-05-11 10:17:43 +02001695 ByteWriter<uint32_t, 3>::WriteBigEndian(ctx->AllocateData(3),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001696 reportBlock->cumulativeLost);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001697
1698 // extended highest seq_no, contain the highest sequence number received
Erik Språng242e22b2015-05-11 10:17:43 +02001699 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001700 reportBlock->extendedHighSeqNum);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001701
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001702 // Jitter
Erik Språng242e22b2015-05-11 10:17:43 +02001703 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001704 reportBlock->jitter);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001705
Erik Språng242e22b2015-05-11 10:17:43 +02001706 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001707 reportBlock->lastSR);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001708
Erik Språng242e22b2015-05-11 10:17:43 +02001709 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001710 reportBlock->delaySinceLastSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001711 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001712 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001713}
1714
1715// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001716int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1717 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001718 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001719
Erik Språng242e22b2015-05-11 10:17:43 +02001720 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1721 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001722 return 0;
1723 }
1724 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001725}
Erik Språng61be2a42015-04-27 13:32:52 +02001726
Erik Språng242e22b2015-05-11 10:17:43 +02001727void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1728 report_flags_.insert(ReportFlag(type, is_volatile));
1729}
1730
1731void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1732 bool is_volatile) {
1733 for (RTCPPacketType type : types)
1734 SetFlag(type, is_volatile);
1735}
1736
1737bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1738 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1739}
1740
1741bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1742 auto it = report_flags_.find(ReportFlag(type, false));
1743 if (it == report_flags_.end())
1744 return false;
1745 if (it->is_volatile || forced)
1746 report_flags_.erase((it));
1747 return true;
1748}
1749
1750bool RTCPSender::AllVolatileFlagsConsumed() const {
1751 for (const ReportFlag& flag : report_flags_) {
1752 if (flag.is_volatile)
1753 return false;
1754 }
1755 return true;
1756}
1757
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001758} // namespace webrtc