blob: d79e199e8c7b91b9200b7c92e07b1b32a1e4d190 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Danil Chapovalov70ffead2016-07-20 15:26:59 +020015#include <utility>
16
Mirko Bonadei71207422017-09-15 13:58:09 +020017#include "common_types.h" // NOLINT(build/include)
Elad Alon4a87e1c2017-10-03 16:11:34 +020018#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "logging/rtc_event_log/rtc_event_log.h"
20#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
21#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
22#include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
23#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
24#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
25#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
26#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
27#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
28#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
29#include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
30#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
31#include "modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
32#include "modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
33#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
34#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
35#include "modules/rtp_rtcp/source/time_util.h"
36#include "modules/rtp_rtcp/source/tmmbr_help.h"
37#include "rtc_base/checks.h"
38#include "rtc_base/constructormagic.h"
39#include "rtc_base/logging.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020040#include "rtc_base/ptr_util.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020041#include "rtc_base/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000042
niklase@google.com470e71d2011-07-07 08:21:25 +000043namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000044
sprang5e38c962016-12-01 05:18:09 -080045namespace {
46const uint32_t kRtcpAnyExtendedReports =
47 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
48 kRtcpXrTargetBitrate;
49} // namespace
50
Erik Språng61be2a42015-04-27 13:32:52 +020051NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080052 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000053
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000054NACKStringBuilder::~NACKStringBuilder() {}
55
danilchap162abd32015-12-10 02:39:40 -080056void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020057 if (count_ == 0) {
58 stream_ << nack;
59 } else if (nack == prevNack_ + 1) {
60 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020061 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020062 if (consecutive_) {
63 stream_ << "-" << prevNack_;
64 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000065 }
Erik Språng242e22b2015-05-11 10:17:43 +020066 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020067 }
Erik Språng242e22b2015-05-11 10:17:43 +020068 count_++;
69 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000070}
71
Erik Språng61be2a42015-04-27 13:32:52 +020072std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020073 if (consecutive_) {
74 stream_ << "-" << prevNack_;
75 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020076 }
Erik Språng242e22b2015-05-11 10:17:43 +020077 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000078}
79
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000080RTCPSender::FeedbackState::FeedbackState()
nisse40ba3ad2017-03-17 07:04:00 -070081 : packets_sent(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000082 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000083 send_bitrate(0),
84 last_rr_ntp_secs(0),
85 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000086 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020087 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080088 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000089
danilchap2f7dea12016-01-13 02:03:04 -080090class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010091 public rtcp::RtcpPacket::PacketReadyCallback {
92 public:
terelius429c3452016-01-21 05:42:04 -080093 PacketContainer(Transport* transport, RtcEventLog* event_log)
94 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010095 virtual ~PacketContainer() {
96 for (RtcpPacket* packet : appended_packets_)
97 delete packet;
98 }
99
100 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800101 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100102 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800103 if (event_log_) {
Elad Alon4a87e1c2017-10-03 16:11:34 +0200104 event_log_->Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(
105 rtc::ArrayView<const uint8_t>(data, length)));
terelius429c3452016-01-21 05:42:04 -0800106 }
107 }
Erik Språngf7c57762015-12-04 10:40:35 +0100108 }
109
danilchap41befce2016-03-30 11:11:51 -0700110 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800111 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700112 uint8_t buffer[IP_PACKET_SIZE];
113 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100114 return bytes_sent_;
115 }
116
117 private:
118 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800119 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100120 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800121
122 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100123};
124
125class RTCPSender::RtcpContext {
126 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200127 RtcpContext(const FeedbackState& feedback_state,
128 int32_t nack_size,
129 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800130 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100131 : feedback_state_(feedback_state),
132 nack_size_(nack_size),
133 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800134 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200135
Erik Språngf7c57762015-12-04 10:40:35 +0100136 const FeedbackState& feedback_state_;
137 const int32_t nack_size_;
138 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800139 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200140};
141
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000143 bool audio,
144 Clock* clock,
danilchapf5f793c2017-07-27 04:44:18 -0700145 ReceiveStatisticsProvider* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700146 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800147 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700148 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200149 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200150 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800151 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700152 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800153 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700154 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 using_nack_(false),
156 sending_(false),
157 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200158 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700159 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000160 last_rtp_timestamp_(0),
161 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200162 ssrc_(0),
163 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000164 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000167
Erik Språng242e22b2015-05-11 10:17:43 +0200168 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
danilchap2b616392016-08-18 06:17:42 -0700170 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200171 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800172 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000173
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200175 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200176 app_data_(nullptr),
177 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000178
Erik Språng242e22b2015-05-11 10:17:43 +0200179 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000180 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700181 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200182
183 builders_[kRtcpSr] = &RTCPSender::BuildSR;
184 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200185 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200186 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
187 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200188 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
189 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
190 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
191 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
192 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
193 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800194 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000195}
196
danilchap162abd32015-12-10 02:39:40 -0800197RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000198
pbosda903ea2015-10-02 02:36:56 -0700199RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700200 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200201 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
skvlad1c392cc2016-04-01 14:46:44 -0700204void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700205 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000206
skvlad1c392cc2016-04-01 14:46:44 -0700207 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
208 // When switching on, reschedule the next packet
209 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200210 clock_->TimeInMilliseconds() +
211 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700212 }
213 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
Erik Språng61be2a42015-04-27 13:32:52 +0200216bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700217 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200218 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
Erik Språng61be2a42015-04-27 13:32:52 +0200221int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
222 bool sending) {
223 bool sendRTCPBye = false;
224 {
danilchap56036ff2016-03-22 11:14:09 -0700225 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000226
pbosda903ea2015-10-02 02:36:56 -0700227 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200228 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200229 // Trigger RTCP bye
230 sendRTCPBye = true;
231 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000232 }
Erik Språng242e22b2015-05-11 10:17:43 +0200233 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200234 }
235 if (sendRTCPBye)
236 return SendRTCP(feedback_state, kRtcpBye);
237 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000238}
239
Erik Språng61be2a42015-04-27 13:32:52 +0200240bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700241 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200242 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000243}
244
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700246 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200247 remb_enabled_ = enable;
danilchapba6aa902017-04-18 06:57:02 -0700248 if (!enable) {
249 // Stop sending remb each report until it is reenabled and remb data set.
250 ConsumeFlag(kRtcpRemb, true);
251 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000252}
253
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000254void RTCPSender::SetREMBData(uint32_t bitrate,
255 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700256 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200257 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000258 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000259
Erik Språng242e22b2015-05-11 10:17:43 +0200260 if (remb_enabled_)
261 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000262 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
263 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200264 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000265}
266
Erik Språng61be2a42015-04-27 13:32:52 +0200267bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700268 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200269 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000270}
271
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000272void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700273 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200274 if (enable) {
275 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
276 } else {
277 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
278 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000279}
280
nisse284542b2017-01-10 08:58:32 -0800281void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800282 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800283 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700284}
285
danilchap71fead22016-08-18 02:01:49 -0700286void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700287 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700288 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289}
290
291void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
292 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700293 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000294 last_rtp_timestamp_ = rtp_timestamp;
295 if (capture_time_ms < 0) {
296 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200297 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000298 } else {
299 last_frame_capture_time_ms_ = capture_time_ms;
300 }
301}
302
nisse14adba72017-03-20 03:52:39 -0700303uint32_t RTCPSender::SSRC() const {
304 rtc::CritScope lock(&critical_section_rtcp_sender_);
305 return ssrc_;
306}
307
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000308void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700309 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000310
Erik Språng242e22b2015-05-11 10:17:43 +0200311 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200312 // not first SetSSRC, probably due to a collision
313 // schedule a new RTCP report
314 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200315 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200316 }
Erik Språng242e22b2015-05-11 10:17:43 +0200317 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
Erik Språng61be2a42015-04-27 13:32:52 +0200320void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700321 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200322 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000323}
324
Peter Boström9ba52f82015-06-01 14:12:28 +0200325int32_t RTCPSender::SetCNAME(const char* c_name) {
326 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000327 return -1;
328
kwiberg352444f2016-11-28 15:58:53 -0800329 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700330 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200331 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000332 return 0;
333}
334
Erik Språng0ea42d32015-06-25 14:46:16 +0200335int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700336 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800337 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700338 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700339 // One spot is reserved for ssrc_/cname_.
340 // TODO(danilchap): Add support for more than 30 contributes by sending
341 // several sdes packets.
342 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200344
345 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return 0;
347}
348
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000349int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700350 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200351 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352
Erik Språng242e22b2015-05-11 10:17:43 +0200353 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000354 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200355
Erik Språng242e22b2015-05-11 10:17:43 +0200356 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000357 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000358}
359
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000360bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800361 /*
362 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
danilchap162abd32015-12-10 02:39:40 -0800364 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
365 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
366 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
368
danilchap162abd32015-12-10 02:39:40 -0800369 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000370
danilchap162abd32015-12-10 02:39:40 -0800371 MAX RTCP BW is 5% if the session BW
372 A send report is approximately 65 bytes inc CNAME
373 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000374
danilchap162abd32015-12-10 02:39:40 -0800375 The RECOMMENDED value for the reduced minimum in seconds is 360
376 divided by the session bandwidth in kilobits/second. This minimum
377 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000378
danilchap162abd32015-12-10 02:39:40 -0800379 If the participant has not yet sent an RTCP packet (the variable
380 initial is true), the constant Tmin is set to 2.5 seconds, else it
381 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000382
danilchap162abd32015-12-10 02:39:40 -0800383 The interval between RTCP packets is varied randomly over the
384 range [0.5,1.5] times the calculated interval to avoid unintended
385 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
danilchap162abd32015-12-10 02:39:40 -0800387 if we send
388 If the participant is a sender (we_sent true), the constant C is
389 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
390 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
391 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
danilchap162abd32015-12-10 02:39:40 -0800393 if we receive only
394 If we_sent is not true, the constant C is set
395 to the average RTCP packet size divided by 75% of the RTCP
396 bandwidth. The constant n is set to the number of receivers
397 (members - senders). If the number of senders is greater than
398 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 reconsideration NOT required for peer-to-peer
401 "timer reconsideration" is
402 employed. This algorithm implements a simple back-off mechanism
403 which causes users to hold back RTCP packet transmission if the
404 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 n = number of members
407 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
danilchap162abd32015-12-10 02:39:40 -0800411 4. The calculated interval T is set to a number uniformly distributed
412 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
danilchap162abd32015-12-10 02:39:40 -0800414 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
415 for the fact that the timer reconsideration algorithm converges to
416 a value of the RTCP bandwidth below the intended average
417 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
Erik Språng242e22b2015-05-11 10:17:43 +0200419 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000420
danilchap56036ff2016-03-22 11:14:09 -0700421 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000422
pbosda903ea2015-10-02 02:36:56 -0700423 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000424 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000425
Erik Språng242e22b2015-05-11 10:17:43 +0200426 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200427 // for video key-frames we want to send the RTCP before the large key-frame
428 // if we have a 100 ms margin
429 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
430 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000431
Erik Språng242e22b2015-05-11 10:17:43 +0200432 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200433 return true;
434 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200435 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200436 // wrap
437 return true;
438 }
439 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000440}
441
danilchap56036ff2016-03-22 11:14:09 -0700442std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200443 // Timestamp shouldn't be estimated before first media frame.
444 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200445 // The timestamp of this RTCP packet should be estimated as the timestamp of
446 // the frame being captured at this moment. We are calculating that
447 // timestamp as the last frame's timestamp + the time since the last frame
448 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700449 uint32_t rtp_rate =
450 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200451 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700452 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700453 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
Erik Språngf7c57762015-12-04 10:40:35 +0100455 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700456 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800457 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700458 report->SetRtpTimestamp(rtp_timestamp);
459 report->SetPacketCount(ctx.feedback_state_.packets_sent);
460 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
danilchap96b69bd2017-07-25 09:15:14 -0700461 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språngf7c57762015-12-04 10:40:35 +0100462
danilchap56036ff2016-03-22 11:14:09 -0700463 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000464}
465
danilchap56036ff2016-03-22 11:14:09 -0700466std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100467 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200468 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800469 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
Erik Språngf7c57762015-12-04 10:40:35 +0100471 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700472 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200473
danilchap74e8df8f2017-03-16 08:04:08 -0700474 for (const auto& it : csrc_cnames_)
475 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200476
danilchap56036ff2016-03-22 11:14:09 -0700477 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000478}
479
danilchap56036ff2016-03-22 11:14:09 -0700480std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100481 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700482 report->SetSenderSsrc(ssrc_);
danilchap96b69bd2017-07-25 09:15:14 -0700483 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språng61be2a42015-04-27 13:32:52 +0200484
danilchap56036ff2016-03-22 11:14:09 -0700485 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000486}
487
danilchap56036ff2016-03-22 11:14:09 -0700488std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100489 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700490 pli->SetSenderSsrc(ssrc_);
491 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200492
Erik Språng242e22b2015-05-11 10:17:43 +0200493 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
494 "RTCPSender::PLI");
495 ++packet_type_counter_.pli_packets;
496 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
497 ssrc_, packet_type_counter_.pli_packets);
498
danilchap56036ff2016-03-22 11:14:09 -0700499 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200500}
501
danilchap56036ff2016-03-22 11:14:09 -0700502std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800503 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
Erik Språngf7c57762015-12-04 10:40:35 +0100505 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700506 fir->SetSenderSsrc(ssrc_);
507 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200508
509 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
510 "RTCPSender::FIR");
511 ++packet_type_counter_.fir_packets;
512 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
513 ssrc_, packet_type_counter_.fir_packets);
514
danilchap56036ff2016-03-22 11:14:09 -0700515 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000516}
517
danilchap56036ff2016-03-22 11:14:09 -0700518std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100519 const RtcpContext& ctx) {
520 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700521 remb->SetSenderSsrc(ssrc_);
522 remb->SetBitrateBps(remb_bitrate_);
523 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200524
Erik Språng242e22b2015-05-11 10:17:43 +0200525 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
526 "RTCPSender::REMB");
527
danilchap56036ff2016-03-22 11:14:09 -0700528 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000529}
530
Erik Språng61be2a42015-04-27 13:32:52 +0200531void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700532 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700533 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000534}
535
danilchap56036ff2016-03-22 11:14:09 -0700536std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100537 const RtcpContext& ctx) {
538 if (ctx.feedback_state_.module == nullptr)
539 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200540 // Before sending the TMMBR check the received TMMBN, only an owner is
541 // allowed to raise the bitrate:
542 // * If the sender is an owner of the TMMBN -> send TMMBR
543 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000544
Erik Språng61be2a42015-04-27 13:32:52 +0200545 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700546 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
Erik Språng242e22b2015-05-11 10:17:43 +0200548 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
549 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200550 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700551 std::vector<rtcp::TmmbItem> candidates =
552 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000553
danilchap2b616392016-08-18 06:17:42 -0700554 if (!candidates.empty()) {
555 for (const auto& candidate : candidates) {
556 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
557 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100558 // Do not send the same tuple.
559 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200560 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000561 }
danilchap2b616392016-08-18 06:17:42 -0700562 if (!tmmbr_owner) {
563 // Use received bounding set as candidate set.
564 // Add current tuple.
565 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000566
danilchap2b616392016-08-18 06:17:42 -0700567 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700568 std::vector<rtcp::TmmbItem> bounding =
569 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700570 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
571 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100572 // Did not enter bounding set, no meaning to send this request.
573 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200574 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000575 }
Erik Språng61be2a42015-04-27 13:32:52 +0200576 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000577
danilchap2b616392016-08-18 06:17:42 -0700578 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100579 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700580
Erik Språngf7c57762015-12-04 10:40:35 +0100581 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700582 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800583 rtcp::TmmbItem request;
584 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700585 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800586 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700587 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100588
danilchap56036ff2016-03-22 11:14:09 -0700589 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200590}
591
danilchap56036ff2016-03-22 11:14:09 -0700592std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100593 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100594 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700595 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700596 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
597 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700598 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000599 }
Erik Språng61be2a42015-04-27 13:32:52 +0200600 }
sprangd83df502015-08-27 01:05:08 -0700601
danilchap56036ff2016-03-22 11:14:09 -0700602 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000603}
604
danilchap56036ff2016-03-22 11:14:09 -0700605std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100606 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700607 app->SetSsrc(ssrc_);
608 app->SetSubType(app_sub_type_);
609 app->SetName(app_name_);
610 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200611
danilchap56036ff2016-03-22 11:14:09 -0700612 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200613}
614
danilchap56036ff2016-03-22 11:14:09 -0700615std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100616 const RtcpContext& ctx) {
617 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700618 nack->SetSenderSsrc(ssrc_);
619 nack->SetMediaSsrc(remote_ssrc_);
620 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200621
622 // Report stats.
623 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100624 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
625 stringBuilder.PushNACK(ctx.nack_list_[idx]);
626 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200627 }
Erik Språng61be2a42015-04-27 13:32:52 +0200628 packet_type_counter_.nack_requests = nack_stats_.requests();
629 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200630
631 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
632 "RTCPSender::NACK", "nacks",
633 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
634 ++packet_type_counter_.nack_packets;
635 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
636 ssrc_, packet_type_counter_.nack_packets);
637
danilchap56036ff2016-03-22 11:14:09 -0700638 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200639}
640
danilchap56036ff2016-03-22 11:14:09 -0700641std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100642 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700643 bye->SetSenderSsrc(ssrc_);
644 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700645
danilchap56036ff2016-03-22 11:14:09 -0700646 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000647}
648
sprang5e38c962016-12-01 05:18:09 -0800649std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100650 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800651 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700652 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000653
sprang5e38c962016-12-01 05:18:09 -0800654 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
655 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800656 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800657 xr->SetRrtr(rrtr);
658 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000659
sprang5e38c962016-12-01 05:18:09 -0800660 if (ctx.feedback_state_.has_last_xr_rr) {
661 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
662 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000663
sprang5e38c962016-12-01 05:18:09 -0800664 if (video_bitrate_allocation_) {
665 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000666
sprang5e38c962016-12-01 05:18:09 -0800667 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
668 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
669 uint32_t layer_bitrate_bps =
670 video_bitrate_allocation_->GetBitrate(sl, tl);
671 if (layer_bitrate_bps > 0)
672 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
673 }
674 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000675
sprang5e38c962016-12-01 05:18:09 -0800676 xr->SetTargetBitrate(target_bitrate);
677 video_bitrate_allocation_.reset();
678 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200679
sprang5e38c962016-12-01 05:18:09 -0800680 if (xr_voip_metric_) {
681 rtcp::VoipMetric voip;
682 voip.SetMediaSsrc(remote_ssrc_);
683 voip.SetVoipMetric(*xr_voip_metric_);
684 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000685
sprang5e38c962016-12-01 05:18:09 -0800686 xr->SetVoipMetric(voip);
687 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200688
sprang5e38c962016-12-01 05:18:09 -0800689 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000690}
691
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000692int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200693 RTCPPacketType packetType,
694 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700695 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200696 return SendCompoundRTCP(
697 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700698 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200699}
700
701int32_t RTCPSender::SendCompoundRTCP(
702 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100703 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200704 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700705 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800706 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800707 size_t max_packet_size;
708
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000709 {
danilchap56036ff2016-03-22 11:14:09 -0700710 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700711 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200712 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
713 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000714 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200715 // Add all flags as volatile. Non volatile entries will not be overwritten.
716 // All new volatile flags added will be consumed by the end of this call.
717 SetFlags(packet_types, true);
718
719 // Prevent sending streams to send SR before any media has been sent.
720 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
721 if (!can_calculate_rtp_timestamp) {
722 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
723 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
724 bool sender_report = consumed_report_flag || consumed_sr_flag;
725 if (sender_report && AllVolatileFlagsConsumed()) {
726 // This call was for Sender Report and nothing else.
727 return 0;
728 }
729 if (sending_ && method_ == RtcpMode::kCompound) {
730 // Not allowed to send any RTCP packet without sender report.
731 return -1;
732 }
733 }
734
735 if (packet_type_counter_.first_packet_time_ms == -1)
736 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100737
738 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700739 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800740 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100741
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200742 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100743
danilchap56036ff2016-03-22 11:14:09 -0700744 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800745
Erik Språngf7c57762015-12-04 10:40:35 +0100746 auto it = report_flags_.begin();
747 while (it != report_flags_.end()) {
748 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800749 RTC_DCHECK(builder_it != builders_.end())
750 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100751 if (it->is_volatile) {
752 report_flags_.erase(it++);
753 } else {
754 ++it;
755 }
756
757 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700758 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100759 if (packet.get() == nullptr)
760 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800761 // If there is a BYE, don't append now - save it and append it
762 // at the end later.
763 if (builder_it->first == kRtcpBye) {
764 packet_bye = std::move(packet);
765 } else {
766 container.Append(packet.release());
767 }
768 }
769
770 // Append the BYE now at the end
771 if (packet_bye) {
772 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100773 }
774
775 if (packet_type_counter_observer_ != nullptr) {
776 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
777 remote_ssrc_, packet_type_counter_);
778 }
779
780 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800781 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000782 }
Erik Språng61be2a42015-04-27 13:32:52 +0200783
nisse6f142eb2017-02-21 07:32:47 -0800784 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100785 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000786}
787
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200788void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200789 bool generate_report;
790 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
791 // Report type already explicitly set, don't automatically populate.
792 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700793 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200794 } else {
795 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700796 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
797 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200798 if (generate_report)
799 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000800 }
801
Erik Språng0ea42d32015-06-25 14:46:16 +0200802 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200803 SetFlag(kRtcpSdes, true);
804
Erik Språng242e22b2015-05-11 10:17:43 +0200805 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800806 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
807 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
808 SetFlag(kRtcpAnyExtendedReports, true);
809 }
Erik Språng242e22b2015-05-11 10:17:43 +0200810
811 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800812 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000813
danilchap47a740b2015-12-15 00:30:07 -0800814 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200815 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200816 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
817 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
818 if (send_bitrate_kbit != 0)
819 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000820 }
Erik Språng61be2a42015-04-27 13:32:52 +0200821 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
822 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200823 }
danilchap47a740b2015-12-15 00:30:07 -0800824 // The interval between RTCP packets is varied randomly over the
825 // range [1/2,3/2] times the calculated interval.
826 uint32_t timeToNext =
827 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200828 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000829
danilchap96b69bd2017-07-25 09:15:14 -0700830 // RtcpSender expected to be used for sending either just sender reports
831 // or just receiver reports.
832 RTC_DCHECK(!(IsFlagPresent(kRtcpSr) && IsFlagPresent(kRtcpRr)));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000833 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000834}
835
danilchap96b69bd2017-07-25 09:15:14 -0700836std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
837 const FeedbackState& feedback_state) {
838 std::vector<rtcp::ReportBlock> result;
839 if (!receive_statistics_)
840 return result;
danilchapa72e7342015-12-22 08:07:45 -0800841
danilchapf5f793c2017-07-27 04:44:18 -0700842 // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
843 // compound rtcp packet when single rtcp module is used for multiple media
844 // streams.
845 result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
danilchap96b69bd2017-07-25 09:15:14 -0700846
847 if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
848 (feedback_state.last_rr_ntp_frac != 0))) {
849 // Get our NTP as late as possible to avoid a race.
850 uint32_t now = CompactNtp(clock_->CurrentNtpTime());
851
852 uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
853 receive_time <<= 16;
854 receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
855
856 uint32_t delay_since_last_sr = now - receive_time;
857 // TODO(danilchap): Instead of setting same value on all report blocks,
858 // set only when media_ssrc match sender ssrc of the sender report
859 // remote times were taken from.
860 for (auto& report_block : result) {
861 report_block.SetLastSr(feedback_state.remote_sr);
862 report_block.SetDelayLastSr(delay_since_last_sr);
863 }
danilchapa72e7342015-12-22 08:07:45 -0800864 }
danilchap96b69bd2017-07-25 09:15:14 -0700865 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000866}
867
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000868void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800869 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700870 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000871 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000872}
873
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000874int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
875 uint32_t name,
876 const uint8_t* data,
877 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200878 if (length % 4 != 0) {
879 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
880 return -1;
881 }
danilchap56036ff2016-03-22 11:14:09 -0700882 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000883
Erik Språng242e22b2015-05-11 10:17:43 +0200884 SetFlag(kRtcpApp, true);
885 app_sub_type_ = subType;
886 app_name_ = name;
887 app_data_.reset(new uint8_t[length]);
888 app_length_ = length;
889 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200890 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000891}
892
spranga790d832016-12-02 07:29:44 -0800893// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200894int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700895 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800896 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000897
sprang5e38c962016-12-01 05:18:09 -0800898 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200899 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000900}
901
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000902void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700903 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200904 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000905}
906
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000907bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700908 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200909 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000910}
911
danilchap853ecb22016-08-22 08:26:15 -0700912void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700913 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700914 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700915 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000916}
Erik Språng61be2a42015-04-27 13:32:52 +0200917
sprang5e38c962016-12-01 05:18:09 -0800918void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
919 if (type & kRtcpAnyExtendedReports) {
920 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
921 } else {
922 report_flags_.insert(ReportFlag(type, is_volatile));
923 }
Erik Språng242e22b2015-05-11 10:17:43 +0200924}
925
926void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
927 bool is_volatile) {
928 for (RTCPPacketType type : types)
929 SetFlag(type, is_volatile);
930}
931
sprang5e38c962016-12-01 05:18:09 -0800932bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200933 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
934}
935
sprang5e38c962016-12-01 05:18:09 -0800936bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200937 auto it = report_flags_.find(ReportFlag(type, false));
938 if (it == report_flags_.end())
939 return false;
940 if (it->is_volatile || forced)
941 report_flags_.erase((it));
942 return true;
943}
944
945bool RTCPSender::AllVolatileFlagsConsumed() const {
946 for (const ReportFlag& flag : report_flags_) {
947 if (flag.is_volatile)
948 return false;
949 }
950 return true;
951}
952
sprang5e38c962016-12-01 05:18:09 -0800953void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
954 rtc::CritScope lock(&critical_section_rtcp_sender_);
955 video_bitrate_allocation_.emplace(bitrate);
956 SetFlag(kRtcpAnyExtendedReports, true);
957}
958
sprang233bd872015-09-08 13:25:16 -0700959bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700960 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
961 public:
terelius429c3452016-01-21 05:42:04 -0800962 Sender(Transport* transport, RtcEventLog* event_log)
963 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700964
965 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800966 if (transport_->SendRtcp(data, length)) {
967 if (event_log_) {
Elad Alon4a87e1c2017-10-03 16:11:34 +0200968 event_log_->Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(
969 rtc::ArrayView<const uint8_t>(data, length)));
terelius429c3452016-01-21 05:42:04 -0800970 }
971 } else {
sprang233bd872015-09-08 13:25:16 -0700972 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800973 }
sprang233bd872015-09-08 13:25:16 -0700974 }
975
976 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800977 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700978 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800979 // TODO(terelius): We would like to
980 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
981 // but we can't because of an incorrect warning (C4822) in MVS 2013.
982 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700983
nisse6f142eb2017-02-21 07:32:47 -0800984 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800985 {
986 rtc::CritScope lock(&critical_section_rtcp_sender_);
987 if (method_ == RtcpMode::kOff)
988 return false;
nisse6f142eb2017-02-21 07:32:47 -0800989 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -0800990 }
991
nisse6f142eb2017-02-21 07:32:47 -0800992 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -0700993 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -0800994 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -0700995 !sender.send_failure_;
996}
997
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000998} // namespace webrtc