blob: 15b7e2fa96879e15bc29b2cb3cf5857a3e315545 [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),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700158 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000159 last_rtp_timestamp_(0),
160 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200161 ssrc_(0),
162 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000163 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
danilchap2b616392016-08-18 06:17:42 -0700169 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800171 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200174 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200175 app_data_(nullptr),
176 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
Erik Språng242e22b2015-05-11 10:17:43 +0200178 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000179 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700180 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200181
182 builders_[kRtcpSr] = &RTCPSender::BuildSR;
183 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200184 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200185 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
186 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200187 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
188 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
189 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
190 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
191 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
192 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800193 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
danilchap162abd32015-12-10 02:39:40 -0800196RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
pbosda903ea2015-10-02 02:36:56 -0700198RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700199 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200200 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
skvlad1c392cc2016-04-01 14:46:44 -0700203void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700204 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000205
skvlad1c392cc2016-04-01 14:46:44 -0700206 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
207 // When switching on, reschedule the next packet
208 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200209 clock_->TimeInMilliseconds() +
210 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700211 }
212 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213}
214
Erik Språng61be2a42015-04-27 13:32:52 +0200215bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700216 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200217 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
221 bool sending) {
222 bool sendRTCPBye = false;
223 {
danilchap56036ff2016-03-22 11:14:09 -0700224 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
pbosda903ea2015-10-02 02:36:56 -0700226 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200228 // Trigger RTCP bye
229 sendRTCPBye = true;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Erik Språng242e22b2015-05-11 10:17:43 +0200232 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200233 }
234 if (sendRTCPBye)
235 return SendRTCP(feedback_state, kRtcpBye);
236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200239void RTCPSender::SetRemb(uint32_t bitrate, const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700240 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200241 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000242 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000243
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200244 SetFlag(kRtcpRemb, /*is_volatile=*/false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000245 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
246 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200247 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000248}
249
Danil Chapovalovf74d6412017-10-18 13:32:57 +0200250void RTCPSender::UnsetRemb() {
251 rtc::CritScope lock(&critical_section_rtcp_sender_);
252 // Stop sending REMB each report until it is reenabled and REMB data set.
253 ConsumeFlag(kRtcpRemb, /*forced=*/true);
254}
255
Erik Språng61be2a42015-04-27 13:32:52 +0200256bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700257 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200258 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000259}
260
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000261void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700262 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200263 if (enable) {
264 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
265 } else {
266 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
267 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000268}
269
nisse284542b2017-01-10 08:58:32 -0800270void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800271 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800272 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700273}
274
danilchap71fead22016-08-18 02:01:49 -0700275void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700276 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700277 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000278}
279
280void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
281 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700282 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000283 last_rtp_timestamp_ = rtp_timestamp;
284 if (capture_time_ms < 0) {
285 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200286 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287 } else {
288 last_frame_capture_time_ms_ = capture_time_ms;
289 }
290}
291
nisse14adba72017-03-20 03:52:39 -0700292uint32_t RTCPSender::SSRC() const {
293 rtc::CritScope lock(&critical_section_rtcp_sender_);
294 return ssrc_;
295}
296
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000297void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700298 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000299
Erik Språng242e22b2015-05-11 10:17:43 +0200300 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200301 // not first SetSSRC, probably due to a collision
302 // schedule a new RTCP report
303 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200304 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200305 }
Erik Språng242e22b2015-05-11 10:17:43 +0200306 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000307}
308
Erik Språng61be2a42015-04-27 13:32:52 +0200309void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700310 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200311 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000312}
313
Peter Boström9ba52f82015-06-01 14:12:28 +0200314int32_t RTCPSender::SetCNAME(const char* c_name) {
315 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000316 return -1;
317
kwiberg352444f2016-11-28 15:58:53 -0800318 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200320 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000321 return 0;
322}
323
Erik Språng0ea42d32015-06-25 14:46:16 +0200324int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700325 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800326 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700327 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700328 // One spot is reserved for ssrc_/cname_.
329 // TODO(danilchap): Add support for more than 30 contributes by sending
330 // several sdes packets.
331 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000332 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200333
334 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000335 return 0;
336}
337
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000338int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700339 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200340 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341
Erik Språng242e22b2015-05-11 10:17:43 +0200342 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200344
Erik Språng242e22b2015-05-11 10:17:43 +0200345 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000346 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000347}
348
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000349bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800350 /*
351 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000352
danilchap162abd32015-12-10 02:39:40 -0800353 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
354 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
355 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000356
357
danilchap162abd32015-12-10 02:39:40 -0800358 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000359
danilchap162abd32015-12-10 02:39:40 -0800360 MAX RTCP BW is 5% if the session BW
361 A send report is approximately 65 bytes inc CNAME
362 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000363
danilchap162abd32015-12-10 02:39:40 -0800364 The RECOMMENDED value for the reduced minimum in seconds is 360
365 divided by the session bandwidth in kilobits/second. This minimum
366 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
danilchap162abd32015-12-10 02:39:40 -0800368 If the participant has not yet sent an RTCP packet (the variable
369 initial is true), the constant Tmin is set to 2.5 seconds, else it
370 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
danilchap162abd32015-12-10 02:39:40 -0800372 The interval between RTCP packets is varied randomly over the
373 range [0.5,1.5] times the calculated interval to avoid unintended
374 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 if we send
377 If the participant is a sender (we_sent true), the constant C is
378 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
379 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
380 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 if we receive only
383 If we_sent is not true, the constant C is set
384 to the average RTCP packet size divided by 75% of the RTCP
385 bandwidth. The constant n is set to the number of receivers
386 (members - senders). If the number of senders is greater than
387 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000388
danilchap162abd32015-12-10 02:39:40 -0800389 reconsideration NOT required for peer-to-peer
390 "timer reconsideration" is
391 employed. This algorithm implements a simple back-off mechanism
392 which causes users to hold back RTCP packet transmission if the
393 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 n = number of members
396 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
danilchap162abd32015-12-10 02:39:40 -0800400 4. The calculated interval T is set to a number uniformly distributed
401 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
404 for the fact that the timer reconsideration algorithm converges to
405 a value of the RTCP bandwidth below the intended average
406 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
Erik Språng242e22b2015-05-11 10:17:43 +0200408 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000409
danilchap56036ff2016-03-22 11:14:09 -0700410 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000411
pbosda903ea2015-10-02 02:36:56 -0700412 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000413 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
Erik Språng242e22b2015-05-11 10:17:43 +0200415 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200416 // for video key-frames we want to send the RTCP before the large key-frame
417 // if we have a 100 ms margin
418 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
419 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 return true;
423 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200424 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // wrap
426 return true;
427 }
428 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000429}
430
danilchap56036ff2016-03-22 11:14:09 -0700431std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200432 // Timestamp shouldn't be estimated before first media frame.
433 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // The timestamp of this RTCP packet should be estimated as the timestamp of
435 // the frame being captured at this moment. We are calculating that
436 // timestamp as the last frame's timestamp + the time since the last frame
437 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700438 uint32_t rtp_rate =
439 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200440 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700441 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700442 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000443
Erik Språngf7c57762015-12-04 10:40:35 +0100444 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700445 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800446 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700447 report->SetRtpTimestamp(rtp_timestamp);
448 report->SetPacketCount(ctx.feedback_state_.packets_sent);
449 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
danilchap96b69bd2017-07-25 09:15:14 -0700450 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språngf7c57762015-12-04 10:40:35 +0100451
danilchap56036ff2016-03-22 11:14:09 -0700452 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453}
454
danilchap56036ff2016-03-22 11:14:09 -0700455std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100456 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200457 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800458 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
Erik Språngf7c57762015-12-04 10:40:35 +0100460 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700461 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200462
danilchap74e8df8f2017-03-16 08:04:08 -0700463 for (const auto& it : csrc_cnames_)
464 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200465
danilchap56036ff2016-03-22 11:14:09 -0700466 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467}
468
danilchap56036ff2016-03-22 11:14:09 -0700469std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100470 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700471 report->SetSenderSsrc(ssrc_);
danilchap96b69bd2017-07-25 09:15:14 -0700472 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språng61be2a42015-04-27 13:32:52 +0200473
danilchap56036ff2016-03-22 11:14:09 -0700474 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
danilchap56036ff2016-03-22 11:14:09 -0700477std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100478 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700479 pli->SetSenderSsrc(ssrc_);
480 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200481
Erik Språng242e22b2015-05-11 10:17:43 +0200482 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
483 "RTCPSender::PLI");
484 ++packet_type_counter_.pli_packets;
485 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
486 ssrc_, packet_type_counter_.pli_packets);
487
danilchap56036ff2016-03-22 11:14:09 -0700488 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200489}
490
danilchap56036ff2016-03-22 11:14:09 -0700491std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800492 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000493
Erik Språngf7c57762015-12-04 10:40:35 +0100494 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700495 fir->SetSenderSsrc(ssrc_);
496 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200497
498 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
499 "RTCPSender::FIR");
500 ++packet_type_counter_.fir_packets;
501 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
502 ssrc_, packet_type_counter_.fir_packets);
503
danilchap56036ff2016-03-22 11:14:09 -0700504 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000505}
506
danilchap56036ff2016-03-22 11:14:09 -0700507std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100508 const RtcpContext& ctx) {
509 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700510 remb->SetSenderSsrc(ssrc_);
511 remb->SetBitrateBps(remb_bitrate_);
512 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200513
Erik Språng242e22b2015-05-11 10:17:43 +0200514 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
515 "RTCPSender::REMB");
516
danilchap56036ff2016-03-22 11:14:09 -0700517 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000518}
519
Erik Språng61be2a42015-04-27 13:32:52 +0200520void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700521 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700522 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000523}
524
danilchap56036ff2016-03-22 11:14:09 -0700525std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100526 const RtcpContext& ctx) {
527 if (ctx.feedback_state_.module == nullptr)
528 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200529 // Before sending the TMMBR check the received TMMBN, only an owner is
530 // allowed to raise the bitrate:
531 // * If the sender is an owner of the TMMBN -> send TMMBR
532 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000533
Erik Språng61be2a42015-04-27 13:32:52 +0200534 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700535 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000536
Erik Språng242e22b2015-05-11 10:17:43 +0200537 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
538 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200539 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700540 std::vector<rtcp::TmmbItem> candidates =
541 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000542
danilchap2b616392016-08-18 06:17:42 -0700543 if (!candidates.empty()) {
544 for (const auto& candidate : candidates) {
545 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
546 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100547 // Do not send the same tuple.
548 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200549 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000550 }
danilchap2b616392016-08-18 06:17:42 -0700551 if (!tmmbr_owner) {
552 // Use received bounding set as candidate set.
553 // Add current tuple.
554 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000555
danilchap2b616392016-08-18 06:17:42 -0700556 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700557 std::vector<rtcp::TmmbItem> bounding =
558 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700559 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
560 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100561 // Did not enter bounding set, no meaning to send this request.
562 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200563 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000564 }
Erik Språng61be2a42015-04-27 13:32:52 +0200565 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000566
danilchap2b616392016-08-18 06:17:42 -0700567 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100568 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700569
Erik Språngf7c57762015-12-04 10:40:35 +0100570 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700571 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800572 rtcp::TmmbItem request;
573 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700574 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800575 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700576 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100577
danilchap56036ff2016-03-22 11:14:09 -0700578 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200579}
580
danilchap56036ff2016-03-22 11:14:09 -0700581std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100582 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100583 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700584 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700585 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
586 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700587 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000588 }
Erik Språng61be2a42015-04-27 13:32:52 +0200589 }
sprangd83df502015-08-27 01:05:08 -0700590
danilchap56036ff2016-03-22 11:14:09 -0700591 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000592}
593
danilchap56036ff2016-03-22 11:14:09 -0700594std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100595 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700596 app->SetSsrc(ssrc_);
597 app->SetSubType(app_sub_type_);
598 app->SetName(app_name_);
599 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200600
danilchap56036ff2016-03-22 11:14:09 -0700601 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200602}
603
danilchap56036ff2016-03-22 11:14:09 -0700604std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100605 const RtcpContext& ctx) {
606 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700607 nack->SetSenderSsrc(ssrc_);
608 nack->SetMediaSsrc(remote_ssrc_);
609 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200610
611 // Report stats.
612 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100613 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
614 stringBuilder.PushNACK(ctx.nack_list_[idx]);
615 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200616 }
Erik Språng61be2a42015-04-27 13:32:52 +0200617 packet_type_counter_.nack_requests = nack_stats_.requests();
618 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200619
620 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
621 "RTCPSender::NACK", "nacks",
622 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
623 ++packet_type_counter_.nack_packets;
624 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
625 ssrc_, packet_type_counter_.nack_packets);
626
danilchap56036ff2016-03-22 11:14:09 -0700627 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200628}
629
danilchap56036ff2016-03-22 11:14:09 -0700630std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100631 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700632 bye->SetSenderSsrc(ssrc_);
633 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700634
danilchap56036ff2016-03-22 11:14:09 -0700635 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000636}
637
sprang5e38c962016-12-01 05:18:09 -0800638std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100639 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800640 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700641 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000642
sprang5e38c962016-12-01 05:18:09 -0800643 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
644 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800645 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800646 xr->SetRrtr(rrtr);
647 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000648
sprang5e38c962016-12-01 05:18:09 -0800649 if (ctx.feedback_state_.has_last_xr_rr) {
650 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
651 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000652
sprang5e38c962016-12-01 05:18:09 -0800653 if (video_bitrate_allocation_) {
654 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000655
sprang5e38c962016-12-01 05:18:09 -0800656 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
657 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
erikvarga@webrtc.org01f2ec32017-11-15 14:58:23 +0100658 if (video_bitrate_allocation_->HasBitrate(sl, tl)) {
659 target_bitrate.AddTargetBitrate(
660 sl, tl, video_bitrate_allocation_->GetBitrate(sl, tl) / 1000);
661 }
sprang5e38c962016-12-01 05:18:09 -0800662 }
663 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000664
sprang5e38c962016-12-01 05:18:09 -0800665 xr->SetTargetBitrate(target_bitrate);
666 video_bitrate_allocation_.reset();
667 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200668
sprang5e38c962016-12-01 05:18:09 -0800669 if (xr_voip_metric_) {
670 rtcp::VoipMetric voip;
671 voip.SetMediaSsrc(remote_ssrc_);
672 voip.SetVoipMetric(*xr_voip_metric_);
673 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000674
sprang5e38c962016-12-01 05:18:09 -0800675 xr->SetVoipMetric(voip);
676 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200677
sprang5e38c962016-12-01 05:18:09 -0800678 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000679}
680
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000681int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200682 RTCPPacketType packetType,
683 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700684 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200685 return SendCompoundRTCP(
686 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700687 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200688}
689
690int32_t RTCPSender::SendCompoundRTCP(
691 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100692 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200693 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700694 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800695 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800696 size_t max_packet_size;
697
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000698 {
danilchap56036ff2016-03-22 11:14:09 -0700699 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700700 if (method_ == RtcpMode::kOff) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100701 RTC_LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
Erik Språng61be2a42015-04-27 13:32:52 +0200702 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000703 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200704 // Add all flags as volatile. Non volatile entries will not be overwritten.
705 // All new volatile flags added will be consumed by the end of this call.
706 SetFlags(packet_types, true);
707
708 // Prevent sending streams to send SR before any media has been sent.
709 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
710 if (!can_calculate_rtp_timestamp) {
711 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
712 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
713 bool sender_report = consumed_report_flag || consumed_sr_flag;
714 if (sender_report && AllVolatileFlagsConsumed()) {
715 // This call was for Sender Report and nothing else.
716 return 0;
717 }
718 if (sending_ && method_ == RtcpMode::kCompound) {
719 // Not allowed to send any RTCP packet without sender report.
720 return -1;
721 }
722 }
723
724 if (packet_type_counter_.first_packet_time_ms == -1)
725 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100726
727 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700728 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800729 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100730
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200731 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100732
danilchap56036ff2016-03-22 11:14:09 -0700733 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800734
Erik Språngf7c57762015-12-04 10:40:35 +0100735 auto it = report_flags_.begin();
736 while (it != report_flags_.end()) {
737 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800738 RTC_DCHECK(builder_it != builders_.end())
739 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100740 if (it->is_volatile) {
741 report_flags_.erase(it++);
742 } else {
743 ++it;
744 }
745
746 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700747 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100748 if (packet.get() == nullptr)
749 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800750 // If there is a BYE, don't append now - save it and append it
751 // at the end later.
752 if (builder_it->first == kRtcpBye) {
753 packet_bye = std::move(packet);
754 } else {
755 container.Append(packet.release());
756 }
757 }
758
759 // Append the BYE now at the end
760 if (packet_bye) {
761 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100762 }
763
764 if (packet_type_counter_observer_ != nullptr) {
765 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
766 remote_ssrc_, packet_type_counter_);
767 }
768
769 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800770 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000771 }
Erik Språng61be2a42015-04-27 13:32:52 +0200772
nisse6f142eb2017-02-21 07:32:47 -0800773 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100774 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000775}
776
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200777void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200778 bool generate_report;
779 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
780 // Report type already explicitly set, don't automatically populate.
781 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700782 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200783 } else {
784 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700785 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
786 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200787 if (generate_report)
788 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000789 }
790
Erik Språng0ea42d32015-06-25 14:46:16 +0200791 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200792 SetFlag(kRtcpSdes, true);
793
Erik Språng242e22b2015-05-11 10:17:43 +0200794 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800795 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
796 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
797 SetFlag(kRtcpAnyExtendedReports, true);
798 }
Erik Språng242e22b2015-05-11 10:17:43 +0200799
800 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800801 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000802
danilchap47a740b2015-12-15 00:30:07 -0800803 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200804 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200805 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
806 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
807 if (send_bitrate_kbit != 0)
808 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000809 }
Erik Språng61be2a42015-04-27 13:32:52 +0200810 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
811 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200812 }
danilchap47a740b2015-12-15 00:30:07 -0800813 // The interval between RTCP packets is varied randomly over the
814 // range [1/2,3/2] times the calculated interval.
815 uint32_t timeToNext =
816 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200817 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000818
danilchap96b69bd2017-07-25 09:15:14 -0700819 // RtcpSender expected to be used for sending either just sender reports
820 // or just receiver reports.
821 RTC_DCHECK(!(IsFlagPresent(kRtcpSr) && IsFlagPresent(kRtcpRr)));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000822 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000823}
824
danilchap96b69bd2017-07-25 09:15:14 -0700825std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
826 const FeedbackState& feedback_state) {
827 std::vector<rtcp::ReportBlock> result;
828 if (!receive_statistics_)
829 return result;
danilchapa72e7342015-12-22 08:07:45 -0800830
danilchapf5f793c2017-07-27 04:44:18 -0700831 // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
832 // compound rtcp packet when single rtcp module is used for multiple media
833 // streams.
834 result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
danilchap96b69bd2017-07-25 09:15:14 -0700835
836 if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
837 (feedback_state.last_rr_ntp_frac != 0))) {
838 // Get our NTP as late as possible to avoid a race.
839 uint32_t now = CompactNtp(clock_->CurrentNtpTime());
840
841 uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
842 receive_time <<= 16;
843 receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
844
845 uint32_t delay_since_last_sr = now - receive_time;
846 // TODO(danilchap): Instead of setting same value on all report blocks,
847 // set only when media_ssrc match sender ssrc of the sender report
848 // remote times were taken from.
849 for (auto& report_block : result) {
850 report_block.SetLastSr(feedback_state.remote_sr);
851 report_block.SetDelayLastSr(delay_since_last_sr);
852 }
danilchapa72e7342015-12-22 08:07:45 -0800853 }
danilchap96b69bd2017-07-25 09:15:14 -0700854 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000855}
856
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000857void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800858 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700859 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000860 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000861}
862
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000863int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
864 uint32_t name,
865 const uint8_t* data,
866 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200867 if (length % 4 != 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100868 RTC_LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
Erik Språng61be2a42015-04-27 13:32:52 +0200869 return -1;
870 }
danilchap56036ff2016-03-22 11:14:09 -0700871 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000872
Erik Språng242e22b2015-05-11 10:17:43 +0200873 SetFlag(kRtcpApp, true);
874 app_sub_type_ = subType;
875 app_name_ = name;
876 app_data_.reset(new uint8_t[length]);
877 app_length_ = length;
878 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200879 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000880}
881
spranga790d832016-12-02 07:29:44 -0800882// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200883int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700884 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800885 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000886
sprang5e38c962016-12-01 05:18:09 -0800887 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200888 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000889}
890
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000891void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700892 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200893 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000894}
895
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000896bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700897 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200898 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000899}
900
danilchap853ecb22016-08-22 08:26:15 -0700901void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700902 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700903 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700904 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000905}
Erik Språng61be2a42015-04-27 13:32:52 +0200906
sprang5e38c962016-12-01 05:18:09 -0800907void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
908 if (type & kRtcpAnyExtendedReports) {
909 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
910 } else {
911 report_flags_.insert(ReportFlag(type, is_volatile));
912 }
Erik Språng242e22b2015-05-11 10:17:43 +0200913}
914
915void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
916 bool is_volatile) {
917 for (RTCPPacketType type : types)
918 SetFlag(type, is_volatile);
919}
920
sprang5e38c962016-12-01 05:18:09 -0800921bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200922 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
923}
924
sprang5e38c962016-12-01 05:18:09 -0800925bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200926 auto it = report_flags_.find(ReportFlag(type, false));
927 if (it == report_flags_.end())
928 return false;
929 if (it->is_volatile || forced)
930 report_flags_.erase((it));
931 return true;
932}
933
934bool RTCPSender::AllVolatileFlagsConsumed() const {
935 for (const ReportFlag& flag : report_flags_) {
936 if (flag.is_volatile)
937 return false;
938 }
939 return true;
940}
941
sprang5e38c962016-12-01 05:18:09 -0800942void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
943 rtc::CritScope lock(&critical_section_rtcp_sender_);
944 video_bitrate_allocation_.emplace(bitrate);
945 SetFlag(kRtcpAnyExtendedReports, true);
946}
947
sprang233bd872015-09-08 13:25:16 -0700948bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700949 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
950 public:
terelius429c3452016-01-21 05:42:04 -0800951 Sender(Transport* transport, RtcEventLog* event_log)
952 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700953
954 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800955 if (transport_->SendRtcp(data, length)) {
956 if (event_log_) {
Elad Alon4a87e1c2017-10-03 16:11:34 +0200957 event_log_->Log(rtc::MakeUnique<RtcEventRtcpPacketOutgoing>(
958 rtc::ArrayView<const uint8_t>(data, length)));
terelius429c3452016-01-21 05:42:04 -0800959 }
960 } else {
sprang233bd872015-09-08 13:25:16 -0700961 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800962 }
sprang233bd872015-09-08 13:25:16 -0700963 }
964
965 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800966 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700967 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800968 // TODO(terelius): We would like to
969 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
970 // but we can't because of an incorrect warning (C4822) in MVS 2013.
971 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700972
nisse6f142eb2017-02-21 07:32:47 -0800973 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800974 {
975 rtc::CritScope lock(&critical_section_rtcp_sender_);
976 if (method_ == RtcpMode::kOff)
977 return false;
nisse6f142eb2017-02-21 07:32:47 -0800978 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -0800979 }
980
nisse6f142eb2017-02-21 07:32:47 -0800981 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -0700982 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -0800983 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -0700984 !sender.send_failure_;
985}
986
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000987} // namespace webrtc