blob: c75768d85094125b6521fa862d9840f03610ff8c [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 Chapovalovf74d6412017-10-18 13:32:57 +0200233void RTCPSender::SetRemb(uint32_t bitrate, const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700234 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200235 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000236 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000237
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200238 SetFlag(kRtcpRemb, /*is_volatile=*/false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000239 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
240 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200241 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000242}
243
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200244void RTCPSender::UnsetRemb() {
245 rtc::CritScope lock(&critical_section_rtcp_sender_);
246 // Stop sending REMB each report until it is reenabled and REMB data set.
247 ConsumeFlag(kRtcpRemb, /*forced=*/true);
248}
249
Erik Språng61be2a42015-04-27 13:32:52 +0200250bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700251 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200252 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000253}
254
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700256 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200257 if (enable) {
258 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
259 } else {
260 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
261 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000262}
263
nisse284542b2017-01-10 08:58:32 -0800264void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800265 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800266 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700267}
268
danilchap71fead22016-08-18 02:01:49 -0700269void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700270 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700271 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000272}
273
274void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
275 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700276 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000277 last_rtp_timestamp_ = rtp_timestamp;
278 if (capture_time_ms < 0) {
279 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200280 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000281 } else {
282 last_frame_capture_time_ms_ = capture_time_ms;
283 }
284}
285
nisse14adba72017-03-20 03:52:39 -0700286uint32_t RTCPSender::SSRC() const {
287 rtc::CritScope lock(&critical_section_rtcp_sender_);
288 return ssrc_;
289}
290
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000291void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700292 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000293
Erik Språng242e22b2015-05-11 10:17:43 +0200294 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200295 // not first SetSSRC, probably due to a collision
296 // schedule a new RTCP report
297 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200298 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200299 }
Erik Språng242e22b2015-05-11 10:17:43 +0200300 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000301}
302
Erik Språng61be2a42015-04-27 13:32:52 +0200303void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700304 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200305 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000306}
307
Peter Boström9ba52f82015-06-01 14:12:28 +0200308int32_t RTCPSender::SetCNAME(const char* c_name) {
309 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000310 return -1;
311
kwiberg352444f2016-11-28 15:58:53 -0800312 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700313 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200314 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000315 return 0;
316}
317
Erik Språng0ea42d32015-06-25 14:46:16 +0200318int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700319 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800320 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700321 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700322 // One spot is reserved for ssrc_/cname_.
323 // TODO(danilchap): Add support for more than 30 contributes by sending
324 // several sdes packets.
325 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000326 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200327
328 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000329 return 0;
330}
331
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000332int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700333 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200334 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335
Erik Språng242e22b2015-05-11 10:17:43 +0200336 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200338
Erik Språng242e22b2015-05-11 10:17:43 +0200339 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800344 /*
345 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000346
danilchap162abd32015-12-10 02:39:40 -0800347 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
348 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
349 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000350
351
danilchap162abd32015-12-10 02:39:40 -0800352 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000353
danilchap162abd32015-12-10 02:39:40 -0800354 MAX RTCP BW is 5% if the session BW
355 A send report is approximately 65 bytes inc CNAME
356 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
danilchap162abd32015-12-10 02:39:40 -0800358 The RECOMMENDED value for the reduced minimum in seconds is 360
359 divided by the session bandwidth in kilobits/second. This minimum
360 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 If the participant has not yet sent an RTCP packet (the variable
363 initial is true), the constant Tmin is set to 2.5 seconds, else it
364 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 The interval between RTCP packets is varied randomly over the
367 range [0.5,1.5] times the calculated interval to avoid unintended
368 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 if we send
371 If the participant is a sender (we_sent true), the constant C is
372 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
373 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
374 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 if we receive only
377 If we_sent is not true, the constant C is set
378 to the average RTCP packet size divided by 75% of the RTCP
379 bandwidth. The constant n is set to the number of receivers
380 (members - senders). If the number of senders is greater than
381 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 reconsideration NOT required for peer-to-peer
384 "timer reconsideration" is
385 employed. This algorithm implements a simple back-off mechanism
386 which causes users to hold back RTCP packet transmission if the
387 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 n = number of members
390 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 4. The calculated interval T is set to a number uniformly distributed
395 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
398 for the fact that the timer reconsideration algorithm converges to
399 a value of the RTCP bandwidth below the intended average
400 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
Erik Språng242e22b2015-05-11 10:17:43 +0200402 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000403
danilchap56036ff2016-03-22 11:14:09 -0700404 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000405
pbosda903ea2015-10-02 02:36:56 -0700406 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
Erik Språng242e22b2015-05-11 10:17:43 +0200409 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200410 // for video key-frames we want to send the RTCP before the large key-frame
411 // if we have a 100 ms margin
412 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
413 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 return true;
417 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200418 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200419 // wrap
420 return true;
421 }
422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423}
424
danilchap56036ff2016-03-22 11:14:09 -0700425std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200426 // Timestamp shouldn't be estimated before first media frame.
427 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200428 // The timestamp of this RTCP packet should be estimated as the timestamp of
429 // the frame being captured at this moment. We are calculating that
430 // timestamp as the last frame's timestamp + the time since the last frame
431 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700432 uint32_t rtp_rate =
433 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200434 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700435 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700436 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437
Erik Språngf7c57762015-12-04 10:40:35 +0100438 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700439 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800440 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700441 report->SetRtpTimestamp(rtp_timestamp);
442 report->SetPacketCount(ctx.feedback_state_.packets_sent);
443 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
danilchap96b69bd2017-07-25 09:15:14 -0700444 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språngf7c57762015-12-04 10:40:35 +0100445
danilchap56036ff2016-03-22 11:14:09 -0700446 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000447}
448
danilchap56036ff2016-03-22 11:14:09 -0700449std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100450 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200451 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800452 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
Erik Språngf7c57762015-12-04 10:40:35 +0100454 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700455 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200456
danilchap74e8df8f2017-03-16 08:04:08 -0700457 for (const auto& it : csrc_cnames_)
458 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200459
danilchap56036ff2016-03-22 11:14:09 -0700460 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000461}
462
danilchap56036ff2016-03-22 11:14:09 -0700463std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100464 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700465 report->SetSenderSsrc(ssrc_);
danilchap96b69bd2017-07-25 09:15:14 -0700466 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språng61be2a42015-04-27 13:32:52 +0200467
danilchap56036ff2016-03-22 11:14:09 -0700468 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000469}
470
danilchap56036ff2016-03-22 11:14:09 -0700471std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100472 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700473 pli->SetSenderSsrc(ssrc_);
474 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200475
Erik Språng242e22b2015-05-11 10:17:43 +0200476 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
477 "RTCPSender::PLI");
478 ++packet_type_counter_.pli_packets;
479 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
480 ssrc_, packet_type_counter_.pli_packets);
481
danilchap56036ff2016-03-22 11:14:09 -0700482 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200483}
484
danilchap56036ff2016-03-22 11:14:09 -0700485std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800486 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
Erik Språngf7c57762015-12-04 10:40:35 +0100488 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700489 fir->SetSenderSsrc(ssrc_);
490 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200491
492 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
493 "RTCPSender::FIR");
494 ++packet_type_counter_.fir_packets;
495 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
496 ssrc_, packet_type_counter_.fir_packets);
497
danilchap56036ff2016-03-22 11:14:09 -0700498 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000499}
500
danilchap56036ff2016-03-22 11:14:09 -0700501std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100502 const RtcpContext& ctx) {
503 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700504 remb->SetSenderSsrc(ssrc_);
505 remb->SetBitrateBps(remb_bitrate_);
506 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200507
Erik Språng242e22b2015-05-11 10:17:43 +0200508 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
509 "RTCPSender::REMB");
510
danilchap56036ff2016-03-22 11:14:09 -0700511 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000512}
513
Erik Språng61be2a42015-04-27 13:32:52 +0200514void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700515 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700516 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000517}
518
danilchap56036ff2016-03-22 11:14:09 -0700519std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100520 const RtcpContext& ctx) {
521 if (ctx.feedback_state_.module == nullptr)
522 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200523 // Before sending the TMMBR check the received TMMBN, only an owner is
524 // allowed to raise the bitrate:
525 // * If the sender is an owner of the TMMBN -> send TMMBR
526 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000527
Erik Språng61be2a42015-04-27 13:32:52 +0200528 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700529 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000530
Erik Språng242e22b2015-05-11 10:17:43 +0200531 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
532 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200533 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700534 std::vector<rtcp::TmmbItem> candidates =
535 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000536
danilchap2b616392016-08-18 06:17:42 -0700537 if (!candidates.empty()) {
538 for (const auto& candidate : candidates) {
539 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
540 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100541 // Do not send the same tuple.
542 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200543 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 }
danilchap2b616392016-08-18 06:17:42 -0700545 if (!tmmbr_owner) {
546 // Use received bounding set as candidate set.
547 // Add current tuple.
548 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000549
danilchap2b616392016-08-18 06:17:42 -0700550 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700551 std::vector<rtcp::TmmbItem> bounding =
552 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700553 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
554 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100555 // Did not enter bounding set, no meaning to send this request.
556 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200557 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000558 }
Erik Språng61be2a42015-04-27 13:32:52 +0200559 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000560
danilchap2b616392016-08-18 06:17:42 -0700561 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100562 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700563
Erik Språngf7c57762015-12-04 10:40:35 +0100564 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700565 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800566 rtcp::TmmbItem request;
567 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700568 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800569 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700570 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100571
danilchap56036ff2016-03-22 11:14:09 -0700572 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200573}
574
danilchap56036ff2016-03-22 11:14:09 -0700575std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100576 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100577 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700578 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700579 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
580 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700581 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000582 }
Erik Språng61be2a42015-04-27 13:32:52 +0200583 }
sprangd83df502015-08-27 01:05:08 -0700584
danilchap56036ff2016-03-22 11:14:09 -0700585 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000586}
587
danilchap56036ff2016-03-22 11:14:09 -0700588std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100589 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700590 app->SetSsrc(ssrc_);
591 app->SetSubType(app_sub_type_);
592 app->SetName(app_name_);
593 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200594
danilchap56036ff2016-03-22 11:14:09 -0700595 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200596}
597
danilchap56036ff2016-03-22 11:14:09 -0700598std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100599 const RtcpContext& ctx) {
600 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700601 nack->SetSenderSsrc(ssrc_);
602 nack->SetMediaSsrc(remote_ssrc_);
603 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200604
605 // Report stats.
606 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100607 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
608 stringBuilder.PushNACK(ctx.nack_list_[idx]);
609 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200610 }
Erik Språng61be2a42015-04-27 13:32:52 +0200611 packet_type_counter_.nack_requests = nack_stats_.requests();
612 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200613
614 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
615 "RTCPSender::NACK", "nacks",
616 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
617 ++packet_type_counter_.nack_packets;
618 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
619 ssrc_, packet_type_counter_.nack_packets);
620
danilchap56036ff2016-03-22 11:14:09 -0700621 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200622}
623
danilchap56036ff2016-03-22 11:14:09 -0700624std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100625 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700626 bye->SetSenderSsrc(ssrc_);
627 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700628
danilchap56036ff2016-03-22 11:14:09 -0700629 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000630}
631
sprang5e38c962016-12-01 05:18:09 -0800632std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100633 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800634 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700635 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000636
sprang5e38c962016-12-01 05:18:09 -0800637 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
638 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800639 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800640 xr->SetRrtr(rrtr);
641 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000642
sprang5e38c962016-12-01 05:18:09 -0800643 if (ctx.feedback_state_.has_last_xr_rr) {
644 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
645 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000646
sprang5e38c962016-12-01 05:18:09 -0800647 if (video_bitrate_allocation_) {
648 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000649
sprang5e38c962016-12-01 05:18:09 -0800650 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
651 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100652 if (video_bitrate_allocation_->HasBitrate(sl, tl)) {
653 target_bitrate.AddTargetBitrate(
654 sl, tl, video_bitrate_allocation_->GetBitrate(sl, tl) / 1000);
655 }
sprang5e38c962016-12-01 05:18:09 -0800656 }
657 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000658
sprang5e38c962016-12-01 05:18:09 -0800659 xr->SetTargetBitrate(target_bitrate);
660 video_bitrate_allocation_.reset();
661 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200662
sprang5e38c962016-12-01 05:18:09 -0800663 if (xr_voip_metric_) {
664 rtcp::VoipMetric voip;
665 voip.SetMediaSsrc(remote_ssrc_);
666 voip.SetVoipMetric(*xr_voip_metric_);
667 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000668
sprang5e38c962016-12-01 05:18:09 -0800669 xr->SetVoipMetric(voip);
670 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200671
sprang5e38c962016-12-01 05:18:09 -0800672 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000673}
674
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000675int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200676 RTCPPacketType packetType,
677 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700678 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200679 return SendCompoundRTCP(
680 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700681 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200682}
683
684int32_t RTCPSender::SendCompoundRTCP(
685 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100686 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200687 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700688 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800689 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800690 size_t max_packet_size;
691
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000692 {
danilchap56036ff2016-03-22 11:14:09 -0700693 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700694 if (method_ == RtcpMode::kOff) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100695 RTC_LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
Erik Språng61be2a42015-04-27 13:32:52 +0200696 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000697 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200698 // Add all flags as volatile. Non volatile entries will not be overwritten.
699 // All new volatile flags added will be consumed by the end of this call.
700 SetFlags(packet_types, true);
701
702 // Prevent sending streams to send SR before any media has been sent.
703 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
704 if (!can_calculate_rtp_timestamp) {
705 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
706 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
707 bool sender_report = consumed_report_flag || consumed_sr_flag;
708 if (sender_report && AllVolatileFlagsConsumed()) {
709 // This call was for Sender Report and nothing else.
710 return 0;
711 }
712 if (sending_ && method_ == RtcpMode::kCompound) {
713 // Not allowed to send any RTCP packet without sender report.
714 return -1;
715 }
716 }
717
718 if (packet_type_counter_.first_packet_time_ms == -1)
719 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100720
721 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700722 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800723 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100724
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200725 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100726
danilchap56036ff2016-03-22 11:14:09 -0700727 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800728
Erik Språngf7c57762015-12-04 10:40:35 +0100729 auto it = report_flags_.begin();
730 while (it != report_flags_.end()) {
731 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800732 RTC_DCHECK(builder_it != builders_.end())
733 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100734 if (it->is_volatile) {
735 report_flags_.erase(it++);
736 } else {
737 ++it;
738 }
739
740 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700741 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100742 if (packet.get() == nullptr)
743 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800744 // If there is a BYE, don't append now - save it and append it
745 // at the end later.
746 if (builder_it->first == kRtcpBye) {
747 packet_bye = std::move(packet);
748 } else {
749 container.Append(packet.release());
750 }
751 }
752
753 // Append the BYE now at the end
754 if (packet_bye) {
755 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100756 }
757
758 if (packet_type_counter_observer_ != nullptr) {
759 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
760 remote_ssrc_, packet_type_counter_);
761 }
762
763 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800764 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000765 }
Erik Språng61be2a42015-04-27 13:32:52 +0200766
nisse6f142eb2017-02-21 07:32:47 -0800767 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100768 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000769}
770
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200771void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200772 bool generate_report;
773 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
774 // Report type already explicitly set, don't automatically populate.
775 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700776 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200777 } else {
778 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700779 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
780 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200781 if (generate_report)
782 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000783 }
784
Erik Språng0ea42d32015-06-25 14:46:16 +0200785 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200786 SetFlag(kRtcpSdes, true);
787
Erik Språng242e22b2015-05-11 10:17:43 +0200788 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800789 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
790 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
791 SetFlag(kRtcpAnyExtendedReports, true);
792 }
Erik Språng242e22b2015-05-11 10:17:43 +0200793
794 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800795 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000796
danilchap47a740b2015-12-15 00:30:07 -0800797 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200798 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200799 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
800 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
801 if (send_bitrate_kbit != 0)
802 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000803 }
Erik Språng61be2a42015-04-27 13:32:52 +0200804 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
805 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200806 }
danilchap47a740b2015-12-15 00:30:07 -0800807 // The interval between RTCP packets is varied randomly over the
808 // range [1/2,3/2] times the calculated interval.
809 uint32_t timeToNext =
810 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200811 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000812
danilchap96b69bd2017-07-25 09:15:14 -0700813 // RtcpSender expected to be used for sending either just sender reports
814 // or just receiver reports.
815 RTC_DCHECK(!(IsFlagPresent(kRtcpSr) && IsFlagPresent(kRtcpRr)));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000816 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000817}
818
danilchap96b69bd2017-07-25 09:15:14 -0700819std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
820 const FeedbackState& feedback_state) {
821 std::vector<rtcp::ReportBlock> result;
822 if (!receive_statistics_)
823 return result;
danilchapa72e7342015-12-22 08:07:45 -0800824
danilchapf5f793c2017-07-27 04:44:18 -0700825 // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
826 // compound rtcp packet when single rtcp module is used for multiple media
827 // streams.
828 result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
danilchap96b69bd2017-07-25 09:15:14 -0700829
830 if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
831 (feedback_state.last_rr_ntp_frac != 0))) {
832 // Get our NTP as late as possible to avoid a race.
833 uint32_t now = CompactNtp(clock_->CurrentNtpTime());
834
835 uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
836 receive_time <<= 16;
837 receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
838
839 uint32_t delay_since_last_sr = now - receive_time;
840 // TODO(danilchap): Instead of setting same value on all report blocks,
841 // set only when media_ssrc match sender ssrc of the sender report
842 // remote times were taken from.
843 for (auto& report_block : result) {
844 report_block.SetLastSr(feedback_state.remote_sr);
845 report_block.SetDelayLastSr(delay_since_last_sr);
846 }
danilchapa72e7342015-12-22 08:07:45 -0800847 }
danilchap96b69bd2017-07-25 09:15:14 -0700848 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000849}
850
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000851void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800852 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700853 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000854 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000855}
856
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000857int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
858 uint32_t name,
859 const uint8_t* data,
860 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200861 if (length % 4 != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100862 RTC_LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
Erik Språng61be2a42015-04-27 13:32:52 +0200863 return -1;
864 }
danilchap56036ff2016-03-22 11:14:09 -0700865 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000866
Erik Språng242e22b2015-05-11 10:17:43 +0200867 SetFlag(kRtcpApp, true);
868 app_sub_type_ = subType;
869 app_name_ = name;
870 app_data_.reset(new uint8_t[length]);
871 app_length_ = length;
872 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200873 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000874}
875
spranga790d832016-12-02 07:29:44 -0800876// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200877int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700878 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800879 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000880
sprang5e38c962016-12-01 05:18:09 -0800881 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200882 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000883}
884
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000885void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700886 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200887 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000888}
889
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000890bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700891 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200892 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000893}
894
danilchap853ecb22016-08-22 08:26:15 -0700895void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700896 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700897 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700898 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000899}
Erik Språng61be2a42015-04-27 13:32:52 +0200900
sprang5e38c962016-12-01 05:18:09 -0800901void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
902 if (type & kRtcpAnyExtendedReports) {
903 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
904 } else {
905 report_flags_.insert(ReportFlag(type, is_volatile));
906 }
Erik Språng242e22b2015-05-11 10:17:43 +0200907}
908
909void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
910 bool is_volatile) {
911 for (RTCPPacketType type : types)
912 SetFlag(type, is_volatile);
913}
914
sprang5e38c962016-12-01 05:18:09 -0800915bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200916 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
917}
918
sprang5e38c962016-12-01 05:18:09 -0800919bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200920 auto it = report_flags_.find(ReportFlag(type, false));
921 if (it == report_flags_.end())
922 return false;
923 if (it->is_volatile || forced)
924 report_flags_.erase((it));
925 return true;
926}
927
928bool RTCPSender::AllVolatileFlagsConsumed() const {
929 for (const ReportFlag& flag : report_flags_) {
930 if (flag.is_volatile)
931 return false;
932 }
933 return true;
934}
935
sprang5e38c962016-12-01 05:18:09 -0800936void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
937 rtc::CritScope lock(&critical_section_rtcp_sender_);
938 video_bitrate_allocation_.emplace(bitrate);
939 SetFlag(kRtcpAnyExtendedReports, true);
940}
941
sprang233bd872015-09-08 13:25:16 -0700942bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
nisse6f142eb2017-02-21 07:32:47 -0800943 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800944 {
945 rtc::CritScope lock(&critical_section_rtcp_sender_);
946 if (method_ == RtcpMode::kOff)
947 return false;
nisse6f142eb2017-02-21 07:32:47 -0800948 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -0800949 }
950
nisse6f142eb2017-02-21 07:32:47 -0800951 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
Danil Chapovalov5c3cc412017-12-07 10:15:53 +0100952 bool send_failure = false;
953 auto callback = [&](rtc::ArrayView<const uint8_t> packet) {
954 if (transport_->SendRtcp(packet.data(), packet.size())) {
955 if (event_log_)
956 event_log_->Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(packet));
957 } else {
958 send_failure = true;
959 }
960 };
961 return packet.Build(max_packet_size, callback) && !send_failure;
sprang233bd872015-09-08 13:25:16 -0700962}
963
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000964} // namespace webrtc