blob: bd1a5d4b62d614732b1d4a6022a3a3cb90823f5b [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Danil Chapovalov70ffead2016-07-20 15:26:59 +020015#include <utility>
16
Mirko Bonadei71207422017-09-15 13:58:09 +020017#include "common_types.h" // NOLINT(build/include)
Elad Alon4a87e1c2017-10-03 16:11:34 +020018#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "logging/rtc_event_log/rtc_event_log.h"
20#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
21#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
22#include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
23#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
24#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
25#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
26#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
27#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
28#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
29#include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
30#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
31#include "modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
32#include "modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
33#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
34#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
35#include "modules/rtp_rtcp/source/time_util.h"
36#include "modules/rtp_rtcp/source/tmmbr_help.h"
37#include "rtc_base/checks.h"
38#include "rtc_base/constructormagic.h"
39#include "rtc_base/logging.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020040#include "rtc_base/ptr_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020041#include "rtc_base/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000042
niklase@google.com470e71d2011-07-07 08:21:25 +000043namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000044
sprang5e38c962016-12-01 05:18:09 -080045namespace {
46const uint32_t kRtcpAnyExtendedReports =
47 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
48 kRtcpXrTargetBitrate;
49} // namespace
50
Erik Språng61be2a42015-04-27 13:32:52 +020051NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080052 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000053
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000054NACKStringBuilder::~NACKStringBuilder() {}
55
danilchap162abd32015-12-10 02:39:40 -080056void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (count_ == 0) {
58 stream_ << nack;
59 } else if (nack == prevNack_ + 1) {
60 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020061 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020062 if (consecutive_) {
63 stream_ << "-" << prevNack_;
64 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000065 }
Erik Språng242e22b2015-05-11 10:17:43 +020066 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020067 }
Erik Språng242e22b2015-05-11 10:17:43 +020068 count_++;
69 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000070}
71
Erik Språng61be2a42015-04-27 13:32:52 +020072std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020073 if (consecutive_) {
74 stream_ << "-" << prevNack_;
75 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020076 }
Erik Språng242e22b2015-05-11 10:17:43 +020077 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000078}
79
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000080RTCPSender::FeedbackState::FeedbackState()
nisse40ba3ad2017-03-17 07:04:00 -070081 : packets_sent(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000082 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000083 send_bitrate(0),
84 last_rr_ntp_secs(0),
85 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000086 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020087 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080088 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000089
Danil Chapovalov5c3cc412017-12-07 10:15:53 +010090class PacketContainer : public rtcp::CompoundPacket {
Erik Språngf7c57762015-12-04 10:40:35 +010091 public:
terelius429c3452016-01-21 05:42:04 -080092 PacketContainer(Transport* transport, RtcEventLog* event_log)
Danil Chapovalov5c3cc412017-12-07 10:15:53 +010093 : transport_(transport), event_log_(event_log) {}
Erik Språngf7c57762015-12-04 10:40:35 +010094 virtual ~PacketContainer() {
95 for (RtcpPacket* packet : appended_packets_)
96 delete packet;
97 }
98
danilchap41befce2016-03-30 11:11:51 -070099 size_t SendPackets(size_t max_payload_length) {
Danil Chapovalov5c3cc412017-12-07 10:15:53 +0100100 size_t bytes_sent = 0;
101 Build(max_payload_length, [&](rtc::ArrayView<const uint8_t> packet) {
102 if (transport_->SendRtcp(packet.data(), packet.size())) {
103 bytes_sent += packet.size();
104 if (event_log_) {
105 event_log_->Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(packet));
106 }
107 }
108 });
109 return bytes_sent;
Erik Språngf7c57762015-12-04 10:40:35 +0100110 }
111
112 private:
113 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800114 RtcEventLog* const event_log_;
terelius429c3452016-01-21 05:42:04 -0800115
116 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100117};
118
119class RTCPSender::RtcpContext {
120 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200121 RtcpContext(const FeedbackState& feedback_state,
122 int32_t nack_size,
123 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800124 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100125 : feedback_state_(feedback_state),
126 nack_size_(nack_size),
127 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800128 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200129
Erik Språngf7c57762015-12-04 10:40:35 +0100130 const FeedbackState& feedback_state_;
131 const int32_t nack_size_;
132 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800133 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200134};
135
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000136RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000137 bool audio,
138 Clock* clock,
danilchapf5f793c2017-07-27 04:44:18 -0700139 ReceiveStatisticsProvider* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700140 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800141 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700142 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200143 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200144 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800145 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700146 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800147 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700148 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 using_nack_(false),
150 sending_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200151 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700152 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000153 last_rtp_timestamp_(0),
154 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 ssrc_(0),
156 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000158
Erik Språng242e22b2015-05-11 10:17:43 +0200159 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000160
Erik Språng242e22b2015-05-11 10:17:43 +0200161 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
danilchap2b616392016-08-18 06:17:42 -0700163 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200164 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800165 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200168 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 app_data_(nullptr),
170 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000173 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700174 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200175
176 builders_[kRtcpSr] = &RTCPSender::BuildSR;
177 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200178 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200179 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
180 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200181 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
182 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
183 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
184 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
185 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
186 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800187 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000188}
189
danilchap162abd32015-12-10 02:39:40 -0800190RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000191
pbosda903ea2015-10-02 02:36:56 -0700192RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700193 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200194 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
skvlad1c392cc2016-04-01 14:46:44 -0700197void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700198 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000199
skvlad1c392cc2016-04-01 14:46:44 -0700200 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
201 // When switching on, reschedule the next packet
202 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200203 clock_->TimeInMilliseconds() +
204 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700205 }
206 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000207}
208
Erik Språng61be2a42015-04-27 13:32:52 +0200209bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700210 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200211 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212}
213
Erik Språng61be2a42015-04-27 13:32:52 +0200214int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
215 bool sending) {
216 bool sendRTCPBye = false;
217 {
danilchap56036ff2016-03-22 11:14:09 -0700218 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219
pbosda903ea2015-10-02 02:36:56 -0700220 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200221 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200222 // Trigger RTCP bye
223 sendRTCPBye = true;
224 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000225 }
Erik Språng242e22b2015-05-11 10:17:43 +0200226 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200227 }
228 if (sendRTCPBye)
229 return SendRTCP(feedback_state, kRtcpBye);
230 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000231}
232
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100233void RTCPSender::SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
234 RTC_CHECK_GE(bitrate_bps, 0);
danilchap56036ff2016-03-22 11:14:09 -0700235 rtc::CritScope lock(&critical_section_rtcp_sender_);
Danil Chapovalov1de4b622017-12-13 13:35:10 +0100236 remb_bitrate_ = bitrate_bps;
237 remb_ssrcs_ = std::move(ssrcs);
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000238
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200239 SetFlag(kRtcpRemb, /*is_volatile=*/false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000240 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
241 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200242 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200245void RTCPSender::UnsetRemb() {
246 rtc::CritScope lock(&critical_section_rtcp_sender_);
247 // Stop sending REMB each report until it is reenabled and REMB data set.
248 ConsumeFlag(kRtcpRemb, /*forced=*/true);
249}
250
Erik Språng61be2a42015-04-27 13:32:52 +0200251bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700252 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200253 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000254}
255
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700257 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200258 if (enable) {
259 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
260 } else {
261 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
262 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000263}
264
nisse284542b2017-01-10 08:58:32 -0800265void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800266 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800267 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700268}
269
danilchap71fead22016-08-18 02:01:49 -0700270void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700271 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700272 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000273}
274
275void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
276 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700277 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278 last_rtp_timestamp_ = rtp_timestamp;
279 if (capture_time_ms < 0) {
280 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200281 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000282 } else {
283 last_frame_capture_time_ms_ = capture_time_ms;
284 }
285}
286
nisse14adba72017-03-20 03:52:39 -0700287uint32_t RTCPSender::SSRC() const {
288 rtc::CritScope lock(&critical_section_rtcp_sender_);
289 return ssrc_;
290}
291
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000292void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700293 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000294
Erik Språng242e22b2015-05-11 10:17:43 +0200295 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200296 // not first SetSSRC, probably due to a collision
297 // schedule a new RTCP report
298 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200299 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200300 }
Erik Språng242e22b2015-05-11 10:17:43 +0200301 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000302}
303
Erik Språng61be2a42015-04-27 13:32:52 +0200304void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700305 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200306 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
Peter Boström9ba52f82015-06-01 14:12:28 +0200309int32_t RTCPSender::SetCNAME(const char* c_name) {
310 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000311 return -1;
312
kwiberg352444f2016-11-28 15:58:53 -0800313 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700314 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200315 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000316 return 0;
317}
318
Erik Språng0ea42d32015-06-25 14:46:16 +0200319int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700320 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800321 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700322 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700323 // One spot is reserved for ssrc_/cname_.
324 // TODO(danilchap): Add support for more than 30 contributes by sending
325 // several sdes packets.
326 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000327 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200328
329 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000330 return 0;
331}
332
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000333int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700334 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200335 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000336
Erik Språng242e22b2015-05-11 10:17:43 +0200337 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200339
Erik Språng242e22b2015-05-11 10:17:43 +0200340 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800345 /*
346 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000347
danilchap162abd32015-12-10 02:39:40 -0800348 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
349 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
350 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000351
352
danilchap162abd32015-12-10 02:39:40 -0800353 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000354
danilchap162abd32015-12-10 02:39:40 -0800355 MAX RTCP BW is 5% if the session BW
356 A send report is approximately 65 bytes inc CNAME
357 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 The RECOMMENDED value for the reduced minimum in seconds is 360
360 divided by the session bandwidth in kilobits/second. This minimum
361 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 If the participant has not yet sent an RTCP packet (the variable
364 initial is true), the constant Tmin is set to 2.5 seconds, else it
365 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
danilchap162abd32015-12-10 02:39:40 -0800367 The interval between RTCP packets is varied randomly over the
368 range [0.5,1.5] times the calculated interval to avoid unintended
369 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 if we send
372 If the participant is a sender (we_sent true), the constant C is
373 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
374 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
375 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 if we receive only
378 If we_sent is not true, the constant C is set
379 to the average RTCP packet size divided by 75% of the RTCP
380 bandwidth. The constant n is set to the number of receivers
381 (members - senders). If the number of senders is greater than
382 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
danilchap162abd32015-12-10 02:39:40 -0800384 reconsideration NOT required for peer-to-peer
385 "timer reconsideration" is
386 employed. This algorithm implements a simple back-off mechanism
387 which causes users to hold back RTCP packet transmission if the
388 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
danilchap162abd32015-12-10 02:39:40 -0800390 n = number of members
391 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 4. The calculated interval T is set to a number uniformly distributed
396 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
399 for the fact that the timer reconsideration algorithm converges to
400 a value of the RTCP bandwidth below the intended average
401 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
Erik Språng242e22b2015-05-11 10:17:43 +0200403 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000404
danilchap56036ff2016-03-22 11:14:09 -0700405 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000406
pbosda903ea2015-10-02 02:36:56 -0700407 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000408 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
Erik Språng242e22b2015-05-11 10:17:43 +0200410 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200411 // for video key-frames we want to send the RTCP before the large key-frame
412 // if we have a 100 ms margin
413 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
414 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200417 return true;
418 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200419 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200420 // wrap
421 return true;
422 }
423 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424}
425
danilchap56036ff2016-03-22 11:14:09 -0700426std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200427 // Timestamp shouldn't be estimated before first media frame.
428 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200429 // The timestamp of this RTCP packet should be estimated as the timestamp of
430 // the frame being captured at this moment. We are calculating that
431 // timestamp as the last frame's timestamp + the time since the last frame
432 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700433 uint32_t rtp_rate =
434 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200435 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700436 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700437 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438
Erik Språngf7c57762015-12-04 10:40:35 +0100439 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700440 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800441 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700442 report->SetRtpTimestamp(rtp_timestamp);
443 report->SetPacketCount(ctx.feedback_state_.packets_sent);
444 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
danilchap96b69bd2017-07-25 09:15:14 -0700445 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språngf7c57762015-12-04 10:40:35 +0100446
danilchap56036ff2016-03-22 11:14:09 -0700447 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000448}
449
danilchap56036ff2016-03-22 11:14:09 -0700450std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100451 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200452 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800453 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
Erik Språngf7c57762015-12-04 10:40:35 +0100455 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700456 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200457
danilchap74e8df8f2017-03-16 08:04:08 -0700458 for (const auto& it : csrc_cnames_)
459 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200460
danilchap56036ff2016-03-22 11:14:09 -0700461 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462}
463
danilchap56036ff2016-03-22 11:14:09 -0700464std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100465 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700466 report->SetSenderSsrc(ssrc_);
danilchap96b69bd2017-07-25 09:15:14 -0700467 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språng61be2a42015-04-27 13:32:52 +0200468
danilchap56036ff2016-03-22 11:14:09 -0700469 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000470}
471
danilchap56036ff2016-03-22 11:14:09 -0700472std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100473 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700474 pli->SetSenderSsrc(ssrc_);
475 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200476
Erik Språng242e22b2015-05-11 10:17:43 +0200477 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
478 "RTCPSender::PLI");
479 ++packet_type_counter_.pli_packets;
480 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
481 ssrc_, packet_type_counter_.pli_packets);
482
danilchap56036ff2016-03-22 11:14:09 -0700483 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200484}
485
danilchap56036ff2016-03-22 11:14:09 -0700486std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800487 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000488
Erik Språngf7c57762015-12-04 10:40:35 +0100489 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700490 fir->SetSenderSsrc(ssrc_);
491 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200492
493 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
494 "RTCPSender::FIR");
495 ++packet_type_counter_.fir_packets;
496 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
497 ssrc_, packet_type_counter_.fir_packets);
498
danilchap56036ff2016-03-22 11:14:09 -0700499 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000500}
501
danilchap56036ff2016-03-22 11:14:09 -0700502std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100503 const RtcpContext& ctx) {
504 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700505 remb->SetSenderSsrc(ssrc_);
506 remb->SetBitrateBps(remb_bitrate_);
507 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200508
Erik Språng242e22b2015-05-11 10:17:43 +0200509 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
510 "RTCPSender::REMB");
511
danilchap56036ff2016-03-22 11:14:09 -0700512 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000513}
514
Erik Språng61be2a42015-04-27 13:32:52 +0200515void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700516 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700517 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000518}
519
danilchap56036ff2016-03-22 11:14:09 -0700520std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100521 const RtcpContext& ctx) {
522 if (ctx.feedback_state_.module == nullptr)
523 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200524 // Before sending the TMMBR check the received TMMBN, only an owner is
525 // allowed to raise the bitrate:
526 // * If the sender is an owner of the TMMBN -> send TMMBR
527 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000528
Erik Språng61be2a42015-04-27 13:32:52 +0200529 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700530 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000531
Erik Språng242e22b2015-05-11 10:17:43 +0200532 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
533 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200534 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700535 std::vector<rtcp::TmmbItem> candidates =
536 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000537
danilchap2b616392016-08-18 06:17:42 -0700538 if (!candidates.empty()) {
539 for (const auto& candidate : candidates) {
540 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
541 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100542 // Do not send the same tuple.
543 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200544 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000545 }
danilchap2b616392016-08-18 06:17:42 -0700546 if (!tmmbr_owner) {
547 // Use received bounding set as candidate set.
548 // Add current tuple.
549 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
danilchap2b616392016-08-18 06:17:42 -0700551 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700552 std::vector<rtcp::TmmbItem> bounding =
553 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700554 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
555 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100556 // Did not enter bounding set, no meaning to send this request.
557 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200558 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000559 }
Erik Språng61be2a42015-04-27 13:32:52 +0200560 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000561
danilchap2b616392016-08-18 06:17:42 -0700562 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100563 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700564
Erik Språngf7c57762015-12-04 10:40:35 +0100565 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700566 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800567 rtcp::TmmbItem request;
568 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700569 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800570 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700571 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100572
danilchap56036ff2016-03-22 11:14:09 -0700573 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200574}
575
danilchap56036ff2016-03-22 11:14:09 -0700576std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100577 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100578 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700579 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700580 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
581 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700582 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000583 }
Erik Språng61be2a42015-04-27 13:32:52 +0200584 }
sprangd83df502015-08-27 01:05:08 -0700585
danilchap56036ff2016-03-22 11:14:09 -0700586 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000587}
588
danilchap56036ff2016-03-22 11:14:09 -0700589std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100590 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700591 app->SetSsrc(ssrc_);
592 app->SetSubType(app_sub_type_);
593 app->SetName(app_name_);
594 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200595
danilchap56036ff2016-03-22 11:14:09 -0700596 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200597}
598
danilchap56036ff2016-03-22 11:14:09 -0700599std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100600 const RtcpContext& ctx) {
601 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700602 nack->SetSenderSsrc(ssrc_);
603 nack->SetMediaSsrc(remote_ssrc_);
604 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200605
606 // Report stats.
607 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100608 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
609 stringBuilder.PushNACK(ctx.nack_list_[idx]);
610 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200611 }
Erik Språng61be2a42015-04-27 13:32:52 +0200612 packet_type_counter_.nack_requests = nack_stats_.requests();
613 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200614
615 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
616 "RTCPSender::NACK", "nacks",
617 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
618 ++packet_type_counter_.nack_packets;
619 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
620 ssrc_, packet_type_counter_.nack_packets);
621
danilchap56036ff2016-03-22 11:14:09 -0700622 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200623}
624
danilchap56036ff2016-03-22 11:14:09 -0700625std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100626 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700627 bye->SetSenderSsrc(ssrc_);
628 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700629
danilchap56036ff2016-03-22 11:14:09 -0700630 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000631}
632
sprang5e38c962016-12-01 05:18:09 -0800633std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100634 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800635 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700636 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000637
sprang5e38c962016-12-01 05:18:09 -0800638 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
639 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800640 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800641 xr->SetRrtr(rrtr);
642 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000643
sprang5e38c962016-12-01 05:18:09 -0800644 if (ctx.feedback_state_.has_last_xr_rr) {
645 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
646 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000647
sprang5e38c962016-12-01 05:18:09 -0800648 if (video_bitrate_allocation_) {
649 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000650
sprang5e38c962016-12-01 05:18:09 -0800651 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
652 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100653 if (video_bitrate_allocation_->HasBitrate(sl, tl)) {
654 target_bitrate.AddTargetBitrate(
655 sl, tl, video_bitrate_allocation_->GetBitrate(sl, tl) / 1000);
656 }
sprang5e38c962016-12-01 05:18:09 -0800657 }
658 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000659
sprang5e38c962016-12-01 05:18:09 -0800660 xr->SetTargetBitrate(target_bitrate);
661 video_bitrate_allocation_.reset();
662 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200663
sprang5e38c962016-12-01 05:18:09 -0800664 if (xr_voip_metric_) {
665 rtcp::VoipMetric voip;
666 voip.SetMediaSsrc(remote_ssrc_);
667 voip.SetVoipMetric(*xr_voip_metric_);
668 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000669
sprang5e38c962016-12-01 05:18:09 -0800670 xr->SetVoipMetric(voip);
671 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200672
sprang5e38c962016-12-01 05:18:09 -0800673 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000674}
675
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000676int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200677 RTCPPacketType packetType,
678 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700679 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200680 return SendCompoundRTCP(
681 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700682 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200683}
684
685int32_t RTCPSender::SendCompoundRTCP(
686 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100687 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200688 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700689 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800690 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800691 size_t max_packet_size;
692
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000693 {
danilchap56036ff2016-03-22 11:14:09 -0700694 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700695 if (method_ == RtcpMode::kOff) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100696 RTC_LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
Erik Språng61be2a42015-04-27 13:32:52 +0200697 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000698 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200699 // Add all flags as volatile. Non volatile entries will not be overwritten.
700 // All new volatile flags added will be consumed by the end of this call.
701 SetFlags(packet_types, true);
702
703 // Prevent sending streams to send SR before any media has been sent.
704 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
705 if (!can_calculate_rtp_timestamp) {
706 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
707 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
708 bool sender_report = consumed_report_flag || consumed_sr_flag;
709 if (sender_report && AllVolatileFlagsConsumed()) {
710 // This call was for Sender Report and nothing else.
711 return 0;
712 }
713 if (sending_ && method_ == RtcpMode::kCompound) {
714 // Not allowed to send any RTCP packet without sender report.
715 return -1;
716 }
717 }
718
719 if (packet_type_counter_.first_packet_time_ms == -1)
720 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100721
722 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700723 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800724 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100725
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200726 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100727
danilchap56036ff2016-03-22 11:14:09 -0700728 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800729
Erik Språngf7c57762015-12-04 10:40:35 +0100730 auto it = report_flags_.begin();
731 while (it != report_flags_.end()) {
732 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800733 RTC_DCHECK(builder_it != builders_.end())
734 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100735 if (it->is_volatile) {
736 report_flags_.erase(it++);
737 } else {
738 ++it;
739 }
740
741 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700742 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100743 if (packet.get() == nullptr)
744 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800745 // If there is a BYE, don't append now - save it and append it
746 // at the end later.
747 if (builder_it->first == kRtcpBye) {
748 packet_bye = std::move(packet);
749 } else {
750 container.Append(packet.release());
751 }
752 }
753
754 // Append the BYE now at the end
755 if (packet_bye) {
756 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100757 }
758
759 if (packet_type_counter_observer_ != nullptr) {
760 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
761 remote_ssrc_, packet_type_counter_);
762 }
763
764 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800765 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000766 }
Erik Språng61be2a42015-04-27 13:32:52 +0200767
nisse6f142eb2017-02-21 07:32:47 -0800768 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100769 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000770}
771
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200772void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200773 bool generate_report;
774 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
775 // Report type already explicitly set, don't automatically populate.
776 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700777 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200778 } else {
779 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700780 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
781 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200782 if (generate_report)
783 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000784 }
785
Erik Språng0ea42d32015-06-25 14:46:16 +0200786 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200787 SetFlag(kRtcpSdes, true);
788
Erik Språng242e22b2015-05-11 10:17:43 +0200789 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800790 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
791 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
792 SetFlag(kRtcpAnyExtendedReports, true);
793 }
Erik Språng242e22b2015-05-11 10:17:43 +0200794
795 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800796 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000797
danilchap47a740b2015-12-15 00:30:07 -0800798 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200799 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200800 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
801 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
802 if (send_bitrate_kbit != 0)
803 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000804 }
Erik Språng61be2a42015-04-27 13:32:52 +0200805 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
806 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200807 }
danilchap47a740b2015-12-15 00:30:07 -0800808 // The interval between RTCP packets is varied randomly over the
809 // range [1/2,3/2] times the calculated interval.
810 uint32_t timeToNext =
811 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200812 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000813
danilchap96b69bd2017-07-25 09:15:14 -0700814 // RtcpSender expected to be used for sending either just sender reports
815 // or just receiver reports.
816 RTC_DCHECK(!(IsFlagPresent(kRtcpSr) && IsFlagPresent(kRtcpRr)));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000817 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000818}
819
danilchap96b69bd2017-07-25 09:15:14 -0700820std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
821 const FeedbackState& feedback_state) {
822 std::vector<rtcp::ReportBlock> result;
823 if (!receive_statistics_)
824 return result;
danilchapa72e7342015-12-22 08:07:45 -0800825
danilchapf5f793c2017-07-27 04:44:18 -0700826 // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
827 // compound rtcp packet when single rtcp module is used for multiple media
828 // streams.
829 result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
danilchap96b69bd2017-07-25 09:15:14 -0700830
831 if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
832 (feedback_state.last_rr_ntp_frac != 0))) {
833 // Get our NTP as late as possible to avoid a race.
834 uint32_t now = CompactNtp(clock_->CurrentNtpTime());
835
836 uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
837 receive_time <<= 16;
838 receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
839
840 uint32_t delay_since_last_sr = now - receive_time;
841 // TODO(danilchap): Instead of setting same value on all report blocks,
842 // set only when media_ssrc match sender ssrc of the sender report
843 // remote times were taken from.
844 for (auto& report_block : result) {
845 report_block.SetLastSr(feedback_state.remote_sr);
846 report_block.SetDelayLastSr(delay_since_last_sr);
847 }
danilchapa72e7342015-12-22 08:07:45 -0800848 }
danilchap96b69bd2017-07-25 09:15:14 -0700849 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000850}
851
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000852void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800853 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700854 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000855 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000856}
857
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000858int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
859 uint32_t name,
860 const uint8_t* data,
861 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200862 if (length % 4 != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100863 RTC_LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
Erik Språng61be2a42015-04-27 13:32:52 +0200864 return -1;
865 }
danilchap56036ff2016-03-22 11:14:09 -0700866 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000867
Erik Språng242e22b2015-05-11 10:17:43 +0200868 SetFlag(kRtcpApp, true);
869 app_sub_type_ = subType;
870 app_name_ = name;
871 app_data_.reset(new uint8_t[length]);
872 app_length_ = length;
873 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200874 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000875}
876
spranga790d832016-12-02 07:29:44 -0800877// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200878int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700879 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800880 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000881
sprang5e38c962016-12-01 05:18:09 -0800882 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200883 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000884}
885
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000886void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700887 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200888 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000889}
890
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000891bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700892 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200893 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000894}
895
danilchap853ecb22016-08-22 08:26:15 -0700896void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700897 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700898 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700899 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000900}
Erik Språng61be2a42015-04-27 13:32:52 +0200901
sprang5e38c962016-12-01 05:18:09 -0800902void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
903 if (type & kRtcpAnyExtendedReports) {
904 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
905 } else {
906 report_flags_.insert(ReportFlag(type, is_volatile));
907 }
Erik Språng242e22b2015-05-11 10:17:43 +0200908}
909
910void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
911 bool is_volatile) {
912 for (RTCPPacketType type : types)
913 SetFlag(type, is_volatile);
914}
915
sprang5e38c962016-12-01 05:18:09 -0800916bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200917 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
918}
919
sprang5e38c962016-12-01 05:18:09 -0800920bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200921 auto it = report_flags_.find(ReportFlag(type, false));
922 if (it == report_flags_.end())
923 return false;
924 if (it->is_volatile || forced)
925 report_flags_.erase((it));
926 return true;
927}
928
929bool RTCPSender::AllVolatileFlagsConsumed() const {
930 for (const ReportFlag& flag : report_flags_) {
931 if (flag.is_volatile)
932 return false;
933 }
934 return true;
935}
936
sprang5e38c962016-12-01 05:18:09 -0800937void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
938 rtc::CritScope lock(&critical_section_rtcp_sender_);
939 video_bitrate_allocation_.emplace(bitrate);
940 SetFlag(kRtcpAnyExtendedReports, true);
941}
942
sprang233bd872015-09-08 13:25:16 -0700943bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
nisse6f142eb2017-02-21 07:32:47 -0800944 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800945 {
946 rtc::CritScope lock(&critical_section_rtcp_sender_);
947 if (method_ == RtcpMode::kOff)
948 return false;
nisse6f142eb2017-02-21 07:32:47 -0800949 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -0800950 }
951
nisse6f142eb2017-02-21 07:32:47 -0800952 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
Danil Chapovalov5c3cc412017-12-07 10:15:53 +0100953 bool send_failure = false;
954 auto callback = [&](rtc::ArrayView<const uint8_t> packet) {
955 if (transport_->SendRtcp(packet.data(), packet.size())) {
956 if (event_log_)
957 event_log_->Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(packet));
958 } else {
959 send_failure = true;
960 }
961 };
962 return packet.Build(max_packet_size, callback) && !send_failure;
sprang233bd872015-09-08 13:25:16 -0700963}
964
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000965} // namespace webrtc