blob: a104fec09fc23089c8cd5adaa2e7185271b8834d [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ång242e22b2015-05-11 10:17:43 +0200187 for (auto it : csrc_cnames_)
Erik Språng61be2a42015-04-27 13:32:52 +0200188 delete it.second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000189}
190
Erik Språng61be2a42015-04-27 13:32:52 +0200191int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200192 CriticalSectionScoped lock(critical_section_transport_.get());
193 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200194 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
Erik Språng61be2a42015-04-27 13:32:52 +0200197RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200198 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
199 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000202void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200203 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
204 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000205
206 if (method == kRtcpOff)
207 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200208 next_time_to_send_rtcp_ =
209 clock_->TimeInMilliseconds() +
210 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
Erik Språng61be2a42015-04-27 13:32:52 +0200213bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200214 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
215 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
Erik Språng61be2a42015-04-27 13:32:52 +0200218int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
219 bool sending) {
220 bool sendRTCPBye = false;
221 {
Erik Språng242e22b2015-05-11 10:17:43 +0200222 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000223
Erik Språng242e22b2015-05-11 10:17:43 +0200224 if (method_ != kRtcpOff) {
225 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200226 // Trigger RTCP bye
227 sendRTCPBye = true;
228 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000229 }
Erik Språng242e22b2015-05-11 10:17:43 +0200230 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200231 }
232 if (sendRTCPBye)
233 return SendRTCP(feedback_state, kRtcpBye);
234 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235}
236
Erik Språng61be2a42015-04-27 13:32:52 +0200237bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200238 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
239 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000240}
241
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000242void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200243 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
244 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000245}
246
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000247void RTCPSender::SetREMBData(uint32_t bitrate,
248 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200249 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
250 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000252
Erik Språng242e22b2015-05-11 10:17:43 +0200253 if (remb_enabled_)
254 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
256 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200257 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000258}
259
Erik Språng61be2a42015-04-27 13:32:52 +0200260bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200261 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
262 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000263}
264
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000265void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200266 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
267 if (enable) {
268 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
269 } else {
270 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
271 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000272}
273
Erik Språng61be2a42015-04-27 13:32:52 +0200274bool RTCPSender::IJ() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200275 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
276 return extended_jitter_report_enabled_;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000277}
278
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000279void RTCPSender::SetIJStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200280 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
281 extended_jitter_report_enabled_ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000282}
283
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200285 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286 start_timestamp_ = start_timestamp;
287}
288
289void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
290 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200291 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 last_rtp_timestamp_ = rtp_timestamp;
293 if (capture_time_ms < 0) {
294 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200295 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 } else {
297 last_frame_capture_time_ms_ = capture_time_ms;
298 }
299}
300
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000301void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200302 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000303
Erik Språng242e22b2015-05-11 10:17:43 +0200304 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200305 // not first SetSSRC, probably due to a collision
306 // schedule a new RTCP report
307 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200308 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200309 }
Erik Språng242e22b2015-05-11 10:17:43 +0200310 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311}
312
Erik Språng61be2a42015-04-27 13:32:52 +0200313void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200314 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
315 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Peter Boström9ba52f82015-06-01 14:12:28 +0200318int32_t RTCPSender::SetCNAME(const char* c_name) {
319 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000320 return -1;
321
Peter Boström9ba52f82015-06-01 14:12:28 +0200322 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200323 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
324 cname_[RTCP_CNAME_SIZE - 1] = 0;
Peter Boström9ba52f82015-06-01 14:12:28 +0200325 strncpy(cname_, c_name, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000326 return 0;
327}
328
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000329int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000330 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000331 assert(cName);
Erik Språng242e22b2015-05-11 10:17:43 +0200332 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
333 if (csrc_cnames_.size() >= kRtpCsrcSize) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334 return -1;
335 }
336 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000337 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
338 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
Erik Språng242e22b2015-05-11 10:17:43 +0200339 csrc_cnames_[SSRC] = ptr;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200344 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000345 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
Erik Språng242e22b2015-05-11 10:17:43 +0200346 csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347
Erik Språng242e22b2015-05-11 10:17:43 +0200348 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200350
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351 delete it->second;
Erik Språng242e22b2015-05-11 10:17:43 +0200352 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000353 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000354}
355
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000356bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000357/*
358 For audio we use a fix 5 sec interval
359
360 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000361 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
362 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
364
365From RFC 3550
366
367 MAX RTCP BW is 5% if the session BW
368 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000369 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
371 The RECOMMENDED value for the reduced minimum in seconds is 360
372 divided by the session bandwidth in kilobits/second. This minimum
373 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
374
375 If the participant has not yet sent an RTCP packet (the variable
376 initial is true), the constant Tmin is set to 2.5 seconds, else it
377 is set to 5 seconds.
378
379 The interval between RTCP packets is varied randomly over the
380 range [0.5,1.5] times the calculated interval to avoid unintended
381 synchronization of all participants
382
383 if we send
384 If the participant is a sender (we_sent true), the constant C is
385 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
386 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
387 number of senders.
388
389 if we receive only
390 If we_sent is not true, the constant C is set
391 to the average RTCP packet size divided by 75% of the RTCP
392 bandwidth. The constant n is set to the number of receivers
393 (members - senders). If the number of senders is greater than
394 25%, senders and receivers are treated together.
395
396 reconsideration NOT required for peer-to-peer
397 "timer reconsideration" is
398 employed. This algorithm implements a simple back-off mechanism
399 which causes users to hold back RTCP packet transmission if the
400 group sizes are increasing.
401
402 n = number of members
403 C = avg_size/(rtcpBW/4)
404
405 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
406
407 4. The calculated interval T is set to a number uniformly distributed
408 between 0.5 and 1.5 times the deterministic calculated interval.
409
410 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
411 for the fact that the timer reconsideration algorithm converges to
412 a value of the RTCP bandwidth below the intended average
413*/
414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000418
Erik Språng242e22b2015-05-11 10:17:43 +0200419 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000420 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
Erik Språng242e22b2015-05-11 10:17:43 +0200422 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200423 // for video key-frames we want to send the RTCP before the large key-frame
424 // if we have a 100 ms margin
425 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
426 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
Erik Språng242e22b2015-05-11 10:17:43 +0200428 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200429 return true;
430 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200431 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200432 // wrap
433 return true;
434 }
435 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000436}
437
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000438int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200439 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000440
Erik Språng61be2a42015-04-27 13:32:52 +0200441 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200442 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200443 return 0; // will be ignored
444 } else {
445 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200446 if (last_send_report_[i] == sendReport)
447 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000448 }
Erik Språng61be2a42015-04-27 13:32:52 +0200449 }
450 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000451}
452
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000453bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
454 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200455 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000456
457 if (last_xr_rr_.empty()) {
458 return false;
459 }
460 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
461 if (it == last_xr_rr_.end()) {
462 return false;
463 }
464 *time_ms = it->second;
465 return true;
466}
467
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000468int32_t RTCPSender::AddReportBlock(
469 uint32_t SSRC,
470 std::map<uint32_t, RTCPReportBlock*>* report_blocks,
471 const RTCPReportBlock* reportBlock) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000472 assert(reportBlock);
niklase@google.com470e71d2011-07-07 08:21:25 +0000473
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000474 if (report_blocks->size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000475 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000476 return -1;
477 }
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000478 std::map<uint32_t, RTCPReportBlock*>::iterator it =
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000479 report_blocks->find(SSRC);
480 if (it != report_blocks->end()) {
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000481 delete it->second;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000482 report_blocks->erase(it);
stefan@webrtc.org8d0cd072012-12-03 14:01:46 +0000483 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000484 RTCPReportBlock* copyReportBlock = new RTCPReportBlock();
485 memcpy(copyReportBlock, reportBlock, sizeof(RTCPReportBlock));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000486 (*report_blocks)[SSRC] = copyReportBlock;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000487 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000488}
489
Erik Språng242e22b2015-05-11 10:17:43 +0200490RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200491 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200492 if (ctx->position + 52 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200493 LOG(LS_WARNING) << "Failed to build Sender Report.";
Erik Språng242e22b2015-05-11 10:17:43 +0200494 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200495 }
496 uint32_t RTPtime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
Erik Språng242e22b2015-05-11 10:17:43 +0200498 uint32_t posNumberOfReportBlocks = ctx->position;
499 *ctx->AllocateData(1) = 0x80;
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
Erik Språng61be2a42015-04-27 13:32:52 +0200501 // Sender report
Erik Språng242e22b2015-05-11 10:17:43 +0200502 *ctx->AllocateData(1) = 200;
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språng61be2a42015-04-27 13:32:52 +0200504 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
505 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200506 last_send_report_[i + 1] = last_send_report_[i];
507 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200508 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000509
Erik Språng242e22b2015-05-11 10:17:43 +0200510 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
511 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000512
Erik Språng61be2a42015-04-27 13:32:52 +0200513 // The timestamp of this RTCP packet should be estimated as the timestamp of
514 // the frame being captured at this moment. We are calculating that
515 // timestamp as the last frame's timestamp + the time since the last frame
516 // was captured.
517 RTPtime = start_timestamp_ + last_rtp_timestamp_ +
Erik Språng242e22b2015-05-11 10:17:43 +0200518 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
519 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000520
Erik Språng61be2a42015-04-27 13:32:52 +0200521 // Add sender data
522 // Save for our length field
Erik Språng242e22b2015-05-11 10:17:43 +0200523 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000524
Erik Språng61be2a42015-04-27 13:32:52 +0200525 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200526 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200527 // NTP
Erik Språng242e22b2015-05-11 10:17:43 +0200528 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
529 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
530 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), RTPtime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000531
Erik Språng61be2a42015-04-27 13:32:52 +0200532 // sender's packet count
Erik Språng242e22b2015-05-11 10:17:43 +0200533 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
534 ctx->feedback_state.packets_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000535
Erik Språng61be2a42015-04-27 13:32:52 +0200536 // sender's octet count
Erik Språng242e22b2015-05-11 10:17:43 +0200537 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
538 ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000539
Erik Språng61be2a42015-04-27 13:32:52 +0200540 uint8_t numberOfReportBlocks = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200541 BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
542 switch (result) {
543 case BuildResult::kError:
544 case BuildResult::kTruncated:
545 case BuildResult::kAborted:
546 return result;
547 case BuildResult::kSuccess:
548 break;
549 default:
550 abort();
551 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000552
Erik Språng242e22b2015-05-11 10:17:43 +0200553 ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
Erik Språng61be2a42015-04-27 13:32:52 +0200554
Erik Språng242e22b2015-05-11 10:17:43 +0200555 uint16_t len = static_cast<uint16_t>((ctx->position / 4) - 1);
556 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[2], len);
557
558 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000559}
560
Erik Språng242e22b2015-05-11 10:17:43 +0200561RTCPSender::BuildResult RTCPSender::BuildSDEC(RtcpContext* ctx) {
562 size_t lengthCname = strlen(cname_);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000563 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000564
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000565 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200566 if (ctx->position + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000567 LOG(LS_WARNING) << "Failed to build SDEC.";
Erik Språng242e22b2015-05-11 10:17:43 +0200568 return BuildResult::kTruncated;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000569 }
570 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000572 // We always need to add SDES CNAME
Erik Språng242e22b2015-05-11 10:17:43 +0200573 size_t size = 0x80 + 1 + csrc_cnames_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200574 DCHECK_LE(size, std::numeric_limits<uint8_t>::max());
Erik Språng242e22b2015-05-11 10:17:43 +0200575 *ctx->AllocateData(1) = static_cast<uint8_t>(size);
576 *ctx->AllocateData(1) = 202;
niklase@google.com470e71d2011-07-07 08:21:25 +0000577
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000578 // handle SDES length later on
Erik Språng242e22b2015-05-11 10:17:43 +0200579 uint32_t SDESLengthPos = ctx->position;
580 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000581
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000582 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200583 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000584
585 // CNAME = 1
Erik Språng242e22b2015-05-11 10:17:43 +0200586 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200587 DCHECK_LE(lengthCname, std::numeric_limits<uint8_t>::max());
Erik Språng242e22b2015-05-11 10:17:43 +0200588 *ctx->AllocateData(1) = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000589
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000590 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000591
Erik Språng242e22b2015-05-11 10:17:43 +0200592 memcpy(ctx->AllocateData(lengthCname), cname_, lengthCname);
Erik Språng61be2a42015-04-27 13:32:52 +0200593 SDESLength += static_cast<uint16_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000595 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000596 // We must have a zero field even if we have an even multiple of 4 bytes
Erik Språng242e22b2015-05-11 10:17:43 +0200597 do {
598 ++padding;
599 *ctx->AllocateData(1) = 0;
600 } while ((ctx->position % 4) != 0);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000601 SDESLength += padding;
602
Erik Språng242e22b2015-05-11 10:17:43 +0200603 for (auto it = csrc_cnames_.begin(); it != csrc_cnames_.end(); ++it) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000604 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000605 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000606
607 // Add SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200608 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609
610 // CNAME = 1
Erik Språng242e22b2015-05-11 10:17:43 +0200611 *ctx->AllocateData(1) = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000612
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000613 size_t length = strlen(cname->name);
614 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000615
Erik Språng242e22b2015-05-11 10:17:43 +0200616 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000617 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000618
Erik Språng242e22b2015-05-11 10:17:43 +0200619 memcpy(ctx->AllocateData(length), cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000621 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000622 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
624 // We must have a zero field even if we have an even multiple of 4 bytes
Erik Språng242e22b2015-05-11 10:17:43 +0200625 do {
626 ++padding;
627 *ctx->AllocateData(1) = 0;
628 } while ((ctx->position % 4) != 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000629 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000630 }
631 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000632 uint16_t buffer_length = (SDESLength / 4) - 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200633 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[SDESLengthPos],
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000634 buffer_length);
Erik Språng242e22b2015-05-11 10:17:43 +0200635 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000636}
637
Erik Språng242e22b2015-05-11 10:17:43 +0200638RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200639 // sanity one block
Erik Språng242e22b2015-05-11 10:17:43 +0200640 if (ctx->position + 32 >= IP_PACKET_SIZE)
641 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000642
Erik Språng242e22b2015-05-11 10:17:43 +0200643 uint32_t posNumberOfReportBlocks = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +0000644
Erik Språng242e22b2015-05-11 10:17:43 +0200645 *ctx->AllocateData(1) = 0x80;
646 *ctx->AllocateData(1) = 201;
niklase@google.com470e71d2011-07-07 08:21:25 +0000647
Erik Språng61be2a42015-04-27 13:32:52 +0200648 // Save for our length field
Erik Språng242e22b2015-05-11 10:17:43 +0200649 uint32_t len_pos = ctx->position;
650 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651
Erik Språng61be2a42015-04-27 13:32:52 +0200652 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200653 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000654
Erik Språng61be2a42015-04-27 13:32:52 +0200655 uint8_t numberOfReportBlocks = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200656 BuildResult result = WriteAllReportBlocksToBuffer(ctx, &numberOfReportBlocks);
657 switch (result) {
658 case BuildResult::kError:
659 case BuildResult::kTruncated:
660 case BuildResult::kAborted:
661 return result;
662 case BuildResult::kSuccess:
663 break;
664 default:
665 abort();
666 }
Erik Språng61be2a42015-04-27 13:32:52 +0200667
Erik Språng242e22b2015-05-11 10:17:43 +0200668 ctx->buffer[posNumberOfReportBlocks] += numberOfReportBlocks;
Erik Språng61be2a42015-04-27 13:32:52 +0200669
Erik Språng242e22b2015-05-11 10:17:43 +0200670 uint16_t len = uint16_t((ctx->position) / 4 - 1);
671 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[len_pos], len);
672
673 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000674}
675
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000676// From RFC 5450: Transmission Time Offsets in RTP Streams.
677// 0 1 2 3
678// 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
679// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
680// hdr |V=2|P| RC | PT=IJ=195 | length |
681// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
682// | inter-arrival jitter |
683// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
684// . .
685// . .
686// . .
687// | inter-arrival jitter |
688// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
689//
690// If present, this RTCP packet must be placed after a receiver report
691// (inside a compound RTCP packet), and MUST have the same value for RC
692// (reception report count) as the receiver report.
693
Erik Språng242e22b2015-05-11 10:17:43 +0200694RTCPSender::BuildResult RTCPSender::BuildExtendedJitterReport(
695 RtcpContext* ctx) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000696 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200697 if (ctx->position + 8 >= IP_PACKET_SIZE)
698 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200699
700 // add picture loss indicator
701 uint8_t RC = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200702 *ctx->AllocateData(1) = 0x80 + RC;
703 *ctx->AllocateData(1) = 195;
Erik Språng61be2a42015-04-27 13:32:52 +0200704
705 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200706 *ctx->AllocateData(1) = 0;
707 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200708
709 // Add inter-arrival jitter
Erik Språng242e22b2015-05-11 10:17:43 +0200710 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
711 ctx->jitter_transmission_offset);
712 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200713}
714
Erik Språng242e22b2015-05-11 10:17:43 +0200715RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200716 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200717 if (ctx->position + 12 >= IP_PACKET_SIZE)
718 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200719
720 // add picture loss indicator
721 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200722 *ctx->AllocateData(1) = 0x80 + FMT;
723 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200724
725 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200726 *ctx->AllocateData(1) = 0;
727 *ctx->AllocateData(1) = 2;
Erik Språng61be2a42015-04-27 13:32:52 +0200728
729 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200730 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200731
732 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200733 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
734
735 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
736 "RTCPSender::PLI");
737 ++packet_type_counter_.pli_packets;
738 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
739 ssrc_, packet_type_counter_.pli_packets);
740
741 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200742}
743
Erik Språng242e22b2015-05-11 10:17:43 +0200744RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200745 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200746 if (ctx->position + 20 >= IP_PACKET_SIZE)
747 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200748
Erik Språng242e22b2015-05-11 10:17:43 +0200749 if (!ctx->repeat)
750 sequence_number_fir_++; // do not increase if repetition
niklase@google.com470e71d2011-07-07 08:21:25 +0000751
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000752 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000753 uint8_t FMT = 4;
Erik Språng242e22b2015-05-11 10:17:43 +0200754 *ctx->AllocateData(1) = 0x80 + FMT;
755 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000756
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000757 //Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200758 *ctx->AllocateData(1) = 0;
759 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000760
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000761 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200762 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000763
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000764 // RFC 5104 4.3.1.2. Semantics
765 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200766 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000767
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000768 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200769 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000770
Erik Språng242e22b2015-05-11 10:17:43 +0200771 *ctx->AllocateData(1) = sequence_number_fir_;
772 *ctx->AllocateData(1) = 0;
773 *ctx->AllocateData(1) = 0;
774 *ctx->AllocateData(1) = 0;
775
776 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
777 "RTCPSender::FIR");
778 ++packet_type_counter_.fir_packets;
779 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
780 ssrc_, packet_type_counter_.fir_packets);
781
782 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000783}
784
785/*
786 0 1 2 3
787 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
788 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
789 | First | Number | PictureID |
790 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
791*/
Erik Språng242e22b2015-05-11 10:17:43 +0200792RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200793 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200794 if (ctx->position + 16 >= IP_PACKET_SIZE)
795 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000796
Erik Språng61be2a42015-04-27 13:32:52 +0200797 // add slice loss indicator
798 uint8_t FMT = 2;
Erik Språng242e22b2015-05-11 10:17:43 +0200799 *ctx->AllocateData(1) = 0x80 + FMT;
800 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000801
Erik Språng61be2a42015-04-27 13:32:52 +0200802 // Used fixed length of 3
Erik Språng242e22b2015-05-11 10:17:43 +0200803 *ctx->AllocateData(1) = 0;
804 *ctx->AllocateData(1) = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000805
Erik Språng61be2a42015-04-27 13:32:52 +0200806 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200807 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000808
Erik Språng61be2a42015-04-27 13:32:52 +0200809 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200810 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200811
812 // Add first, number & picture ID 6 bits
813 // first = 0, 13 - bits
814 // number = 0x1fff, 13 - bits only ones for now
Erik Språng242e22b2015-05-11 10:17:43 +0200815 uint32_t sliField = (0x1fff << 6) + (0x3f & ctx->picture_id);
816 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), sliField);
817
818 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000819}
820
821/*
822 0 1 2 3
823 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
824 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
825 | PB |0| Payload Type| Native RPSI bit string |
826 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
827 | defined per codec ... | Padding (0) |
828 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
829*/
830/*
831* Note: not generic made for VP8
832*/
Erik Språng242e22b2015-05-11 10:17:43 +0200833RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
834 if (ctx->feedback_state.send_payload_type == 0xFF)
835 return BuildResult::kError;
836
Erik Språng61be2a42015-04-27 13:32:52 +0200837 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200838 if (ctx->position + 24 >= IP_PACKET_SIZE)
839 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000840
Erik Språng61be2a42015-04-27 13:32:52 +0200841 // add Reference Picture Selection Indication
842 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200843 *ctx->AllocateData(1) = 0x80 + FMT;
844 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000845
Erik Språng61be2a42015-04-27 13:32:52 +0200846 // calc length
847 uint32_t bitsRequired = 7;
848 uint8_t bytesRequired = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200849 while ((ctx->picture_id >> bitsRequired) > 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200850 bitsRequired += 7;
851 bytesRequired++;
852 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000853
Erik Språng61be2a42015-04-27 13:32:52 +0200854 uint8_t size = 3;
855 if (bytesRequired > 6) {
856 size = 5;
857 } else if (bytesRequired > 2) {
858 size = 4;
859 }
Erik Språng242e22b2015-05-11 10:17:43 +0200860 *ctx->AllocateData(1) = 0;
861 *ctx->AllocateData(1) = size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000862
Erik Språng61be2a42015-04-27 13:32:52 +0200863 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200864 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000865
Erik Språng61be2a42015-04-27 13:32:52 +0200866 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200867 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200868
869 // calc padding length
870 uint8_t paddingBytes = 4 - ((2 + bytesRequired) % 4);
871 if (paddingBytes == 4)
872 paddingBytes = 0;
873 // add padding length in bits
Erik Språng242e22b2015-05-11 10:17:43 +0200874 *ctx->AllocateData(1) = paddingBytes * 8; // padding can be 0, 8, 16 or 24
Erik Språng61be2a42015-04-27 13:32:52 +0200875
876 // add payload type
Erik Språng242e22b2015-05-11 10:17:43 +0200877 *ctx->AllocateData(1) = ctx->feedback_state.send_payload_type;
Erik Språng61be2a42015-04-27 13:32:52 +0200878
879 // add picture ID
880 for (int i = bytesRequired - 1; i > 0; --i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200881 *ctx->AllocateData(1) =
882 0x80 | static_cast<uint8_t>(ctx->picture_id >> (i * 7));
Erik Språng61be2a42015-04-27 13:32:52 +0200883 }
884 // add last byte of picture ID
Erik Språng242e22b2015-05-11 10:17:43 +0200885 *ctx->AllocateData(1) = static_cast<uint8_t>(ctx->picture_id & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
Erik Språng61be2a42015-04-27 13:32:52 +0200887 // add padding
888 for (int j = 0; j < paddingBytes; j++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200889 *ctx->AllocateData(1) = 0;
Erik Språng61be2a42015-04-27 13:32:52 +0200890 }
Erik Språng242e22b2015-05-11 10:17:43 +0200891
892 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000893}
894
Erik Språng242e22b2015-05-11 10:17:43 +0200895RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200896 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200897 if (ctx->position + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
898 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200899
900 // add application layer feedback
901 uint8_t FMT = 15;
Erik Språng242e22b2015-05-11 10:17:43 +0200902 *ctx->AllocateData(1) = 0x80 + FMT;
903 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200904
Erik Språng242e22b2015-05-11 10:17:43 +0200905 *ctx->AllocateData(1) = 0;
906 *ctx->AllocateData(1) = static_cast<uint8_t>(remb_ssrcs_.size() + 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200907
908 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200909 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200910
911 // Remote SSRC must be 0
Erik Språng242e22b2015-05-11 10:17:43 +0200912 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200913
Erik Språng242e22b2015-05-11 10:17:43 +0200914 *ctx->AllocateData(1) = 'R';
915 *ctx->AllocateData(1) = 'E';
916 *ctx->AllocateData(1) = 'M';
917 *ctx->AllocateData(1) = 'B';
Erik Språng61be2a42015-04-27 13:32:52 +0200918
Erik Språng242e22b2015-05-11 10:17:43 +0200919 *ctx->AllocateData(1) = remb_ssrcs_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200920 // 6 bit Exp
921 // 18 bit mantissa
922 uint8_t brExp = 0;
923 for (uint32_t i = 0; i < 64; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200924 if (remb_bitrate_ <= (0x3FFFFu << i)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200925 brExp = i;
926 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000927 }
Erik Språng61be2a42015-04-27 13:32:52 +0200928 }
Erik Språng242e22b2015-05-11 10:17:43 +0200929 const uint32_t brMantissa = (remb_bitrate_ >> brExp);
930 *ctx->AllocateData(1) =
931 static_cast<uint8_t>((brExp << 2) + ((brMantissa >> 16) & 0x03));
932 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa >> 8);
933 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000934
Erik Språng242e22b2015-05-11 10:17:43 +0200935 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
936 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remb_ssrcs_[i]);
937
938 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
939 "RTCPSender::REMB");
940
941 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000942}
943
Erik Språng61be2a42015-04-27 13:32:52 +0200944void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200945 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
946 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000947}
948
Erik Språng242e22b2015-05-11 10:17:43 +0200949RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
950 if (ctx->feedback_state.module == NULL)
951 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200952 // Before sending the TMMBR check the received TMMBN, only an owner is
953 // allowed to raise the bitrate:
954 // * If the sender is an owner of the TMMBN -> send TMMBR
955 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
Erik Språng61be2a42015-04-27 13:32:52 +0200957 // get current bounding set from RTCP receiver
958 bool tmmbrOwner = false;
959 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200960 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000961
Erik Språng242e22b2015-05-11 10:17:43 +0200962 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
963 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200964 // since RTCPreceiver is not doing the reverse we should be fine
965 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200966 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000967
Erik Språng61be2a42015-04-27 13:32:52 +0200968 if (lengthOfBoundingSet > 0) {
969 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200970 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
971 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200972 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200973 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200974 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000975 }
Erik Språng61be2a42015-04-27 13:32:52 +0200976 if (!tmmbrOwner) {
977 // use received bounding set as candidate set
978 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200979 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
980 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200981 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000982
Erik Språng61be2a42015-04-27 13:32:52 +0200983 // find bounding set
984 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200985 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200986 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200987 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200988 if (!tmmbrOwner) {
989 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200990 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200991 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000992 }
Erik Språng61be2a42015-04-27 13:32:52 +0200993 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000994
Erik Språng242e22b2015-05-11 10:17:43 +0200995 if (tmmbr_send_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000996 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200997 if (ctx->position + 20 >= IP_PACKET_SIZE)
998 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000999
Erik Språng61be2a42015-04-27 13:32:52 +02001000 // add TMMBR indicator
1001 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +02001002 *ctx->AllocateData(1) = 0x80 + FMT;
1003 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001004
1005 // Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +02001006 *ctx->AllocateData(1) = 0;
1007 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +00001008
1009 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001010 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001011
Erik Språng61be2a42015-04-27 13:32:52 +02001012 // RFC 5104 4.2.1.2. Semantics
niklase@google.com470e71d2011-07-07 08:21:25 +00001013
1014 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +02001015 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +00001016
1017 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +02001018 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001019
Erik Språng242e22b2015-05-11 10:17:43 +02001020 uint32_t bitRate = tmmbr_send_ * 1000;
Erik Språng61be2a42015-04-27 13:32:52 +02001021 uint32_t mmbrExp = 0;
1022 for (uint32_t i = 0; i < 64; i++) {
1023 if (bitRate <= (0x1FFFFu << i)) {
1024 mmbrExp = i;
1025 break;
1026 }
1027 }
1028 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1029
Erik Språng242e22b2015-05-11 10:17:43 +02001030 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +02001031 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +02001032 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
1033 *ctx->AllocateData(1) = static_cast<uint8_t>(
1034 (mmbrMantissa << 1) + ((packet_oh_send_ >> 8) & 0x01));
1035 *ctx->AllocateData(1) = static_cast<uint8_t>(packet_oh_send_);
Erik Språng61be2a42015-04-27 13:32:52 +02001036 }
Erik Språng242e22b2015-05-11 10:17:43 +02001037 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001038}
1039
Erik Språng242e22b2015-05-11 10:17:43 +02001040RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
1041 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +02001042 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +02001043 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +02001044
1045 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001046 if (ctx->position + 12 + boundingSet->lengthOfSet() * 8 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001047 LOG(LS_WARNING) << "Failed to build TMMBN.";
Erik Språng242e22b2015-05-11 10:17:43 +02001048 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001049 }
1050
1051 uint8_t FMT = 4;
1052 // add TMMBN indicator
Erik Språng242e22b2015-05-11 10:17:43 +02001053 *ctx->AllocateData(1) = 0x80 + FMT;
1054 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001055
1056 // Add length later
Erik Språng242e22b2015-05-11 10:17:43 +02001057 int posLength = ctx->position;
1058 ctx->AllocateData(2);
Erik Språng61be2a42015-04-27 13:32:52 +02001059
1060 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001061 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001062
1063 // RFC 5104 4.2.2.2. Semantics
1064
1065 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +02001066 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +02001067
1068 // Additional Feedback Control Information (FCI)
1069 int numBoundingSet = 0;
1070 for (uint32_t n = 0; n < boundingSet->lengthOfSet(); n++) {
1071 if (boundingSet->Tmmbr(n) > 0) {
1072 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
Erik Språng242e22b2015-05-11 10:17:43 +02001073 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), tmmbrSSRC);
Erik Språng61be2a42015-04-27 13:32:52 +02001074
1075 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1076 uint32_t mmbrExp = 0;
1077 for (int i = 0; i < 64; i++) {
1078 if (bitRate <= (0x1FFFFu << i)) {
1079 mmbrExp = i;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001080 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001081 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001082 }
Erik Språng61be2a42015-04-27 13:32:52 +02001083 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1084 uint32_t measuredOH = boundingSet->PacketOH(n);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001085
Erik Språng242e22b2015-05-11 10:17:43 +02001086 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +02001087 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +02001088 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
1089 *ctx->AllocateData(1) = static_cast<uint8_t>((mmbrMantissa << 1) +
1090 ((measuredOH >> 8) & 0x01));
1091 *ctx->AllocateData(1) = static_cast<uint8_t>(measuredOH);
Erik Språng61be2a42015-04-27 13:32:52 +02001092 numBoundingSet++;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001093 }
Erik Språng61be2a42015-04-27 13:32:52 +02001094 }
1095 uint16_t length = static_cast<uint16_t>(2 + 2 * numBoundingSet);
Erik Språng242e22b2015-05-11 10:17:43 +02001096 ctx->buffer[posLength++] = static_cast<uint8_t>(length >> 8);
1097 ctx->buffer[posLength] = static_cast<uint8_t>(length);
1098
1099 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001100}
1101
Erik Språng242e22b2015-05-11 10:17:43 +02001102RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001103 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001104 if (app_data_ == NULL) {
Erik Språng61be2a42015-04-27 13:32:52 +02001105 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001106 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +02001107 }
Erik Språng242e22b2015-05-11 10:17:43 +02001108 if (ctx->position + 12 + app_length_ >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001109 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001110 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001111 }
Erik Språng242e22b2015-05-11 10:17:43 +02001112 *ctx->AllocateData(1) = 0x80 + app_sub_type_;
Erik Språng61be2a42015-04-27 13:32:52 +02001113
1114 // Add APP ID
Erik Språng242e22b2015-05-11 10:17:43 +02001115 *ctx->AllocateData(1) = 204;
Erik Språng61be2a42015-04-27 13:32:52 +02001116
Erik Språng242e22b2015-05-11 10:17:43 +02001117 uint16_t length = (app_length_ >> 2) + 2; // include SSRC and name
1118 *ctx->AllocateData(1) = static_cast<uint8_t>(length >> 8);
1119 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
Erik Språng61be2a42015-04-27 13:32:52 +02001120
1121 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001122 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001123
1124 // Add our application name
Erik Språng242e22b2015-05-11 10:17:43 +02001125 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), app_name_);
Erik Språng61be2a42015-04-27 13:32:52 +02001126
1127 // Add the data
Erik Språng242e22b2015-05-11 10:17:43 +02001128 memcpy(ctx->AllocateData(app_length_), app_data_.get(), app_length_);
1129
1130 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001131}
1132
Erik Språng242e22b2015-05-11 10:17:43 +02001133RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001134 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001135 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001136 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +02001137 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001138 }
1139
Erik Språng242e22b2015-05-11 10:17:43 +02001140 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +02001141 // add nack list
1142 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +02001143 *ctx->AllocateData(1) = 0x80 + FMT;
1144 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001145
Erik Språng242e22b2015-05-11 10:17:43 +02001146 *ctx->AllocateData(1) = 0;
1147 int nack_size_pos_ = ctx->position;
1148 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +02001149
1150 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001151 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001152
1153 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001154 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001155
1156 // Build NACK bitmasks and write them to the RTCP message.
1157 // The nack list should be sorted and not contain duplicates if one
1158 // wants to build the smallest rtcp nack packet.
1159 int numOfNackFields = 0;
1160 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +02001161 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +02001162 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001163 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
1164 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +02001165 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001166 while (i < ctx->nack_size) {
1167 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +02001168 if (shift >= 0 && shift <= 15) {
1169 bitmask |= (1 << shift);
1170 ++i;
1171 } else {
1172 break;
1173 }
1174 }
1175 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +02001176 assert(ctx->position + 4 < IP_PACKET_SIZE);
1177 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
1178 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +02001179 numOfNackFields++;
1180 }
Erik Språng242e22b2015-05-11 10:17:43 +02001181 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +02001182
Erik Språng242e22b2015-05-11 10:17:43 +02001183 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +02001184 LOG(LS_WARNING) << "Nack list too large for one packet.";
1185
1186 // Report stats.
1187 NACKStringBuilder stringBuilder;
1188 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +02001189 stringBuilder.PushNACK(ctx->nack_list[idx]);
1190 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +02001191 }
Erik Språng61be2a42015-04-27 13:32:52 +02001192 packet_type_counter_.nack_requests = nack_stats_.requests();
1193 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +02001194
1195 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1196 "RTCPSender::NACK", "nacks",
1197 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
1198 ++packet_type_counter_.nack_packets;
1199 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
1200 ssrc_, packet_type_counter_.nack_packets);
1201
1202 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001203}
1204
Erik Språng242e22b2015-05-11 10:17:43 +02001205RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001206 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001207 if (ctx->position + 8 >= IP_PACKET_SIZE)
1208 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001209
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001210 // Add a bye packet
1211 // Number of SSRC + CSRCs.
Erik Språng242e22b2015-05-11 10:17:43 +02001212 *ctx->AllocateData(1) = static_cast<uint8_t>(0x80 + 1 + csrcs_.size());
1213 *ctx->AllocateData(1) = 203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001214
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001215 // length
Erik Språng242e22b2015-05-11 10:17:43 +02001216 *ctx->AllocateData(1) = 0;
1217 *ctx->AllocateData(1) = static_cast<uint8_t>(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001218
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001219 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001220 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001221
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001222 // add CSRCs
Erik Språng242e22b2015-05-11 10:17:43 +02001223 for (size_t i = 0; i < csrcs_.size(); i++)
1224 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), csrcs_[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001225
Erik Språng242e22b2015-05-11 10:17:43 +02001226 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001227}
1228
Erik Språng242e22b2015-05-11 10:17:43 +02001229RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
1230 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001231 const int kRrTimeBlockLength = 20;
Erik Språng242e22b2015-05-11 10:17:43 +02001232 if (ctx->position + kRrTimeBlockLength >= IP_PACKET_SIZE)
1233 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001234
Erik Språng61be2a42015-04-27 13:32:52 +02001235 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001236 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001237 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +02001238 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
1239 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001240
1241 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001242 *ctx->AllocateData(1) = 0x80;
1243 *ctx->AllocateData(1) = 207;
1244 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1245 4); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001246
1247 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001248 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001249
1250 // 0 1 2 3
1251 // 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
1252 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1253 // | BT=4 | reserved | block length = 2 |
1254 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1255 // | NTP timestamp, most significant word |
1256 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1257 // | NTP timestamp, least significant word |
1258 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1259
1260 // Add Receiver Reference Time Report block.
Erik Språng242e22b2015-05-11 10:17:43 +02001261 *ctx->AllocateData(1) = 4; // BT.
1262 *ctx->AllocateData(1) = 0; // Reserved.
1263 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1264 2); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001265
1266 // NTP timestamp.
Erik Språng242e22b2015-05-11 10:17:43 +02001267 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
1268 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001269
Erik Språng242e22b2015-05-11 10:17:43 +02001270 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001271}
1272
Erik Språng242e22b2015-05-11 10:17:43 +02001273RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001274 const int kDlrrBlockLength = 24;
Erik Språng242e22b2015-05-11 10:17:43 +02001275 if (ctx->position + kDlrrBlockLength >= IP_PACKET_SIZE)
1276 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001277
1278 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001279 *ctx->AllocateData(1) = 0x80;
1280 *ctx->AllocateData(1) = 207;
1281 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1282 5); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001283
1284 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001285 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001286
1287 // 0 1 2 3
1288 // 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
1289 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1290 // | BT=5 | reserved | block length |
1291 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1292 // | SSRC_1 (SSRC of first receiver) | sub-
1293 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1294 // | last RR (LRR) | 1
1295 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1296 // | delay since last RR (DLRR) |
1297 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1298 // | SSRC_2 (SSRC of second receiver) | sub-
1299 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1300 // : ... : 2
1301
1302 // Add DLRR sub block.
Erik Språng242e22b2015-05-11 10:17:43 +02001303 *ctx->AllocateData(1) = 5; // BT.
1304 *ctx->AllocateData(1) = 0; // Reserved.
1305 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1306 3); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001307
1308 // NTP timestamp.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001309
Erik Språng242e22b2015-05-11 10:17:43 +02001310 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
1311 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.sourceSSRC);
1312 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.lastRR);
1313 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
1314 info.delaySinceLastRR);
1315
1316 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001317}
1318
Erik Språng242e22b2015-05-11 10:17:43 +02001319// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
1320RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001321 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001322 if (ctx->position + 44 >= IP_PACKET_SIZE)
1323 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001324
Erik Språng61be2a42015-04-27 13:32:52 +02001325 // Add XR header
Erik Språng242e22b2015-05-11 10:17:43 +02001326 *ctx->AllocateData(1) = 0x80;
1327 *ctx->AllocateData(1) = 207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001328
Erik Språng242e22b2015-05-11 10:17:43 +02001329 uint32_t XRLengthPos = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +00001330
Erik Språng61be2a42015-04-27 13:32:52 +02001331 // handle length later on
Erik Språng242e22b2015-05-11 10:17:43 +02001332 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +00001333
Erik Språng61be2a42015-04-27 13:32:52 +02001334 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001335 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001336
Erik Språng61be2a42015-04-27 13:32:52 +02001337 // Add a VoIP metrics block
Erik Språng242e22b2015-05-11 10:17:43 +02001338 *ctx->AllocateData(1) = 7;
1339 *ctx->AllocateData(1) = 0;
1340 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), 8);
niklase@google.com470e71d2011-07-07 08:21:25 +00001341
Erik Språng61be2a42015-04-27 13:32:52 +02001342 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001343 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001344
Erik Språng242e22b2015-05-11 10:17:43 +02001345 *ctx->AllocateData(1) = xr_voip_metric_.lossRate;
1346 *ctx->AllocateData(1) = xr_voip_metric_.discardRate;
1347 *ctx->AllocateData(1) = xr_voip_metric_.burstDensity;
1348 *ctx->AllocateData(1) = xr_voip_metric_.gapDensity;
niklase@google.com470e71d2011-07-07 08:21:25 +00001349
Erik Språng242e22b2015-05-11 10:17:43 +02001350 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1351 xr_voip_metric_.burstDuration);
1352 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1353 xr_voip_metric_.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001354
Erik Språng242e22b2015-05-11 10:17:43 +02001355 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1356 xr_voip_metric_.roundTripDelay);
1357 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1358 xr_voip_metric_.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001359
Erik Språng242e22b2015-05-11 10:17:43 +02001360 *ctx->AllocateData(1) = xr_voip_metric_.signalLevel;
1361 *ctx->AllocateData(1) = xr_voip_metric_.noiseLevel;
1362 *ctx->AllocateData(1) = xr_voip_metric_.RERL;
1363 *ctx->AllocateData(1) = xr_voip_metric_.Gmin;
niklase@google.com470e71d2011-07-07 08:21:25 +00001364
Erik Språng242e22b2015-05-11 10:17:43 +02001365 *ctx->AllocateData(1) = xr_voip_metric_.Rfactor;
1366 *ctx->AllocateData(1) = xr_voip_metric_.extRfactor;
1367 *ctx->AllocateData(1) = xr_voip_metric_.MOSLQ;
1368 *ctx->AllocateData(1) = xr_voip_metric_.MOSCQ;
niklase@google.com470e71d2011-07-07 08:21:25 +00001369
Erik Språng242e22b2015-05-11 10:17:43 +02001370 *ctx->AllocateData(1) = xr_voip_metric_.RXconfig;
1371 *ctx->AllocateData(1) = 0; // reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001372
Erik Språng242e22b2015-05-11 10:17:43 +02001373 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1374 xr_voip_metric_.JBnominal);
1375 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1376 xr_voip_metric_.JBmax);
1377 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1378 xr_voip_metric_.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001379
Erik Språng242e22b2015-05-11 10:17:43 +02001380 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[XRLengthPos], 10);
1381
1382 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001383}
1384
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001385int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001386 RTCPPacketType packetType,
1387 int32_t nack_size,
1388 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001389 bool repeat,
1390 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +02001391 return SendCompoundRTCP(
1392 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
1393 nack_size, nack_list, repeat, pictureID);
1394}
1395
1396int32_t RTCPSender::SendCompoundRTCP(
1397 const FeedbackState& feedback_state,
1398 const std::set<RTCPPacketType>& packetTypes,
1399 int32_t nack_size,
1400 const uint16_t* nack_list,
1401 bool repeat,
1402 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001403 {
Erik Språng242e22b2015-05-11 10:17:43 +02001404 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1405 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +02001406 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1407 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001408 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001409 }
1410 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +02001411 int rtcp_length =
1412 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
1413 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +02001414
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001415 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +02001416 if (rtcp_length <= 0)
1417 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001418
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001419 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001420}
1421
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001422int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001423 const std::set<RTCPPacketType>& packetTypes,
1424 int32_t nack_size,
1425 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001426 bool repeat,
1427 uint64_t pictureID,
1428 uint8_t* rtcp_buffer,
1429 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +02001430 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001431
Erik Språng242e22b2015-05-11 10:17:43 +02001432 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
1433 rtcp_buffer, buffer_size);
1434
1435 // Add all flags as volatile. Non volatile entries will not be overwritten
1436 // and all new volatile flags added will be consumed by the end of this call.
1437 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001438
Erik Språng61be2a42015-04-27 13:32:52 +02001439 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +02001440 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +02001441
Erik Språng242e22b2015-05-11 10:17:43 +02001442 bool generate_report;
1443 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
1444 // Report type already explicitly set, don't automatically populate.
1445 generate_report = true;
1446 DCHECK(ConsumeFlag(kRtcpReport) == false);
1447 } else {
1448 generate_report =
1449 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
1450 method_ == kRtcpCompound;
1451 if (generate_report)
1452 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001453 }
1454
Erik Språng242e22b2015-05-11 10:17:43 +02001455 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && cname_[0] != 0))
1456 SetFlag(kRtcpSdes, true);
1457
1458 // We need to send our NTP even if we haven't received any reports.
1459 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
1460
1461 if (generate_report) {
1462 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1463 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001464 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001465 SetFlag(kRtcpXrDlrrReportBlock, true);
1466
1467 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001468 // seeded from RTP constructor
1469 int32_t random = rand() % 1000;
1470 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001471
Erik Språng242e22b2015-05-11 10:17:43 +02001472 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001473 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1474 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1475 } else {
1476 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001477 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001478 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1479 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1480 if (send_bitrate_kbit != 0)
1481 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001482 }
Erik Språng61be2a42015-04-27 13:32:52 +02001483 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1484 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1485 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1486 }
Erik Språng242e22b2015-05-11 10:17:43 +02001487 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001488
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001489 StatisticianMap statisticians =
1490 receive_statistics_->GetActiveStatisticians();
1491 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001492 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001493 RTCPReportBlock report_block;
Erik Språng242e22b2015-05-11 10:17:43 +02001494 if (PrepareReport(feedback_state, it->second, &report_block,
1495 &context.ntp_sec, &context.ntp_frac)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001496 AddReportBlock(it->first, &internal_report_blocks_, &report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001497 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001498 }
Erik Språng242e22b2015-05-11 10:17:43 +02001499 if (extended_jitter_report_enabled_)
1500 SetFlag(kRtcpTransmissionTimeOffset, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001501 }
1502 }
1503
Erik Språng242e22b2015-05-11 10:17:43 +02001504 auto it = report_flags_.begin();
1505 while (it != report_flags_.end()) {
1506 auto builder = builders_.find(it->type);
1507 DCHECK(builder != builders_.end());
1508 if (it->is_volatile) {
1509 report_flags_.erase(it++);
1510 } else {
1511 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001512 }
Erik Språng242e22b2015-05-11 10:17:43 +02001513
1514 uint32_t start_position = context.position;
1515 BuildResult result = (*this.*(builder->second))(&context);
1516 switch (result) {
1517 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001518 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001519 case BuildResult::kTruncated:
1520 return context.position;
1521 case BuildResult::kAborted:
1522 context.position = start_position;
1523 FALLTHROUGH();
1524 case BuildResult::kSuccess:
1525 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001526 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001527 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001528 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001529 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001530
1531 if (packet_type_counter_observer_ != NULL) {
1532 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001533 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001534 }
1535
Erik Språng242e22b2015-05-11 10:17:43 +02001536 DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001537
Erik Språng242e22b2015-05-11 10:17:43 +02001538 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001539}
1540
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001541bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
1542 StreamStatistician* statistician,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001543 RTCPReportBlock* report_block,
1544 uint32_t* ntp_secs, uint32_t* ntp_frac) {
1545 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001546 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001547 if (!statistician->GetStatistics(&stats, true))
1548 return false;
1549 report_block->fractionLost = stats.fraction_lost;
1550 report_block->cumulativeLost = stats.cumulative_lost;
1551 report_block->extendedHighSeqNum =
1552 stats.extended_max_sequence_number;
1553 report_block->jitter = stats.jitter;
1554
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001555 // get our NTP as late as possible to avoid a race
Erik Språng242e22b2015-05-11 10:17:43 +02001556 clock_->CurrentNtp(*ntp_secs, *ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001557
1558 // Delay since last received report
1559 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001560 if ((feedback_state.last_rr_ntp_secs != 0) ||
1561 (feedback_state.last_rr_ntp_frac != 0)) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001562 // get the 16 lowest bits of seconds and the 16 higest bits of fractions
Erik Språng61be2a42015-04-27 13:32:52 +02001563 uint32_t now = *ntp_secs & 0x0000FFFF;
1564 now <<= 16;
1565 now += (*ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001566
Erik Språng61be2a42015-04-27 13:32:52 +02001567 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1568 receiveTime <<= 16;
1569 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001570
1571 delaySinceLastReceivedSR = now-receiveTime;
1572 }
1573 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001574 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001575 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001576}
1577
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001578int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001579 CriticalSectionScoped lock(critical_section_transport_.get());
1580 if (cbTransport_) {
1581 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001582 return 0;
1583 }
1584 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001585}
1586
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001587void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1588 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001589 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001590 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001591}
1592
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001593int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1594 uint32_t name,
1595 const uint8_t* data,
1596 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001597 if (length % 4 != 0) {
1598 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1599 return -1;
1600 }
Erik Språng242e22b2015-05-11 10:17:43 +02001601 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001602
Erik Språng242e22b2015-05-11 10:17:43 +02001603 SetFlag(kRtcpApp, true);
1604 app_sub_type_ = subType;
1605 app_name_ = name;
1606 app_data_.reset(new uint8_t[length]);
1607 app_length_ = length;
1608 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001609 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001610}
1611
Erik Språng61be2a42015-04-27 13:32:52 +02001612int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001613 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1614 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001615
Erik Språng242e22b2015-05-11 10:17:43 +02001616 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001617 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001618}
1619
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001620void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001621 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1622 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001623}
1624
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001625bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001626 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1627 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001628}
1629
Erik Språng242e22b2015-05-11 10:17:43 +02001630// called under critsect critical_section_rtcp_sender_
1631RTCPSender::BuildResult RTCPSender::WriteAllReportBlocksToBuffer(
1632 RtcpContext* ctx,
1633 uint8_t* numberOfReportBlocks) {
Erik Språng11beccd2015-05-28 11:10:25 +02001634 *numberOfReportBlocks = internal_report_blocks_.size();
Erik Språng242e22b2015-05-11 10:17:43 +02001635 if ((ctx->position + *numberOfReportBlocks * 24) >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +00001636 LOG(LS_WARNING) << "Can't fit all report blocks.";
Erik Språng242e22b2015-05-11 10:17:43 +02001637 return BuildResult::kError;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001638 }
Erik Språng242e22b2015-05-11 10:17:43 +02001639 WriteReportBlocksToBuffer(ctx, internal_report_blocks_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001640 while (!internal_report_blocks_.empty()) {
1641 delete internal_report_blocks_.begin()->second;
1642 internal_report_blocks_.erase(internal_report_blocks_.begin());
1643 }
Erik Språng242e22b2015-05-11 10:17:43 +02001644 return BuildResult::kSuccess;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001645}
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001646
Erik Språng242e22b2015-05-11 10:17:43 +02001647void RTCPSender::WriteReportBlocksToBuffer(
1648 RtcpContext* ctx,
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001649 const std::map<uint32_t, RTCPReportBlock*>& report_blocks) {
1650 std::map<uint32_t, RTCPReportBlock*>::const_iterator it =
1651 report_blocks.begin();
1652 for (; it != report_blocks.end(); it++) {
pbos@webrtc.org2f446732013-04-08 11:08:41 +00001653 uint32_t remoteSSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001654 RTCPReportBlock* reportBlock = it->second;
1655 if (reportBlock) {
1656 // Remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001657 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remoteSSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001658
1659 // fraction lost
Erik Språng242e22b2015-05-11 10:17:43 +02001660 *ctx->AllocateData(1) = reportBlock->fractionLost;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001661
1662 // cumulative loss
Erik Språng242e22b2015-05-11 10:17:43 +02001663 ByteWriter<uint32_t, 3>::WriteBigEndian(ctx->AllocateData(3),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001664 reportBlock->cumulativeLost);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001665
1666 // extended highest seq_no, contain the highest sequence number received
Erik Språng242e22b2015-05-11 10:17:43 +02001667 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001668 reportBlock->extendedHighSeqNum);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001669
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001670 // Jitter
Erik Språng242e22b2015-05-11 10:17:43 +02001671 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001672 reportBlock->jitter);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001673
Erik Språng242e22b2015-05-11 10:17:43 +02001674 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001675 reportBlock->lastSR);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001676
Erik Språng242e22b2015-05-11 10:17:43 +02001677 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
sprang@webrtc.org779c3d12015-03-17 16:42:49 +00001678 reportBlock->delaySinceLastSR);
niklase@google.com470e71d2011-07-07 08:21:25 +00001679 }
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +00001680 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001681}
1682
1683// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001684int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1685 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001686 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001687
Erik Språng242e22b2015-05-11 10:17:43 +02001688 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1689 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001690 return 0;
1691 }
1692 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001693}
Erik Språng61be2a42015-04-27 13:32:52 +02001694
Erik Språng242e22b2015-05-11 10:17:43 +02001695void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1696 report_flags_.insert(ReportFlag(type, is_volatile));
1697}
1698
1699void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1700 bool is_volatile) {
1701 for (RTCPPacketType type : types)
1702 SetFlag(type, is_volatile);
1703}
1704
1705bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1706 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1707}
1708
1709bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1710 auto it = report_flags_.find(ReportFlag(type, false));
1711 if (it == report_flags_.end())
1712 return false;
1713 if (it->is_volatile || forced)
1714 report_flags_.erase((it));
1715 return true;
1716}
1717
1718bool RTCPSender::AllVolatileFlagsConsumed() const {
1719 for (const ReportFlag& flag : report_flags_) {
1720 if (flag.is_volatile)
1721 return false;
1722 }
1723 return true;
1724}
1725
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001726} // namespace webrtc