blob: cab55d3bbf3c282b95d2a80c3d0252b2f810ee1a [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_) {
perkj77cd58e2017-05-30 03:52:10 -0700103 event_log_->LogRtcpPacket(kOutgoingPacket, data, length);
terelius429c3452016-01-21 05:42:04 -0800104 }
105 }
Erik Språngf7c57762015-12-04 10:40:35 +0100106 }
107
danilchap41befce2016-03-30 11:11:51 -0700108 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800109 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700110 uint8_t buffer[IP_PACKET_SIZE];
111 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100112 return bytes_sent_;
113 }
114
115 private:
116 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800117 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100118 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800119
120 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100121};
122
123class RTCPSender::RtcpContext {
124 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200125 RtcpContext(const FeedbackState& feedback_state,
126 int32_t nack_size,
127 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800128 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100129 : feedback_state_(feedback_state),
130 nack_size_(nack_size),
131 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800132 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200133
Erik Språngf7c57762015-12-04 10:40:35 +0100134 const FeedbackState& feedback_state_;
135 const int32_t nack_size_;
136 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800137 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200138};
139
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000140RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000141 bool audio,
142 Clock* clock,
143 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700144 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800145 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700146 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200147 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200148 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800149 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700150 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800151 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700152 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200153 using_nack_(false),
154 sending_(false),
155 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700157 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 last_rtp_timestamp_(0),
159 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 ssrc_(0),
161 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000162 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
danilchap2b616392016-08-18 06:17:42 -0700168 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800170 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200173 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_data_(nullptr),
175 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000176
Erik Språng242e22b2015-05-11 10:17:43 +0200177 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000178 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700179 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200180
181 builders_[kRtcpSr] = &RTCPSender::BuildSR;
182 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200183 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200184 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
185 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800192 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000193}
194
danilchap162abd32015-12-10 02:39:40 -0800195RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000196
pbosda903ea2015-10-02 02:36:56 -0700197RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700198 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200199 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
skvlad1c392cc2016-04-01 14:46:44 -0700202void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700203 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000204
skvlad1c392cc2016-04-01 14:46:44 -0700205 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
206 // When switching on, reschedule the next packet
207 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200208 clock_->TimeInMilliseconds() +
209 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700210 }
211 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212}
213
Erik Språng61be2a42015-04-27 13:32:52 +0200214bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700215 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200216 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217}
218
Erik Språng61be2a42015-04-27 13:32:52 +0200219int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
220 bool sending) {
221 bool sendRTCPBye = false;
222 {
danilchap56036ff2016-03-22 11:14:09 -0700223 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000224
pbosda903ea2015-10-02 02:36:56 -0700225 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200226 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200227 // Trigger RTCP bye
228 sendRTCPBye = true;
229 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 }
Erik Språng242e22b2015-05-11 10:17:43 +0200231 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200232 }
233 if (sendRTCPBye)
234 return SendRTCP(feedback_state, kRtcpBye);
235 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000236}
237
Erik Språng61be2a42015-04-27 13:32:52 +0200238bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700239 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200240 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000241}
242
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000243void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700244 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200245 remb_enabled_ = enable;
danilchapba6aa902017-04-18 06:57:02 -0700246 if (!enable) {
247 // Stop sending remb each report until it is reenabled and remb data set.
248 ConsumeFlag(kRtcpRemb, true);
249 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBData(uint32_t bitrate,
253 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700254 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200255 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000257
Erik Språng242e22b2015-05-11 10:17:43 +0200258 if (remb_enabled_)
259 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
261 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200262 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000263}
264
Erik Språng61be2a42015-04-27 13:32:52 +0200265bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700266 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200267 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000268}
269
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000270void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700271 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200272 if (enable) {
273 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
274 } else {
275 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
276 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000277}
278
nisse284542b2017-01-10 08:58:32 -0800279void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800280 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800281 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700282}
283
danilchap71fead22016-08-18 02:01:49 -0700284void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700285 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700286 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287}
288
289void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
290 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700291 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 last_rtp_timestamp_ = rtp_timestamp;
293 if (capture_time_ms < 0) {
294 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200295 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 } else {
297 last_frame_capture_time_ms_ = capture_time_ms;
298 }
299}
300
nisse14adba72017-03-20 03:52:39 -0700301uint32_t RTCPSender::SSRC() const {
302 rtc::CritScope lock(&critical_section_rtcp_sender_);
303 return ssrc_;
304}
305
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000306void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700307 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
Erik Språng242e22b2015-05-11 10:17:43 +0200309 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200310 // not first SetSSRC, probably due to a collision
311 // schedule a new RTCP report
312 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200313 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200314 }
Erik Språng242e22b2015-05-11 10:17:43 +0200315 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Erik Språng61be2a42015-04-27 13:32:52 +0200318void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200320 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321}
322
Peter Boström9ba52f82015-06-01 14:12:28 +0200323int32_t RTCPSender::SetCNAME(const char* c_name) {
324 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000325 return -1;
326
kwiberg352444f2016-11-28 15:58:53 -0800327 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700328 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200329 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000330 return 0;
331}
332
Erik Språng0ea42d32015-06-25 14:46:16 +0200333int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700334 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800335 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700336 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700337 // One spot is reserved for ssrc_/cname_.
338 // TODO(danilchap): Add support for more than 30 contributes by sending
339 // several sdes packets.
340 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200342
343 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 return 0;
345}
346
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000347int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700348 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200349 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000350
Erik Språng242e22b2015-05-11 10:17:43 +0200351 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200353
Erik Språng242e22b2015-05-11 10:17:43 +0200354 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000355 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356}
357
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000358bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800359 /*
360 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
363 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
364 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
366
danilchap162abd32015-12-10 02:39:40 -0800367 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 MAX RTCP BW is 5% if the session BW
370 A send report is approximately 65 bytes inc CNAME
371 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 The RECOMMENDED value for the reduced minimum in seconds is 360
374 divided by the session bandwidth in kilobits/second. This minimum
375 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 If the participant has not yet sent an RTCP packet (the variable
378 initial is true), the constant Tmin is set to 2.5 seconds, else it
379 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 The interval between RTCP packets is varied randomly over the
382 range [0.5,1.5] times the calculated interval to avoid unintended
383 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000384
danilchap162abd32015-12-10 02:39:40 -0800385 if we send
386 If the participant is a sender (we_sent true), the constant C is
387 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
388 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
389 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
danilchap162abd32015-12-10 02:39:40 -0800391 if we receive only
392 If we_sent is not true, the constant C is set
393 to the average RTCP packet size divided by 75% of the RTCP
394 bandwidth. The constant n is set to the number of receivers
395 (members - senders). If the number of senders is greater than
396 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 reconsideration NOT required for peer-to-peer
399 "timer reconsideration" is
400 employed. This algorithm implements a simple back-off mechanism
401 which causes users to hold back RTCP packet transmission if the
402 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 n = number of members
405 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
danilchap162abd32015-12-10 02:39:40 -0800407 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 4. The calculated interval T is set to a number uniformly distributed
410 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
danilchap162abd32015-12-10 02:39:40 -0800412 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
413 for the fact that the timer reconsideration algorithm converges to
414 a value of the RTCP bandwidth below the intended average
415 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000418
danilchap56036ff2016-03-22 11:14:09 -0700419 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000420
pbosda903ea2015-10-02 02:36:56 -0700421 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
Erik Språng242e22b2015-05-11 10:17:43 +0200424 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // for video key-frames we want to send the RTCP before the large key-frame
426 // if we have a 100 ms margin
427 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
428 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
Erik Språng242e22b2015-05-11 10:17:43 +0200430 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200431 return true;
432 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200433 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // wrap
435 return true;
436 }
437 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
danilchap56036ff2016-03-22 11:14:09 -0700440std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200441 // Timestamp shouldn't be estimated before first media frame.
442 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200443 // The timestamp of this RTCP packet should be estimated as the timestamp of
444 // the frame being captured at this moment. We are calculating that
445 // timestamp as the last frame's timestamp + the time since the last frame
446 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700447 uint32_t rtp_rate =
448 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200449 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700450 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700451 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
Erik Språngf7c57762015-12-04 10:40:35 +0100453 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700454 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800455 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700456 report->SetRtpTimestamp(rtp_timestamp);
457 report->SetPacketCount(ctx.feedback_state_.packets_sent);
458 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700461 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200463 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100464
danilchap56036ff2016-03-22 11:14:09 -0700465 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000466}
467
danilchap56036ff2016-03-22 11:14:09 -0700468std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100469 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200470 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800471 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000472
Erik Språngf7c57762015-12-04 10:40:35 +0100473 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700474 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200475
danilchap74e8df8f2017-03-16 08:04:08 -0700476 for (const auto& it : csrc_cnames_)
477 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200478
danilchap56036ff2016-03-22 11:14:09 -0700479 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480}
481
danilchap56036ff2016-03-22 11:14:09 -0700482std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100483 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700484 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200485 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700486 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200487
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200488 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700489 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000490}
491
danilchap56036ff2016-03-22 11:14:09 -0700492std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100493 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700494 pli->SetSenderSsrc(ssrc_);
495 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200496
Erik Språng242e22b2015-05-11 10:17:43 +0200497 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
498 "RTCPSender::PLI");
499 ++packet_type_counter_.pli_packets;
500 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
501 ssrc_, packet_type_counter_.pli_packets);
502
danilchap56036ff2016-03-22 11:14:09 -0700503 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200504}
505
danilchap56036ff2016-03-22 11:14:09 -0700506std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800507 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000508
Erik Språngf7c57762015-12-04 10:40:35 +0100509 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700510 fir->SetSenderSsrc(ssrc_);
511 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200512
513 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
514 "RTCPSender::FIR");
515 ++packet_type_counter_.fir_packets;
516 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
517 ssrc_, packet_type_counter_.fir_packets);
518
danilchap56036ff2016-03-22 11:14:09 -0700519 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000520}
521
danilchap56036ff2016-03-22 11:14:09 -0700522std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100523 const RtcpContext& ctx) {
524 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700525 remb->SetSenderSsrc(ssrc_);
526 remb->SetBitrateBps(remb_bitrate_);
527 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200528
Erik Språng242e22b2015-05-11 10:17:43 +0200529 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
530 "RTCPSender::REMB");
531
danilchap56036ff2016-03-22 11:14:09 -0700532 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000533}
534
Erik Språng61be2a42015-04-27 13:32:52 +0200535void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700536 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700537 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000538}
539
danilchap56036ff2016-03-22 11:14:09 -0700540std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100541 const RtcpContext& ctx) {
542 if (ctx.feedback_state_.module == nullptr)
543 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200544 // Before sending the TMMBR check the received TMMBN, only an owner is
545 // allowed to raise the bitrate:
546 // * If the sender is an owner of the TMMBN -> send TMMBR
547 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000548
Erik Språng61be2a42015-04-27 13:32:52 +0200549 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700550 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
Erik Språng242e22b2015-05-11 10:17:43 +0200552 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
553 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200554 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700555 std::vector<rtcp::TmmbItem> candidates =
556 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000557
danilchap2b616392016-08-18 06:17:42 -0700558 if (!candidates.empty()) {
559 for (const auto& candidate : candidates) {
560 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
561 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100562 // Do not send the same tuple.
563 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200564 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000565 }
danilchap2b616392016-08-18 06:17:42 -0700566 if (!tmmbr_owner) {
567 // Use received bounding set as candidate set.
568 // Add current tuple.
569 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000570
danilchap2b616392016-08-18 06:17:42 -0700571 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700572 std::vector<rtcp::TmmbItem> bounding =
573 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700574 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
575 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100576 // Did not enter bounding set, no meaning to send this request.
577 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200578 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000579 }
Erik Språng61be2a42015-04-27 13:32:52 +0200580 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000581
danilchap2b616392016-08-18 06:17:42 -0700582 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100583 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700584
Erik Språngf7c57762015-12-04 10:40:35 +0100585 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700586 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800587 rtcp::TmmbItem request;
588 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700589 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800590 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700591 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100592
danilchap56036ff2016-03-22 11:14:09 -0700593 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200594}
595
danilchap56036ff2016-03-22 11:14:09 -0700596std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100597 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100598 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700599 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700600 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
601 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700602 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000603 }
Erik Språng61be2a42015-04-27 13:32:52 +0200604 }
sprangd83df502015-08-27 01:05:08 -0700605
danilchap56036ff2016-03-22 11:14:09 -0700606 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000607}
608
danilchap56036ff2016-03-22 11:14:09 -0700609std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100610 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700611 app->SetSsrc(ssrc_);
612 app->SetSubType(app_sub_type_);
613 app->SetName(app_name_);
614 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200615
danilchap56036ff2016-03-22 11:14:09 -0700616 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200617}
618
danilchap56036ff2016-03-22 11:14:09 -0700619std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100620 const RtcpContext& ctx) {
621 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700622 nack->SetSenderSsrc(ssrc_);
623 nack->SetMediaSsrc(remote_ssrc_);
624 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200625
626 // Report stats.
627 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100628 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
629 stringBuilder.PushNACK(ctx.nack_list_[idx]);
630 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200631 }
Erik Språng61be2a42015-04-27 13:32:52 +0200632 packet_type_counter_.nack_requests = nack_stats_.requests();
633 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200634
635 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
636 "RTCPSender::NACK", "nacks",
637 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
638 ++packet_type_counter_.nack_packets;
639 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
640 ssrc_, packet_type_counter_.nack_packets);
641
danilchap56036ff2016-03-22 11:14:09 -0700642 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200643}
644
danilchap56036ff2016-03-22 11:14:09 -0700645std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100646 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700647 bye->SetSenderSsrc(ssrc_);
648 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700649
danilchap56036ff2016-03-22 11:14:09 -0700650 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000651}
652
sprang5e38c962016-12-01 05:18:09 -0800653std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100654 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800655 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700656 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000657
sprang5e38c962016-12-01 05:18:09 -0800658 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
659 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800660 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800661 xr->SetRrtr(rrtr);
662 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000663
sprang5e38c962016-12-01 05:18:09 -0800664 if (ctx.feedback_state_.has_last_xr_rr) {
665 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
666 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000667
sprang5e38c962016-12-01 05:18:09 -0800668 if (video_bitrate_allocation_) {
669 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000670
sprang5e38c962016-12-01 05:18:09 -0800671 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
672 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
673 uint32_t layer_bitrate_bps =
674 video_bitrate_allocation_->GetBitrate(sl, tl);
675 if (layer_bitrate_bps > 0)
676 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
677 }
678 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000679
sprang5e38c962016-12-01 05:18:09 -0800680 xr->SetTargetBitrate(target_bitrate);
681 video_bitrate_allocation_.reset();
682 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200683
sprang5e38c962016-12-01 05:18:09 -0800684 if (xr_voip_metric_) {
685 rtcp::VoipMetric voip;
686 voip.SetMediaSsrc(remote_ssrc_);
687 voip.SetVoipMetric(*xr_voip_metric_);
688 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000689
sprang5e38c962016-12-01 05:18:09 -0800690 xr->SetVoipMetric(voip);
691 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200692
sprang5e38c962016-12-01 05:18:09 -0800693 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000694}
695
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000696int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200697 RTCPPacketType packetType,
698 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700699 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200700 return SendCompoundRTCP(
701 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700702 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200703}
704
705int32_t RTCPSender::SendCompoundRTCP(
706 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100707 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200708 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700709 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800710 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800711 size_t max_packet_size;
712
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000713 {
danilchap56036ff2016-03-22 11:14:09 -0700714 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700715 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200716 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
717 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000718 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200719 // Add all flags as volatile. Non volatile entries will not be overwritten.
720 // All new volatile flags added will be consumed by the end of this call.
721 SetFlags(packet_types, true);
722
723 // Prevent sending streams to send SR before any media has been sent.
724 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
725 if (!can_calculate_rtp_timestamp) {
726 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
727 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
728 bool sender_report = consumed_report_flag || consumed_sr_flag;
729 if (sender_report && AllVolatileFlagsConsumed()) {
730 // This call was for Sender Report and nothing else.
731 return 0;
732 }
733 if (sending_ && method_ == RtcpMode::kCompound) {
734 // Not allowed to send any RTCP packet without sender report.
735 return -1;
736 }
737 }
738
739 if (packet_type_counter_.first_packet_time_ms == -1)
740 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100741
742 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700743 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800744 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100745
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200746 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100747
danilchap56036ff2016-03-22 11:14:09 -0700748 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800749
Erik Språngf7c57762015-12-04 10:40:35 +0100750 auto it = report_flags_.begin();
751 while (it != report_flags_.end()) {
752 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800753 RTC_DCHECK(builder_it != builders_.end())
754 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100755 if (it->is_volatile) {
756 report_flags_.erase(it++);
757 } else {
758 ++it;
759 }
760
761 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700762 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100763 if (packet.get() == nullptr)
764 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800765 // If there is a BYE, don't append now - save it and append it
766 // at the end later.
767 if (builder_it->first == kRtcpBye) {
768 packet_bye = std::move(packet);
769 } else {
770 container.Append(packet.release());
771 }
772 }
773
774 // Append the BYE now at the end
775 if (packet_bye) {
776 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100777 }
778
779 if (packet_type_counter_observer_ != nullptr) {
780 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
781 remote_ssrc_, packet_type_counter_);
782 }
783
784 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800785 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000786 }
Erik Språng61be2a42015-04-27 13:32:52 +0200787
nisse6f142eb2017-02-21 07:32:47 -0800788 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100789 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000790}
791
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200792void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200793 bool generate_report;
794 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
795 // Report type already explicitly set, don't automatically populate.
796 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700797 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200798 } else {
799 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700800 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
801 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200802 if (generate_report)
803 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000804 }
805
Erik Språng0ea42d32015-06-25 14:46:16 +0200806 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200807 SetFlag(kRtcpSdes, true);
808
Erik Språng242e22b2015-05-11 10:17:43 +0200809 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800810 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
811 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
812 SetFlag(kRtcpAnyExtendedReports, true);
813 }
Erik Språng242e22b2015-05-11 10:17:43 +0200814
815 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800816 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000817
danilchap47a740b2015-12-15 00:30:07 -0800818 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200819 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200820 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
821 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
822 if (send_bitrate_kbit != 0)
823 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000824 }
Erik Språng61be2a42015-04-27 13:32:52 +0200825 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
826 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200827 }
danilchap47a740b2015-12-15 00:30:07 -0800828 // The interval between RTCP packets is varied randomly over the
829 // range [1/2,3/2] times the calculated interval.
830 uint32_t timeToNext =
831 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200832 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000833
Per83d09102016-04-15 14:59:13 +0200834 if (receive_statistics_) {
835 StatisticianMap statisticians =
836 receive_statistics_->GetActiveStatisticians();
837 RTC_DCHECK(report_blocks_.empty());
838 for (auto& it : statisticians) {
839 AddReportBlock(feedback_state, it.first, it.second);
840 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000841 }
842 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000843}
844
danilchapa72e7342015-12-22 08:07:45 -0800845bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
846 uint32_t ssrc,
847 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000848 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000849 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000850 if (!statistician->GetStatistics(&stats, true))
851 return false;
danilchapa72e7342015-12-22 08:07:45 -0800852
853 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
854 LOG(LS_WARNING) << "Too many report blocks.";
855 return false;
856 }
857 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
858 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700859 block->SetMediaSsrc(ssrc);
860 block->SetFractionLost(stats.fraction_lost);
861 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800862 report_blocks_.erase(ssrc);
863 LOG(LS_WARNING) << "Cumulative lost is oversized.";
864 return false;
865 }
danilchap822a16f2016-09-27 09:27:47 -0700866 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
867 block->SetJitter(stats.jitter);
868 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000869
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200870 // TODO(sprang): Do we really need separate time stamps for each report?
871 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800872 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000873
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200874 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000875 if ((feedback_state.last_rr_ntp_secs != 0) ||
876 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200877 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800878 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000879
Erik Språng61be2a42015-04-27 13:32:52 +0200880 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
881 receiveTime <<= 16;
882 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883
danilchap822a16f2016-09-27 09:27:47 -0700884 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000886 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000887}
888
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000889void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800890 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700891 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000892 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000893}
894
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000895int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
896 uint32_t name,
897 const uint8_t* data,
898 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200899 if (length % 4 != 0) {
900 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
901 return -1;
902 }
danilchap56036ff2016-03-22 11:14:09 -0700903 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000904
Erik Språng242e22b2015-05-11 10:17:43 +0200905 SetFlag(kRtcpApp, true);
906 app_sub_type_ = subType;
907 app_name_ = name;
908 app_data_.reset(new uint8_t[length]);
909 app_length_ = length;
910 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200911 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000912}
913
spranga790d832016-12-02 07:29:44 -0800914// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200915int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700916 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800917 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000918
sprang5e38c962016-12-01 05:18:09 -0800919 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200920 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000921}
922
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000923void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700924 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200925 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000926}
927
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000928bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700929 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200930 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000931}
932
danilchap853ecb22016-08-22 08:26:15 -0700933void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700934 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700935 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700936 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000937}
Erik Språng61be2a42015-04-27 13:32:52 +0200938
sprang5e38c962016-12-01 05:18:09 -0800939void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
940 if (type & kRtcpAnyExtendedReports) {
941 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
942 } else {
943 report_flags_.insert(ReportFlag(type, is_volatile));
944 }
Erik Språng242e22b2015-05-11 10:17:43 +0200945}
946
947void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
948 bool is_volatile) {
949 for (RTCPPacketType type : types)
950 SetFlag(type, is_volatile);
951}
952
sprang5e38c962016-12-01 05:18:09 -0800953bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200954 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
955}
956
sprang5e38c962016-12-01 05:18:09 -0800957bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200958 auto it = report_flags_.find(ReportFlag(type, false));
959 if (it == report_flags_.end())
960 return false;
961 if (it->is_volatile || forced)
962 report_flags_.erase((it));
963 return true;
964}
965
966bool RTCPSender::AllVolatileFlagsConsumed() const {
967 for (const ReportFlag& flag : report_flags_) {
968 if (flag.is_volatile)
969 return false;
970 }
971 return true;
972}
973
sprang5e38c962016-12-01 05:18:09 -0800974void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
975 rtc::CritScope lock(&critical_section_rtcp_sender_);
976 video_bitrate_allocation_.emplace(bitrate);
977 SetFlag(kRtcpAnyExtendedReports, true);
978}
979
sprang233bd872015-09-08 13:25:16 -0700980bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700981 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
982 public:
terelius429c3452016-01-21 05:42:04 -0800983 Sender(Transport* transport, RtcEventLog* event_log)
984 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700985
986 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800987 if (transport_->SendRtcp(data, length)) {
988 if (event_log_) {
perkj77cd58e2017-05-30 03:52:10 -0700989 event_log_->LogRtcpPacket(kOutgoingPacket, data, length);
terelius429c3452016-01-21 05:42:04 -0800990 }
991 } else {
sprang233bd872015-09-08 13:25:16 -0700992 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800993 }
sprang233bd872015-09-08 13:25:16 -0700994 }
995
996 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800997 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700998 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800999 // TODO(terelius): We would like to
1000 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1001 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1002 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001003
nisse6f142eb2017-02-21 07:32:47 -08001004 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -08001005 {
1006 rtc::CritScope lock(&critical_section_rtcp_sender_);
1007 if (method_ == RtcpMode::kOff)
1008 return false;
nisse6f142eb2017-02-21 07:32:47 -08001009 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001010 }
1011
nisse6f142eb2017-02-21 07:32:47 -08001012 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001013 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001014 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001015 !sender.send_failure_;
1016}
1017
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001018} // namespace webrtc