blob: c7e75b67e7c30b2320842c2dc07a4fe8ac83f383 [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)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "logging/rtc_event_log/rtc_event_log.h"
19#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
20#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
21#include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
22#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
23#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
24#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
25#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
26#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
27#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
28#include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
29#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
30#include "modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
31#include "modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
32#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
33#include "modules/rtp_rtcp/source/rtp_rtcp_impl.h"
34#include "modules/rtp_rtcp/source/time_util.h"
35#include "modules/rtp_rtcp/source/tmmbr_help.h"
36#include "rtc_base/checks.h"
37#include "rtc_base/constructormagic.h"
38#include "rtc_base/logging.h"
39#include "rtc_base/trace_event.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000040
niklase@google.com470e71d2011-07-07 08:21:25 +000041namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000042
sprang5e38c962016-12-01 05:18:09 -080043namespace {
44const uint32_t kRtcpAnyExtendedReports =
45 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
46 kRtcpXrTargetBitrate;
47} // namespace
48
Erik Språng61be2a42015-04-27 13:32:52 +020049NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080050 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000051
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000052NACKStringBuilder::~NACKStringBuilder() {}
53
danilchap162abd32015-12-10 02:39:40 -080054void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020055 if (count_ == 0) {
56 stream_ << nack;
57 } else if (nack == prevNack_ + 1) {
58 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020059 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020060 if (consecutive_) {
61 stream_ << "-" << prevNack_;
62 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000063 }
Erik Språng242e22b2015-05-11 10:17:43 +020064 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020065 }
Erik Språng242e22b2015-05-11 10:17:43 +020066 count_++;
67 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000068}
69
Erik Språng61be2a42015-04-27 13:32:52 +020070std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020071 if (consecutive_) {
72 stream_ << "-" << prevNack_;
73 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020074 }
Erik Språng242e22b2015-05-11 10:17:43 +020075 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000076}
77
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000078RTCPSender::FeedbackState::FeedbackState()
nisse40ba3ad2017-03-17 07:04:00 -070079 : packets_sent(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000080 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000081 send_bitrate(0),
82 last_rr_ntp_secs(0),
83 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000084 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020085 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080086 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000087
danilchap2f7dea12016-01-13 02:03:04 -080088class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010089 public rtcp::RtcpPacket::PacketReadyCallback {
90 public:
terelius429c3452016-01-21 05:42:04 -080091 PacketContainer(Transport* transport, RtcEventLog* event_log)
92 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010093 virtual ~PacketContainer() {
94 for (RtcpPacket* packet : appended_packets_)
95 delete packet;
96 }
97
98 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -080099 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100100 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800101 if (event_log_) {
Bjorn Terelius440216f2017-09-29 21:01:42 +0200102 event_log_->LogOutgoingRtcpPacket(
103 rtc::ArrayView<const uint8_t>(data, length));
terelius429c3452016-01-21 05:42:04 -0800104 }
105 }
Erik Språngf7c57762015-12-04 10:40:35 +0100106 }
107
danilchap41befce2016-03-30 11:11:51 -0700108 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800109 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700110 uint8_t buffer[IP_PACKET_SIZE];
111 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100112 return bytes_sent_;
113 }
114
115 private:
116 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800117 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100118 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800119
120 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100121};
122
123class RTCPSender::RtcpContext {
124 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200125 RtcpContext(const FeedbackState& feedback_state,
126 int32_t nack_size,
127 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800128 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100129 : feedback_state_(feedback_state),
130 nack_size_(nack_size),
131 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800132 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200133
Erik Språngf7c57762015-12-04 10:40:35 +0100134 const FeedbackState& feedback_state_;
135 const int32_t nack_size_;
136 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800137 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200138};
139
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000140RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000141 bool audio,
142 Clock* clock,
danilchapf5f793c2017-07-27 04:44:18 -0700143 ReceiveStatisticsProvider* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700144 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800145 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700146 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200147 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200148 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800149 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700150 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800151 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700152 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200153 using_nack_(false),
154 sending_(false),
155 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200156 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700157 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000158 last_rtp_timestamp_(0),
159 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200160 ssrc_(0),
161 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000162 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000163
Erik Språng242e22b2015-05-11 10:17:43 +0200164 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000165
Erik Språng242e22b2015-05-11 10:17:43 +0200166 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000167
danilchap2b616392016-08-18 06:17:42 -0700168 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200169 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800170 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000171
Erik Språng242e22b2015-05-11 10:17:43 +0200172 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200173 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200174 app_data_(nullptr),
175 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000176
Erik Språng242e22b2015-05-11 10:17:43 +0200177 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000178 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700179 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200180
181 builders_[kRtcpSr] = &RTCPSender::BuildSR;
182 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200183 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200184 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
185 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200186 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
187 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
188 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
189 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
190 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
191 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800192 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000193}
194
danilchap162abd32015-12-10 02:39:40 -0800195RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000196
pbosda903ea2015-10-02 02:36:56 -0700197RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700198 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200199 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200}
201
skvlad1c392cc2016-04-01 14:46:44 -0700202void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700203 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000204
skvlad1c392cc2016-04-01 14:46:44 -0700205 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
206 // When switching on, reschedule the next packet
207 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200208 clock_->TimeInMilliseconds() +
209 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700210 }
211 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212}
213
Erik Språng61be2a42015-04-27 13:32:52 +0200214bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700215 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200216 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000217}
218
Erik Språng61be2a42015-04-27 13:32:52 +0200219int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
220 bool sending) {
221 bool sendRTCPBye = false;
222 {
danilchap56036ff2016-03-22 11:14:09 -0700223 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000224
pbosda903ea2015-10-02 02:36:56 -0700225 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200226 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200227 // Trigger RTCP bye
228 sendRTCPBye = true;
229 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000230 }
Erik Språng242e22b2015-05-11 10:17:43 +0200231 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200232 }
233 if (sendRTCPBye)
234 return SendRTCP(feedback_state, kRtcpBye);
235 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000236}
237
Erik Språng61be2a42015-04-27 13:32:52 +0200238bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700239 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200240 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000241}
242
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000243void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700244 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200245 remb_enabled_ = enable;
danilchapba6aa902017-04-18 06:57:02 -0700246 if (!enable) {
247 // Stop sending remb each report until it is reenabled and remb data set.
248 ConsumeFlag(kRtcpRemb, true);
249 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000250}
251
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000252void RTCPSender::SetREMBData(uint32_t bitrate,
253 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700254 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200255 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000256 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000257
Erik Språng242e22b2015-05-11 10:17:43 +0200258 if (remb_enabled_)
259 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000260 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
261 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200262 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000263}
264
Erik Språng61be2a42015-04-27 13:32:52 +0200265bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700266 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200267 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000268}
269
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000270void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700271 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200272 if (enable) {
273 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
274 } else {
275 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
276 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000277}
278
nisse284542b2017-01-10 08:58:32 -0800279void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800280 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800281 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700282}
283
danilchap71fead22016-08-18 02:01:49 -0700284void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700285 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700286 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000287}
288
289void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
290 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700291 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000292 last_rtp_timestamp_ = rtp_timestamp;
293 if (capture_time_ms < 0) {
294 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200295 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000296 } else {
297 last_frame_capture_time_ms_ = capture_time_ms;
298 }
299}
300
nisse14adba72017-03-20 03:52:39 -0700301uint32_t RTCPSender::SSRC() const {
302 rtc::CritScope lock(&critical_section_rtcp_sender_);
303 return ssrc_;
304}
305
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000306void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700307 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
Erik Språng242e22b2015-05-11 10:17:43 +0200309 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200310 // not first SetSSRC, probably due to a collision
311 // schedule a new RTCP report
312 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200313 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200314 }
Erik Språng242e22b2015-05-11 10:17:43 +0200315 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000316}
317
Erik Språng61be2a42015-04-27 13:32:52 +0200318void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700319 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200320 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000321}
322
Peter Boström9ba52f82015-06-01 14:12:28 +0200323int32_t RTCPSender::SetCNAME(const char* c_name) {
324 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000325 return -1;
326
kwiberg352444f2016-11-28 15:58:53 -0800327 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700328 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200329 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000330 return 0;
331}
332
Erik Språng0ea42d32015-06-25 14:46:16 +0200333int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700334 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800335 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700336 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700337 // One spot is reserved for ssrc_/cname_.
338 // TODO(danilchap): Add support for more than 30 contributes by sending
339 // several sdes packets.
340 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200342
343 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000344 return 0;
345}
346
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000347int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700348 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200349 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000350
Erik Språng242e22b2015-05-11 10:17:43 +0200351 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200353
Erik Språng242e22b2015-05-11 10:17:43 +0200354 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000355 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000356}
357
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000358bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800359 /*
360 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000361
danilchap162abd32015-12-10 02:39:40 -0800362 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
363 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
364 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
366
danilchap162abd32015-12-10 02:39:40 -0800367 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000368
danilchap162abd32015-12-10 02:39:40 -0800369 MAX RTCP BW is 5% if the session BW
370 A send report is approximately 65 bytes inc CNAME
371 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000372
danilchap162abd32015-12-10 02:39:40 -0800373 The RECOMMENDED value for the reduced minimum in seconds is 360
374 divided by the session bandwidth in kilobits/second. This minimum
375 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000376
danilchap162abd32015-12-10 02:39:40 -0800377 If the participant has not yet sent an RTCP packet (the variable
378 initial is true), the constant Tmin is set to 2.5 seconds, else it
379 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
danilchap162abd32015-12-10 02:39:40 -0800381 The interval between RTCP packets is varied randomly over the
382 range [0.5,1.5] times the calculated interval to avoid unintended
383 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000384
danilchap162abd32015-12-10 02:39:40 -0800385 if we send
386 If the participant is a sender (we_sent true), the constant C is
387 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
388 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
389 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
danilchap162abd32015-12-10 02:39:40 -0800391 if we receive only
392 If we_sent is not true, the constant C is set
393 to the average RTCP packet size divided by 75% of the RTCP
394 bandwidth. The constant n is set to the number of receivers
395 (members - senders). If the number of senders is greater than
396 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000397
danilchap162abd32015-12-10 02:39:40 -0800398 reconsideration NOT required for peer-to-peer
399 "timer reconsideration" is
400 employed. This algorithm implements a simple back-off mechanism
401 which causes users to hold back RTCP packet transmission if the
402 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 n = number of members
405 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000406
danilchap162abd32015-12-10 02:39:40 -0800407 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 4. The calculated interval T is set to a number uniformly distributed
410 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000411
danilchap162abd32015-12-10 02:39:40 -0800412 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
413 for the fact that the timer reconsideration algorithm converges to
414 a value of the RTCP bandwidth below the intended average
415 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000416
Erik Språng242e22b2015-05-11 10:17:43 +0200417 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000418
danilchap56036ff2016-03-22 11:14:09 -0700419 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000420
pbosda903ea2015-10-02 02:36:56 -0700421 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000422 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000423
Erik Språng242e22b2015-05-11 10:17:43 +0200424 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200425 // for video key-frames we want to send the RTCP before the large key-frame
426 // if we have a 100 ms margin
427 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
428 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000429
Erik Språng242e22b2015-05-11 10:17:43 +0200430 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200431 return true;
432 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200433 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200434 // wrap
435 return true;
436 }
437 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438}
439
danilchap56036ff2016-03-22 11:14:09 -0700440std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200441 // Timestamp shouldn't be estimated before first media frame.
442 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200443 // The timestamp of this RTCP packet should be estimated as the timestamp of
444 // the frame being captured at this moment. We are calculating that
445 // timestamp as the last frame's timestamp + the time since the last frame
446 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700447 uint32_t rtp_rate =
448 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200449 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700450 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700451 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000452
Erik Språngf7c57762015-12-04 10:40:35 +0100453 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700454 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800455 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700456 report->SetRtpTimestamp(rtp_timestamp);
457 report->SetPacketCount(ctx.feedback_state_.packets_sent);
458 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
danilchap96b69bd2017-07-25 09:15:14 -0700459 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språngf7c57762015-12-04 10:40:35 +0100460
danilchap56036ff2016-03-22 11:14:09 -0700461 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000462}
463
danilchap56036ff2016-03-22 11:14:09 -0700464std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100465 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200466 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800467 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000468
Erik Språngf7c57762015-12-04 10:40:35 +0100469 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700470 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200471
danilchap74e8df8f2017-03-16 08:04:08 -0700472 for (const auto& it : csrc_cnames_)
473 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200474
danilchap56036ff2016-03-22 11:14:09 -0700475 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000476}
477
danilchap56036ff2016-03-22 11:14:09 -0700478std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100479 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700480 report->SetSenderSsrc(ssrc_);
danilchap96b69bd2017-07-25 09:15:14 -0700481 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språng61be2a42015-04-27 13:32:52 +0200482
danilchap56036ff2016-03-22 11:14:09 -0700483 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000484}
485
danilchap56036ff2016-03-22 11:14:09 -0700486std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100487 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700488 pli->SetSenderSsrc(ssrc_);
489 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200490
Erik Språng242e22b2015-05-11 10:17:43 +0200491 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
492 "RTCPSender::PLI");
493 ++packet_type_counter_.pli_packets;
494 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
495 ssrc_, packet_type_counter_.pli_packets);
496
danilchap56036ff2016-03-22 11:14:09 -0700497 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200498}
499
danilchap56036ff2016-03-22 11:14:09 -0700500std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800501 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000502
Erik Språngf7c57762015-12-04 10:40:35 +0100503 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700504 fir->SetSenderSsrc(ssrc_);
505 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200506
507 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
508 "RTCPSender::FIR");
509 ++packet_type_counter_.fir_packets;
510 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
511 ssrc_, packet_type_counter_.fir_packets);
512
danilchap56036ff2016-03-22 11:14:09 -0700513 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000514}
515
danilchap56036ff2016-03-22 11:14:09 -0700516std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100517 const RtcpContext& ctx) {
518 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700519 remb->SetSenderSsrc(ssrc_);
520 remb->SetBitrateBps(remb_bitrate_);
521 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200522
Erik Språng242e22b2015-05-11 10:17:43 +0200523 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
524 "RTCPSender::REMB");
525
danilchap56036ff2016-03-22 11:14:09 -0700526 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000527}
528
Erik Språng61be2a42015-04-27 13:32:52 +0200529void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700530 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700531 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000532}
533
danilchap56036ff2016-03-22 11:14:09 -0700534std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100535 const RtcpContext& ctx) {
536 if (ctx.feedback_state_.module == nullptr)
537 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200538 // Before sending the TMMBR check the received TMMBN, only an owner is
539 // allowed to raise the bitrate:
540 // * If the sender is an owner of the TMMBN -> send TMMBR
541 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000542
Erik Språng61be2a42015-04-27 13:32:52 +0200543 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700544 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000545
Erik Språng242e22b2015-05-11 10:17:43 +0200546 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
547 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200548 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700549 std::vector<rtcp::TmmbItem> candidates =
550 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000551
danilchap2b616392016-08-18 06:17:42 -0700552 if (!candidates.empty()) {
553 for (const auto& candidate : candidates) {
554 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
555 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100556 // Do not send the same tuple.
557 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200558 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000559 }
danilchap2b616392016-08-18 06:17:42 -0700560 if (!tmmbr_owner) {
561 // Use received bounding set as candidate set.
562 // Add current tuple.
563 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000564
danilchap2b616392016-08-18 06:17:42 -0700565 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700566 std::vector<rtcp::TmmbItem> bounding =
567 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700568 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
569 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100570 // Did not enter bounding set, no meaning to send this request.
571 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200572 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000573 }
Erik Språng61be2a42015-04-27 13:32:52 +0200574 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000575
danilchap2b616392016-08-18 06:17:42 -0700576 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100577 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700578
Erik Språngf7c57762015-12-04 10:40:35 +0100579 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700580 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800581 rtcp::TmmbItem request;
582 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700583 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800584 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700585 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100586
danilchap56036ff2016-03-22 11:14:09 -0700587 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200588}
589
danilchap56036ff2016-03-22 11:14:09 -0700590std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100591 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100592 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700593 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700594 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
595 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700596 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000597 }
Erik Språng61be2a42015-04-27 13:32:52 +0200598 }
sprangd83df502015-08-27 01:05:08 -0700599
danilchap56036ff2016-03-22 11:14:09 -0700600 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000601}
602
danilchap56036ff2016-03-22 11:14:09 -0700603std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100604 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700605 app->SetSsrc(ssrc_);
606 app->SetSubType(app_sub_type_);
607 app->SetName(app_name_);
608 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200609
danilchap56036ff2016-03-22 11:14:09 -0700610 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200611}
612
danilchap56036ff2016-03-22 11:14:09 -0700613std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100614 const RtcpContext& ctx) {
615 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700616 nack->SetSenderSsrc(ssrc_);
617 nack->SetMediaSsrc(remote_ssrc_);
618 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200619
620 // Report stats.
621 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100622 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
623 stringBuilder.PushNACK(ctx.nack_list_[idx]);
624 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200625 }
Erik Språng61be2a42015-04-27 13:32:52 +0200626 packet_type_counter_.nack_requests = nack_stats_.requests();
627 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200628
629 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
630 "RTCPSender::NACK", "nacks",
631 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
632 ++packet_type_counter_.nack_packets;
633 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
634 ssrc_, packet_type_counter_.nack_packets);
635
danilchap56036ff2016-03-22 11:14:09 -0700636 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200637}
638
danilchap56036ff2016-03-22 11:14:09 -0700639std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100640 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700641 bye->SetSenderSsrc(ssrc_);
642 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700643
danilchap56036ff2016-03-22 11:14:09 -0700644 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000645}
646
sprang5e38c962016-12-01 05:18:09 -0800647std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100648 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800649 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700650 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000651
sprang5e38c962016-12-01 05:18:09 -0800652 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
653 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800654 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800655 xr->SetRrtr(rrtr);
656 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000657
sprang5e38c962016-12-01 05:18:09 -0800658 if (ctx.feedback_state_.has_last_xr_rr) {
659 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
660 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000661
sprang5e38c962016-12-01 05:18:09 -0800662 if (video_bitrate_allocation_) {
663 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000664
sprang5e38c962016-12-01 05:18:09 -0800665 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
666 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
667 uint32_t layer_bitrate_bps =
668 video_bitrate_allocation_->GetBitrate(sl, tl);
669 if (layer_bitrate_bps > 0)
670 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
671 }
672 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000673
sprang5e38c962016-12-01 05:18:09 -0800674 xr->SetTargetBitrate(target_bitrate);
675 video_bitrate_allocation_.reset();
676 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200677
sprang5e38c962016-12-01 05:18:09 -0800678 if (xr_voip_metric_) {
679 rtcp::VoipMetric voip;
680 voip.SetMediaSsrc(remote_ssrc_);
681 voip.SetVoipMetric(*xr_voip_metric_);
682 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000683
sprang5e38c962016-12-01 05:18:09 -0800684 xr->SetVoipMetric(voip);
685 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200686
sprang5e38c962016-12-01 05:18:09 -0800687 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000688}
689
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000690int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200691 RTCPPacketType packetType,
692 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700693 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200694 return SendCompoundRTCP(
695 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700696 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200697}
698
699int32_t RTCPSender::SendCompoundRTCP(
700 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100701 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200702 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700703 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800704 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800705 size_t max_packet_size;
706
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000707 {
danilchap56036ff2016-03-22 11:14:09 -0700708 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700709 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200710 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
711 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000712 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200713 // Add all flags as volatile. Non volatile entries will not be overwritten.
714 // All new volatile flags added will be consumed by the end of this call.
715 SetFlags(packet_types, true);
716
717 // Prevent sending streams to send SR before any media has been sent.
718 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
719 if (!can_calculate_rtp_timestamp) {
720 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
721 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
722 bool sender_report = consumed_report_flag || consumed_sr_flag;
723 if (sender_report && AllVolatileFlagsConsumed()) {
724 // This call was for Sender Report and nothing else.
725 return 0;
726 }
727 if (sending_ && method_ == RtcpMode::kCompound) {
728 // Not allowed to send any RTCP packet without sender report.
729 return -1;
730 }
731 }
732
733 if (packet_type_counter_.first_packet_time_ms == -1)
734 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100735
736 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700737 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800738 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100739
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200740 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100741
danilchap56036ff2016-03-22 11:14:09 -0700742 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800743
Erik Språngf7c57762015-12-04 10:40:35 +0100744 auto it = report_flags_.begin();
745 while (it != report_flags_.end()) {
746 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800747 RTC_DCHECK(builder_it != builders_.end())
748 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100749 if (it->is_volatile) {
750 report_flags_.erase(it++);
751 } else {
752 ++it;
753 }
754
755 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700756 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100757 if (packet.get() == nullptr)
758 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800759 // If there is a BYE, don't append now - save it and append it
760 // at the end later.
761 if (builder_it->first == kRtcpBye) {
762 packet_bye = std::move(packet);
763 } else {
764 container.Append(packet.release());
765 }
766 }
767
768 // Append the BYE now at the end
769 if (packet_bye) {
770 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100771 }
772
773 if (packet_type_counter_observer_ != nullptr) {
774 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
775 remote_ssrc_, packet_type_counter_);
776 }
777
778 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800779 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000780 }
Erik Språng61be2a42015-04-27 13:32:52 +0200781
nisse6f142eb2017-02-21 07:32:47 -0800782 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100783 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000784}
785
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200786void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200787 bool generate_report;
788 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
789 // Report type already explicitly set, don't automatically populate.
790 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700791 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200792 } else {
793 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700794 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
795 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200796 if (generate_report)
797 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000798 }
799
Erik Språng0ea42d32015-06-25 14:46:16 +0200800 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200801 SetFlag(kRtcpSdes, true);
802
Erik Språng242e22b2015-05-11 10:17:43 +0200803 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800804 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
805 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
806 SetFlag(kRtcpAnyExtendedReports, true);
807 }
Erik Språng242e22b2015-05-11 10:17:43 +0200808
809 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800810 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000811
danilchap47a740b2015-12-15 00:30:07 -0800812 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200813 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200814 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
815 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
816 if (send_bitrate_kbit != 0)
817 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000818 }
Erik Språng61be2a42015-04-27 13:32:52 +0200819 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
820 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200821 }
danilchap47a740b2015-12-15 00:30:07 -0800822 // The interval between RTCP packets is varied randomly over the
823 // range [1/2,3/2] times the calculated interval.
824 uint32_t timeToNext =
825 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200826 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000827
danilchap96b69bd2017-07-25 09:15:14 -0700828 // RtcpSender expected to be used for sending either just sender reports
829 // or just receiver reports.
830 RTC_DCHECK(!(IsFlagPresent(kRtcpSr) && IsFlagPresent(kRtcpRr)));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000831 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000832}
833
danilchap96b69bd2017-07-25 09:15:14 -0700834std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
835 const FeedbackState& feedback_state) {
836 std::vector<rtcp::ReportBlock> result;
837 if (!receive_statistics_)
838 return result;
danilchapa72e7342015-12-22 08:07:45 -0800839
danilchapf5f793c2017-07-27 04:44:18 -0700840 // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
841 // compound rtcp packet when single rtcp module is used for multiple media
842 // streams.
843 result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
danilchap96b69bd2017-07-25 09:15:14 -0700844
845 if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
846 (feedback_state.last_rr_ntp_frac != 0))) {
847 // Get our NTP as late as possible to avoid a race.
848 uint32_t now = CompactNtp(clock_->CurrentNtpTime());
849
850 uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
851 receive_time <<= 16;
852 receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
853
854 uint32_t delay_since_last_sr = now - receive_time;
855 // TODO(danilchap): Instead of setting same value on all report blocks,
856 // set only when media_ssrc match sender ssrc of the sender report
857 // remote times were taken from.
858 for (auto& report_block : result) {
859 report_block.SetLastSr(feedback_state.remote_sr);
860 report_block.SetDelayLastSr(delay_since_last_sr);
861 }
danilchapa72e7342015-12-22 08:07:45 -0800862 }
danilchap96b69bd2017-07-25 09:15:14 -0700863 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000864}
865
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000866void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800867 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700868 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000869 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000870}
871
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000872int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
873 uint32_t name,
874 const uint8_t* data,
875 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200876 if (length % 4 != 0) {
877 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
878 return -1;
879 }
danilchap56036ff2016-03-22 11:14:09 -0700880 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000881
Erik Språng242e22b2015-05-11 10:17:43 +0200882 SetFlag(kRtcpApp, true);
883 app_sub_type_ = subType;
884 app_name_ = name;
885 app_data_.reset(new uint8_t[length]);
886 app_length_ = length;
887 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200888 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000889}
890
spranga790d832016-12-02 07:29:44 -0800891// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200892int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700893 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800894 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000895
sprang5e38c962016-12-01 05:18:09 -0800896 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200897 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000898}
899
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000900void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700901 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200902 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000903}
904
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000905bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700906 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200907 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000908}
909
danilchap853ecb22016-08-22 08:26:15 -0700910void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700911 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700912 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700913 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000914}
Erik Språng61be2a42015-04-27 13:32:52 +0200915
sprang5e38c962016-12-01 05:18:09 -0800916void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
917 if (type & kRtcpAnyExtendedReports) {
918 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
919 } else {
920 report_flags_.insert(ReportFlag(type, is_volatile));
921 }
Erik Språng242e22b2015-05-11 10:17:43 +0200922}
923
924void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
925 bool is_volatile) {
926 for (RTCPPacketType type : types)
927 SetFlag(type, is_volatile);
928}
929
sprang5e38c962016-12-01 05:18:09 -0800930bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200931 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
932}
933
sprang5e38c962016-12-01 05:18:09 -0800934bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200935 auto it = report_flags_.find(ReportFlag(type, false));
936 if (it == report_flags_.end())
937 return false;
938 if (it->is_volatile || forced)
939 report_flags_.erase((it));
940 return true;
941}
942
943bool RTCPSender::AllVolatileFlagsConsumed() const {
944 for (const ReportFlag& flag : report_flags_) {
945 if (flag.is_volatile)
946 return false;
947 }
948 return true;
949}
950
sprang5e38c962016-12-01 05:18:09 -0800951void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
952 rtc::CritScope lock(&critical_section_rtcp_sender_);
953 video_bitrate_allocation_.emplace(bitrate);
954 SetFlag(kRtcpAnyExtendedReports, true);
955}
956
sprang233bd872015-09-08 13:25:16 -0700957bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700958 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
959 public:
terelius429c3452016-01-21 05:42:04 -0800960 Sender(Transport* transport, RtcEventLog* event_log)
961 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700962
963 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800964 if (transport_->SendRtcp(data, length)) {
965 if (event_log_) {
Bjorn Terelius440216f2017-09-29 21:01:42 +0200966 event_log_->LogOutgoingRtcpPacket(
967 rtc::ArrayView<const uint8_t>(data, length));
terelius429c3452016-01-21 05:42:04 -0800968 }
969 } else {
sprang233bd872015-09-08 13:25:16 -0700970 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800971 }
sprang233bd872015-09-08 13:25:16 -0700972 }
973
974 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800975 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700976 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800977 // TODO(terelius): We would like to
978 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
979 // but we can't because of an incorrect warning (C4822) in MVS 2013.
980 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700981
nisse6f142eb2017-02-21 07:32:47 -0800982 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800983 {
984 rtc::CritScope lock(&critical_section_rtcp_sender_);
985 if (method_ == RtcpMode::kOff)
986 return false;
nisse6f142eb2017-02-21 07:32:47 -0800987 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -0800988 }
989
nisse6f142eb2017-02-21 07:32:47 -0800990 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -0700991 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -0800992 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -0700993 !sender.send_failure_;
994}
995
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000996} // namespace webrtc