blob: f250e29af7dec7ff29f6d8f1cf5b404cd1f1a2d6 [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"
sprang233bd872015-09-08 13:25:16 -070024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000025#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +000026#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000027#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000028
niklase@google.com470e71d2011-07-07 08:21:25 +000029namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000030
31using RTCPUtility::RTCPCnameInformation;
32
Erik Språng61be2a42015-04-27 13:32:52 +020033NACKStringBuilder::NACKStringBuilder()
Erik Språng242e22b2015-05-11 10:17:43 +020034 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {
edjee@google.com79b02892013-04-04 19:43:34 +000035}
36
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000037NACKStringBuilder::~NACKStringBuilder() {}
38
pbos@webrtc.org2f446732013-04-08 11:08:41 +000039void NACKStringBuilder::PushNACK(uint16_t nack)
edjee@google.com79b02892013-04-04 19:43:34 +000040{
Erik Språng242e22b2015-05-11 10:17:43 +020041 if (count_ == 0) {
42 stream_ << nack;
43 } else if (nack == prevNack_ + 1) {
44 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020045 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020046 if (consecutive_) {
47 stream_ << "-" << prevNack_;
48 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000049 }
Erik Språng242e22b2015-05-11 10:17:43 +020050 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020051 }
Erik Språng242e22b2015-05-11 10:17:43 +020052 count_++;
53 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000054}
55
Erik Språng61be2a42015-04-27 13:32:52 +020056std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (consecutive_) {
58 stream_ << "-" << prevNack_;
59 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020060 }
Erik Språng242e22b2015-05-11 10:17:43 +020061 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000062}
63
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000064RTCPSender::FeedbackState::FeedbackState()
65 : send_payload_type(0),
66 frequency_hz(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000067 packets_sent(0),
68 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000069 send_bitrate(0),
70 last_rr_ntp_secs(0),
71 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000072 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020073 has_last_xr_rr(false),
74 module(nullptr) {
75}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000076
Erik Språng242e22b2015-05-11 10:17:43 +020077struct RTCPSender::RtcpContext {
78 RtcpContext(const FeedbackState& feedback_state,
79 int32_t nack_size,
80 const uint16_t* nack_list,
81 bool repeat,
82 uint64_t picture_id,
83 uint8_t* buffer,
84 uint32_t buffer_size)
85 : feedback_state(feedback_state),
86 nack_size(nack_size),
87 nack_list(nack_list),
88 repeat(repeat),
89 picture_id(picture_id),
90 buffer(buffer),
91 buffer_size(buffer_size),
92 ntp_sec(0),
93 ntp_frac(0),
Erik Språng242e22b2015-05-11 10:17:43 +020094 position(0) {}
95
96 uint8_t* AllocateData(uint32_t bytes) {
henrikg91d6ede2015-09-17 00:24:34 -070097 RTC_DCHECK_LE(position + bytes, buffer_size);
Erik Språng242e22b2015-05-11 10:17:43 +020098 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;
Erik Språng242e22b2015-05-11 10:17:43 +0200112 uint32_t position;
113};
114
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200115// TODO(sprang): Once all builders use RtcpPacket, call SendToNetwork() here.
116class RTCPSender::PacketBuiltCallback
117 : public rtcp::RtcpPacket::PacketReadyCallback {
118 public:
119 PacketBuiltCallback(RtcpContext* context) : context_(context) {}
120 virtual ~PacketBuiltCallback() {}
121 void OnPacketReady(uint8_t* data, size_t length) override {
122 context_->position += length;
123 }
Erik Språng72aa9a62015-07-31 16:16:02 +0200124 bool BuildPacket(const rtcp::RtcpPacket& packet) {
125 return packet.BuildExternalBuffer(
126 &context_->buffer[context_->position],
127 context_->buffer_size - context_->position, this);
128 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200129
130 private:
131 RtcpContext* const context_;
132};
133
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000134RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000135 bool audio,
136 Clock* clock,
137 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700138 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
139 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200140 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200141 clock_(clock),
142 method_(kRtcpOff),
sprang86fd9ed2015-09-29 04:45:43 -0700143 transport_(outgoing_transport),
niklase@google.com470e71d2011-07-07 08:21:25 +0000144
Erik Språng242e22b2015-05-11 10:17:43 +0200145 critical_section_rtcp_sender_(
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000146 CriticalSectionWrapper::CreateCriticalSection()),
Erik Språng242e22b2015-05-11 10:17:43 +0200147 using_nack_(false),
148 sending_(false),
149 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 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(last_send_report_, 0, sizeof(last_send_report_));
174 memset(last_rtcp_time_, 0, sizeof(last_rtcp_time_));
sprang86fd9ed2015-09-29 04:45:43 -0700175 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200176
177 builders_[kRtcpSr] = &RTCPSender::BuildSR;
178 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200179 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200180 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
181 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
182 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
183 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
184 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
185 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
186 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
187 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
188 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
189 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
190 builders_[kRtcpXrVoipMetric] = &RTCPSender::BuildVoIPMetric;
191 builders_[kRtcpXrReceiverReferenceTime] =
192 &RTCPSender::BuildReceiverReferenceTime;
193 builders_[kRtcpXrDlrrReportBlock] = &RTCPSender::BuildDlrr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000196RTCPSender::~RTCPSender() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000197}
198
Erik Språng61be2a42015-04-27 13:32:52 +0200199RTCPMethod RTCPSender::Status() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200200 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
201 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000204void RTCPSender::SetRTCPStatus(RTCPMethod method) {
Erik Språng242e22b2015-05-11 10:17:43 +0200205 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
206 method_ = method;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000207
208 if (method == kRtcpOff)
209 return;
Erik Språng242e22b2015-05-11 10:17:43 +0200210 next_time_to_send_rtcp_ =
211 clock_->TimeInMilliseconds() +
212 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
niklase@google.com470e71d2011-07-07 08:21:25 +0000213}
214
Erik Språng61be2a42015-04-27 13:32:52 +0200215bool RTCPSender::Sending() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200216 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
217 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
221 bool sending) {
222 bool sendRTCPBye = false;
223 {
Erik Språng242e22b2015-05-11 10:17:43 +0200224 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
Erik Språng242e22b2015-05-11 10:17:43 +0200226 if (method_ != kRtcpOff) {
227 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200228 // Trigger RTCP bye
229 sendRTCPBye = true;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Erik Språng242e22b2015-05-11 10:17:43 +0200232 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200233 }
234 if (sendRTCPBye)
235 return SendRTCP(feedback_state, kRtcpBye);
236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Erik Språng61be2a42015-04-27 13:32:52 +0200239bool RTCPSender::REMB() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200240 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
241 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000242}
243
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000244void RTCPSender::SetREMBStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200245 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
246 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000247}
248
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000249void RTCPSender::SetREMBData(uint32_t bitrate,
250 const std::vector<uint32_t>& ssrcs) {
Erik Språng242e22b2015-05-11 10:17:43 +0200251 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
252 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000254
Erik Språng242e22b2015-05-11 10:17:43 +0200255 if (remb_enabled_)
256 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
258 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200259 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260}
261
Erik Språng61be2a42015-04-27 13:32:52 +0200262bool RTCPSender::TMMBR() const {
Erik Språng242e22b2015-05-11 10:17:43 +0200263 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
264 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000265}
266
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267void RTCPSender::SetTMMBRStatus(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +0200268 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
269 if (enable) {
270 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
271 } else {
272 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
273 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000276void RTCPSender::SetStartTimestamp(uint32_t start_timestamp) {
Erik Språng242e22b2015-05-11 10:17:43 +0200277 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278 start_timestamp_ = start_timestamp;
279}
280
281void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
282 int64_t capture_time_ms) {
Erik Språng242e22b2015-05-11 10:17:43 +0200283 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284 last_rtp_timestamp_ = rtp_timestamp;
285 if (capture_time_ms < 0) {
286 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200287 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288 } else {
289 last_frame_capture_time_ms_ = capture_time_ms;
290 }
291}
292
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000293void RTCPSender::SetSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200294 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
Erik Språng242e22b2015-05-11 10:17:43 +0200296 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200297 // not first SetSSRC, probably due to a collision
298 // schedule a new RTCP report
299 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200300 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200301 }
Erik Språng242e22b2015-05-11 10:17:43 +0200302 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000303}
304
Erik Språng61be2a42015-04-27 13:32:52 +0200305void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
Erik Språng242e22b2015-05-11 10:17:43 +0200306 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
307 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308}
309
Peter Boström9ba52f82015-06-01 14:12:28 +0200310int32_t RTCPSender::SetCNAME(const char* c_name) {
311 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000312 return -1;
313
henrikg91d6ede2015-09-17 00:24:34 -0700314 RTC_DCHECK_LT(strlen(c_name), static_cast<size_t>(RTCP_CNAME_SIZE));
Erik Språng242e22b2015-05-11 10:17:43 +0200315 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200316 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000317 return 0;
318}
319
Erik Språng0ea42d32015-06-25 14:46:16 +0200320int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
321 assert(c_name);
henrikg91d6ede2015-09-17 00:24:34 -0700322 RTC_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());
Erik Språng0ea42d32015-06-25 14:46:16 +0200324 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000325 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200326
327 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000328 return 0;
329}
330
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000331int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
Erik Språng242e22b2015-05-11 10:17:43 +0200332 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
Erik Språng0ea42d32015-06-25 14:46:16 +0200333 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000334
Erik Språng242e22b2015-05-11 10:17:43 +0200335 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200337
Erik Språng242e22b2015-05-11 10:17:43 +0200338 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000340}
341
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000342bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
niklase@google.com470e71d2011-07-07 08:21:25 +0000343/*
344 For audio we use a fix 5 sec interval
345
346 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000347 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
348 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000349
350
351From RFC 3550
352
353 MAX RTCP BW is 5% if the session BW
354 A send report is approximately 65 bytes inc CNAME
stefan@webrtc.org9d4762e2014-03-24 17:13:00 +0000355 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
357 The RECOMMENDED value for the reduced minimum in seconds is 360
358 divided by the session bandwidth in kilobits/second. This minimum
359 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
360
361 If the participant has not yet sent an RTCP packet (the variable
362 initial is true), the constant Tmin is set to 2.5 seconds, else it
363 is set to 5 seconds.
364
365 The interval between RTCP packets is varied randomly over the
366 range [0.5,1.5] times the calculated interval to avoid unintended
367 synchronization of all participants
368
369 if we send
370 If the participant is a sender (we_sent true), the constant C is
371 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
372 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
373 number of senders.
374
375 if we receive only
376 If we_sent is not true, the constant C is set
377 to the average RTCP packet size divided by 75% of the RTCP
378 bandwidth. The constant n is set to the number of receivers
379 (members - senders). If the number of senders is greater than
380 25%, senders and receivers are treated together.
381
382 reconsideration NOT required for peer-to-peer
383 "timer reconsideration" is
384 employed. This algorithm implements a simple back-off mechanism
385 which causes users to hold back RTCP packet transmission if the
386 group sizes are increasing.
387
388 n = number of members
389 C = avg_size/(rtcpBW/4)
390
391 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
392
393 4. The calculated interval T is set to a number uniformly distributed
394 between 0.5 and 1.5 times the deterministic calculated interval.
395
396 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
397 for the fact that the timer reconsideration algorithm converges to
398 a value of the RTCP bandwidth below the intended average
399*/
400
Erik Språng242e22b2015-05-11 10:17:43 +0200401 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000402
Erik Språng242e22b2015-05-11 10:17:43 +0200403 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
xians@webrtc.org8738d272011-11-25 13:43:53 +0000404
Erik Språng242e22b2015-05-11 10:17:43 +0200405 if (method_ == kRtcpOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200409 // for video key-frames we want to send the RTCP before the large key-frame
410 // if we have a 100 ms margin
411 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
412 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200415 return true;
416 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200417 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200418 // wrap
419 return true;
420 }
421 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422}
423
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000424int64_t RTCPSender::SendTimeOfSendReport(uint32_t sendReport) {
Erik Språng242e22b2015-05-11 10:17:43 +0200425 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng61be2a42015-04-27 13:32:52 +0200427 // This is only saved when we are the sender
Erik Språng242e22b2015-05-11 10:17:43 +0200428 if ((last_send_report_[0] == 0) || (sendReport == 0)) {
Erik Språng61be2a42015-04-27 13:32:52 +0200429 return 0; // will be ignored
430 } else {
431 for (int i = 0; i < RTCP_NUMBER_OF_SR; ++i) {
Erik Språng242e22b2015-05-11 10:17:43 +0200432 if (last_send_report_[i] == sendReport)
433 return last_rtcp_time_[i];
niklase@google.com470e71d2011-07-07 08:21:25 +0000434 }
Erik Språng61be2a42015-04-27 13:32:52 +0200435 }
436 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437}
438
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000439bool RTCPSender::SendTimeOfXrRrReport(uint32_t mid_ntp,
440 int64_t* time_ms) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200441 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000442
443 if (last_xr_rr_.empty()) {
444 return false;
445 }
446 std::map<uint32_t, int64_t>::const_iterator it = last_xr_rr_.find(mid_ntp);
447 if (it == last_xr_rr_.end()) {
448 return false;
449 }
450 *time_ms = it->second;
451 return true;
452}
453
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200454int32_t RTCPSender::AddReportBlock(const RTCPReportBlock& report_block) {
455 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
andresp@webrtc.orgdc80bae2014-04-08 11:06:12 +0000456 LOG(LS_WARNING) << "Too many report blocks.";
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000457 return -1;
458 }
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200459 rtcp::ReportBlock* block = &report_blocks_[report_block.remoteSSRC];
460 block->To(report_block.remoteSSRC);
461 block->WithFractionLost(report_block.fractionLost);
462 block->WithCumulativeLost(report_block.cumulativeLost);
463 block->WithExtHighestSeqNum(report_block.extendedHighSeqNum);
464 block->WithJitter(report_block.jitter);
465 block->WithLastSr(report_block.lastSR);
466 block->WithDelayLastSr(report_block.delaySinceLastSR);
467
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000468 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000469}
470
Erik Språng242e22b2015-05-11 10:17:43 +0200471RTCPSender::BuildResult RTCPSender::BuildSR(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200472 for (int i = (RTCP_NUMBER_OF_SR - 2); i >= 0; i--) {
473 // shift old
Erik Språng242e22b2015-05-11 10:17:43 +0200474 last_send_report_[i + 1] = last_send_report_[i];
475 last_rtcp_time_[i + 1] = last_rtcp_time_[i];
Erik Språng61be2a42015-04-27 13:32:52 +0200476 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000477
Erik Språng242e22b2015-05-11 10:17:43 +0200478 last_rtcp_time_[0] = Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac);
479 last_send_report_[0] = (ctx->ntp_sec << 16) + (ctx->ntp_frac >> 16);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
Erik Språng61be2a42015-04-27 13:32:52 +0200481 // The timestamp of this RTCP packet should be estimated as the timestamp of
482 // the frame being captured at this moment. We are calculating that
483 // timestamp as the last frame's timestamp + the time since the last frame
484 // was captured.
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200485 uint32_t rtp_timestamp =
486 start_timestamp_ + last_rtp_timestamp_ +
487 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) *
488 (ctx->feedback_state.frequency_hz / 1000);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200490 rtcp::SenderReport report;
491 report.From(ssrc_);
492 report.WithNtpSec(ctx->ntp_sec);
493 report.WithNtpFrac(ctx->ntp_frac);
494 report.WithRtpTimestamp(rtp_timestamp);
495 report.WithPacketCount(ctx->feedback_state.packets_sent);
496 report.WithOctetCount(ctx->feedback_state.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000497
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200498 for (auto it : report_blocks_)
499 report.WithReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000500
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200501 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200502 if (!callback.BuildPacket(report))
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200503 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200505 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200506 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000507}
508
Erik Språng0ea42d32015-06-25 14:46:16 +0200509RTCPSender::BuildResult RTCPSender::BuildSDES(RtcpContext* ctx) {
510 size_t length_cname = cname_.length();
henrikg91d6ede2015-09-17 00:24:34 -0700511 RTC_CHECK_LT(length_cname, static_cast<size_t>(RTCP_CNAME_SIZE));
niklase@google.com470e71d2011-07-07 08:21:25 +0000512
Erik Språng0ea42d32015-06-25 14:46:16 +0200513 rtcp::Sdes sdes;
514 sdes.WithCName(ssrc_, cname_);
515
516 for (const auto it : csrc_cnames_)
517 sdes.WithCName(it.first, it.second);
518
519 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200520 if (!callback.BuildPacket(sdes))
Erik Språng242e22b2015-05-11 10:17:43 +0200521 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000522
Erik Språng242e22b2015-05-11 10:17:43 +0200523 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000524}
525
Erik Språng242e22b2015-05-11 10:17:43 +0200526RTCPSender::BuildResult RTCPSender::BuildRR(RtcpContext* ctx) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200527 rtcp::ReceiverReport report;
528 report.From(ssrc_);
529 for (auto it : report_blocks_)
530 report.WithReportBlock(it.second);
531
532 PacketBuiltCallback callback(ctx);
Erik Språng72aa9a62015-07-31 16:16:02 +0200533 if (!callback.BuildPacket(report))
Erik Språng242e22b2015-05-11 10:17:43 +0200534 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200535
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200536 report_blocks_.clear();
Erik Språng242e22b2015-05-11 10:17:43 +0200537
538 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000539}
540
Erik Språng242e22b2015-05-11 10:17:43 +0200541RTCPSender::BuildResult RTCPSender::BuildPLI(RtcpContext* ctx) {
Erik Språng72aa9a62015-07-31 16:16:02 +0200542 rtcp::Pli pli;
543 pli.From(ssrc_);
544 pli.To(remote_ssrc_);
545
546 PacketBuiltCallback callback(ctx);
547 if (!callback.BuildPacket(pli))
Erik Språng242e22b2015-05-11 10:17:43 +0200548 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200549
Erik Språng242e22b2015-05-11 10:17:43 +0200550 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
551 "RTCPSender::PLI");
552 ++packet_type_counter_.pli_packets;
553 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
554 ssrc_, packet_type_counter_.pli_packets);
555
556 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200557}
558
Erik Språng242e22b2015-05-11 10:17:43 +0200559RTCPSender::BuildResult RTCPSender::BuildFIR(RtcpContext* ctx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200560 if (!ctx->repeat)
sprang62dae192015-08-05 02:35:35 -0700561 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000562
sprang62dae192015-08-05 02:35:35 -0700563 rtcp::Fir fir;
564 fir.From(ssrc_);
565 fir.To(remote_ssrc_);
566 fir.WithCommandSeqNum(sequence_number_fir_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000567
sprang62dae192015-08-05 02:35:35 -0700568 PacketBuiltCallback callback(ctx);
569 if (!callback.BuildPacket(fir))
570 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200571
572 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
573 "RTCPSender::FIR");
574 ++packet_type_counter_.fir_packets;
575 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
576 ssrc_, packet_type_counter_.fir_packets);
577
578 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000579}
580
581/*
582 0 1 2 3
583 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
584 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
585 | First | Number | PictureID |
586 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
587*/
Erik Språng242e22b2015-05-11 10:17:43 +0200588RTCPSender::BuildResult RTCPSender::BuildSLI(RtcpContext* ctx) {
sprang0365a272015-08-11 01:02:37 -0700589 rtcp::Sli sli;
590 sli.From(ssrc_);
591 sli.To(remote_ssrc_);
592 // Crop picture id to 6 least significant bits.
593 sli.WithPictureId(ctx->picture_id & 0x3F);
594 sli.WithFirstMb(0);
595 sli.WithNumberOfMb(0x1FFF); // 13 bits, only ones for now.
596
597 PacketBuiltCallback callback(ctx);
598 if (!callback.BuildPacket(sli))
Erik Språng242e22b2015-05-11 10:17:43 +0200599 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000600
Erik Språng242e22b2015-05-11 10:17:43 +0200601 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000602}
603
604/*
605 0 1 2 3
606 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
607 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
608 | PB |0| Payload Type| Native RPSI bit string |
609 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
610 | defined per codec ... | Padding (0) |
611 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
612*/
613/*
614* Note: not generic made for VP8
615*/
Erik Språng242e22b2015-05-11 10:17:43 +0200616RTCPSender::BuildResult RTCPSender::BuildRPSI(RtcpContext* ctx) {
617 if (ctx->feedback_state.send_payload_type == 0xFF)
618 return BuildResult::kError;
619
sprangcf7f54d2015-08-13 04:37:42 -0700620 rtcp::Rpsi rpsi;
621 rpsi.From(ssrc_);
622 rpsi.To(remote_ssrc_);
623 rpsi.WithPayloadType(ctx->feedback_state.send_payload_type);
624 rpsi.WithPictureId(ctx->picture_id);
625
626 PacketBuiltCallback callback(ctx);
627 if (!callback.BuildPacket(rpsi))
Erik Språng242e22b2015-05-11 10:17:43 +0200628 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000629
Erik Språng242e22b2015-05-11 10:17:43 +0200630 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000631}
632
Erik Språng242e22b2015-05-11 10:17:43 +0200633RTCPSender::BuildResult RTCPSender::BuildREMB(RtcpContext* ctx) {
sprangdd4edc52015-08-21 04:21:51 -0700634 rtcp::Remb remb;
635 remb.From(ssrc_);
636 for (uint32_t ssrc : remb_ssrcs_)
637 remb.AppliesTo(ssrc);
638 remb.WithBitrateBps(remb_bitrate_);
639
640 PacketBuiltCallback callback(ctx);
641 if (!callback.BuildPacket(remb))
Erik Språng242e22b2015-05-11 10:17:43 +0200642 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200643
Erik Språng242e22b2015-05-11 10:17:43 +0200644 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
645 "RTCPSender::REMB");
646
647 return BuildResult::kSuccess;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000648}
649
Erik Språng61be2a42015-04-27 13:32:52 +0200650void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
Erik Språng242e22b2015-05-11 10:17:43 +0200651 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
652 tmmbr_send_ = target_bitrate / 1000;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000653}
654
Erik Språng242e22b2015-05-11 10:17:43 +0200655RTCPSender::BuildResult RTCPSender::BuildTMMBR(RtcpContext* ctx) {
656 if (ctx->feedback_state.module == NULL)
657 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200658 // Before sending the TMMBR check the received TMMBN, only an owner is
659 // allowed to raise the bitrate:
660 // * If the sender is an owner of the TMMBN -> send TMMBR
661 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000662
Erik Språng61be2a42015-04-27 13:32:52 +0200663 // get current bounding set from RTCP receiver
664 bool tmmbrOwner = false;
665 // store in candidateSet, allocates one extra slot
Erik Språng242e22b2015-05-11 10:17:43 +0200666 TMMBRSet* candidateSet = tmmbr_help_.CandidateSet();
niklase@google.com470e71d2011-07-07 08:21:25 +0000667
Erik Språng242e22b2015-05-11 10:17:43 +0200668 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
669 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200670 // since RTCPreceiver is not doing the reverse we should be fine
671 int32_t lengthOfBoundingSet =
Erik Språng242e22b2015-05-11 10:17:43 +0200672 ctx->feedback_state.module->BoundingSet(tmmbrOwner, candidateSet);
niklase@google.com470e71d2011-07-07 08:21:25 +0000673
Erik Språng61be2a42015-04-27 13:32:52 +0200674 if (lengthOfBoundingSet > 0) {
675 for (int32_t i = 0; i < lengthOfBoundingSet; i++) {
Erik Språng242e22b2015-05-11 10:17:43 +0200676 if (candidateSet->Tmmbr(i) == tmmbr_send_ &&
677 candidateSet->PacketOH(i) == packet_oh_send_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200678 // do not send the same tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200679 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200680 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000681 }
Erik Språng61be2a42015-04-27 13:32:52 +0200682 if (!tmmbrOwner) {
683 // use received bounding set as candidate set
684 // add current tuple
Erik Språng242e22b2015-05-11 10:17:43 +0200685 candidateSet->SetEntry(lengthOfBoundingSet, tmmbr_send_, packet_oh_send_,
686 ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200687 int numCandidates = lengthOfBoundingSet + 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000688
Erik Språng61be2a42015-04-27 13:32:52 +0200689 // find bounding set
690 TMMBRSet* boundingSet = NULL;
Erik Språng242e22b2015-05-11 10:17:43 +0200691 int numBoundingSet = tmmbr_help_.FindTMMBRBoundingSet(boundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200692 if (numBoundingSet > 0 || numBoundingSet <= numCandidates)
Erik Språng242e22b2015-05-11 10:17:43 +0200693 tmmbrOwner = tmmbr_help_.IsOwner(ssrc_, numBoundingSet);
Erik Språng61be2a42015-04-27 13:32:52 +0200694 if (!tmmbrOwner) {
695 // did not enter bounding set, no meaning to send this request
Erik Språng242e22b2015-05-11 10:17:43 +0200696 return BuildResult::kAborted;
Erik Språng61be2a42015-04-27 13:32:52 +0200697 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000698 }
Erik Språng61be2a42015-04-27 13:32:52 +0200699 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000700
Erik Språng242e22b2015-05-11 10:17:43 +0200701 if (tmmbr_send_) {
sprang81a3e602015-08-21 05:30:11 -0700702 rtcp::Tmmbr tmmbr;
703 tmmbr.From(ssrc_);
704 tmmbr.To(remote_ssrc_);
705 tmmbr.WithBitrateKbps(tmmbr_send_);
706 tmmbr.WithOverhead(packet_oh_send_);
707
708 PacketBuiltCallback callback(ctx);
709 if (!callback.BuildPacket(tmmbr))
Erik Språng242e22b2015-05-11 10:17:43 +0200710 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200711 }
Erik Språng242e22b2015-05-11 10:17:43 +0200712 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200713}
714
Erik Språng242e22b2015-05-11 10:17:43 +0200715RTCPSender::BuildResult RTCPSender::BuildTMMBN(RtcpContext* ctx) {
716 TMMBRSet* boundingSet = tmmbr_help_.BoundingSetToSend();
Erik Språng61be2a42015-04-27 13:32:52 +0200717 if (boundingSet == NULL)
Erik Språng242e22b2015-05-11 10:17:43 +0200718 return BuildResult::kError;
Erik Språng61be2a42015-04-27 13:32:52 +0200719
sprangd83df502015-08-27 01:05:08 -0700720 rtcp::Tmmbn tmmbn;
721 tmmbn.From(ssrc_);
722 for (uint32_t i = 0; i < boundingSet->lengthOfSet(); i++) {
723 if (boundingSet->Tmmbr(i) > 0) {
724 tmmbn.WithTmmbr(boundingSet->Ssrc(i), boundingSet->Tmmbr(i),
725 boundingSet->PacketOH(i));
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000726 }
Erik Språng61be2a42015-04-27 13:32:52 +0200727 }
sprangd83df502015-08-27 01:05:08 -0700728
729 PacketBuiltCallback callback(ctx);
730 if (!callback.BuildPacket(tmmbn))
731 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200732
733 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000734}
735
Erik Språng242e22b2015-05-11 10:17:43 +0200736RTCPSender::BuildResult RTCPSender::BuildAPP(RtcpContext* ctx) {
Erik Språng521875a2015-09-01 10:11:16 +0200737 rtcp::App app;
738 app.From(ssrc_);
739 app.WithSubType(app_sub_type_);
740 app.WithName(app_name_);
741 app.WithData(app_data_.get(), app_length_);
742
743 PacketBuiltCallback callback(ctx);
744 if (!callback.BuildPacket(app))
Erik Språng242e22b2015-05-11 10:17:43 +0200745 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200746
747 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200748}
749
Erik Språng242e22b2015-05-11 10:17:43 +0200750RTCPSender::BuildResult RTCPSender::BuildNACK(RtcpContext* ctx) {
Erik Språng61be2a42015-04-27 13:32:52 +0200751 // sanity
Erik Språng242e22b2015-05-11 10:17:43 +0200752 if (ctx->position + 16 >= IP_PACKET_SIZE) {
Erik Språng61be2a42015-04-27 13:32:52 +0200753 LOG(LS_WARNING) << "Failed to build NACK.";
Erik Språng242e22b2015-05-11 10:17:43 +0200754 return BuildResult::kTruncated;
Erik Språng61be2a42015-04-27 13:32:52 +0200755 }
756
Erik Språng242e22b2015-05-11 10:17:43 +0200757 // int size, uint16_t* nack_list
Erik Språng61be2a42015-04-27 13:32:52 +0200758 // add nack list
759 uint8_t FMT = 1;
Erik Språng242e22b2015-05-11 10:17:43 +0200760 *ctx->AllocateData(1) = 0x80 + FMT;
761 *ctx->AllocateData(1) = 205;
Erik Språng61be2a42015-04-27 13:32:52 +0200762
Erik Språng242e22b2015-05-11 10:17:43 +0200763 *ctx->AllocateData(1) = 0;
764 int nack_size_pos_ = ctx->position;
765 *ctx->AllocateData(1) = 3; // setting it to one kNACK signal as default
Erik Språng61be2a42015-04-27 13:32:52 +0200766
767 // Add our own SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200768 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200769
770 // Add the remote SSRC
Erik Språng242e22b2015-05-11 10:17:43 +0200771 ByteWriter<uint32_t>::WriteBigEndian(ctx->AllocateData(4), remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200772
773 // Build NACK bitmasks and write them to the RTCP message.
774 // The nack list should be sorted and not contain duplicates if one
775 // wants to build the smallest rtcp nack packet.
776 int numOfNackFields = 0;
777 int maxNackFields =
Erik Språng242e22b2015-05-11 10:17:43 +0200778 std::min<int>(kRtcpMaxNackFields, (IP_PACKET_SIZE - ctx->position) / 4);
Erik Språng61be2a42015-04-27 13:32:52 +0200779 int i = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200780 while (i < ctx->nack_size && numOfNackFields < maxNackFields) {
781 uint16_t nack = ctx->nack_list[i++];
Erik Språng61be2a42015-04-27 13:32:52 +0200782 uint16_t bitmask = 0;
Erik Språng242e22b2015-05-11 10:17:43 +0200783 while (i < ctx->nack_size) {
784 int shift = static_cast<uint16_t>(ctx->nack_list[i] - nack) - 1;
Erik Språng61be2a42015-04-27 13:32:52 +0200785 if (shift >= 0 && shift <= 15) {
786 bitmask |= (1 << shift);
787 ++i;
788 } else {
789 break;
790 }
791 }
792 // Write the sequence number and the bitmask to the packet.
Erik Språng242e22b2015-05-11 10:17:43 +0200793 assert(ctx->position + 4 < IP_PACKET_SIZE);
794 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), nack);
795 ByteWriter<uint16_t>::WriteBigEndian(ctx->AllocateData(2), bitmask);
Erik Språng61be2a42015-04-27 13:32:52 +0200796 numOfNackFields++;
797 }
Erik Språng242e22b2015-05-11 10:17:43 +0200798 ctx->buffer[nack_size_pos_] = static_cast<uint8_t>(2 + numOfNackFields);
Erik Språng61be2a42015-04-27 13:32:52 +0200799
Erik Språng242e22b2015-05-11 10:17:43 +0200800 if (i != ctx->nack_size)
Erik Språng61be2a42015-04-27 13:32:52 +0200801 LOG(LS_WARNING) << "Nack list too large for one packet.";
802
803 // Report stats.
804 NACKStringBuilder stringBuilder;
805 for (int idx = 0; idx < i; ++idx) {
Erik Språng242e22b2015-05-11 10:17:43 +0200806 stringBuilder.PushNACK(ctx->nack_list[idx]);
807 nack_stats_.ReportRequest(ctx->nack_list[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200808 }
Erik Språng61be2a42015-04-27 13:32:52 +0200809 packet_type_counter_.nack_requests = nack_stats_.requests();
810 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200811
812 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
813 "RTCPSender::NACK", "nacks",
814 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
815 ++packet_type_counter_.nack_packets;
816 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
817 ssrc_, packet_type_counter_.nack_packets);
818
819 return BuildResult::kSuccess;
Erik Språng61be2a42015-04-27 13:32:52 +0200820}
821
Erik Språng242e22b2015-05-11 10:17:43 +0200822RTCPSender::BuildResult RTCPSender::BuildBYE(RtcpContext* ctx) {
sprangd8ee4f92015-08-24 03:25:19 -0700823 rtcp::Bye bye;
824 bye.From(ssrc_);
825 for (uint32_t csrc : csrcs_)
826 bye.WithCsrc(csrc);
827
828 PacketBuiltCallback callback(ctx);
829 if (!callback.BuildPacket(bye))
Erik Språng242e22b2015-05-11 10:17:43 +0200830 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000831
Erik Språng242e22b2015-05-11 10:17:43 +0200832 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000833}
834
Erik Språng242e22b2015-05-11 10:17:43 +0200835RTCPSender::BuildResult RTCPSender::BuildReceiverReferenceTime(
836 RtcpContext* ctx) {
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000837
Erik Språng61be2a42015-04-27 13:32:52 +0200838 if (last_xr_rr_.size() >= RTCP_NUMBER_OF_SR)
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000839 last_xr_rr_.erase(last_xr_rr_.begin());
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000840 last_xr_rr_.insert(std::pair<uint32_t, int64_t>(
Erik Språng242e22b2015-05-11 10:17:43 +0200841 RTCPUtility::MidNtp(ctx->ntp_sec, ctx->ntp_frac),
842 Clock::NtpToMs(ctx->ntp_sec, ctx->ntp_frac)));
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000843
Erik Språngca28fdc2015-08-31 14:00:50 +0200844 rtcp::Xr xr;
845 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000846
Erik Språngca28fdc2015-08-31 14:00:50 +0200847 rtcp::Rrtr rrtr;
848 rrtr.WithNtpSec(ctx->ntp_sec);
849 rrtr.WithNtpFrac(ctx->ntp_frac);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000850
Erik Språngca28fdc2015-08-31 14:00:50 +0200851 xr.WithRrtr(&rrtr);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000852
Erik Språngca28fdc2015-08-31 14:00:50 +0200853 // TODO(sprang): Merge XR report sending to contain all of RRTR, DLRR, VOIP?
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000854
Erik Språngca28fdc2015-08-31 14:00:50 +0200855 PacketBuiltCallback callback(ctx);
856 if (!callback.BuildPacket(xr))
857 return BuildResult::kTruncated;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000858
Erik Språng242e22b2015-05-11 10:17:43 +0200859 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000860}
861
Erik Språng242e22b2015-05-11 10:17:43 +0200862RTCPSender::BuildResult RTCPSender::BuildDlrr(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200863 rtcp::Xr xr;
864 xr.From(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000865
Erik Språngca28fdc2015-08-31 14:00:50 +0200866 rtcp::Dlrr dlrr;
Erik Språng242e22b2015-05-11 10:17:43 +0200867 const RtcpReceiveTimeInfo& info = ctx->feedback_state.last_xr_rr;
Erik Språngca28fdc2015-08-31 14:00:50 +0200868 dlrr.WithDlrrItem(info.sourceSSRC, info.lastRR, info.delaySinceLastRR);
869
870 xr.WithDlrr(&dlrr);
871
872 PacketBuiltCallback callback(ctx);
873 if (!callback.BuildPacket(xr))
874 return BuildResult::kTruncated;
Erik Språng242e22b2015-05-11 10:17:43 +0200875
876 return BuildResult::kSuccess;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000877}
878
Erik Språng242e22b2015-05-11 10:17:43 +0200879// TODO(sprang): Add a unit test for this, or remove if the code isn't used.
880RTCPSender::BuildResult RTCPSender::BuildVoIPMetric(RtcpContext* ctx) {
Erik Språngca28fdc2015-08-31 14:00:50 +0200881 rtcp::Xr xr;
882 xr.From(ssrc_);
883
884 rtcp::VoipMetric voip;
885 voip.To(remote_ssrc_);
886 voip.LossRate(xr_voip_metric_.lossRate);
887 voip.DiscardRate(xr_voip_metric_.discardRate);
888 voip.BurstDensity(xr_voip_metric_.burstDensity);
889 voip.GapDensity(xr_voip_metric_.gapDensity);
890 voip.BurstDuration(xr_voip_metric_.burstDuration);
891 voip.GapDuration(xr_voip_metric_.gapDuration);
892 voip.RoundTripDelay(xr_voip_metric_.roundTripDelay);
893 voip.EndSystemDelay(xr_voip_metric_.endSystemDelay);
894 voip.SignalLevel(xr_voip_metric_.signalLevel);
895 voip.NoiseLevel(xr_voip_metric_.noiseLevel);
896 voip.Rerl(xr_voip_metric_.RERL);
897 voip.Gmin(xr_voip_metric_.Gmin);
898 voip.Rfactor(xr_voip_metric_.Rfactor);
899 voip.ExtRfactor(xr_voip_metric_.extRfactor);
900 voip.MosLq(xr_voip_metric_.MOSLQ);
901 voip.MosCq(xr_voip_metric_.MOSCQ);
902 voip.RxConfig(xr_voip_metric_.RXconfig);
903 voip.JbNominal(xr_voip_metric_.JBnominal);
904 voip.JbMax(xr_voip_metric_.JBmax);
905 voip.JbAbsMax(xr_voip_metric_.JBabsMax);
906
907 xr.WithVoipMetric(&voip);
908
909 PacketBuiltCallback callback(ctx);
910 if (!callback.BuildPacket(xr))
Erik Språng242e22b2015-05-11 10:17:43 +0200911 return BuildResult::kTruncated;
niklase@google.com470e71d2011-07-07 08:21:25 +0000912
Erik Språng242e22b2015-05-11 10:17:43 +0200913 return BuildResult::kSuccess;
niklase@google.com470e71d2011-07-07 08:21:25 +0000914}
915
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000916int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200917 RTCPPacketType packetType,
918 int32_t nack_size,
919 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000920 bool repeat,
921 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200922 return SendCompoundRTCP(
923 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
924 nack_size, nack_list, repeat, pictureID);
925}
926
927int32_t RTCPSender::SendCompoundRTCP(
928 const FeedbackState& feedback_state,
929 const std::set<RTCPPacketType>& packetTypes,
930 int32_t nack_size,
931 const uint16_t* nack_list,
932 bool repeat,
933 uint64_t pictureID) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000934 {
Erik Språng242e22b2015-05-11 10:17:43 +0200935 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
936 if (method_ == kRtcpOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200937 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
938 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000939 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000940 }
941 uint8_t rtcp_buffer[IP_PACKET_SIZE];
Erik Språng242e22b2015-05-11 10:17:43 +0200942 int rtcp_length =
943 PrepareRTCP(feedback_state, packetTypes, nack_size, nack_list, repeat,
944 pictureID, rtcp_buffer, IP_PACKET_SIZE);
Erik Språng61be2a42015-04-27 13:32:52 +0200945
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000946 // Sanity don't send empty packets.
Erik Språng242e22b2015-05-11 10:17:43 +0200947 if (rtcp_length <= 0)
948 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200949
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000950 return SendToNetwork(rtcp_buffer, static_cast<size_t>(rtcp_length));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000951}
952
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000953int RTCPSender::PrepareRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200954 const std::set<RTCPPacketType>& packetTypes,
955 int32_t nack_size,
956 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000957 bool repeat,
958 uint64_t pictureID,
959 uint8_t* rtcp_buffer,
960 int buffer_size) {
Erik Språng242e22b2015-05-11 10:17:43 +0200961 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000962
Erik Språng242e22b2015-05-11 10:17:43 +0200963 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
964 rtcp_buffer, buffer_size);
965
966 // Add all flags as volatile. Non volatile entries will not be overwritten
967 // and all new volatile flags added will be consumed by the end of this call.
968 SetFlags(packetTypes, true);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000969
Erik Språng61be2a42015-04-27 13:32:52 +0200970 if (packet_type_counter_.first_packet_time_ms == -1)
Erik Språng242e22b2015-05-11 10:17:43 +0200971 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språng61be2a42015-04-27 13:32:52 +0200972
Erik Språng242e22b2015-05-11 10:17:43 +0200973 bool generate_report;
974 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
975 // Report type already explicitly set, don't automatically populate.
976 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700977 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200978 } else {
979 generate_report =
980 (ConsumeFlag(kRtcpReport) && method_ == kRtcpNonCompound) ||
981 method_ == kRtcpCompound;
982 if (generate_report)
983 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000984 }
985
Erik Språng0ea42d32015-06-25 14:46:16 +0200986 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200987 SetFlag(kRtcpSdes, true);
988
989 // We need to send our NTP even if we haven't received any reports.
990 clock_->CurrentNtp(context.ntp_sec, context.ntp_frac);
991
992 if (generate_report) {
993 if (!sending_ && xr_send_receiver_reference_time_enabled_)
994 SetFlag(kRtcpXrReceiverReferenceTime, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200995 if (feedback_state.has_last_xr_rr)
Erik Språng242e22b2015-05-11 10:17:43 +0200996 SetFlag(kRtcpXrDlrrReportBlock, true);
997
998 // generate next time to send an RTCP report
Erik Språng61be2a42015-04-27 13:32:52 +0200999 // seeded from RTP constructor
1000 int32_t random = rand() % 1000;
1001 int32_t timeToNext = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001002
Erik Språng242e22b2015-05-11 10:17:43 +02001003 if (audio_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001004 timeToNext = (RTCP_INTERVAL_AUDIO_MS / 2) +
1005 (RTCP_INTERVAL_AUDIO_MS * random / 1000);
1006 } else {
1007 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
Erik Språng242e22b2015-05-11 10:17:43 +02001008 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +02001009 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
1010 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
1011 if (send_bitrate_kbit != 0)
1012 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001013 }
Erik Språng61be2a42015-04-27 13:32:52 +02001014 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
1015 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
1016 timeToNext = (minIntervalMs / 2) + (minIntervalMs * random / 1000);
1017 }
Erik Språng242e22b2015-05-11 10:17:43 +02001018 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001019
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001020 StatisticianMap statisticians =
1021 receive_statistics_->GetActiveStatisticians();
1022 if (!statisticians.empty()) {
Erik Språng61be2a42015-04-27 13:32:52 +02001023 for (auto it = statisticians.begin(); it != statisticians.end(); ++it) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001024 RTCPReportBlock report_block;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001025 if (PrepareReport(feedback_state, it->first, it->second,
1026 &report_block)) {
1027 AddReportBlock(report_block);
Erik Språng61be2a42015-04-27 13:32:52 +02001028 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001029 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001030 }
1031 }
1032
Erik Språng242e22b2015-05-11 10:17:43 +02001033 auto it = report_flags_.begin();
1034 while (it != report_flags_.end()) {
1035 auto builder = builders_.find(it->type);
henrikg91d6ede2015-09-17 00:24:34 -07001036 RTC_DCHECK(builder != builders_.end());
Erik Språng242e22b2015-05-11 10:17:43 +02001037 if (it->is_volatile) {
1038 report_flags_.erase(it++);
1039 } else {
1040 ++it;
Erik Språng61be2a42015-04-27 13:32:52 +02001041 }
Erik Språng242e22b2015-05-11 10:17:43 +02001042
1043 uint32_t start_position = context.position;
Erik Språng0ea42d32015-06-25 14:46:16 +02001044 BuildResult result = (this->*(builder->second))(&context);
Erik Språng242e22b2015-05-11 10:17:43 +02001045 switch (result) {
1046 case BuildResult::kError:
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001047 return -1;
Erik Språng242e22b2015-05-11 10:17:43 +02001048 case BuildResult::kTruncated:
1049 return context.position;
1050 case BuildResult::kAborted:
1051 context.position = start_position;
1052 FALLTHROUGH();
1053 case BuildResult::kSuccess:
1054 continue;
Erik Språng61be2a42015-04-27 13:32:52 +02001055 default:
Erik Språng242e22b2015-05-11 10:17:43 +02001056 abort();
Erik Språng61be2a42015-04-27 13:32:52 +02001057 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001058 }
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001059
1060 if (packet_type_counter_observer_ != NULL) {
1061 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
Erik Språng242e22b2015-05-11 10:17:43 +02001062 remote_ssrc_, packet_type_counter_);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001063 }
1064
henrikg91d6ede2015-09-17 00:24:34 -07001065 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001066
Erik Språng242e22b2015-05-11 10:17:43 +02001067 return context.position;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001068}
1069
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001070bool RTCPSender::PrepareReport(const FeedbackState& feedback_state,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001071 uint32_t ssrc,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001072 StreamStatistician* statistician,
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001073 RTCPReportBlock* report_block) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001074 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +00001075 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001076 if (!statistician->GetStatistics(&stats, true))
1077 return false;
1078 report_block->fractionLost = stats.fraction_lost;
1079 report_block->cumulativeLost = stats.cumulative_lost;
1080 report_block->extendedHighSeqNum =
1081 stats.extended_max_sequence_number;
1082 report_block->jitter = stats.jitter;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001083 report_block->remoteSSRC = ssrc;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001084
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001085 // TODO(sprang): Do we really need separate time stamps for each report?
1086 // Get our NTP as late as possible to avoid a race.
1087 uint32_t ntp_secs;
1088 uint32_t ntp_frac;
1089 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001090
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001091 // Delay since last received report.
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001092 uint32_t delaySinceLastReceivedSR = 0;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001093 if ((feedback_state.last_rr_ntp_secs != 0) ||
1094 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001095 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
1096 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +02001097 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +02001098 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001099
Erik Språng61be2a42015-04-27 13:32:52 +02001100 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
1101 receiveTime <<= 16;
1102 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001103
1104 delaySinceLastReceivedSR = now-receiveTime;
1105 }
1106 report_block->delaySinceLastSR = delaySinceLastReceivedSR;
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +00001107 report_block->lastSR = feedback_state.remote_sr;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +00001108 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +00001109}
1110
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001111int32_t RTCPSender::SendToNetwork(const uint8_t* dataBuffer, size_t length) {
sprang86fd9ed2015-09-29 04:45:43 -07001112 if (transport_->SendRtcp(dataBuffer, length))
1113 return 0;
Erik Språng61be2a42015-04-27 13:32:52 +02001114 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001115}
1116
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001117void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
1118 assert(csrcs.size() <= kRtpCsrcSize);
Erik Språng242e22b2015-05-11 10:17:43 +02001119 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
pbos@webrtc.org9334ac22014-11-24 08:25:50 +00001120 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001121}
1122
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001123int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
1124 uint32_t name,
1125 const uint8_t* data,
1126 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +02001127 if (length % 4 != 0) {
1128 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
1129 return -1;
1130 }
Erik Språng242e22b2015-05-11 10:17:43 +02001131 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001132
Erik Språng242e22b2015-05-11 10:17:43 +02001133 SetFlag(kRtcpApp, true);
1134 app_sub_type_ = subType;
1135 app_name_ = name;
1136 app_data_.reset(new uint8_t[length]);
1137 app_length_ = length;
1138 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +02001139 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001140}
1141
Erik Språng61be2a42015-04-27 13:32:52 +02001142int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
Erik Språng242e22b2015-05-11 10:17:43 +02001143 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1144 memcpy(&xr_voip_metric_, VoIPMetric, sizeof(RTCPVoIPMetric));
niklase@google.com470e71d2011-07-07 08:21:25 +00001145
Erik Språng242e22b2015-05-11 10:17:43 +02001146 SetFlag(kRtcpXrVoipMetric, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001147 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001148}
1149
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001150void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
Erik Språng242e22b2015-05-11 10:17:43 +02001151 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1152 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +00001153}
1154
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001155bool RTCPSender::RtcpXrReceiverReferenceTime() const {
Erik Språng242e22b2015-05-11 10:17:43 +02001156 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
1157 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +00001158}
1159
niklase@google.com470e71d2011-07-07 08:21:25 +00001160// no callbacks allowed inside this function
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00001161int32_t RTCPSender::SetTMMBN(const TMMBRSet* boundingSet,
1162 uint32_t maxBitrateKbit) {
Erik Språng242e22b2015-05-11 10:17:43 +02001163 CriticalSectionScoped lock(critical_section_rtcp_sender_.get());
niklase@google.com470e71d2011-07-07 08:21:25 +00001164
Erik Språng242e22b2015-05-11 10:17:43 +02001165 if (0 == tmmbr_help_.SetTMMBRBoundingSetToSend(boundingSet, maxBitrateKbit)) {
1166 SetFlag(kRtcpTmmbn, true);
Erik Språng61be2a42015-04-27 13:32:52 +02001167 return 0;
1168 }
1169 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001170}
Erik Språng61be2a42015-04-27 13:32:52 +02001171
Erik Språng242e22b2015-05-11 10:17:43 +02001172void RTCPSender::SetFlag(RTCPPacketType type, bool is_volatile) {
1173 report_flags_.insert(ReportFlag(type, is_volatile));
1174}
1175
1176void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
1177 bool is_volatile) {
1178 for (RTCPPacketType type : types)
1179 SetFlag(type, is_volatile);
1180}
1181
1182bool RTCPSender::IsFlagPresent(RTCPPacketType type) const {
1183 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1184}
1185
1186bool RTCPSender::ConsumeFlag(RTCPPacketType type, bool forced) {
1187 auto it = report_flags_.find(ReportFlag(type, false));
1188 if (it == report_flags_.end())
1189 return false;
1190 if (it->is_volatile || forced)
1191 report_flags_.erase((it));
1192 return true;
1193}
1194
1195bool RTCPSender::AllVolatileFlagsConsumed() const {
1196 for (const ReportFlag& flag : report_flags_) {
1197 if (flag.is_volatile)
1198 return false;
1199 }
1200 return true;
1201}
1202
sprang233bd872015-09-08 13:25:16 -07001203bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001204 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1205 public:
Peter Boströmac547a62015-09-17 23:03:57 +02001206 Sender(Transport* transport)
1207 : transport_(transport), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001208
1209 void OnPacketReady(uint8_t* data, size_t length) override {
pbos2d566682015-09-28 09:59:31 -07001210 if (!transport_->SendRtcp(data, length))
sprang233bd872015-09-08 13:25:16 -07001211 send_failure_ = true;
1212 }
1213
1214 Transport* const transport_;
sprang233bd872015-09-08 13:25:16 -07001215 bool send_failure_;
sprang86fd9ed2015-09-29 04:45:43 -07001216 } sender(transport_);
sprang233bd872015-09-08 13:25:16 -07001217
1218 uint8_t buffer[IP_PACKET_SIZE];
1219 return packet.BuildExternalBuffer(buffer, IP_PACKET_SIZE, &sender) &&
1220 !sender.send_failure_;
1221}
1222
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001223} // namespace webrtc