blob: 11ff4b3b53d19f4c21f9ef51396c4521479f64bf [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
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200116// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
117class RTCPSender::PacketBuiltCallback
118 : public rtcp::RtcpPacket::PacketReadyCallback {
119 public:
120 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
121 virtual ~PacketBuiltCallback() {}
122 void OnPacketReady(uint8_t* data, size_t length) override {
123 context_->position += length;
124 }
125
126 private:
127 RtcpContext* const context_;
128};
129
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000130RTCPSender::RTCPSender(
131 int32_t id,
132 bool audio,
133 Clock* clock,
134 ReceiveStatistics* receive_statistics,
135 RtcpPacketTypeCounterObserver* packet_type_counter_observer)
Erik Språng242e22b2015-05-11 10:17:43 +0200136 : id_(id),
137 audio_(audio),
138 clock_(clock),
139 method_(kRtcpOff),
140 critical_section_transport_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000141 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200142 cbTransport_(nullptr),
niklase@google.com470e71d2011-07-07 08:21:25 +0000143
Erik Språng242e22b2015-05-11 10:17:43 +0200144 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000145 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200146 using_nack_(false),
147 sending_(false),
148 remb_enabled_(false),
149 extended_jitter_report_enabled_(false),
150 next_time_to_send_rtcp_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000151 start_timestamp_(0),
152 last_rtp_timestamp_(0),
153 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 ssrc_(0),
155 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000156 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
Erik Språng242e22b2015-05-11 10:17:43 +0200158 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000159
Erik Språng242e22b2015-05-11 10:17:43 +0200160 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000161
Erik Språng242e22b2015-05-11 10:17:43 +0200162 tmmbr_help_(),
163 tmmbr_send_(0),
164 packet_oh_send_(0),
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200167 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200168 app_data_(nullptr),
169 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000172 packet_type_counter_observer_(packet_type_counter_observer) {
Erik Språng242e22b2015-05-11 10:17:43 +0200173 memset(cname_, 0, sizeof(cname_));
174 memset(last_send_report_, 0, sizeof(last_send_report_));
175 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
176
177 builders_[kRtcpSr] = &RTCPSender::BuildSR;
178 builders_[kRtcpRr] = &RTCPSender::BuildRR;
179 builders_[kRtcpSdes] = &RTCPSender::BuildSDEC;
180 builders_[kRtcpTransmissionTimeOffset] =
181 &RTCPSender::BuildExtendedJitterReport;
182 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
183 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
184 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
185 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
192 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
193 builders_[kRtcpXrReceiverReferenceTime] =
194 &RTCPSender::BuildReceiverReferenceTime;
195 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196}
197
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000198RTCPSender::~RTCPSender() {
Erik Språng242e22b2015-05-11 10:17:43 +0200199 for (auto it : csrc_cnames_)
Erik Språng61be2a42015-04-27 13:32:52 +0200200 delete it.second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
Erik Språng61be2a42015-04-27 13:32:52 +0200203int32_t RTCPSender::RegisterSendTransport(Transport* outgoingTransport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200204 CriticalSectionScoped lock(critical_section_transport_.get());
205 cbTransport_ = outgoingTransport;
Erik Språng61be2a42015-04-27 13:32:52 +0200206 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207}
208
Erik Språng61be2a42015-04-27 13:32:52 +0200209RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200210 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
211 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212}
213
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000214void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200215 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
216 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000217
218 if (method == kRtcpOff)
219 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200220 next_time_to_send_rtcp_ =
221 clock_->TimeInMilliseconds() +
222 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
224
Erik Språng61be2a42015-04-27 13:32:52 +0200225bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200226 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
227 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228}
229
Erik Språng61be2a42015-04-27 13:32:52 +0200230int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
231 bool sending) {
232 bool sendRTCPBye = false;
233 {
Erik Språng242e22b2015-05-11 10:17:43 +0200234 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
Erik Språng242e22b2015-05-11 10:17:43 +0200236 if (method_ != kRtcpOff) {
237 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200238 // Trigger RTCP bye
239 sendRTCPBye = true;
240 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000241 }
Erik Språng242e22b2015-05-11 10:17:43 +0200242 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200243 }
244 if (sendRTCPBye)
245 return SendRTCP(feedback_state, kRtcpBye);
246 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000247}
248
Erik Språng61be2a42015-04-27 13:32:52 +0200249bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200250 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
251 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000252}
253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200255 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
256 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000257}
258
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259void RTCPSender::SetREMBData(uint32_t bitrate,
260 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200261 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
262 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000263 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000264
Erik Språng242e22b2015-05-11 10:17:43 +0200265 if (remb_enabled_)
266 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
268 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200269 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000270}
271
Erik Språng61be2a42015-04-27 13:32:52 +0200272bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200273 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
274 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000277void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200278 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
279 if (enable) {
280 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
281 } else {
282 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
283 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000284}
285
Erik Språng61be2a42015-04-27 13:32:52 +0200286bool RTCPSender::IJ() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200287 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
288 return extended_jitter_report_enabled_;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000289}
290
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000291void RTCPSender::SetIJStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200292 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
293 extended_jitter_report_enabled_ = enable;
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000294}
295
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200297 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000298 start_timestamp_ = start_timestamp;
299}
300
301void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
302 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200303 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000304 last_rtp_timestamp_ = rtp_timestamp;
305 if (capture_time_ms < 0) {
306 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200307 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000308 } else {
309 last_frame_capture_time_ms_ = capture_time_ms;
310 }
311}
312
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000313void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200314 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000315
Erik Språng242e22b2015-05-11 10:17:43 +0200316 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200317 // not first SetSSRC, probably due to a collision
318 // schedule a new RTCP report
319 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200320 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200321 }
Erik Språng242e22b2015-05-11 10:17:43 +0200322 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000323}
324
Erik Språng61be2a42015-04-27 13:32:52 +0200325void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200326 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
327 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000328}
329
Peter Boström9ba52f82015-06-01 14:12:28 +0200330int32_t RTCPSender::SetCNAME(const char* c_name) {
331 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000332 return -1;
333
Peter Boström9ba52f82015-06-01 14:12:28 +0200334 DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200335 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
336 cname_[RTCP_CNAME_SIZE - 1] = 0;
Peter Boström9ba52f82015-06-01 14:12:28 +0200337 strncpy(cname_, c_name, RTCP_CNAME_SIZE - 1);
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000338 return 0;
339}
340
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000341int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC,
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000342 const char cName[RTCP_CNAME_SIZE]) {
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000343 assert(cName);
Erik Språng242e22b2015-05-11 10:17:43 +0200344 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
345 if (csrc_cnames_.size() >= kRtpCsrcSize) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return -1;
347 }
348 RTCPCnameInformation* ptr = new RTCPCnameInformation();
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000349 ptr->name[RTCP_CNAME_SIZE - 1] = 0;
350 strncpy(ptr->name, cName, RTCP_CNAME_SIZE - 1);
Erik Språng242e22b2015-05-11 10:17:43 +0200351 csrc_cnames_[SSRC] = ptr;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
353}
354
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000355int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200356 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000357 std::map<uint32_t, RTCPCnameInformation*>::iterator it =
Erik Språng242e22b2015-05-11 10:17:43 +0200358 csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000359
Erik Språng242e22b2015-05-11 10:17:43 +0200360 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000361 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200362
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000363 delete it->second;
Erik Språng242e22b2015-05-11 10:17:43 +0200364 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000365 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000366}
367
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000368bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000369/*
370 For audio we use a fix 5 sec interval
371
372 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000373 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
374 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
376
377From RFC 3550
378
379 MAX RTCP BW is 5% if the session BW
380 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000381 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
383 The RECOMMENDED value for the reduced minimum in seconds is 360
384 divided by the session bandwidth in kilobits/second. This minimum
385 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
386
387 If the participant has not yet sent an RTCP packet (the variable
388 initial is true), the constant Tmin is set to 2.5 seconds, else it
389 is set to 5 seconds.
390
391 The interval between RTCP packets is varied randomly over the
392 range [0.5,1.5] times the calculated interval to avoid unintended
393 synchronization of all participants
394
395 if we send
396 If the participant is a sender (we_sent true), the constant C is
397 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
398 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
399 number of senders.
400
401 if we receive only
402 If we_sent is not true, the constant C is set
403 to the average RTCP packet size divided by 75% of the RTCP
404 bandwidth. The constant n is set to the number of receivers
405 (members - senders). If the number of senders is greater than
406 25%, senders and receivers are treated together.
407
408 reconsideration NOT required for peer-to-peer
409 "timer reconsideration" is
410 employed. This algorithm implements a simple back-off mechanism
411 which causes users to hold back RTCP packet transmission if the
412 group sizes are increasing.
413
414 n = number of members
415 C = avg_size/(rtcpBW/4)
416
417 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
418
419 4. The calculated interval T is set to a number uniformly distributed
420 between 0.5 and 1.5 times the deterministic calculated interval.
421
422 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
423 for the fact that the timer reconsideration algorithm converges to
424 a value of the RTCP bandwidth below the intended average
425*/
426
Erik Språng242e22b2015-05-11 10:17:43 +0200427 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000428
Erik Språng242e22b2015-05-11 10:17:43 +0200429 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000430
Erik Språng242e22b2015-05-11 10:17:43 +0200431 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000432 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000433
Erik Språng242e22b2015-05-11 10:17:43 +0200434 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // for video key-frames we want to send the RTCP before the large key-frame
436 // if we have a 100 ms margin
437 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
438 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000439
Erik Språng242e22b2015-05-11 10:17:43 +0200440 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200441 return true;
442 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200443 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200444 // wrap
445 return true;
446 }
447 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000448}
449
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000450int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200451 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
Erik Språng61be2a42015-04-27 13:32:52 +0200453 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200454 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200455 return 0; // will be ignored
456 } else {
457 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200458 if (last_send_report_[i] == sendReport)
459 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000460 }
Erik Språng61be2a42015-04-27 13:32:52 +0200461 }
462 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000463}
464
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000465bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
466 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200467 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000468
469 if (last_xr_rr_.empty()) {
470 return false;
471 }
472 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
473 if (it == last_xr_rr_.end()) {
474 return false;
475 }
476 *time_ms = it->second;
477 return true;
478}
479
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200480int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
481 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000482 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000483 return -1;
484 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200485 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
486 block->To(report_block.remoteSSRC);
487 block->WithFractionLost(report_block.fractionLost);
488 block->WithCumulativeLost(report_block.cumulativeLost);
489 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
490 block->WithJitter(report_block.jitter);
491 block->WithLastSr(report_block.lastSR);
492 block->WithDelayLastSr(report_block.delaySinceLastSR);
493
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000494 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000495}
496
Erik Språng242e22b2015-05-11 10:17:43 +0200497RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200498 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
499 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200500 last_send_report_[i + 1] = last_send_report_[i];
501 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200502 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
Erik Språng242e22b2015-05-11 10:17:43 +0200504 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
505 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000506
Erik Språng61be2a42015-04-27 13:32:52 +0200507 // The timestamp of this RTCP packet should be estimated as the timestamp of
508 // the frame being captured at this moment. We are calculating that
509 // timestamp as the last frame's timestamp + the time since the last frame
510 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200511 uint32_t rtp_timestamp =
512 start_timestamp_ + last_rtp_timestamp_ +
513 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
514 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000515
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200516 rtcp::SenderReport report;
517 report.From(ssrc_);
518 report.WithNtpSec(ctx->ntp_sec);
519 report.WithNtpFrac(ctx->ntp_frac);
520 report.WithRtpTimestamp(rtp_timestamp);
521 report.WithPacketCount(ctx->feedback_state.packets_sent);
522 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000523
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200524 for (auto it : report_blocks_)
525 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000526
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200527 PacketBuiltCallback callback(ctx);
528 if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
529 ctx->buffer_size - ctx->position,
530 &callback)) {
531 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200532 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000533
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200534 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200535 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000536}
537
Erik Språng242e22b2015-05-11 10:17:43 +0200538RTCPSender::BuildResult RTCPSender::BuildSDEC(RtcpContext* ctx) {
539 size_t lengthCname = strlen(cname_);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000540 assert(lengthCname < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000542 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200543 if (ctx->position + 12 + lengthCname >= IP_PACKET_SIZE) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000544 LOG(LS_WARNING) << "Failed to build SDEC.";
Erik Språng242e22b2015-05-11 10:17:43 +0200545 return BuildResult::kTruncated;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000546 }
547 // SDEC Source Description
niklase@google.com470e71d2011-07-07 08:21:25 +0000548
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000549 // We always need to add SDES CNAME
Erik Språng242e22b2015-05-11 10:17:43 +0200550 size_t size = 0x80 + 1 + csrc_cnames_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200551 DCHECK_LE(size, std::numeric_limits<uint8_t>::max());
Erik Språng242e22b2015-05-11 10:17:43 +0200552 *ctx->AllocateData(1) = static_cast<uint8_t>(size);
553 *ctx->AllocateData(1) = 202;
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000555 // handle SDES length later on
Erik Språng242e22b2015-05-11 10:17:43 +0200556 uint32_t SDESLengthPos = ctx->position;
557 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000559 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200560 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000561
562 // CNAME = 1
Erik Språng242e22b2015-05-11 10:17:43 +0200563 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200564 DCHECK_LE(lengthCname, std::numeric_limits<uint8_t>::max());
Erik Språng242e22b2015-05-11 10:17:43 +0200565 *ctx->AllocateData(1) = static_cast<uint8_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000566
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000567 uint16_t SDESLength = 10;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000568
Erik Språng242e22b2015-05-11 10:17:43 +0200569 memcpy(ctx->AllocateData(lengthCname), cname_, lengthCname);
Erik Språng61be2a42015-04-27 13:32:52 +0200570 SDESLength += static_cast<uint16_t>(lengthCname);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000571
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000572 uint16_t padding = 0;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000573 // We must have a zero field even if we have an even multiple of 4 bytes
Erik Språng242e22b2015-05-11 10:17:43 +0200574 do {
575 ++padding;
576 *ctx->AllocateData(1) = 0;
577 } while ((ctx->position % 4) != 0);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000578 SDESLength += padding;
579
Erik Språng242e22b2015-05-11 10:17:43 +0200580 for (auto it = csrc_cnames_.begin(); it != csrc_cnames_.end(); ++it) {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000581 RTCPCnameInformation* cname = it->second;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000582 uint32_t SSRC = it->first;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000583
584 // Add SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200585 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), SSRC);
niklase@google.com470e71d2011-07-07 08:21:25 +0000586
587 // CNAME = 1
Erik Språng242e22b2015-05-11 10:17:43 +0200588 *ctx->AllocateData(1) = 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000589
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000590 size_t length = strlen(cname->name);
591 assert(length < RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592
Erik Språng242e22b2015-05-11 10:17:43 +0200593 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000594 SDESLength += 6;
niklase@google.com470e71d2011-07-07 08:21:25 +0000595
Erik Språng242e22b2015-05-11 10:17:43 +0200596 memcpy(ctx->AllocateData(length), cname->name, length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000597
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000598 SDESLength += length;
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000599 uint16_t padding = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000600
601 // We must have a zero field even if we have an even multiple of 4 bytes
Erik Språng242e22b2015-05-11 10:17:43 +0200602 do {
603 ++padding;
604 *ctx->AllocateData(1) = 0;
605 } while ((ctx->position % 4) != 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000606 SDESLength += padding;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000607 }
608 // in 32-bit words minus one and we don't count the header
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000609 uint16_t buffer_length = (SDESLength / 4) - 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200610 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[SDESLengthPos],
sprang@webrtc.org779c3d12015-03-17 16:42:49 +0000611 buffer_length);
Erik Språng242e22b2015-05-11 10:17:43 +0200612 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000613}
614
Erik Språng242e22b2015-05-11 10:17:43 +0200615RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200616 rtcp::ReceiverReport report;
617 report.From(ssrc_);
618 for (auto it : report_blocks_)
619 report.WithReportBlock(it.second);
620
621 PacketBuiltCallback callback(ctx);
622 if (!report.BuildExternalBuffer(&ctx->buffer[ctx->position],
623 ctx->buffer_size - ctx->position,
624 &callback)) {
Erik Språng242e22b2015-05-11 10:17:43 +0200625 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200626 }
Erik Språng61be2a42015-04-27 13:32:52 +0200627
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200628 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200629
630 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000631}
632
asapersson@webrtc.org5249cc82011-12-16 14:31:37 +0000633// From RFC 5450: Transmission Time Offsets in RTP Streams.
634// 0 1 2 3
635// 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
636// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
637// hdr |V=2|P| RC | PT=IJ=195 | length |
638// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
639// | inter-arrival jitter |
640// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
641// . .
642// . .
643// . .
644// | inter-arrival jitter |
645// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
646//
647// If present, this RTCP packet must be placed after a receiver report
648// (inside a compound RTCP packet), and MUST have the same value for RC
649// (reception report count) as the receiver report.
650
Erik Språng242e22b2015-05-11 10:17:43 +0200651RTCPSender::BuildResult RTCPSender::BuildExtendedJitterReport(
652 RtcpContext* ctx) {
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000653 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200654 if (ctx->position + 8 >= IP_PACKET_SIZE)
655 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200656
657 // add picture loss indicator
658 uint8_t RC = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200659 *ctx->AllocateData(1) = 0x80 + RC;
660 *ctx->AllocateData(1) = 195;
Erik Språng61be2a42015-04-27 13:32:52 +0200661
662 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200663 *ctx->AllocateData(1) = 0;
664 *ctx->AllocateData(1) = 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200665
666 // Add inter-arrival jitter
Erik Språng242e22b2015-05-11 10:17:43 +0200667 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
668 ctx->jitter_transmission_offset);
669 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200670}
671
Erik Språng242e22b2015-05-11 10:17:43 +0200672RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200673 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200674 if (ctx->position + 12 >= IP_PACKET_SIZE)
675 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200676
677 // add picture loss indicator
678 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200679 *ctx->AllocateData(1) = 0x80 + FMT;
680 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200681
682 // Used fixed length of 2
Erik Språng242e22b2015-05-11 10:17:43 +0200683 *ctx->AllocateData(1) = 0;
684 *ctx->AllocateData(1) = 2;
Erik Språng61be2a42015-04-27 13:32:52 +0200685
686 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200687 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200688
689 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200690 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
691
692 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
693 "RTCPSender::PLI");
694 ++packet_type_counter_.pli_packets;
695 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
696 ssrc_, packet_type_counter_.pli_packets);
697
698 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200699}
700
Erik Språng242e22b2015-05-11 10:17:43 +0200701RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200702 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200703 if (ctx->position + 20 >= IP_PACKET_SIZE)
704 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200705
Erik Språng242e22b2015-05-11 10:17:43 +0200706 if (!ctx->repeat)
707 sequence_number_fir_++; // do not increase if repetition
niklase@google.com470e71d2011-07-07 08:21:25 +0000708
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000709 // add full intra request indicator
pbos@webrtc.org2f446732013-04-08 11:08:41 +0000710 uint8_t FMT = 4;
Erik Språng242e22b2015-05-11 10:17:43 +0200711 *ctx->AllocateData(1) = 0x80 + FMT;
712 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000713
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000714 //Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200715 *ctx->AllocateData(1) = 0;
716 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000717
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000718 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200719 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000720
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000721 // RFC 5104 4.3.1.2. Semantics
722 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200723 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000724
pwestin@webrtc.org5e954812012-02-10 12:13:12 +0000725 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200726 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000727
Erik Språng242e22b2015-05-11 10:17:43 +0200728 *ctx->AllocateData(1) = sequence_number_fir_;
729 *ctx->AllocateData(1) = 0;
730 *ctx->AllocateData(1) = 0;
731 *ctx->AllocateData(1) = 0;
732
733 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
734 "RTCPSender::FIR");
735 ++packet_type_counter_.fir_packets;
736 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
737 ssrc_, packet_type_counter_.fir_packets);
738
739 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000740}
741
742/*
743 0 1 2 3
744 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
745 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
746 | First | Number | PictureID |
747 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
748*/
Erik Språng242e22b2015-05-11 10:17:43 +0200749RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200750 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200751 if (ctx->position + 16 >= IP_PACKET_SIZE)
752 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000753
Erik Språng61be2a42015-04-27 13:32:52 +0200754 // add slice loss indicator
755 uint8_t FMT = 2;
Erik Språng242e22b2015-05-11 10:17:43 +0200756 *ctx->AllocateData(1) = 0x80 + FMT;
757 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000758
Erik Språng61be2a42015-04-27 13:32:52 +0200759 // Used fixed length of 3
Erik Språng242e22b2015-05-11 10:17:43 +0200760 *ctx->AllocateData(1) = 0;
761 *ctx->AllocateData(1) = 3;
niklase@google.com470e71d2011-07-07 08:21:25 +0000762
Erik Språng61be2a42015-04-27 13:32:52 +0200763 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200764 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000765
Erik Språng61be2a42015-04-27 13:32:52 +0200766 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200767 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200768
769 // Add first, number & picture ID 6 bits
770 // first = 0, 13 - bits
771 // number = 0x1fff, 13 - bits only ones for now
Erik Språng242e22b2015-05-11 10:17:43 +0200772 uint32_t sliField = (0x1fff << 6) + (0x3f & ctx->picture_id);
773 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), sliField);
774
775 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000776}
777
778/*
779 0 1 2 3
780 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
781 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
782 | PB |0| Payload Type| Native RPSI bit string |
783 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
784 | defined per codec ... | Padding (0) |
785 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
786*/
787/*
788* Note: not generic made for VP8
789*/
Erik Språng242e22b2015-05-11 10:17:43 +0200790RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
791 if (ctx->feedback_state.send_payload_type == 0xFF)
792 return BuildResult::kError;
793
Erik Språng61be2a42015-04-27 13:32:52 +0200794 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200795 if (ctx->position + 24 >= IP_PACKET_SIZE)
796 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000797
Erik Språng61be2a42015-04-27 13:32:52 +0200798 // add Reference Picture Selection Indication
799 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200800 *ctx->AllocateData(1) = 0x80 + FMT;
801 *ctx->AllocateData(1) = 206;
niklase@google.com470e71d2011-07-07 08:21:25 +0000802
Erik Språng61be2a42015-04-27 13:32:52 +0200803 // calc length
804 uint32_t bitsRequired = 7;
805 uint8_t bytesRequired = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200806 while ((ctx->picture_id >> bitsRequired) > 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200807 bitsRequired += 7;
808 bytesRequired++;
809 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
Erik Språng61be2a42015-04-27 13:32:52 +0200811 uint8_t size = 3;
812 if (bytesRequired > 6) {
813 size = 5;
814 } else if (bytesRequired > 2) {
815 size = 4;
816 }
Erik Språng242e22b2015-05-11 10:17:43 +0200817 *ctx->AllocateData(1) = 0;
818 *ctx->AllocateData(1) = size;
niklase@google.com470e71d2011-07-07 08:21:25 +0000819
Erik Språng61be2a42015-04-27 13:32:52 +0200820 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200821 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000822
Erik Språng61be2a42015-04-27 13:32:52 +0200823 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200824 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200825
826 // calc padding length
827 uint8_t paddingBytes = 4 - ((2 + bytesRequired) % 4);
828 if (paddingBytes == 4)
829 paddingBytes = 0;
830 // add padding length in bits
Erik Språng242e22b2015-05-11 10:17:43 +0200831 *ctx->AllocateData(1) = paddingBytes * 8; // padding can be 0, 8, 16 or 24
Erik Språng61be2a42015-04-27 13:32:52 +0200832
833 // add payload type
Erik Språng242e22b2015-05-11 10:17:43 +0200834 *ctx->AllocateData(1) = ctx->feedback_state.send_payload_type;
Erik Språng61be2a42015-04-27 13:32:52 +0200835
836 // add picture ID
837 for (int i = bytesRequired - 1; i > 0; --i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200838 *ctx->AllocateData(1) =
839 0x80 | static_cast<uint8_t>(ctx->picture_id >> (i * 7));
Erik Språng61be2a42015-04-27 13:32:52 +0200840 }
841 // add last byte of picture ID
Erik Språng242e22b2015-05-11 10:17:43 +0200842 *ctx->AllocateData(1) = static_cast<uint8_t>(ctx->picture_id & 0x7f);
niklase@google.com470e71d2011-07-07 08:21:25 +0000843
Erik Språng61be2a42015-04-27 13:32:52 +0200844 // add padding
845 for (int j = 0; j < paddingBytes; j++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200846 *ctx->AllocateData(1) = 0;
Erik Språng61be2a42015-04-27 13:32:52 +0200847 }
Erik Språng242e22b2015-05-11 10:17:43 +0200848
849 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000850}
851
Erik Språng242e22b2015-05-11 10:17:43 +0200852RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200853 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200854 if (ctx->position + 20 + 4 * remb_ssrcs_.size() >= IP_PACKET_SIZE)
855 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200856
857 // add application layer feedback
858 uint8_t FMT = 15;
Erik Språng242e22b2015-05-11 10:17:43 +0200859 *ctx->AllocateData(1) = 0x80 + FMT;
860 *ctx->AllocateData(1) = 206;
Erik Språng61be2a42015-04-27 13:32:52 +0200861
Erik Språng242e22b2015-05-11 10:17:43 +0200862 *ctx->AllocateData(1) = 0;
863 *ctx->AllocateData(1) = static_cast<uint8_t>(remb_ssrcs_.size() + 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200864
865 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200866 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200867
868 // Remote SSRC must be 0
Erik Språng242e22b2015-05-11 10:17:43 +0200869 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200870
Erik Språng242e22b2015-05-11 10:17:43 +0200871 *ctx->AllocateData(1) = 'R';
872 *ctx->AllocateData(1) = 'E';
873 *ctx->AllocateData(1) = 'M';
874 *ctx->AllocateData(1) = 'B';
Erik Språng61be2a42015-04-27 13:32:52 +0200875
Erik Språng242e22b2015-05-11 10:17:43 +0200876 *ctx->AllocateData(1) = remb_ssrcs_.size();
Erik Språng61be2a42015-04-27 13:32:52 +0200877 // 6 bit Exp
878 // 18 bit mantissa
879 uint8_t brExp = 0;
880 for (uint32_t i = 0; i < 64; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200881 if (remb_bitrate_ <= (0x3FFFFu << i)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200882 brExp = i;
883 break;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000884 }
Erik Språng61be2a42015-04-27 13:32:52 +0200885 }
Erik Språng242e22b2015-05-11 10:17:43 +0200886 const uint32_t brMantissa = (remb_bitrate_ >> brExp);
887 *ctx->AllocateData(1) =
888 static_cast<uint8_t>((brExp << 2) + ((brMantissa >> 16) & 0x03));
889 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa >> 8);
890 *ctx->AllocateData(1) = static_cast<uint8_t>(brMantissa);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000891
Erik Språng242e22b2015-05-11 10:17:43 +0200892 for (size_t i = 0; i < remb_ssrcs_.size(); i++)
893 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remb_ssrcs_[i]);
894
895 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
896 "RTCPSender::REMB");
897
898 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000899}
900
Erik Språng61be2a42015-04-27 13:32:52 +0200901void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200902 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
903 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000904}
905
Erik Språng242e22b2015-05-11 10:17:43 +0200906RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
907 if (ctx->feedback_state.module == NULL)
908 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200909 // Before sending the TMMBR check the received TMMBN, only an owner is
910 // allowed to raise the bitrate:
911 // * If the sender is an owner of the TMMBN -> send TMMBR
912 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000913
Erik Språng61be2a42015-04-27 13:32:52 +0200914 // get current bounding set from RTCP receiver
915 bool tmmbrOwner = false;
916 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200917 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000918
Erik Språng242e22b2015-05-11 10:17:43 +0200919 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
920 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200921 // since RTCPreceiver is not doing the reverse we should be fine
922 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200923 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000924
Erik Språng61be2a42015-04-27 13:32:52 +0200925 if (lengthOfBoundingSet > 0) {
926 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200927 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
928 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200929 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200930 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200931 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000932 }
Erik Språng61be2a42015-04-27 13:32:52 +0200933 if (!tmmbrOwner) {
934 // use received bounding set as candidate set
935 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200936 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
937 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200938 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000939
Erik Språng61be2a42015-04-27 13:32:52 +0200940 // find bounding set
941 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200942 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200943 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200944 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200945 if (!tmmbrOwner) {
946 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200947 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200948 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000949 }
Erik Språng61be2a42015-04-27 13:32:52 +0200950 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000951
Erik Språng242e22b2015-05-11 10:17:43 +0200952 if (tmmbr_send_) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000953 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200954 if (ctx->position + 20 >= IP_PACKET_SIZE)
955 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
Erik Språng61be2a42015-04-27 13:32:52 +0200957 // add TMMBR indicator
958 uint8_t FMT = 3;
Erik Språng242e22b2015-05-11 10:17:43 +0200959 *ctx->AllocateData(1) = 0x80 + FMT;
960 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200961
962 // Length of 4
Erik Språng242e22b2015-05-11 10:17:43 +0200963 *ctx->AllocateData(1) = 0;
964 *ctx->AllocateData(1) = 4;
niklase@google.com470e71d2011-07-07 08:21:25 +0000965
966 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200967 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000968
Erik Språng61be2a42015-04-27 13:32:52 +0200969 // RFC 5104 4.2.1.2. Semantics
niklase@google.com470e71d2011-07-07 08:21:25 +0000970
971 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +0200972 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
niklase@google.com470e71d2011-07-07 08:21:25 +0000973
974 // Additional Feedback Control Information (FCI)
Erik Språng242e22b2015-05-11 10:17:43 +0200975 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000976
Erik Språng242e22b2015-05-11 10:17:43 +0200977 uint32_t bitRate = tmmbr_send_ * 1000;
Erik Språng61be2a42015-04-27 13:32:52 +0200978 uint32_t mmbrExp = 0;
979 for (uint32_t i = 0; i < 64; i++) {
980 if (bitRate <= (0x1FFFFu << i)) {
981 mmbrExp = i;
982 break;
983 }
984 }
985 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
986
Erik Språng242e22b2015-05-11 10:17:43 +0200987 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +0200988 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +0200989 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
990 *ctx->AllocateData(1) = static_cast<uint8_t>(
991 (mmbrMantissa << 1) + ((packet_oh_send_ >> 8) & 0x01));
992 *ctx->AllocateData(1) = static_cast<uint8_t>(packet_oh_send_);
Erik Språng61be2a42015-04-27 13:32:52 +0200993 }
Erik Språng242e22b2015-05-11 10:17:43 +0200994 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200995}
996
Erik Språng242e22b2015-05-11 10:17:43 +0200997RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
998 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200999 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +02001000 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +02001001
1002 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001003 if (ctx->position + 12 + boundingSet->lengthOfSet() * 8 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001004 LOG(LS_WARNING) << "Failed to build TMMBN.";
Erik Språng242e22b2015-05-11 10:17:43 +02001005 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001006 }
1007
1008 uint8_t FMT = 4;
1009 // add TMMBN indicator
Erik Språng242e22b2015-05-11 10:17:43 +02001010 *ctx->AllocateData(1) = 0x80 + FMT;
1011 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001012
1013 // Add length later
Erik Språng242e22b2015-05-11 10:17:43 +02001014 int posLength = ctx->position;
1015 ctx->AllocateData(2);
Erik Språng61be2a42015-04-27 13:32:52 +02001016
1017 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001018 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001019
1020 // RFC 5104 4.2.2.2. Semantics
1021
1022 // SSRC of media source
Erik Språng242e22b2015-05-11 10:17:43 +02001023 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), 0);
Erik Språng61be2a42015-04-27 13:32:52 +02001024
1025 // Additional Feedback Control Information (FCI)
1026 int numBoundingSet = 0;
1027 for (uint32_t n = 0; n < boundingSet->lengthOfSet(); n++) {
1028 if (boundingSet->Tmmbr(n) > 0) {
1029 uint32_t tmmbrSSRC = boundingSet->Ssrc(n);
Erik Språng242e22b2015-05-11 10:17:43 +02001030 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), tmmbrSSRC);
Erik Språng61be2a42015-04-27 13:32:52 +02001031
1032 uint32_t bitRate = boundingSet->Tmmbr(n) * 1000;
1033 uint32_t mmbrExp = 0;
1034 for (int i = 0; i < 64; i++) {
1035 if (bitRate <= (0x1FFFFu << i)) {
1036 mmbrExp = i;
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001037 break;
niklase@google.com470e71d2011-07-07 08:21:25 +00001038 }
andresp@webrtc.org523f9372013-04-11 11:30:39 +00001039 }
Erik Språng61be2a42015-04-27 13:32:52 +02001040 uint32_t mmbrMantissa = (bitRate >> mmbrExp);
1041 uint32_t measuredOH = boundingSet->PacketOH(n);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001042
Erik Språng242e22b2015-05-11 10:17:43 +02001043 *ctx->AllocateData(1) =
Erik Språng61be2a42015-04-27 13:32:52 +02001044 static_cast<uint8_t>((mmbrExp << 2) + ((mmbrMantissa >> 15) & 0x03));
Erik Språng242e22b2015-05-11 10:17:43 +02001045 *ctx->AllocateData(1) = static_cast<uint8_t>(mmbrMantissa >> 7);
1046 *ctx->AllocateData(1) = static_cast<uint8_t>((mmbrMantissa << 1) +
1047 ((measuredOH >> 8) & 0x01));
1048 *ctx->AllocateData(1) = static_cast<uint8_t>(measuredOH);
Erik Språng61be2a42015-04-27 13:32:52 +02001049 numBoundingSet++;
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +00001050 }
Erik Språng61be2a42015-04-27 13:32:52 +02001051 }
1052 uint16_t length = static_cast<uint16_t>(2 + 2 * numBoundingSet);
Erik Språng242e22b2015-05-11 10:17:43 +02001053 ctx->buffer[posLength++] = static_cast<uint8_t>(length >> 8);
1054 ctx->buffer[posLength] = static_cast<uint8_t>(length);
1055
1056 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001057}
1058
Erik Språng242e22b2015-05-11 10:17:43 +02001059RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001060 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001061 if (app_data_ == NULL) {
Erik Språng61be2a42015-04-27 13:32:52 +02001062 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001063 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +02001064 }
Erik Språng242e22b2015-05-11 10:17:43 +02001065 if (ctx->position + 12 + app_length_ >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001066 LOG(LS_WARNING) << "Failed to build app specific.";
Erik Språng242e22b2015-05-11 10:17:43 +02001067 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001068 }
Erik Språng242e22b2015-05-11 10:17:43 +02001069 *ctx->AllocateData(1) = 0x80 + app_sub_type_;
Erik Språng61be2a42015-04-27 13:32:52 +02001070
1071 // Add APP ID
Erik Språng242e22b2015-05-11 10:17:43 +02001072 *ctx->AllocateData(1) = 204;
Erik Språng61be2a42015-04-27 13:32:52 +02001073
Erik Språng242e22b2015-05-11 10:17:43 +02001074 uint16_t length = (app_length_ >> 2) + 2; // include SSRC and name
1075 *ctx->AllocateData(1) = static_cast<uint8_t>(length >> 8);
1076 *ctx->AllocateData(1) = static_cast<uint8_t>(length);
Erik Språng61be2a42015-04-27 13:32:52 +02001077
1078 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001079 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001080
1081 // Add our application name
Erik Språng242e22b2015-05-11 10:17:43 +02001082 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), app_name_);
Erik Språng61be2a42015-04-27 13:32:52 +02001083
1084 // Add the data
Erik Språng242e22b2015-05-11 10:17:43 +02001085 memcpy(ctx->AllocateData(app_length_), app_data_.get(), app_length_);
1086
1087 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001088}
1089
Erik Språng242e22b2015-05-11 10:17:43 +02001090RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001091 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001092 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +02001093 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +02001094 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +02001095 }
1096
Erik Språng242e22b2015-05-11 10:17:43 +02001097 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +02001098 // add nack list
1099 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +02001100 *ctx->AllocateData(1) = 0x80 + FMT;
1101 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +02001102
Erik Språng242e22b2015-05-11 10:17:43 +02001103 *ctx->AllocateData(1) = 0;
1104 int nack_size_pos_ = ctx->position;
1105 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +02001106
1107 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001108 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001109
1110 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001111 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +02001112
1113 // Build NACK bitmasks and write them to the RTCP message.
1114 // The nack list should be sorted and not contain duplicates if one
1115 // wants to build the smallest rtcp nack packet.
1116 int numOfNackFields = 0;
1117 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +02001118 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +02001119 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001120 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
1121 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +02001122 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +02001123 while (i < ctx->nack_size) {
1124 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +02001125 if (shift >= 0 && shift <= 15) {
1126 bitmask |= (1 << shift);
1127 ++i;
1128 } else {
1129 break;
1130 }
1131 }
1132 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +02001133 assert(ctx->position + 4 < IP_PACKET_SIZE);
1134 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
1135 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +02001136 numOfNackFields++;
1137 }
Erik Språng242e22b2015-05-11 10:17:43 +02001138 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +02001139
Erik Språng242e22b2015-05-11 10:17:43 +02001140 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +02001141 LOG(LS_WARNING) << "Nack list too large for one packet.";
1142
1143 // Report stats.
1144 NACKStringBuilder stringBuilder;
1145 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +02001146 stringBuilder.PushNACK(ctx->nack_list[idx]);
1147 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +02001148 }
Erik Språng61be2a42015-04-27 13:32:52 +02001149 packet_type_counter_.nack_requests = nack_stats_.requests();
1150 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +02001151
1152 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
1153 "RTCPSender::NACK", "nacks",
1154 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
1155 ++packet_type_counter_.nack_packets;
1156 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
1157 ssrc_, packet_type_counter_.nack_packets);
1158
1159 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +02001160}
1161
Erik Språng242e22b2015-05-11 10:17:43 +02001162RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001163 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001164 if (ctx->position + 8 >= IP_PACKET_SIZE)
1165 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001166
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001167 // Add a bye packet
1168 // Number of SSRC + CSRCs.
Erik Språng242e22b2015-05-11 10:17:43 +02001169 *ctx->AllocateData(1) = static_cast<uint8_t>(0x80 + 1 + csrcs_.size());
1170 *ctx->AllocateData(1) = 203;
niklase@google.com470e71d2011-07-07 08:21:25 +00001171
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001172 // length
Erik Språng242e22b2015-05-11 10:17:43 +02001173 *ctx->AllocateData(1) = 0;
1174 *ctx->AllocateData(1) = static_cast<uint8_t>(1 + csrcs_.size());
niklase@google.com470e71d2011-07-07 08:21:25 +00001175
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001176 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001177 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001178
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001179 // add CSRCs
Erik Språng242e22b2015-05-11 10:17:43 +02001180 for (size_t i = 0; i < csrcs_.size(); i++)
1181 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), csrcs_[i]);
niklase@google.com470e71d2011-07-07 08:21:25 +00001182
Erik Språng242e22b2015-05-11 10:17:43 +02001183 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001184}
1185
Erik Språng242e22b2015-05-11 10:17:43 +02001186RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
1187 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001188 const int kRrTimeBlockLength = 20;
Erik Språng242e22b2015-05-11 10:17:43 +02001189 if (ctx->position + kRrTimeBlockLength >= IP_PACKET_SIZE)
1190 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001191
Erik Språng61be2a42015-04-27 13:32:52 +02001192 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001193 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001194 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +02001195 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
1196 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001197
1198 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001199 *ctx->AllocateData(1) = 0x80;
1200 *ctx->AllocateData(1) = 207;
1201 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1202 4); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001203
1204 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001205 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001206
1207 // 0 1 2 3
1208 // 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
1209 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1210 // | BT=4 | reserved | block length = 2 |
1211 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1212 // | NTP timestamp, most significant word |
1213 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1214 // | NTP timestamp, least significant word |
1215 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1216
1217 // Add Receiver Reference Time Report block.
Erik Språng242e22b2015-05-11 10:17:43 +02001218 *ctx->AllocateData(1) = 4; // BT.
1219 *ctx->AllocateData(1) = 0; // Reserved.
1220 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1221 2); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001222
1223 // NTP timestamp.
Erik Språng242e22b2015-05-11 10:17:43 +02001224 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_sec);
1225 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001226
Erik Språng242e22b2015-05-11 10:17:43 +02001227 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001228}
1229
Erik Språng242e22b2015-05-11 10:17:43 +02001230RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001231 const int kDlrrBlockLength = 24;
Erik Språng242e22b2015-05-11 10:17:43 +02001232 if (ctx->position + kDlrrBlockLength >= IP_PACKET_SIZE)
1233 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001234
1235 // Add XR header.
Erik Språng242e22b2015-05-11 10:17:43 +02001236 *ctx->AllocateData(1) = 0x80;
1237 *ctx->AllocateData(1) = 207;
1238 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1239 5); // XR packet length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001240
1241 // Add our own SSRC.
Erik Språng242e22b2015-05-11 10:17:43 +02001242 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001243
1244 // 0 1 2 3
1245 // 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
1246 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1247 // | BT=5 | reserved | block length |
1248 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1249 // | SSRC_1 (SSRC of first receiver) | sub-
1250 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1251 // | last RR (LRR) | 1
1252 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1253 // | delay since last RR (DLRR) |
1254 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1255 // | SSRC_2 (SSRC of second receiver) | sub-
1256 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
1257 // : ... : 2
1258
1259 // Add DLRR sub block.
Erik Språng242e22b2015-05-11 10:17:43 +02001260 *ctx->AllocateData(1) = 5; // BT.
1261 *ctx->AllocateData(1) = 0; // Reserved.
1262 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1263 3); // Block length.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001264
1265 // NTP timestamp.
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001266
Erik Språng242e22b2015-05-11 10:17:43 +02001267 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
1268 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.sourceSSRC);
1269 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), info.lastRR);
1270 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4),
1271 info.delaySinceLastRR);
1272
1273 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001274}
1275
Erik Språng242e22b2015-05-11 10:17:43 +02001276// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
1277RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +02001278 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +02001279 if (ctx->position + 44 >= IP_PACKET_SIZE)
1280 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +00001281
Erik Språng61be2a42015-04-27 13:32:52 +02001282 // Add XR header
Erik Språng242e22b2015-05-11 10:17:43 +02001283 *ctx->AllocateData(1) = 0x80;
1284 *ctx->AllocateData(1) = 207;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285
Erik Språng242e22b2015-05-11 10:17:43 +02001286 uint32_t XRLengthPos = ctx->position;
niklase@google.com470e71d2011-07-07 08:21:25 +00001287
Erik Språng61be2a42015-04-27 13:32:52 +02001288 // handle length later on
Erik Språng242e22b2015-05-11 10:17:43 +02001289 ctx->AllocateData(2);
niklase@google.com470e71d2011-07-07 08:21:25 +00001290
Erik Språng61be2a42015-04-27 13:32:52 +02001291 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001292 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001293
Erik Språng61be2a42015-04-27 13:32:52 +02001294 // Add a VoIP metrics block
Erik Språng242e22b2015-05-11 10:17:43 +02001295 *ctx->AllocateData(1) = 7;
1296 *ctx->AllocateData(1) = 0;
1297 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), 8);
niklase@google.com470e71d2011-07-07 08:21:25 +00001298
Erik Språng61be2a42015-04-27 13:32:52 +02001299 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +02001300 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
niklase@google.com470e71d2011-07-07 08:21:25 +00001301
Erik Språng242e22b2015-05-11 10:17:43 +02001302 *ctx->AllocateData(1) = xr_voip_metric_.lossRate;
1303 *ctx->AllocateData(1) = xr_voip_metric_.discardRate;
1304 *ctx->AllocateData(1) = xr_voip_metric_.burstDensity;
1305 *ctx->AllocateData(1) = xr_voip_metric_.gapDensity;
niklase@google.com470e71d2011-07-07 08:21:25 +00001306
Erik Språng242e22b2015-05-11 10:17:43 +02001307 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1308 xr_voip_metric_.burstDuration);
1309 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1310 xr_voip_metric_.gapDuration);
niklase@google.com470e71d2011-07-07 08:21:25 +00001311
Erik Språng242e22b2015-05-11 10:17:43 +02001312 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1313 xr_voip_metric_.roundTripDelay);
1314 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1315 xr_voip_metric_.endSystemDelay);
niklase@google.com470e71d2011-07-07 08:21:25 +00001316
Erik Språng242e22b2015-05-11 10:17:43 +02001317 *ctx->AllocateData(1) = xr_voip_metric_.signalLevel;
1318 *ctx->AllocateData(1) = xr_voip_metric_.noiseLevel;
1319 *ctx->AllocateData(1) = xr_voip_metric_.RERL;
1320 *ctx->AllocateData(1) = xr_voip_metric_.Gmin;
niklase@google.com470e71d2011-07-07 08:21:25 +00001321
Erik Språng242e22b2015-05-11 10:17:43 +02001322 *ctx->AllocateData(1) = xr_voip_metric_.Rfactor;
1323 *ctx->AllocateData(1) = xr_voip_metric_.extRfactor;
1324 *ctx->AllocateData(1) = xr_voip_metric_.MOSLQ;
1325 *ctx->AllocateData(1) = xr_voip_metric_.MOSCQ;
niklase@google.com470e71d2011-07-07 08:21:25 +00001326
Erik Språng242e22b2015-05-11 10:17:43 +02001327 *ctx->AllocateData(1) = xr_voip_metric_.RXconfig;
1328 *ctx->AllocateData(1) = 0; // reserved
niklase@google.com470e71d2011-07-07 08:21:25 +00001329
Erik Språng242e22b2015-05-11 10:17:43 +02001330 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1331 xr_voip_metric_.JBnominal);
1332 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1333 xr_voip_metric_.JBmax);
1334 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2),
1335 xr_voip_metric_.JBabsMax);
niklase@google.com470e71d2011-07-07 08:21:25 +00001336
Erik Språng242e22b2015-05-11 10:17:43 +02001337 ByteWriter<uint16_t>::WriteBigEndian(&ctx->buffer[XRLengthPos], 10);
1338
1339 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +00001340}
1341
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001342int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001343 RTCPPacketType packetType,
1344 int32_t nack_size,
1345 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001346 bool repeat,
1347 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +02001348 return SendCompoundRTCP(
1349 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
1350 nack_size, nack_list, repeat, pictureID);
1351}
1352
1353int32_t RTCPSender::SendCompoundRTCP(
1354 const FeedbackState& feedback_state,
1355 const std::set<RTCPPacketType>& packetTypes,
1356 int32_t nack_size,
1357 const uint16_t* nack_list,
1358 bool repeat,
1359 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001360 {
Erik Språng242e22b2015-05-11 10:17:43 +02001361 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1362 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +02001363 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
1364 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +00001365 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001366 }
1367 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +02001368 int rtcp_length =
1369 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
1370 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +02001371
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001372 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +02001373 if (rtcp_length <= 0)
1374 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +02001375
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001376 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001377}
1378
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001379int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +02001380 const std::set<RTCPPacketType>& packetTypes,
1381 int32_t nack_size,
1382 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001383 bool repeat,
1384 uint64_t pictureID,
1385 uint8_t* rtcp_buffer,
1386 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +02001387 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001388
Erik Språng242e22b2015-05-11 10:17:43 +02001389 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
1390 rtcp_buffer, buffer_size);
1391
1392 // Add all flags as volatile. Non volatile entries will not be overwritten
1393 // and all new volatile flags added will be consumed by the end of this call.
1394 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001395
Erik Språng61be2a42015-04-27 13:32:52 +02001396 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +02001397 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +02001398
Erik Språng242e22b2015-05-11 10:17:43 +02001399 bool generate_report;
1400 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
1401 // Report type already explicitly set, don't automatically populate.
1402 generate_report = true;
1403 DCHECK(ConsumeFlag(kRtcpReport) == false);
1404 } else {
1405 generate_report =
1406 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
1407 method_ == kRtcpCompound;
1408 if (generate_report)
1409 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +00001410 }
1411
Erik Språng242e22b2015-05-11 10:17:43 +02001412 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && cname_[0] != 0))
1413 SetFlag(kRtcpSdes, true);
1414
1415 // We need to send our NTP even if we haven't received any reports.
1416 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
1417
1418 if (generate_report) {
1419 if (!sending_ && xr_send_receiver_reference_time_enabled_)
1420 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001421 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +02001422 SetFlag(kRtcpXrDlrrReportBlock, true);
1423
1424 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +02001425 // seeded from RTP constructor
1426 int32_t random = rand() % 1000;
1427 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001428
Erik Språng242e22b2015-05-11 10:17:43 +02001429 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001430 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1431 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1432 } else {
1433 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001434 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001435 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1436 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1437 if (send_bitrate_kbit != 0)
1438 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001439 }
Erik Språng61be2a42015-04-27 13:32:52 +02001440 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1441 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1442 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1443 }
Erik Språng242e22b2015-05-11 10:17:43 +02001444 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001445
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001446 StatisticianMap statisticians =
1447 receive_statistics_->GetActiveStatisticians();
1448 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001449 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001450 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001451 if (PrepareReport(feedback_state, it->first, it->second,
1452 &report_block)) {
1453 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001454 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001455 }
Erik Språng242e22b2015-05-11 10:17:43 +02001456 if (extended_jitter_report_enabled_)
1457 SetFlag(kRtcpTransmissionTimeOffset, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001458 }
1459 }
1460
Erik Språng242e22b2015-05-11 10:17:43 +02001461 auto it = report_flags_.begin();
1462 while (it != report_flags_.end()) {
1463 auto builder = builders_.find(it->type);
1464 DCHECK(builder != builders_.end());
1465 if (it->is_volatile) {
1466 report_flags_.erase(it++);
1467 } else {
1468 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001469 }
Erik Språng242e22b2015-05-11 10:17:43 +02001470
1471 uint32_t start_position = context.position;
1472 BuildResult result = (*this.*(builder->second))(&context);
1473 switch (result) {
1474 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001475 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001476 case BuildResult::kTruncated:
1477 return context.position;
1478 case BuildResult::kAborted:
1479 context.position = start_position;
1480 FALLTHROUGH();
1481 case BuildResult::kSuccess:
1482 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001483 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001484 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001485 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001486 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001487
1488 if (packet_type_counter_observer_ != NULL) {
1489 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001490 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001491 }
1492
Erik Språng242e22b2015-05-11 10:17:43 +02001493 DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001494
Erik Språng242e22b2015-05-11 10:17:43 +02001495 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001496}
1497
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001498bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001499 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001500 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001501 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001502 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001503 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001504 if (!statistician->GetStatistics(&stats, true))
1505 return false;
1506 report_block->fractionLost = stats.fraction_lost;
1507 report_block->cumulativeLost = stats.cumulative_lost;
1508 report_block->extendedHighSeqNum =
1509 stats.extended_max_sequence_number;
1510 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001511 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001512
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001513 // TODO(sprang): Do we really need separate time stamps for each report?
1514 // Get our NTP as late as possible to avoid a race.
1515 uint32_t ntp_secs;
1516 uint32_t ntp_frac;
1517 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001518
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001519 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001520 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001521 if ((feedback_state.last_rr_ntp_secs != 0) ||
1522 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001523 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1524 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001525 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001526 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001527
Erik Språng61be2a42015-04-27 13:32:52 +02001528 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1529 receiveTime <<= 16;
1530 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001531
1532 delaySinceLastReceivedSR = now-receiveTime;
1533 }
1534 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001535 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001536 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001537}
1538
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001539int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
Erik Språng242e22b2015-05-11 10:17:43 +02001540 CriticalSectionScoped lock(critical_section_transport_.get());
1541 if (cbTransport_) {
1542 if (cbTransport_->SendRTCPPacket(id_, dataBuffer, length) > 0)
Erik Språng61be2a42015-04-27 13:32:52 +02001543 return 0;
1544 }
1545 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001546}
1547
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001548void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1549 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001550 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001551 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001552}
1553
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001554int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1555 uint32_t name,
1556 const uint8_t* data,
1557 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001558 if (length % 4 != 0) {
1559 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1560 return -1;
1561 }
Erik Språng242e22b2015-05-11 10:17:43 +02001562 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001563
Erik Språng242e22b2015-05-11 10:17:43 +02001564 SetFlag(kRtcpApp, true);
1565 app_sub_type_ = subType;
1566 app_name_ = name;
1567 app_data_.reset(new uint8_t[length]);
1568 app_length_ = length;
1569 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001570 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001571}
1572
Erik Språng61be2a42015-04-27 13:32:52 +02001573int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001574 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1575 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001576
Erik Språng242e22b2015-05-11 10:17:43 +02001577 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001578 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001579}
1580
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001581void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001582 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1583 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001584}
1585
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001586bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001587 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1588 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001589}
1590
niklase@google.com470e71d2011-07-07 08:21:25 +00001591// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001592int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1593 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001594 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001595
Erik Språng242e22b2015-05-11 10:17:43 +02001596 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1597 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001598 return 0;
1599 }
1600 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001601}
Erik Språng61be2a42015-04-27 13:32:52 +02001602
Erik Språng242e22b2015-05-11 10:17:43 +02001603void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1604 report_flags_.insert(ReportFlag(type, is_volatile));
1605}
1606
1607void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1608 bool is_volatile) {
1609 for (RTCPPacketType type : types)
1610 SetFlag(type, is_volatile);
1611}
1612
1613bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1614 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1615}
1616
1617bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1618 auto it = report_flags_.find(ReportFlag(type, false));
1619 if (it == report_flags_.end())
1620 return false;
1621 if (it->is_volatile || forced)
1622 report_flags_.erase((it));
1623 return true;
1624}
1625
1626bool RTCPSender::AllVolatileFlagsConsumed() const {
1627 for (const ReportFlag& flag : report_flags_) {
1628 if (flag.is_volatile)
1629 return false;
1630 }
1631 return true;
1632}
1633
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001634} // namespace webrtc