blob: 776e5bb62069e5eaa11d9657cfaaa94818a740f1 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
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
Erik Språng61be2a42015-04-27 13:32:52 +020017#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070018#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010019#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070020#include "webrtc/base/trace_event.h"
ossuf515ab82016-12-07 04:52:58 -080021#include "webrtc/call/call.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/common_types.h"
skvladcc91d282016-10-03 18:31:22 -070023#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
danilchap0219c9b2015-11-18 05:56:53 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov2c132972016-01-15 15:21:21 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/rpsi.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchap92e677a2016-01-12 10:04:52 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sli.h"
danilchapef3d8052016-01-11 03:31:08 -080037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080038#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070039#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070040#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap42287842017-02-20 06:40:18 -080041#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070042#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000043
niklase@google.com470e71d2011-07-07 08:21:25 +000044namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000045
sprang5e38c962016-12-01 05:18:09 -080046namespace {
47const uint32_t kRtcpAnyExtendedReports =
48 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
49 kRtcpXrTargetBitrate;
50} // namespace
51
Erik Språng61be2a42015-04-27 13:32:52 +020052NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080053 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000054
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000055NACKStringBuilder::~NACKStringBuilder() {}
56
danilchap162abd32015-12-10 02:39:40 -080057void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020058 if (count_ == 0) {
59 stream_ << nack;
60 } else if (nack == prevNack_ + 1) {
61 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020062 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020063 if (consecutive_) {
64 stream_ << "-" << prevNack_;
65 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020068 }
Erik Språng242e22b2015-05-11 10:17:43 +020069 count_++;
70 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000071}
72
Erik Språng61be2a42015-04-27 13:32:52 +020073std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020074 if (consecutive_) {
75 stream_ << "-" << prevNack_;
76 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020077 }
Erik Språng242e22b2015-05-11 10:17:43 +020078 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000079}
80
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000081RTCPSender::FeedbackState::FeedbackState()
82 : send_payload_type(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000083 packets_sent(0),
84 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000085 send_bitrate(0),
86 last_rr_ntp_secs(0),
87 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000088 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020089 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080090 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000091
danilchap2f7dea12016-01-13 02:03:04 -080092class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010093 public rtcp::RtcpPacket::PacketReadyCallback {
94 public:
terelius429c3452016-01-21 05:42:04 -080095 PacketContainer(Transport* transport, RtcEventLog* event_log)
96 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010097 virtual ~PacketContainer() {
98 for (RtcpPacket* packet : appended_packets_)
99 delete packet;
100 }
101
102 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800103 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100104 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800105 if (event_log_) {
106 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
107 length);
108 }
109 }
Erik Språngf7c57762015-12-04 10:40:35 +0100110 }
111
danilchap41befce2016-03-30 11:11:51 -0700112 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800113 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700114 uint8_t buffer[IP_PACKET_SIZE];
115 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100116 return bytes_sent_;
117 }
118
119 private:
120 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800121 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100122 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800123
124 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100125};
126
127class RTCPSender::RtcpContext {
128 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200129 RtcpContext(const FeedbackState& feedback_state,
130 int32_t nack_size,
131 const uint16_t* nack_list,
Erik Språng242e22b2015-05-11 10:17:43 +0200132 uint64_t picture_id,
danilchap51813b32016-12-16 02:44:36 -0800133 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100134 : feedback_state_(feedback_state),
135 nack_size_(nack_size),
136 nack_list_(nack_list),
Erik Språngf7c57762015-12-04 10:40:35 +0100137 picture_id_(picture_id),
danilchap51813b32016-12-16 02:44:36 -0800138 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200139
Erik Språngf7c57762015-12-04 10:40:35 +0100140 const FeedbackState& feedback_state_;
141 const int32_t nack_size_;
142 const uint16_t* nack_list_;
Erik Språngf7c57762015-12-04 10:40:35 +0100143 const uint64_t picture_id_;
danilchap51813b32016-12-16 02:44:36 -0800144 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200145};
146
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000147RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000148 bool audio,
149 Clock* clock,
150 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700151 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800152 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700153 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200154 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800156 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700157 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800158 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700159 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 using_nack_(false),
161 sending_(false),
162 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200163 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700164 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000165 last_rtp_timestamp_(0),
166 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200167 ssrc_(0),
168 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000169 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000174
danilchap2b616392016-08-18 06:17:42 -0700175 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200176 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800177 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200180 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200181 app_data_(nullptr),
182 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000183
Erik Språng242e22b2015-05-11 10:17:43 +0200184 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000185 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700186 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200187
188 builders_[kRtcpSr] = &RTCPSender::BuildSR;
189 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200190 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200191 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
192 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
193 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
194 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
195 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
196 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
197 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
198 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
199 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
200 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800201 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
danilchap162abd32015-12-10 02:39:40 -0800204RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000205
pbosda903ea2015-10-02 02:36:56 -0700206RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700207 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200208 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000209}
210
skvlad1c392cc2016-04-01 14:46:44 -0700211void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700212 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000213
skvlad1c392cc2016-04-01 14:46:44 -0700214 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
215 // When switching on, reschedule the next packet
216 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200217 clock_->TimeInMilliseconds() +
218 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700219 }
220 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221}
222
Erik Språng61be2a42015-04-27 13:32:52 +0200223bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700224 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200225 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000226}
227
Erik Språng61be2a42015-04-27 13:32:52 +0200228int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
229 bool sending) {
230 bool sendRTCPBye = false;
231 {
danilchap56036ff2016-03-22 11:14:09 -0700232 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000233
pbosda903ea2015-10-02 02:36:56 -0700234 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200235 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200236 // Trigger RTCP bye
237 sendRTCPBye = true;
238 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000239 }
Erik Språng242e22b2015-05-11 10:17:43 +0200240 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200241 }
242 if (sendRTCPBye)
243 return SendRTCP(feedback_state, kRtcpBye);
244 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000245}
246
Erik Språng61be2a42015-04-27 13:32:52 +0200247bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700248 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200249 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700253 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200254 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000255}
256
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257void RTCPSender::SetREMBData(uint32_t bitrate,
258 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700259 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200260 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000262
Erik Språng242e22b2015-05-11 10:17:43 +0200263 if (remb_enabled_)
264 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000265 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
266 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200267 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000268}
269
Erik Språng61be2a42015-04-27 13:32:52 +0200270bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700271 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200272 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000273}
274
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000275void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700276 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200277 if (enable) {
278 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
279 } else {
280 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
281 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000282}
283
nisse284542b2017-01-10 08:58:32 -0800284void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
285 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700286}
287
danilchap71fead22016-08-18 02:01:49 -0700288void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700289 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700290 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291}
292
293void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
294 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700295 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 last_rtp_timestamp_ = rtp_timestamp;
297 if (capture_time_ms < 0) {
298 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200299 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000300 } else {
301 last_frame_capture_time_ms_ = capture_time_ms;
302 }
303}
304
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000305void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700306 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000307
Erik Språng242e22b2015-05-11 10:17:43 +0200308 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200309 // not first SetSSRC, probably due to a collision
310 // schedule a new RTCP report
311 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200312 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200313 }
Erik Språng242e22b2015-05-11 10:17:43 +0200314 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Erik Språng61be2a42015-04-27 13:32:52 +0200317void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700318 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200319 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320}
321
Peter Boström9ba52f82015-06-01 14:12:28 +0200322int32_t RTCPSender::SetCNAME(const char* c_name) {
323 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000324 return -1;
325
kwiberg352444f2016-11-28 15:58:53 -0800326 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700327 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200328 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000329 return 0;
330}
331
Erik Språng0ea42d32015-06-25 14:46:16 +0200332int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700333 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800334 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700335 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200336 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000337 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200338
339 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return 0;
341}
342
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000343int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700344 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200345 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346
Erik Språng242e22b2015-05-11 10:17:43 +0200347 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000348 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200349
Erik Språng242e22b2015-05-11 10:17:43 +0200350 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000352}
353
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000354bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800355 /*
356 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000357
danilchap162abd32015-12-10 02:39:40 -0800358 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
359 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
360 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
362
danilchap162abd32015-12-10 02:39:40 -0800363 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
danilchap162abd32015-12-10 02:39:40 -0800365 MAX RTCP BW is 5% if the session BW
366 A send report is approximately 65 bytes inc CNAME
367 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 The RECOMMENDED value for the reduced minimum in seconds is 360
370 divided by the session bandwidth in kilobits/second. This minimum
371 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 If the participant has not yet sent an RTCP packet (the variable
374 initial is true), the constant Tmin is set to 2.5 seconds, else it
375 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 The interval between RTCP packets is varied randomly over the
378 range [0.5,1.5] times the calculated interval to avoid unintended
379 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 if we send
382 If the participant is a sender (we_sent true), the constant C is
383 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
384 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
385 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
danilchap162abd32015-12-10 02:39:40 -0800387 if we receive only
388 If we_sent is not true, the constant C is set
389 to the average RTCP packet size divided by 75% of the RTCP
390 bandwidth. The constant n is set to the number of receivers
391 (members - senders). If the number of senders is greater than
392 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000393
danilchap162abd32015-12-10 02:39:40 -0800394 reconsideration NOT required for peer-to-peer
395 "timer reconsideration" is
396 employed. This algorithm implements a simple back-off mechanism
397 which causes users to hold back RTCP packet transmission if the
398 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 n = number of members
401 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 4. The calculated interval T is set to a number uniformly distributed
406 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap162abd32015-12-10 02:39:40 -0800408 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
409 for the fact that the timer reconsideration algorithm converges to
410 a value of the RTCP bandwidth below the intended average
411 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
Erik Språng242e22b2015-05-11 10:17:43 +0200413 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000414
danilchap56036ff2016-03-22 11:14:09 -0700415 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000416
pbosda903ea2015-10-02 02:36:56 -0700417 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000418 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000419
Erik Språng242e22b2015-05-11 10:17:43 +0200420 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200421 // for video key-frames we want to send the RTCP before the large key-frame
422 // if we have a 100 ms margin
423 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
424 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000425
Erik Språng242e22b2015-05-11 10:17:43 +0200426 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200427 return true;
428 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200429 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200430 // wrap
431 return true;
432 }
433 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000434}
435
danilchap56036ff2016-03-22 11:14:09 -0700436std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200437 // Timestamp shouldn't be estimated before first media frame.
438 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200439 // The timestamp of this RTCP packet should be estimated as the timestamp of
440 // the frame being captured at this moment. We are calculating that
441 // timestamp as the last frame's timestamp + the time since the last frame
442 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700443 uint32_t rtp_rate =
444 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200445 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700446 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700447 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000448
Erik Språngf7c57762015-12-04 10:40:35 +0100449 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700450 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800451 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700452 report->SetRtpTimestamp(rtp_timestamp);
453 report->SetPacketCount(ctx.feedback_state_.packets_sent);
454 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200456 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700457 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200459 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100460
danilchap56036ff2016-03-22 11:14:09 -0700461 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462}
463
danilchap56036ff2016-03-22 11:14:09 -0700464std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100465 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200466 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800467 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000468
Erik Språngf7c57762015-12-04 10:40:35 +0100469 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700470 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200471
472 for (const auto it : csrc_cnames_)
danilchap822a16f2016-09-27 09:27:47 -0700473 sdes->AddCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200474
danilchap56036ff2016-03-22 11:14:09 -0700475 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000476}
477
danilchap56036ff2016-03-22 11:14:09 -0700478std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100479 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700480 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200481 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700482 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200483
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200484 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700485 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000486}
487
danilchap56036ff2016-03-22 11:14:09 -0700488std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100489 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700490 pli->SetSenderSsrc(ssrc_);
491 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200492
Erik Språng242e22b2015-05-11 10:17:43 +0200493 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
494 "RTCPSender::PLI");
495 ++packet_type_counter_.pli_packets;
496 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
497 ssrc_, packet_type_counter_.pli_packets);
498
danilchap56036ff2016-03-22 11:14:09 -0700499 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200500}
501
danilchap56036ff2016-03-22 11:14:09 -0700502std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800503 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngf7c57762015-12-04 10:40:35 +0100505 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700506 fir->SetSenderSsrc(ssrc_);
507 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200508
509 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
510 "RTCPSender::FIR");
511 ++packet_type_counter_.fir_packets;
512 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
513 ssrc_, packet_type_counter_.fir_packets);
514
danilchap56036ff2016-03-22 11:14:09 -0700515 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000516}
517
518/*
519 0 1 2 3
520 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
521 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522 | First | Number | PictureID |
523 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
524*/
danilchap56036ff2016-03-22 11:14:09 -0700525std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100526 rtcp::Sli* sli = new rtcp::Sli();
danilchap822a16f2016-09-27 09:27:47 -0700527 sli->SetSenderSsrc(ssrc_);
528 sli->SetMediaSsrc(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700529 // Crop picture id to 6 least significant bits.
danilchap822a16f2016-09-27 09:27:47 -0700530 sli->AddPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700531
danilchap56036ff2016-03-22 11:14:09 -0700532 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000533}
534
535/*
536 0 1 2 3
537 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
538 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
539 | PB |0| Payload Type| Native RPSI bit string |
540 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
541 | defined per codec ... | Padding (0) |
542 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
543*/
544/*
545* Note: not generic made for VP8
546*/
danilchap56036ff2016-03-22 11:14:09 -0700547std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100548 const RtcpContext& ctx) {
549 if (ctx.feedback_state_.send_payload_type == 0xFF)
550 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200551
Erik Språngf7c57762015-12-04 10:40:35 +0100552 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
danilchap822a16f2016-09-27 09:27:47 -0700553 rpsi->SetSenderSsrc(ssrc_);
554 rpsi->SetMediaSsrc(remote_ssrc_);
555 rpsi->SetPayloadType(ctx.feedback_state_.send_payload_type);
556 rpsi->SetPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700557
danilchap56036ff2016-03-22 11:14:09 -0700558 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000559}
560
danilchap56036ff2016-03-22 11:14:09 -0700561std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100562 const RtcpContext& ctx) {
563 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700564 remb->SetSenderSsrc(ssrc_);
565 remb->SetBitrateBps(remb_bitrate_);
566 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200567
Erik Språng242e22b2015-05-11 10:17:43 +0200568 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
569 "RTCPSender::REMB");
570
danilchap56036ff2016-03-22 11:14:09 -0700571 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000572}
573
Erik Språng61be2a42015-04-27 13:32:52 +0200574void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700575 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700576 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000577}
578
danilchap56036ff2016-03-22 11:14:09 -0700579std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100580 const RtcpContext& ctx) {
581 if (ctx.feedback_state_.module == nullptr)
582 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200583 // Before sending the TMMBR check the received TMMBN, only an owner is
584 // allowed to raise the bitrate:
585 // * If the sender is an owner of the TMMBN -> send TMMBR
586 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000587
Erik Språng61be2a42015-04-27 13:32:52 +0200588 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700589 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000590
Erik Språng242e22b2015-05-11 10:17:43 +0200591 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
592 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200593 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700594 std::vector<rtcp::TmmbItem> candidates =
595 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000596
danilchap2b616392016-08-18 06:17:42 -0700597 if (!candidates.empty()) {
598 for (const auto& candidate : candidates) {
599 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
600 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100601 // Do not send the same tuple.
602 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200603 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000604 }
danilchap2b616392016-08-18 06:17:42 -0700605 if (!tmmbr_owner) {
606 // Use received bounding set as candidate set.
607 // Add current tuple.
608 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000609
danilchap2b616392016-08-18 06:17:42 -0700610 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700611 std::vector<rtcp::TmmbItem> bounding =
612 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700613 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
614 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100615 // Did not enter bounding set, no meaning to send this request.
616 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200617 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000618 }
Erik Språng61be2a42015-04-27 13:32:52 +0200619 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000620
danilchap2b616392016-08-18 06:17:42 -0700621 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100622 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700623
Erik Språngf7c57762015-12-04 10:40:35 +0100624 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700625 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800626 rtcp::TmmbItem request;
627 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700628 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800629 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700630 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100631
danilchap56036ff2016-03-22 11:14:09 -0700632 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200633}
634
danilchap56036ff2016-03-22 11:14:09 -0700635std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100636 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100637 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700638 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700639 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
640 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700641 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000642 }
Erik Språng61be2a42015-04-27 13:32:52 +0200643 }
sprangd83df502015-08-27 01:05:08 -0700644
danilchap56036ff2016-03-22 11:14:09 -0700645 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000646}
647
danilchap56036ff2016-03-22 11:14:09 -0700648std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100649 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700650 app->SetSsrc(ssrc_);
651 app->SetSubType(app_sub_type_);
652 app->SetName(app_name_);
653 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200654
danilchap56036ff2016-03-22 11:14:09 -0700655 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200656}
657
danilchap56036ff2016-03-22 11:14:09 -0700658std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100659 const RtcpContext& ctx) {
660 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700661 nack->SetSenderSsrc(ssrc_);
662 nack->SetMediaSsrc(remote_ssrc_);
663 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200664
665 // Report stats.
666 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100667 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
668 stringBuilder.PushNACK(ctx.nack_list_[idx]);
669 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200670 }
Erik Språng61be2a42015-04-27 13:32:52 +0200671 packet_type_counter_.nack_requests = nack_stats_.requests();
672 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200673
674 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
675 "RTCPSender::NACK", "nacks",
676 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
677 ++packet_type_counter_.nack_packets;
678 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
679 ssrc_, packet_type_counter_.nack_packets);
680
danilchap56036ff2016-03-22 11:14:09 -0700681 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200682}
683
danilchap56036ff2016-03-22 11:14:09 -0700684std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100685 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700686 bye->SetSenderSsrc(ssrc_);
687 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700688
danilchap56036ff2016-03-22 11:14:09 -0700689 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000690}
691
sprang5e38c962016-12-01 05:18:09 -0800692std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100693 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800694 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700695 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000696
sprang5e38c962016-12-01 05:18:09 -0800697 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
698 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800699 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800700 xr->SetRrtr(rrtr);
701 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000702
sprang5e38c962016-12-01 05:18:09 -0800703 if (ctx.feedback_state_.has_last_xr_rr) {
704 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
705 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000706
sprang5e38c962016-12-01 05:18:09 -0800707 if (video_bitrate_allocation_) {
708 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000709
sprang5e38c962016-12-01 05:18:09 -0800710 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
711 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
712 uint32_t layer_bitrate_bps =
713 video_bitrate_allocation_->GetBitrate(sl, tl);
714 if (layer_bitrate_bps > 0)
715 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
716 }
717 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000718
sprang5e38c962016-12-01 05:18:09 -0800719 xr->SetTargetBitrate(target_bitrate);
720 video_bitrate_allocation_.reset();
721 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200722
sprang5e38c962016-12-01 05:18:09 -0800723 if (xr_voip_metric_) {
724 rtcp::VoipMetric voip;
725 voip.SetMediaSsrc(remote_ssrc_);
726 voip.SetVoipMetric(*xr_voip_metric_);
727 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000728
sprang5e38c962016-12-01 05:18:09 -0800729 xr->SetVoipMetric(voip);
730 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200731
sprang5e38c962016-12-01 05:18:09 -0800732 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000733}
734
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000735int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200736 RTCPPacketType packetType,
737 int32_t nack_size,
738 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000739 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200740 return SendCompoundRTCP(
741 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
danilchap498ee8e2017-02-08 05:24:31 -0800742 nack_size, nack_list, pictureID);
Erik Språng242e22b2015-05-11 10:17:43 +0200743}
744
745int32_t RTCPSender::SendCompoundRTCP(
746 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100747 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200748 int32_t nack_size,
749 const uint16_t* nack_list,
Erik Språng242e22b2015-05-11 10:17:43 +0200750 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800751 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000752 {
danilchap56036ff2016-03-22 11:14:09 -0700753 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700754 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200755 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
756 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000757 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200758 // Add all flags as volatile. Non volatile entries will not be overwritten.
759 // All new volatile flags added will be consumed by the end of this call.
760 SetFlags(packet_types, true);
761
762 // Prevent sending streams to send SR before any media has been sent.
763 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
764 if (!can_calculate_rtp_timestamp) {
765 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
766 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
767 bool sender_report = consumed_report_flag || consumed_sr_flag;
768 if (sender_report && AllVolatileFlagsConsumed()) {
769 // This call was for Sender Report and nothing else.
770 return 0;
771 }
772 if (sending_ && method_ == RtcpMode::kCompound) {
773 // Not allowed to send any RTCP packet without sender report.
774 return -1;
775 }
776 }
777
778 if (packet_type_counter_.first_packet_time_ms == -1)
779 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100780
781 // We need to send our NTP even if we haven't received any reports.
danilchap498ee8e2017-02-08 05:24:31 -0800782 RtcpContext context(feedback_state, nack_size, nack_list, pictureID,
danilchap37953762017-02-09 11:15:25 -0800783 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100784
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200785 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100786
danilchap56036ff2016-03-22 11:14:09 -0700787 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800788
Erik Språngf7c57762015-12-04 10:40:35 +0100789 auto it = report_flags_.begin();
790 while (it != report_flags_.end()) {
791 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800792 RTC_DCHECK(builder_it != builders_.end())
793 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100794 if (it->is_volatile) {
795 report_flags_.erase(it++);
796 } else {
797 ++it;
798 }
799
800 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700801 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100802 if (packet.get() == nullptr)
803 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800804 // If there is a BYE, don't append now - save it and append it
805 // at the end later.
806 if (builder_it->first == kRtcpBye) {
807 packet_bye = std::move(packet);
808 } else {
809 container.Append(packet.release());
810 }
811 }
812
813 // Append the BYE now at the end
814 if (packet_bye) {
815 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100816 }
817
818 if (packet_type_counter_observer_ != nullptr) {
819 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
820 remote_ssrc_, packet_type_counter_);
821 }
822
823 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000824 }
Erik Språng61be2a42015-04-27 13:32:52 +0200825
nisse284542b2017-01-10 08:58:32 -0800826 size_t bytes_sent = container.SendPackets(max_packet_size_);
Erik Språngf7c57762015-12-04 10:40:35 +0100827 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000828}
829
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200830void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200831 bool generate_report;
832 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
833 // Report type already explicitly set, don't automatically populate.
834 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700835 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200836 } else {
837 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700838 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
839 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200840 if (generate_report)
841 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000842 }
843
Erik Språng0ea42d32015-06-25 14:46:16 +0200844 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200845 SetFlag(kRtcpSdes, true);
846
Erik Språng242e22b2015-05-11 10:17:43 +0200847 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800848 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
849 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
850 SetFlag(kRtcpAnyExtendedReports, true);
851 }
Erik Språng242e22b2015-05-11 10:17:43 +0200852
853 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800854 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000855
danilchap47a740b2015-12-15 00:30:07 -0800856 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200857 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200858 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
859 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
860 if (send_bitrate_kbit != 0)
861 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000862 }
Erik Språng61be2a42015-04-27 13:32:52 +0200863 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
864 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200865 }
danilchap47a740b2015-12-15 00:30:07 -0800866 // The interval between RTCP packets is varied randomly over the
867 // range [1/2,3/2] times the calculated interval.
868 uint32_t timeToNext =
869 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200870 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000871
Per83d09102016-04-15 14:59:13 +0200872 if (receive_statistics_) {
873 StatisticianMap statisticians =
874 receive_statistics_->GetActiveStatisticians();
875 RTC_DCHECK(report_blocks_.empty());
876 for (auto& it : statisticians) {
877 AddReportBlock(feedback_state, it.first, it.second);
878 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879 }
880 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000881}
882
danilchapa72e7342015-12-22 08:07:45 -0800883bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
884 uint32_t ssrc,
885 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000887 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000888 if (!statistician->GetStatistics(&stats, true))
889 return false;
danilchapa72e7342015-12-22 08:07:45 -0800890
891 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
892 LOG(LS_WARNING) << "Too many report blocks.";
893 return false;
894 }
895 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
896 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700897 block->SetMediaSsrc(ssrc);
898 block->SetFractionLost(stats.fraction_lost);
899 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800900 report_blocks_.erase(ssrc);
901 LOG(LS_WARNING) << "Cumulative lost is oversized.";
902 return false;
903 }
danilchap822a16f2016-09-27 09:27:47 -0700904 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
905 block->SetJitter(stats.jitter);
906 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000907
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200908 // TODO(sprang): Do we really need separate time stamps for each report?
909 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800910 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000911
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200912 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000913 if ((feedback_state.last_rr_ntp_secs != 0) ||
914 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200915 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800916 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000917
Erik Språng61be2a42015-04-27 13:32:52 +0200918 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
919 receiveTime <<= 16;
920 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000921
danilchap822a16f2016-09-27 09:27:47 -0700922 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000923 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000924 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000925}
926
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000927void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800928 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700929 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000930 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000931}
932
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000933int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
934 uint32_t name,
935 const uint8_t* data,
936 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200937 if (length % 4 != 0) {
938 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
939 return -1;
940 }
danilchap56036ff2016-03-22 11:14:09 -0700941 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000942
Erik Språng242e22b2015-05-11 10:17:43 +0200943 SetFlag(kRtcpApp, true);
944 app_sub_type_ = subType;
945 app_name_ = name;
946 app_data_.reset(new uint8_t[length]);
947 app_length_ = length;
948 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200949 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000950}
951
spranga790d832016-12-02 07:29:44 -0800952// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200953int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700954 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800955 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
sprang5e38c962016-12-01 05:18:09 -0800957 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200958 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000959}
960
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000961void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700962 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200963 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000964}
965
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000966bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700967 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200968 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000969}
970
danilchap853ecb22016-08-22 08:26:15 -0700971void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700972 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700973 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700974 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000975}
Erik Språng61be2a42015-04-27 13:32:52 +0200976
sprang5e38c962016-12-01 05:18:09 -0800977void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
978 if (type & kRtcpAnyExtendedReports) {
979 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
980 } else {
981 report_flags_.insert(ReportFlag(type, is_volatile));
982 }
Erik Språng242e22b2015-05-11 10:17:43 +0200983}
984
985void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
986 bool is_volatile) {
987 for (RTCPPacketType type : types)
988 SetFlag(type, is_volatile);
989}
990
sprang5e38c962016-12-01 05:18:09 -0800991bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200992 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
993}
994
sprang5e38c962016-12-01 05:18:09 -0800995bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200996 auto it = report_flags_.find(ReportFlag(type, false));
997 if (it == report_flags_.end())
998 return false;
999 if (it->is_volatile || forced)
1000 report_flags_.erase((it));
1001 return true;
1002}
1003
1004bool RTCPSender::AllVolatileFlagsConsumed() const {
1005 for (const ReportFlag& flag : report_flags_) {
1006 if (flag.is_volatile)
1007 return false;
1008 }
1009 return true;
1010}
1011
sprang5e38c962016-12-01 05:18:09 -08001012void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
1013 rtc::CritScope lock(&critical_section_rtcp_sender_);
1014 video_bitrate_allocation_.emplace(bitrate);
1015 SetFlag(kRtcpAnyExtendedReports, true);
1016}
1017
sprang233bd872015-09-08 13:25:16 -07001018bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001019 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1020 public:
terelius429c3452016-01-21 05:42:04 -08001021 Sender(Transport* transport, RtcEventLog* event_log)
1022 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001023
1024 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001025 if (transport_->SendRtcp(data, length)) {
1026 if (event_log_) {
1027 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1028 length);
1029 }
1030 } else {
sprang233bd872015-09-08 13:25:16 -07001031 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001032 }
sprang233bd872015-09-08 13:25:16 -07001033 }
1034
1035 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001036 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001037 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001038 // TODO(terelius): We would like to
1039 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1040 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1041 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001042
stefanb77c7162017-02-06 06:29:38 -08001043 {
1044 rtc::CritScope lock(&critical_section_rtcp_sender_);
1045 if (method_ == RtcpMode::kOff)
1046 return false;
1047 }
1048
nisse284542b2017-01-10 08:58:32 -08001049 RTC_DCHECK_LE(max_packet_size_, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001050 uint8_t buffer[IP_PACKET_SIZE];
nisse284542b2017-01-10 08:58:32 -08001051 return packet.BuildExternalBuffer(buffer, max_packet_size_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001052 !sender.send_failure_;
1053}
1054
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001055} // namespace webrtc