blob: ff535ea4c61499bd01b8aa0356ae5feeb3659f8a [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"
danilchap13deaad2016-05-24 13:25:27 -070041#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.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()
81 : send_payload_type(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000082 packets_sent(0),
83 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000084 send_bitrate(0),
85 last_rr_ntp_secs(0),
86 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000087 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020088 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080089 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000090
danilchap2f7dea12016-01-13 02:03:04 -080091class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010092 public rtcp::RtcpPacket::PacketReadyCallback {
93 public:
terelius429c3452016-01-21 05:42:04 -080094 PacketContainer(Transport* transport, RtcEventLog* event_log)
95 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010096 virtual ~PacketContainer() {
97 for (RtcpPacket* packet : appended_packets_)
98 delete packet;
99 }
100
101 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800102 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100103 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800104 if (event_log_) {
105 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
106 length);
107 }
108 }
Erik Språngf7c57762015-12-04 10:40:35 +0100109 }
110
danilchap41befce2016-03-30 11:11:51 -0700111 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800112 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700113 uint8_t buffer[IP_PACKET_SIZE];
114 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100115 return bytes_sent_;
116 }
117
118 private:
119 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800120 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100121 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800122
123 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100124};
125
126class RTCPSender::RtcpContext {
127 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200128 RtcpContext(const FeedbackState& feedback_state,
129 int32_t nack_size,
130 const uint16_t* nack_list,
131 bool repeat,
132 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),
137 repeat_(repeat),
138 picture_id_(picture_id),
danilchap51813b32016-12-16 02:44:36 -0800139 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200140
Erik Språngf7c57762015-12-04 10:40:35 +0100141 const FeedbackState& feedback_state_;
142 const int32_t nack_size_;
143 const uint16_t* nack_list_;
144 const bool repeat_;
145 const uint64_t picture_id_;
danilchap51813b32016-12-16 02:44:36 -0800146 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200147};
148
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000149RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000150 bool audio,
151 Clock* clock,
152 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700153 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800154 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700155 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200156 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800158 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700159 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800160 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700161 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200162 using_nack_(false),
163 sending_(false),
164 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200165 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700166 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000167 last_rtp_timestamp_(0),
168 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 ssrc_(0),
170 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000171 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000174
Erik Språng242e22b2015-05-11 10:17:43 +0200175 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000176
danilchap2b616392016-08-18 06:17:42 -0700177 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200178 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800179 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000180
Erik Språng242e22b2015-05-11 10:17:43 +0200181 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200182 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200183 app_data_(nullptr),
184 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000185
Erik Språng242e22b2015-05-11 10:17:43 +0200186 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000187 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700188 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200189
190 builders_[kRtcpSr] = &RTCPSender::BuildSR;
191 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200192 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200193 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
194 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
195 builders_[kRtcpSli] = &RTCPSender::BuildSLI;
196 builders_[kRtcpRpsi] = &RTCPSender::BuildRPSI;
197 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
198 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
199 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
200 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
201 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
202 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800203 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204}
205
danilchap162abd32015-12-10 02:39:40 -0800206RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000207
pbosda903ea2015-10-02 02:36:56 -0700208RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700209 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200210 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
skvlad1c392cc2016-04-01 14:46:44 -0700213void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700214 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000215
skvlad1c392cc2016-04-01 14:46:44 -0700216 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
217 // When switching on, reschedule the next packet
218 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200219 clock_->TimeInMilliseconds() +
220 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700221 }
222 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000223}
224
Erik Språng61be2a42015-04-27 13:32:52 +0200225bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700226 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200227 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000228}
229
Erik Språng61be2a42015-04-27 13:32:52 +0200230int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
231 bool sending) {
232 bool sendRTCPBye = false;
233 {
danilchap56036ff2016-03-22 11:14:09 -0700234 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000235
pbosda903ea2015-10-02 02:36:56 -0700236 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200237 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200238 // Trigger RTCP bye
239 sendRTCPBye = true;
240 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000241 }
Erik Språng242e22b2015-05-11 10:17:43 +0200242 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200243 }
244 if (sendRTCPBye)
245 return SendRTCP(feedback_state, kRtcpBye);
246 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000247}
248
Erik Språng61be2a42015-04-27 13:32:52 +0200249bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700250 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200251 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000252}
253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700255 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200256 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000257}
258
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259void RTCPSender::SetREMBData(uint32_t bitrate,
260 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700261 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200262 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000263 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000264
Erik Språng242e22b2015-05-11 10:17:43 +0200265 if (remb_enabled_)
266 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
268 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200269 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000270}
271
Erik Språng61be2a42015-04-27 13:32:52 +0200272bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700273 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200274 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000275}
276
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000277void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700278 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200279 if (enable) {
280 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
281 } else {
282 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
283 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000284}
285
nisse284542b2017-01-10 08:58:32 -0800286void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
287 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700288}
289
danilchap71fead22016-08-18 02:01:49 -0700290void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700291 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700292 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293}
294
295void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
296 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700297 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000298 last_rtp_timestamp_ = rtp_timestamp;
299 if (capture_time_ms < 0) {
300 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200301 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000302 } else {
303 last_frame_capture_time_ms_ = capture_time_ms;
304 }
305}
306
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000307void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700308 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000309
Erik Språng242e22b2015-05-11 10:17:43 +0200310 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200311 // not first SetSSRC, probably due to a collision
312 // schedule a new RTCP report
313 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200314 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200315 }
Erik Språng242e22b2015-05-11 10:17:43 +0200316 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000317}
318
Erik Språng61be2a42015-04-27 13:32:52 +0200319void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700320 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200321 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000322}
323
Peter Boström9ba52f82015-06-01 14:12:28 +0200324int32_t RTCPSender::SetCNAME(const char* c_name) {
325 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000326 return -1;
327
kwiberg352444f2016-11-28 15:58:53 -0800328 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700329 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200330 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000331 return 0;
332}
333
Erik Språng0ea42d32015-06-25 14:46:16 +0200334int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700335 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800336 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700337 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200338 if (csrc_cnames_.size() >= kRtpCsrcSize)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000339 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200340
341 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return 0;
343}
344
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000345int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700346 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200347 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000348
Erik Språng242e22b2015-05-11 10:17:43 +0200349 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000350 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200351
Erik Språng242e22b2015-05-11 10:17:43 +0200352 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000353 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000354}
355
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000356bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800357 /*
358 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000359
danilchap162abd32015-12-10 02:39:40 -0800360 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
361 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
362 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
364
danilchap162abd32015-12-10 02:39:40 -0800365 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
danilchap162abd32015-12-10 02:39:40 -0800367 MAX RTCP BW is 5% if the session BW
368 A send report is approximately 65 bytes inc CNAME
369 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 The RECOMMENDED value for the reduced minimum in seconds is 360
372 divided by the session bandwidth in kilobits/second. This minimum
373 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
danilchap162abd32015-12-10 02:39:40 -0800375 If the participant has not yet sent an RTCP packet (the variable
376 initial is true), the constant Tmin is set to 2.5 seconds, else it
377 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000378
danilchap162abd32015-12-10 02:39:40 -0800379 The interval between RTCP packets is varied randomly over the
380 range [0.5,1.5] times the calculated interval to avoid unintended
381 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 if we send
384 If the participant is a sender (we_sent true), the constant C is
385 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
386 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
387 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 if we receive only
390 If we_sent is not true, the constant C is set
391 to the average RTCP packet size divided by 75% of the RTCP
392 bandwidth. The constant n is set to the number of receivers
393 (members - senders). If the number of senders is greater than
394 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000395
danilchap162abd32015-12-10 02:39:40 -0800396 reconsideration NOT required for peer-to-peer
397 "timer reconsideration" is
398 employed. This algorithm implements a simple back-off mechanism
399 which causes users to hold back RTCP packet transmission if the
400 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000401
danilchap162abd32015-12-10 02:39:40 -0800402 n = number of members
403 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
danilchap162abd32015-12-10 02:39:40 -0800407 4. The calculated interval T is set to a number uniformly distributed
408 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
danilchap162abd32015-12-10 02:39:40 -0800410 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
411 for the fact that the timer reconsideration algorithm converges to
412 a value of the RTCP bandwidth below the intended average
413 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000416
danilchap56036ff2016-03-22 11:14:09 -0700417 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000418
pbosda903ea2015-10-02 02:36:56 -0700419 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000420 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
Erik Språng242e22b2015-05-11 10:17:43 +0200422 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200423 // for video key-frames we want to send the RTCP before the large key-frame
424 // if we have a 100 ms margin
425 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
426 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000427
Erik Språng242e22b2015-05-11 10:17:43 +0200428 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200429 return true;
430 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200431 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200432 // wrap
433 return true;
434 }
435 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000436}
437
danilchap56036ff2016-03-22 11:14:09 -0700438std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200439 // Timestamp shouldn't be estimated before first media frame.
440 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200441 // The timestamp of this RTCP packet should be estimated as the timestamp of
442 // the frame being captured at this moment. We are calculating that
443 // timestamp as the last frame's timestamp + the time since the last frame
444 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700445 uint32_t rtp_rate =
446 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200447 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700448 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700449 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000450
Erik Språngf7c57762015-12-04 10:40:35 +0100451 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700452 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800453 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700454 report->SetRtpTimestamp(rtp_timestamp);
455 report->SetPacketCount(ctx.feedback_state_.packets_sent);
456 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000457
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200458 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700459 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000460
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100462
danilchap56036ff2016-03-22 11:14:09 -0700463 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000464}
465
danilchap56036ff2016-03-22 11:14:09 -0700466std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100467 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200468 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800469 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
Erik Språngf7c57762015-12-04 10:40:35 +0100471 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700472 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200473
474 for (const auto it : csrc_cnames_)
danilchap822a16f2016-09-27 09:27:47 -0700475 sdes->AddCName(it.first, it.second);
Erik Språng0ea42d32015-06-25 14:46:16 +0200476
danilchap56036ff2016-03-22 11:14:09 -0700477 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478}
479
danilchap56036ff2016-03-22 11:14:09 -0700480std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100481 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700482 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200483 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700484 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200485
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200486 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700487 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000488}
489
danilchap56036ff2016-03-22 11:14:09 -0700490std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100491 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700492 pli->SetSenderSsrc(ssrc_);
493 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200494
Erik Språng242e22b2015-05-11 10:17:43 +0200495 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
496 "RTCPSender::PLI");
497 ++packet_type_counter_.pli_packets;
498 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
499 ssrc_, packet_type_counter_.pli_packets);
500
danilchap56036ff2016-03-22 11:14:09 -0700501 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200502}
503
danilchap56036ff2016-03-22 11:14:09 -0700504std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100505 if (!ctx.repeat_)
sprang62dae192015-08-05 02:35:35 -0700506 ++sequence_number_fir_; // Do not increase if repetition.
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngf7c57762015-12-04 10:40:35 +0100508 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700509 fir->SetSenderSsrc(ssrc_);
510 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200511
512 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
513 "RTCPSender::FIR");
514 ++packet_type_counter_.fir_packets;
515 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
516 ssrc_, packet_type_counter_.fir_packets);
517
danilchap56036ff2016-03-22 11:14:09 -0700518 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519}
520
521/*
522 0 1 2 3
523 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
524 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
525 | First | Number | PictureID |
526 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
527*/
danilchap56036ff2016-03-22 11:14:09 -0700528std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100529 rtcp::Sli* sli = new rtcp::Sli();
danilchap822a16f2016-09-27 09:27:47 -0700530 sli->SetSenderSsrc(ssrc_);
531 sli->SetMediaSsrc(remote_ssrc_);
sprang0365a272015-08-11 01:02:37 -0700532 // Crop picture id to 6 least significant bits.
danilchap822a16f2016-09-27 09:27:47 -0700533 sli->AddPictureId(ctx.picture_id_ & 0x3F);
sprang0365a272015-08-11 01:02:37 -0700534
danilchap56036ff2016-03-22 11:14:09 -0700535 return std::unique_ptr<rtcp::RtcpPacket>(sli);
niklase@google.com470e71d2011-07-07 08:21:25 +0000536}
537
538/*
539 0 1 2 3
540 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
541 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542 | PB |0| Payload Type| Native RPSI bit string |
543 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544 | defined per codec ... | Padding (0) |
545 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546*/
547/*
548* Note: not generic made for VP8
549*/
danilchap56036ff2016-03-22 11:14:09 -0700550std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRPSI(
Erik Språngf7c57762015-12-04 10:40:35 +0100551 const RtcpContext& ctx) {
552 if (ctx.feedback_state_.send_payload_type == 0xFF)
553 return nullptr;
Erik Språng242e22b2015-05-11 10:17:43 +0200554
Erik Språngf7c57762015-12-04 10:40:35 +0100555 rtcp::Rpsi* rpsi = new rtcp::Rpsi();
danilchap822a16f2016-09-27 09:27:47 -0700556 rpsi->SetSenderSsrc(ssrc_);
557 rpsi->SetMediaSsrc(remote_ssrc_);
558 rpsi->SetPayloadType(ctx.feedback_state_.send_payload_type);
559 rpsi->SetPictureId(ctx.picture_id_);
sprangcf7f54d2015-08-13 04:37:42 -0700560
danilchap56036ff2016-03-22 11:14:09 -0700561 return std::unique_ptr<rtcp::RtcpPacket>(rpsi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562}
563
danilchap56036ff2016-03-22 11:14:09 -0700564std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100565 const RtcpContext& ctx) {
566 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700567 remb->SetSenderSsrc(ssrc_);
568 remb->SetBitrateBps(remb_bitrate_);
569 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200570
Erik Språng242e22b2015-05-11 10:17:43 +0200571 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
572 "RTCPSender::REMB");
573
danilchap56036ff2016-03-22 11:14:09 -0700574 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000575}
576
Erik Språng61be2a42015-04-27 13:32:52 +0200577void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700578 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700579 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000580}
581
danilchap56036ff2016-03-22 11:14:09 -0700582std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100583 const RtcpContext& ctx) {
584 if (ctx.feedback_state_.module == nullptr)
585 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200586 // Before sending the TMMBR check the received TMMBN, only an owner is
587 // allowed to raise the bitrate:
588 // * If the sender is an owner of the TMMBN -> send TMMBR
589 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000590
Erik Språng61be2a42015-04-27 13:32:52 +0200591 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700592 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000593
Erik Språng242e22b2015-05-11 10:17:43 +0200594 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
595 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200596 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700597 std::vector<rtcp::TmmbItem> candidates =
598 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000599
danilchap2b616392016-08-18 06:17:42 -0700600 if (!candidates.empty()) {
601 for (const auto& candidate : candidates) {
602 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
603 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100604 // Do not send the same tuple.
605 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200606 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000607 }
danilchap2b616392016-08-18 06:17:42 -0700608 if (!tmmbr_owner) {
609 // Use received bounding set as candidate set.
610 // Add current tuple.
611 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000612
danilchap2b616392016-08-18 06:17:42 -0700613 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700614 std::vector<rtcp::TmmbItem> bounding =
615 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700616 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
617 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100618 // Did not enter bounding set, no meaning to send this request.
619 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200620 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000621 }
Erik Språng61be2a42015-04-27 13:32:52 +0200622 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000623
danilchap2b616392016-08-18 06:17:42 -0700624 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100625 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700626
Erik Språngf7c57762015-12-04 10:40:35 +0100627 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700628 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800629 rtcp::TmmbItem request;
630 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700631 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800632 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700633 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100634
danilchap56036ff2016-03-22 11:14:09 -0700635 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200636}
637
danilchap56036ff2016-03-22 11:14:09 -0700638std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100639 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100640 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700641 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700642 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
643 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700644 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000645 }
Erik Språng61be2a42015-04-27 13:32:52 +0200646 }
sprangd83df502015-08-27 01:05:08 -0700647
danilchap56036ff2016-03-22 11:14:09 -0700648 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000649}
650
danilchap56036ff2016-03-22 11:14:09 -0700651std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100652 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700653 app->SetSsrc(ssrc_);
654 app->SetSubType(app_sub_type_);
655 app->SetName(app_name_);
656 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200657
danilchap56036ff2016-03-22 11:14:09 -0700658 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200659}
660
danilchap56036ff2016-03-22 11:14:09 -0700661std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100662 const RtcpContext& ctx) {
663 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700664 nack->SetSenderSsrc(ssrc_);
665 nack->SetMediaSsrc(remote_ssrc_);
666 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200667
668 // Report stats.
669 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100670 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
671 stringBuilder.PushNACK(ctx.nack_list_[idx]);
672 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200673 }
Erik Språng61be2a42015-04-27 13:32:52 +0200674 packet_type_counter_.nack_requests = nack_stats_.requests();
675 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200676
677 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
678 "RTCPSender::NACK", "nacks",
679 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
680 ++packet_type_counter_.nack_packets;
681 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
682 ssrc_, packet_type_counter_.nack_packets);
683
danilchap56036ff2016-03-22 11:14:09 -0700684 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200685}
686
danilchap56036ff2016-03-22 11:14:09 -0700687std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100688 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700689 bye->SetSenderSsrc(ssrc_);
690 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700691
danilchap56036ff2016-03-22 11:14:09 -0700692 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000693}
694
sprang5e38c962016-12-01 05:18:09 -0800695std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100696 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800697 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700698 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000699
sprang5e38c962016-12-01 05:18:09 -0800700 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
701 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800702 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800703 xr->SetRrtr(rrtr);
704 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000705
sprang5e38c962016-12-01 05:18:09 -0800706 if (ctx.feedback_state_.has_last_xr_rr) {
707 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
708 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000709
sprang5e38c962016-12-01 05:18:09 -0800710 if (video_bitrate_allocation_) {
711 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000712
sprang5e38c962016-12-01 05:18:09 -0800713 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
714 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
715 uint32_t layer_bitrate_bps =
716 video_bitrate_allocation_->GetBitrate(sl, tl);
717 if (layer_bitrate_bps > 0)
718 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
719 }
720 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000721
sprang5e38c962016-12-01 05:18:09 -0800722 xr->SetTargetBitrate(target_bitrate);
723 video_bitrate_allocation_.reset();
724 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200725
sprang5e38c962016-12-01 05:18:09 -0800726 if (xr_voip_metric_) {
727 rtcp::VoipMetric voip;
728 voip.SetMediaSsrc(remote_ssrc_);
729 voip.SetVoipMetric(*xr_voip_metric_);
730 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000731
sprang5e38c962016-12-01 05:18:09 -0800732 xr->SetVoipMetric(voip);
733 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200734
sprang5e38c962016-12-01 05:18:09 -0800735 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000736}
737
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000738int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200739 RTCPPacketType packetType,
740 int32_t nack_size,
741 const uint16_t* nack_list,
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000742 bool repeat,
743 uint64_t pictureID) {
Erik Språng242e22b2015-05-11 10:17:43 +0200744 return SendCompoundRTCP(
745 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
746 nack_size, nack_list, repeat, pictureID);
747}
748
749int32_t RTCPSender::SendCompoundRTCP(
750 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100751 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200752 int32_t nack_size,
753 const uint16_t* nack_list,
754 bool repeat,
755 uint64_t pictureID) {
terelius429c3452016-01-21 05:42:04 -0800756 PacketContainer container(transport_, event_log_);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000757 {
danilchap56036ff2016-03-22 11:14:09 -0700758 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700759 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200760 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
761 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000762 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200763 // Add all flags as volatile. Non volatile entries will not be overwritten.
764 // All new volatile flags added will be consumed by the end of this call.
765 SetFlags(packet_types, true);
766
767 // Prevent sending streams to send SR before any media has been sent.
768 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
769 if (!can_calculate_rtp_timestamp) {
770 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
771 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
772 bool sender_report = consumed_report_flag || consumed_sr_flag;
773 if (sender_report && AllVolatileFlagsConsumed()) {
774 // This call was for Sender Report and nothing else.
775 return 0;
776 }
777 if (sending_ && method_ == RtcpMode::kCompound) {
778 // Not allowed to send any RTCP packet without sender report.
779 return -1;
780 }
781 }
782
783 if (packet_type_counter_.first_packet_time_ms == -1)
784 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100785
786 // We need to send our NTP even if we haven't received any reports.
Erik Språngf7c57762015-12-04 10:40:35 +0100787 RtcpContext context(feedback_state, nack_size, nack_list, repeat, pictureID,
danilchap51813b32016-12-16 02:44:36 -0800788 NtpTime(*clock_));
Erik Språngf7c57762015-12-04 10:40:35 +0100789
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200790 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100791
danilchap56036ff2016-03-22 11:14:09 -0700792 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800793
Erik Språngf7c57762015-12-04 10:40:35 +0100794 auto it = report_flags_.begin();
795 while (it != report_flags_.end()) {
796 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800797 RTC_DCHECK(builder_it != builders_.end())
798 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100799 if (it->is_volatile) {
800 report_flags_.erase(it++);
801 } else {
802 ++it;
803 }
804
805 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700806 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100807 if (packet.get() == nullptr)
808 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800809 // If there is a BYE, don't append now - save it and append it
810 // at the end later.
811 if (builder_it->first == kRtcpBye) {
812 packet_bye = std::move(packet);
813 } else {
814 container.Append(packet.release());
815 }
816 }
817
818 // Append the BYE now at the end
819 if (packet_bye) {
820 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100821 }
822
823 if (packet_type_counter_observer_ != nullptr) {
824 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
825 remote_ssrc_, packet_type_counter_);
826 }
827
828 RTC_DCHECK(AllVolatileFlagsConsumed());
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000829 }
Erik Språng61be2a42015-04-27 13:32:52 +0200830
nisse284542b2017-01-10 08:58:32 -0800831 size_t bytes_sent = container.SendPackets(max_packet_size_);
Erik Språngf7c57762015-12-04 10:40:35 +0100832 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000833}
834
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200835void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200836 bool generate_report;
837 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
838 // Report type already explicitly set, don't automatically populate.
839 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700840 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200841 } else {
842 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700843 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
844 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200845 if (generate_report)
846 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000847 }
848
Erik Språng0ea42d32015-06-25 14:46:16 +0200849 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200850 SetFlag(kRtcpSdes, true);
851
Erik Språng242e22b2015-05-11 10:17:43 +0200852 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800853 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
854 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
855 SetFlag(kRtcpAnyExtendedReports, true);
856 }
Erik Språng242e22b2015-05-11 10:17:43 +0200857
858 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800859 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000860
danilchap47a740b2015-12-15 00:30:07 -0800861 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200862 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200863 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
864 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
865 if (send_bitrate_kbit != 0)
866 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000867 }
Erik Språng61be2a42015-04-27 13:32:52 +0200868 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
869 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200870 }
danilchap47a740b2015-12-15 00:30:07 -0800871 // The interval between RTCP packets is varied randomly over the
872 // range [1/2,3/2] times the calculated interval.
873 uint32_t timeToNext =
874 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200875 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000876
Per83d09102016-04-15 14:59:13 +0200877 if (receive_statistics_) {
878 StatisticianMap statisticians =
879 receive_statistics_->GetActiveStatisticians();
880 RTC_DCHECK(report_blocks_.empty());
881 for (auto& it : statisticians) {
882 AddReportBlock(feedback_state, it.first, it.second);
883 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000884 }
885 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886}
887
danilchapa72e7342015-12-22 08:07:45 -0800888bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
889 uint32_t ssrc,
890 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000891 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000892 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000893 if (!statistician->GetStatistics(&stats, true))
894 return false;
danilchapa72e7342015-12-22 08:07:45 -0800895
896 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
897 LOG(LS_WARNING) << "Too many report blocks.";
898 return false;
899 }
900 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
901 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700902 block->SetMediaSsrc(ssrc);
903 block->SetFractionLost(stats.fraction_lost);
904 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800905 report_blocks_.erase(ssrc);
906 LOG(LS_WARNING) << "Cumulative lost is oversized.";
907 return false;
908 }
danilchap822a16f2016-09-27 09:27:47 -0700909 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
910 block->SetJitter(stats.jitter);
911 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000912
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200913 // TODO(sprang): Do we really need separate time stamps for each report?
914 // Get our NTP as late as possible to avoid a race.
915 uint32_t ntp_secs;
916 uint32_t ntp_frac;
917 clock_->CurrentNtp(ntp_secs, ntp_frac);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000918
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200919 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000920 if ((feedback_state.last_rr_ntp_secs != 0) ||
921 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200922 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
923 uint32_t now = ntp_secs & 0x0000FFFF;
Erik Språng61be2a42015-04-27 13:32:52 +0200924 now <<= 16;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200925 now += (ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000926
Erik Språng61be2a42015-04-27 13:32:52 +0200927 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
928 receiveTime <<= 16;
929 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000930
danilchap822a16f2016-09-27 09:27:47 -0700931 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000932 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000933 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000934}
935
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000936void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800937 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700938 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000939 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000940}
941
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000942int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
943 uint32_t name,
944 const uint8_t* data,
945 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200946 if (length % 4 != 0) {
947 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
948 return -1;
949 }
danilchap56036ff2016-03-22 11:14:09 -0700950 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000951
Erik Språng242e22b2015-05-11 10:17:43 +0200952 SetFlag(kRtcpApp, true);
953 app_sub_type_ = subType;
954 app_name_ = name;
955 app_data_.reset(new uint8_t[length]);
956 app_length_ = length;
957 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200958 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000959}
960
spranga790d832016-12-02 07:29:44 -0800961// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200962int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700963 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800964 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000965
sprang5e38c962016-12-01 05:18:09 -0800966 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200967 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000968}
969
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000970void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700971 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200972 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000973}
974
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000975bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700976 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200977 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000978}
979
danilchap853ecb22016-08-22 08:26:15 -0700980void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700981 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700982 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700983 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000984}
Erik Språng61be2a42015-04-27 13:32:52 +0200985
sprang5e38c962016-12-01 05:18:09 -0800986void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
987 if (type & kRtcpAnyExtendedReports) {
988 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
989 } else {
990 report_flags_.insert(ReportFlag(type, is_volatile));
991 }
Erik Språng242e22b2015-05-11 10:17:43 +0200992}
993
994void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
995 bool is_volatile) {
996 for (RTCPPacketType type : types)
997 SetFlag(type, is_volatile);
998}
999
sprang5e38c962016-12-01 05:18:09 -08001000bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +02001001 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
1002}
1003
sprang5e38c962016-12-01 05:18:09 -08001004bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +02001005 auto it = report_flags_.find(ReportFlag(type, false));
1006 if (it == report_flags_.end())
1007 return false;
1008 if (it->is_volatile || forced)
1009 report_flags_.erase((it));
1010 return true;
1011}
1012
1013bool RTCPSender::AllVolatileFlagsConsumed() const {
1014 for (const ReportFlag& flag : report_flags_) {
1015 if (flag.is_volatile)
1016 return false;
1017 }
1018 return true;
1019}
1020
sprang5e38c962016-12-01 05:18:09 -08001021void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
1022 rtc::CritScope lock(&critical_section_rtcp_sender_);
1023 video_bitrate_allocation_.emplace(bitrate);
1024 SetFlag(kRtcpAnyExtendedReports, true);
1025}
1026
sprang233bd872015-09-08 13:25:16 -07001027bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -07001028 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
1029 public:
terelius429c3452016-01-21 05:42:04 -08001030 Sender(Transport* transport, RtcEventLog* event_log)
1031 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -07001032
1033 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -08001034 if (transport_->SendRtcp(data, length)) {
1035 if (event_log_) {
1036 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
1037 length);
1038 }
1039 } else {
sprang233bd872015-09-08 13:25:16 -07001040 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -08001041 }
sprang233bd872015-09-08 13:25:16 -07001042 }
1043
1044 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -08001045 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001046 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001047 // TODO(terelius): We would like to
1048 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1049 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1050 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001051
stefanb77c7162017-02-06 06:29:38 -08001052 {
1053 rtc::CritScope lock(&critical_section_rtcp_sender_);
1054 if (method_ == RtcpMode::kOff)
1055 return false;
1056 }
1057
nisse284542b2017-01-10 08:58:32 -08001058 RTC_DCHECK_LE(max_packet_size_, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001059 uint8_t buffer[IP_PACKET_SIZE];
nisse284542b2017-01-10 08:58:32 -08001060 return packet.BuildExternalBuffer(buffer, max_packet_size_, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001061 !sender.send_failure_;
1062}
1063
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001064} // namespace webrtc