blob: 97cf8caa92bf8e4169afbd61194f5204aa17b4b5 [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 Chapovalov1567d0b2016-01-15 17:34:27 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchapef3d8052016-01-11 03:31:08 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap42287842017-02-20 06:40:18 -080039#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070040#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000041
niklase@google.com470e71d2011-07-07 08:21:25 +000042namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000043
sprang5e38c962016-12-01 05:18:09 -080044namespace {
45const uint32_t kRtcpAnyExtendedReports =
46 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
47 kRtcpXrTargetBitrate;
48} // namespace
49
Erik Språng61be2a42015-04-27 13:32:52 +020050NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080051 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000052
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000053NACKStringBuilder::~NACKStringBuilder() {}
54
danilchap162abd32015-12-10 02:39:40 -080055void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (count_ == 0) {
57 stream_ << nack;
58 } else if (nack == prevNack_ + 1) {
59 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020060 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020061 if (consecutive_) {
62 stream_ << "-" << prevNack_;
63 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000064 }
Erik Språng242e22b2015-05-11 10:17:43 +020065 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 count_++;
68 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000069}
70
Erik Språng61be2a42015-04-27 13:32:52 +020071std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020072 if (consecutive_) {
73 stream_ << "-" << prevNack_;
74 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020075 }
Erik Språng242e22b2015-05-11 10:17:43 +020076 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000077}
78
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079RTCPSender::FeedbackState::FeedbackState()
nisse40ba3ad2017-03-17 07:04:00 -070080 : packets_sent(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000081 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082 send_bitrate(0),
83 last_rr_ntp_secs(0),
84 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000085 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020086 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080087 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000088
danilchap2f7dea12016-01-13 02:03:04 -080089class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010090 public rtcp::RtcpPacket::PacketReadyCallback {
91 public:
terelius429c3452016-01-21 05:42:04 -080092 PacketContainer(Transport* transport, RtcEventLog* event_log)
93 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010094 virtual ~PacketContainer() {
95 for (RtcpPacket* packet : appended_packets_)
96 delete packet;
97 }
98
99 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800100 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100101 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800102 if (event_log_) {
103 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
104 length);
105 }
106 }
Erik Språngf7c57762015-12-04 10:40:35 +0100107 }
108
danilchap41befce2016-03-30 11:11:51 -0700109 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800110 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700111 uint8_t buffer[IP_PACKET_SIZE];
112 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100113 return bytes_sent_;
114 }
115
116 private:
117 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800118 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100119 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800120
121 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100122};
123
124class RTCPSender::RtcpContext {
125 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200126 RtcpContext(const FeedbackState& feedback_state,
127 int32_t nack_size,
128 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800129 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100130 : feedback_state_(feedback_state),
131 nack_size_(nack_size),
132 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800133 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200134
Erik Språngf7c57762015-12-04 10:40:35 +0100135 const FeedbackState& feedback_state_;
136 const int32_t nack_size_;
137 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800138 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200139};
140
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000141RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142 bool audio,
143 Clock* clock,
144 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700145 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800146 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700147 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200148 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800150 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700151 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800152 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700153 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 using_nack_(false),
155 sending_(false),
156 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700158 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000159 last_rtp_timestamp_(0),
160 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200161 ssrc_(0),
162 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000163 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
danilchap2b616392016-08-18 06:17:42 -0700169 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800171 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200174 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200175 app_data_(nullptr),
176 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
Erik Språng242e22b2015-05-11 10:17:43 +0200178 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000179 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700180 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200181
182 builders_[kRtcpSr] = &RTCPSender::BuildSR;
183 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200184 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200185 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
186 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200187 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
188 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
189 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
190 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
191 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
192 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800193 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
danilchap162abd32015-12-10 02:39:40 -0800196RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
pbosda903ea2015-10-02 02:36:56 -0700198RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700199 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200200 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
skvlad1c392cc2016-04-01 14:46:44 -0700203void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700204 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000205
skvlad1c392cc2016-04-01 14:46:44 -0700206 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
207 // When switching on, reschedule the next packet
208 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200209 clock_->TimeInMilliseconds() +
210 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700211 }
212 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213}
214
Erik Språng61be2a42015-04-27 13:32:52 +0200215bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700216 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200217 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
221 bool sending) {
222 bool sendRTCPBye = false;
223 {
danilchap56036ff2016-03-22 11:14:09 -0700224 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
pbosda903ea2015-10-02 02:36:56 -0700226 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200228 // Trigger RTCP bye
229 sendRTCPBye = true;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Erik Språng242e22b2015-05-11 10:17:43 +0200232 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200233 }
234 if (sendRTCPBye)
235 return SendRTCP(feedback_state, kRtcpBye);
236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Erik Språng61be2a42015-04-27 13:32:52 +0200239bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700240 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200241 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000242}
243
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000244void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700245 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200246 remb_enabled_ = enable;
danilchapba6aa902017-04-18 06:57:02 -0700247 if (!enable) {
248 // Stop sending remb each report until it is reenabled and remb data set.
249 ConsumeFlag(kRtcpRemb, true);
250 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000251}
252
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253void RTCPSender::SetREMBData(uint32_t bitrate,
254 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700255 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200256 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000258
Erik Språng242e22b2015-05-11 10:17:43 +0200259 if (remb_enabled_)
260 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
262 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200263 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000264}
265
Erik Språng61be2a42015-04-27 13:32:52 +0200266bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700267 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200268 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000269}
270
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000271void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700272 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200273 if (enable) {
274 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
275 } else {
276 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
277 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000278}
279
nisse284542b2017-01-10 08:58:32 -0800280void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800281 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800282 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700283}
284
danilchap71fead22016-08-18 02:01:49 -0700285void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700286 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700287 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000288}
289
290void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
291 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700292 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293 last_rtp_timestamp_ = rtp_timestamp;
294 if (capture_time_ms < 0) {
295 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200296 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000297 } else {
298 last_frame_capture_time_ms_ = capture_time_ms;
299 }
300}
301
nisse14adba72017-03-20 03:52:39 -0700302uint32_t RTCPSender::SSRC() const {
303 rtc::CritScope lock(&critical_section_rtcp_sender_);
304 return ssrc_;
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_);
danilchap74e8df8f2017-03-16 08:04:08 -0700338 // One spot is reserved for ssrc_/cname_.
339 // TODO(danilchap): Add support for more than 30 contributes by sending
340 // several sdes packets.
341 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000342 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200343
344 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000345 return 0;
346}
347
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000348int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700349 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200350 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351
Erik Språng242e22b2015-05-11 10:17:43 +0200352 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000353 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200354
Erik Språng242e22b2015-05-11 10:17:43 +0200355 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000356 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000357}
358
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000359bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800360 /*
361 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
danilchap162abd32015-12-10 02:39:40 -0800363 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
364 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
365 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000366
367
danilchap162abd32015-12-10 02:39:40 -0800368 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 MAX RTCP BW is 5% if the session BW
371 A send report is approximately 65 bytes inc CNAME
372 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 The RECOMMENDED value for the reduced minimum in seconds is 360
375 divided by the session bandwidth in kilobits/second. This minimum
376 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 If the participant has not yet sent an RTCP packet (the variable
379 initial is true), the constant Tmin is set to 2.5 seconds, else it
380 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 The interval between RTCP packets is varied randomly over the
383 range [0.5,1.5] times the calculated interval to avoid unintended
384 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000385
danilchap162abd32015-12-10 02:39:40 -0800386 if we send
387 If the participant is a sender (we_sent true), the constant C is
388 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
389 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
390 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000391
danilchap162abd32015-12-10 02:39:40 -0800392 if we receive only
393 If we_sent is not true, the constant C is set
394 to the average RTCP packet size divided by 75% of the RTCP
395 bandwidth. The constant n is set to the number of receivers
396 (members - senders). If the number of senders is greater than
397 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000398
danilchap162abd32015-12-10 02:39:40 -0800399 reconsideration NOT required for peer-to-peer
400 "timer reconsideration" is
401 employed. This algorithm implements a simple back-off mechanism
402 which causes users to hold back RTCP packet transmission if the
403 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
danilchap162abd32015-12-10 02:39:40 -0800405 n = number of members
406 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap162abd32015-12-10 02:39:40 -0800408 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000409
danilchap162abd32015-12-10 02:39:40 -0800410 4. The calculated interval T is set to a number uniformly distributed
411 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000412
danilchap162abd32015-12-10 02:39:40 -0800413 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
414 for the fact that the timer reconsideration algorithm converges to
415 a value of the RTCP bandwidth below the intended average
416 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000417
Erik Språng242e22b2015-05-11 10:17:43 +0200418 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000419
danilchap56036ff2016-03-22 11:14:09 -0700420 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000421
pbosda903ea2015-10-02 02:36:56 -0700422 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000423 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000424
Erik Språng242e22b2015-05-11 10:17:43 +0200425 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200426 // for video key-frames we want to send the RTCP before the large key-frame
427 // if we have a 100 ms margin
428 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
429 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000430
Erik Språng242e22b2015-05-11 10:17:43 +0200431 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200432 return true;
433 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200434 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200435 // wrap
436 return true;
437 }
438 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000439}
440
danilchap56036ff2016-03-22 11:14:09 -0700441std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200442 // Timestamp shouldn't be estimated before first media frame.
443 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200444 // The timestamp of this RTCP packet should be estimated as the timestamp of
445 // the frame being captured at this moment. We are calculating that
446 // timestamp as the last frame's timestamp + the time since the last frame
447 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700448 uint32_t rtp_rate =
449 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200450 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700451 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700452 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
Erik Språngf7c57762015-12-04 10:40:35 +0100454 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700455 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800456 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700457 report->SetRtpTimestamp(rtp_timestamp);
458 report->SetPacketCount(ctx.feedback_state_.packets_sent);
459 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000460
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200461 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700462 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000463
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200464 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100465
danilchap56036ff2016-03-22 11:14:09 -0700466 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467}
468
danilchap56036ff2016-03-22 11:14:09 -0700469std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100470 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200471 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800472 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000473
Erik Språngf7c57762015-12-04 10:40:35 +0100474 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700475 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200476
danilchap74e8df8f2017-03-16 08:04:08 -0700477 for (const auto& it : csrc_cnames_)
478 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200479
danilchap56036ff2016-03-22 11:14:09 -0700480 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000481}
482
danilchap56036ff2016-03-22 11:14:09 -0700483std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100484 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700485 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200486 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700487 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200488
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200489 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700490 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000491}
492
danilchap56036ff2016-03-22 11:14:09 -0700493std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100494 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700495 pli->SetSenderSsrc(ssrc_);
496 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200497
Erik Språng242e22b2015-05-11 10:17:43 +0200498 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
499 "RTCPSender::PLI");
500 ++packet_type_counter_.pli_packets;
501 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
502 ssrc_, packet_type_counter_.pli_packets);
503
danilchap56036ff2016-03-22 11:14:09 -0700504 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200505}
506
danilchap56036ff2016-03-22 11:14:09 -0700507std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800508 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000509
Erik Språngf7c57762015-12-04 10:40:35 +0100510 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700511 fir->SetSenderSsrc(ssrc_);
512 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200513
514 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
515 "RTCPSender::FIR");
516 ++packet_type_counter_.fir_packets;
517 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
518 ssrc_, packet_type_counter_.fir_packets);
519
danilchap56036ff2016-03-22 11:14:09 -0700520 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000521}
522
danilchap56036ff2016-03-22 11:14:09 -0700523std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100524 const RtcpContext& ctx) {
525 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700526 remb->SetSenderSsrc(ssrc_);
527 remb->SetBitrateBps(remb_bitrate_);
528 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200529
Erik Språng242e22b2015-05-11 10:17:43 +0200530 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
531 "RTCPSender::REMB");
532
danilchap56036ff2016-03-22 11:14:09 -0700533 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000534}
535
Erik Språng61be2a42015-04-27 13:32:52 +0200536void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700537 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700538 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000539}
540
danilchap56036ff2016-03-22 11:14:09 -0700541std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100542 const RtcpContext& ctx) {
543 if (ctx.feedback_state_.module == nullptr)
544 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200545 // Before sending the TMMBR check the received TMMBN, only an owner is
546 // allowed to raise the bitrate:
547 // * If the sender is an owner of the TMMBN -> send TMMBR
548 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000549
Erik Språng61be2a42015-04-27 13:32:52 +0200550 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700551 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000552
Erik Språng242e22b2015-05-11 10:17:43 +0200553 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
554 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200555 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700556 std::vector<rtcp::TmmbItem> candidates =
557 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000558
danilchap2b616392016-08-18 06:17:42 -0700559 if (!candidates.empty()) {
560 for (const auto& candidate : candidates) {
561 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
562 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100563 // Do not send the same tuple.
564 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200565 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000566 }
danilchap2b616392016-08-18 06:17:42 -0700567 if (!tmmbr_owner) {
568 // Use received bounding set as candidate set.
569 // Add current tuple.
570 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000571
danilchap2b616392016-08-18 06:17:42 -0700572 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700573 std::vector<rtcp::TmmbItem> bounding =
574 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700575 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
576 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100577 // Did not enter bounding set, no meaning to send this request.
578 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200579 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000580 }
Erik Språng61be2a42015-04-27 13:32:52 +0200581 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000582
danilchap2b616392016-08-18 06:17:42 -0700583 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100584 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700585
Erik Språngf7c57762015-12-04 10:40:35 +0100586 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700587 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800588 rtcp::TmmbItem request;
589 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700590 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800591 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700592 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100593
danilchap56036ff2016-03-22 11:14:09 -0700594 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200595}
596
danilchap56036ff2016-03-22 11:14:09 -0700597std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100598 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100599 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700600 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700601 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
602 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700603 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000604 }
Erik Språng61be2a42015-04-27 13:32:52 +0200605 }
sprangd83df502015-08-27 01:05:08 -0700606
danilchap56036ff2016-03-22 11:14:09 -0700607 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000608}
609
danilchap56036ff2016-03-22 11:14:09 -0700610std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100611 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700612 app->SetSsrc(ssrc_);
613 app->SetSubType(app_sub_type_);
614 app->SetName(app_name_);
615 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200616
danilchap56036ff2016-03-22 11:14:09 -0700617 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200618}
619
danilchap56036ff2016-03-22 11:14:09 -0700620std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100621 const RtcpContext& ctx) {
622 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700623 nack->SetSenderSsrc(ssrc_);
624 nack->SetMediaSsrc(remote_ssrc_);
625 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200626
627 // Report stats.
628 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100629 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
630 stringBuilder.PushNACK(ctx.nack_list_[idx]);
631 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200632 }
Erik Språng61be2a42015-04-27 13:32:52 +0200633 packet_type_counter_.nack_requests = nack_stats_.requests();
634 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200635
636 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
637 "RTCPSender::NACK", "nacks",
638 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
639 ++packet_type_counter_.nack_packets;
640 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
641 ssrc_, packet_type_counter_.nack_packets);
642
danilchap56036ff2016-03-22 11:14:09 -0700643 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200644}
645
danilchap56036ff2016-03-22 11:14:09 -0700646std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100647 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700648 bye->SetSenderSsrc(ssrc_);
649 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700650
danilchap56036ff2016-03-22 11:14:09 -0700651 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000652}
653
sprang5e38c962016-12-01 05:18:09 -0800654std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100655 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800656 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700657 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000658
sprang5e38c962016-12-01 05:18:09 -0800659 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
660 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800661 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800662 xr->SetRrtr(rrtr);
663 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000664
sprang5e38c962016-12-01 05:18:09 -0800665 if (ctx.feedback_state_.has_last_xr_rr) {
666 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
667 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000668
sprang5e38c962016-12-01 05:18:09 -0800669 if (video_bitrate_allocation_) {
670 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000671
sprang5e38c962016-12-01 05:18:09 -0800672 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
673 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
674 uint32_t layer_bitrate_bps =
675 video_bitrate_allocation_->GetBitrate(sl, tl);
676 if (layer_bitrate_bps > 0)
677 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
678 }
679 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000680
sprang5e38c962016-12-01 05:18:09 -0800681 xr->SetTargetBitrate(target_bitrate);
682 video_bitrate_allocation_.reset();
683 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200684
sprang5e38c962016-12-01 05:18:09 -0800685 if (xr_voip_metric_) {
686 rtcp::VoipMetric voip;
687 voip.SetMediaSsrc(remote_ssrc_);
688 voip.SetVoipMetric(*xr_voip_metric_);
689 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000690
sprang5e38c962016-12-01 05:18:09 -0800691 xr->SetVoipMetric(voip);
692 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200693
sprang5e38c962016-12-01 05:18:09 -0800694 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000695}
696
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000697int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200698 RTCPPacketType packetType,
699 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700700 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200701 return SendCompoundRTCP(
702 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700703 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200704}
705
706int32_t RTCPSender::SendCompoundRTCP(
707 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100708 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200709 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700710 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800711 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800712 size_t max_packet_size;
713
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000714 {
danilchap56036ff2016-03-22 11:14:09 -0700715 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700716 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200717 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
718 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000719 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200720 // Add all flags as volatile. Non volatile entries will not be overwritten.
721 // All new volatile flags added will be consumed by the end of this call.
722 SetFlags(packet_types, true);
723
724 // Prevent sending streams to send SR before any media has been sent.
725 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
726 if (!can_calculate_rtp_timestamp) {
727 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
728 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
729 bool sender_report = consumed_report_flag || consumed_sr_flag;
730 if (sender_report && AllVolatileFlagsConsumed()) {
731 // This call was for Sender Report and nothing else.
732 return 0;
733 }
734 if (sending_ && method_ == RtcpMode::kCompound) {
735 // Not allowed to send any RTCP packet without sender report.
736 return -1;
737 }
738 }
739
740 if (packet_type_counter_.first_packet_time_ms == -1)
741 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100742
743 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700744 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800745 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100746
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200747 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100748
danilchap56036ff2016-03-22 11:14:09 -0700749 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800750
Erik Språngf7c57762015-12-04 10:40:35 +0100751 auto it = report_flags_.begin();
752 while (it != report_flags_.end()) {
753 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800754 RTC_DCHECK(builder_it != builders_.end())
755 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100756 if (it->is_volatile) {
757 report_flags_.erase(it++);
758 } else {
759 ++it;
760 }
761
762 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700763 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100764 if (packet.get() == nullptr)
765 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800766 // If there is a BYE, don't append now - save it and append it
767 // at the end later.
768 if (builder_it->first == kRtcpBye) {
769 packet_bye = std::move(packet);
770 } else {
771 container.Append(packet.release());
772 }
773 }
774
775 // Append the BYE now at the end
776 if (packet_bye) {
777 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100778 }
779
780 if (packet_type_counter_observer_ != nullptr) {
781 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
782 remote_ssrc_, packet_type_counter_);
783 }
784
785 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800786 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000787 }
Erik Språng61be2a42015-04-27 13:32:52 +0200788
nisse6f142eb2017-02-21 07:32:47 -0800789 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100790 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000791}
792
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200793void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200794 bool generate_report;
795 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
796 // Report type already explicitly set, don't automatically populate.
797 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700798 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200799 } else {
800 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700801 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
802 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200803 if (generate_report)
804 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000805 }
806
Erik Språng0ea42d32015-06-25 14:46:16 +0200807 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200808 SetFlag(kRtcpSdes, true);
809
Erik Språng242e22b2015-05-11 10:17:43 +0200810 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800811 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
812 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
813 SetFlag(kRtcpAnyExtendedReports, true);
814 }
Erik Språng242e22b2015-05-11 10:17:43 +0200815
816 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800817 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000818
danilchap47a740b2015-12-15 00:30:07 -0800819 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200820 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200821 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
822 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
823 if (send_bitrate_kbit != 0)
824 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000825 }
Erik Språng61be2a42015-04-27 13:32:52 +0200826 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
827 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200828 }
danilchap47a740b2015-12-15 00:30:07 -0800829 // The interval between RTCP packets is varied randomly over the
830 // range [1/2,3/2] times the calculated interval.
831 uint32_t timeToNext =
832 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200833 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000834
Per83d09102016-04-15 14:59:13 +0200835 if (receive_statistics_) {
836 StatisticianMap statisticians =
837 receive_statistics_->GetActiveStatisticians();
838 RTC_DCHECK(report_blocks_.empty());
839 for (auto& it : statisticians) {
840 AddReportBlock(feedback_state, it.first, it.second);
841 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000842 }
843 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000844}
845
danilchapa72e7342015-12-22 08:07:45 -0800846bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
847 uint32_t ssrc,
848 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000849 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000850 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000851 if (!statistician->GetStatistics(&stats, true))
852 return false;
danilchapa72e7342015-12-22 08:07:45 -0800853
854 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
855 LOG(LS_WARNING) << "Too many report blocks.";
856 return false;
857 }
858 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
859 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700860 block->SetMediaSsrc(ssrc);
861 block->SetFractionLost(stats.fraction_lost);
862 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800863 report_blocks_.erase(ssrc);
864 LOG(LS_WARNING) << "Cumulative lost is oversized.";
865 return false;
866 }
danilchap822a16f2016-09-27 09:27:47 -0700867 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
868 block->SetJitter(stats.jitter);
869 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000870
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200871 // TODO(sprang): Do we really need separate time stamps for each report?
872 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800873 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000874
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200875 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000876 if ((feedback_state.last_rr_ntp_secs != 0) ||
877 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200878 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800879 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880
Erik Språng61be2a42015-04-27 13:32:52 +0200881 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
882 receiveTime <<= 16;
883 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000884
danilchap822a16f2016-09-27 09:27:47 -0700885 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000887 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000888}
889
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000890void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800891 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700892 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000893 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000894}
895
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000896int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
897 uint32_t name,
898 const uint8_t* data,
899 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200900 if (length % 4 != 0) {
901 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
902 return -1;
903 }
danilchap56036ff2016-03-22 11:14:09 -0700904 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000905
Erik Språng242e22b2015-05-11 10:17:43 +0200906 SetFlag(kRtcpApp, true);
907 app_sub_type_ = subType;
908 app_name_ = name;
909 app_data_.reset(new uint8_t[length]);
910 app_length_ = length;
911 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200912 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000913}
914
spranga790d832016-12-02 07:29:44 -0800915// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200916int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700917 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800918 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000919
sprang5e38c962016-12-01 05:18:09 -0800920 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200921 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000922}
923
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000924void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700925 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200926 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000927}
928
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000929bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700930 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200931 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000932}
933
danilchap853ecb22016-08-22 08:26:15 -0700934void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700935 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700936 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700937 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000938}
Erik Språng61be2a42015-04-27 13:32:52 +0200939
sprang5e38c962016-12-01 05:18:09 -0800940void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
941 if (type & kRtcpAnyExtendedReports) {
942 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
943 } else {
944 report_flags_.insert(ReportFlag(type, is_volatile));
945 }
Erik Språng242e22b2015-05-11 10:17:43 +0200946}
947
948void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
949 bool is_volatile) {
950 for (RTCPPacketType type : types)
951 SetFlag(type, is_volatile);
952}
953
sprang5e38c962016-12-01 05:18:09 -0800954bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200955 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
956}
957
sprang5e38c962016-12-01 05:18:09 -0800958bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200959 auto it = report_flags_.find(ReportFlag(type, false));
960 if (it == report_flags_.end())
961 return false;
962 if (it->is_volatile || forced)
963 report_flags_.erase((it));
964 return true;
965}
966
967bool RTCPSender::AllVolatileFlagsConsumed() const {
968 for (const ReportFlag& flag : report_flags_) {
969 if (flag.is_volatile)
970 return false;
971 }
972 return true;
973}
974
sprang5e38c962016-12-01 05:18:09 -0800975void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
976 rtc::CritScope lock(&critical_section_rtcp_sender_);
977 video_bitrate_allocation_.emplace(bitrate);
978 SetFlag(kRtcpAnyExtendedReports, true);
979}
980
sprang233bd872015-09-08 13:25:16 -0700981bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700982 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
983 public:
terelius429c3452016-01-21 05:42:04 -0800984 Sender(Transport* transport, RtcEventLog* event_log)
985 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700986
987 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800988 if (transport_->SendRtcp(data, length)) {
989 if (event_log_) {
990 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
991 length);
992 }
993 } else {
sprang233bd872015-09-08 13:25:16 -0700994 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800995 }
sprang233bd872015-09-08 13:25:16 -0700996 }
997
998 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800999 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -07001000 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -08001001 // TODO(terelius): We would like to
1002 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1003 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1004 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001005
nisse6f142eb2017-02-21 07:32:47 -08001006 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -08001007 {
1008 rtc::CritScope lock(&critical_section_rtcp_sender_);
1009 if (method_ == RtcpMode::kOff)
1010 return false;
nisse6f142eb2017-02-21 07:32:47 -08001011 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001012 }
1013
nisse6f142eb2017-02-21 07:32:47 -08001014 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001015 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001016 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001017 !sender.send_failure_;
1018}
1019
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001020} // namespace webrtc