blob: 9145bbce1609000b1beac1d0cc3af5a856bfab2e [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_) {
perkj77cd58e2017-05-30 03:52:10 -0700102 event_log_->LogRtcpPacket(kOutgoingPacket, data, length);
terelius429c3452016-01-21 05:42:04 -0800103 }
104 }
Erik Språngf7c57762015-12-04 10:40:35 +0100105 }
106
danilchap41befce2016-03-30 11:11:51 -0700107 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800108 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700109 uint8_t buffer[IP_PACKET_SIZE];
110 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100111 return bytes_sent_;
112 }
113
114 private:
115 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800116 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100117 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800118
119 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100120};
121
122class RTCPSender::RtcpContext {
123 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200124 RtcpContext(const FeedbackState& feedback_state,
125 int32_t nack_size,
126 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800127 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100128 : feedback_state_(feedback_state),
129 nack_size_(nack_size),
130 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800131 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200132
Erik Språngf7c57762015-12-04 10:40:35 +0100133 const FeedbackState& feedback_state_;
134 const int32_t nack_size_;
135 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800136 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200137};
138
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000139RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000140 bool audio,
141 Clock* clock,
danilchapf5f793c2017-07-27 04:44:18 -0700142 ReceiveStatisticsProvider* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700143 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800144 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700145 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200146 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200147 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800148 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700149 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800150 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700151 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200152 using_nack_(false),
153 sending_(false),
154 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200155 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700156 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000157 last_rtp_timestamp_(0),
158 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200159 ssrc_(0),
160 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000161 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000162
Erik Språng242e22b2015-05-11 10:17:43 +0200163 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000166
danilchap2b616392016-08-18 06:17:42 -0700167 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200168 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800169 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000170
Erik Språng242e22b2015-05-11 10:17:43 +0200171 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200172 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200173 app_data_(nullptr),
174 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000175
Erik Språng242e22b2015-05-11 10:17:43 +0200176 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000177 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700178 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200179
180 builders_[kRtcpSr] = &RTCPSender::BuildSR;
181 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200182 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200183 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
184 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200185 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
186 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
187 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
188 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
189 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
190 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800191 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000192}
193
danilchap162abd32015-12-10 02:39:40 -0800194RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
pbosda903ea2015-10-02 02:36:56 -0700196RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700197 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200198 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000199}
200
skvlad1c392cc2016-04-01 14:46:44 -0700201void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700202 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000203
skvlad1c392cc2016-04-01 14:46:44 -0700204 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
205 // When switching on, reschedule the next packet
206 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200207 clock_->TimeInMilliseconds() +
208 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700209 }
210 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000211}
212
Erik Språng61be2a42015-04-27 13:32:52 +0200213bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700214 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200215 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000216}
217
Erik Språng61be2a42015-04-27 13:32:52 +0200218int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
219 bool sending) {
220 bool sendRTCPBye = false;
221 {
danilchap56036ff2016-03-22 11:14:09 -0700222 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000223
pbosda903ea2015-10-02 02:36:56 -0700224 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200225 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200226 // Trigger RTCP bye
227 sendRTCPBye = true;
228 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000229 }
Erik Språng242e22b2015-05-11 10:17:43 +0200230 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200231 }
232 if (sendRTCPBye)
233 return SendRTCP(feedback_state, kRtcpBye);
234 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235}
236
Erik Språng61be2a42015-04-27 13:32:52 +0200237bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700238 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200239 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000240}
241
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000242void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700243 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200244 remb_enabled_ = enable;
danilchapba6aa902017-04-18 06:57:02 -0700245 if (!enable) {
246 // Stop sending remb each report until it is reenabled and remb data set.
247 ConsumeFlag(kRtcpRemb, true);
248 }
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000249}
250
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000251void RTCPSender::SetREMBData(uint32_t bitrate,
252 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700253 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200254 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000255 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000256
Erik Språng242e22b2015-05-11 10:17:43 +0200257 if (remb_enabled_)
258 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000259 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
260 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200261 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000262}
263
Erik Språng61be2a42015-04-27 13:32:52 +0200264bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700265 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200266 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000267}
268
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000269void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700270 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200271 if (enable) {
272 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
273 } else {
274 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
275 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000276}
277
nisse284542b2017-01-10 08:58:32 -0800278void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800279 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800280 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700281}
282
danilchap71fead22016-08-18 02:01:49 -0700283void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700284 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700285 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000286}
287
288void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
289 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700290 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000291 last_rtp_timestamp_ = rtp_timestamp;
292 if (capture_time_ms < 0) {
293 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200294 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000295 } else {
296 last_frame_capture_time_ms_ = capture_time_ms;
297 }
298}
299
nisse14adba72017-03-20 03:52:39 -0700300uint32_t RTCPSender::SSRC() const {
301 rtc::CritScope lock(&critical_section_rtcp_sender_);
302 return ssrc_;
303}
304
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000305void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700306 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000307
Erik Språng242e22b2015-05-11 10:17:43 +0200308 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200309 // not first SetSSRC, probably due to a collision
310 // schedule a new RTCP report
311 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200312 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200313 }
Erik Språng242e22b2015-05-11 10:17:43 +0200314 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000315}
316
Erik Språng61be2a42015-04-27 13:32:52 +0200317void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700318 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200319 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000320}
321
Peter Boström9ba52f82015-06-01 14:12:28 +0200322int32_t RTCPSender::SetCNAME(const char* c_name) {
323 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000324 return -1;
325
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_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200328 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000329 return 0;
330}
331
Erik Språng0ea42d32015-06-25 14:46:16 +0200332int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700333 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800334 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700335 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700336 // One spot is reserved for ssrc_/cname_.
337 // TODO(danilchap): Add support for more than 30 contributes by sending
338 // several sdes packets.
339 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000340 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200341
342 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000343 return 0;
344}
345
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000346int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700347 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200348 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349
Erik Språng242e22b2015-05-11 10:17:43 +0200350 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000351 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200352
Erik Språng242e22b2015-05-11 10:17:43 +0200353 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000354 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355}
356
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000357bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800358 /*
359 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000360
danilchap162abd32015-12-10 02:39:40 -0800361 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
362 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
363 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
365
danilchap162abd32015-12-10 02:39:40 -0800366 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000367
danilchap162abd32015-12-10 02:39:40 -0800368 MAX RTCP BW is 5% if the session BW
369 A send report is approximately 65 bytes inc CNAME
370 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000371
danilchap162abd32015-12-10 02:39:40 -0800372 The RECOMMENDED value for the reduced minimum in seconds is 360
373 divided by the session bandwidth in kilobits/second. This minimum
374 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000375
danilchap162abd32015-12-10 02:39:40 -0800376 If the participant has not yet sent an RTCP packet (the variable
377 initial is true), the constant Tmin is set to 2.5 seconds, else it
378 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000379
danilchap162abd32015-12-10 02:39:40 -0800380 The interval between RTCP packets is varied randomly over the
381 range [0.5,1.5] times the calculated interval to avoid unintended
382 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
danilchap162abd32015-12-10 02:39:40 -0800384 if we send
385 If the participant is a sender (we_sent true), the constant C is
386 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
387 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
388 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000389
danilchap162abd32015-12-10 02:39:40 -0800390 if we receive only
391 If we_sent is not true, the constant C is set
392 to the average RTCP packet size divided by 75% of the RTCP
393 bandwidth. The constant n is set to the number of receivers
394 (members - senders). If the number of senders is greater than
395 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000396
danilchap162abd32015-12-10 02:39:40 -0800397 reconsideration NOT required for peer-to-peer
398 "timer reconsideration" is
399 employed. This algorithm implements a simple back-off mechanism
400 which causes users to hold back RTCP packet transmission if the
401 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000402
danilchap162abd32015-12-10 02:39:40 -0800403 n = number of members
404 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000407
danilchap162abd32015-12-10 02:39:40 -0800408 4. The calculated interval T is set to a number uniformly distributed
409 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000410
danilchap162abd32015-12-10 02:39:40 -0800411 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
412 for the fact that the timer reconsideration algorithm converges to
413 a value of the RTCP bandwidth below the intended average
414 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
Erik Språng242e22b2015-05-11 10:17:43 +0200416 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000417
danilchap56036ff2016-03-22 11:14:09 -0700418 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000419
pbosda903ea2015-10-02 02:36:56 -0700420 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000421 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000422
Erik Språng242e22b2015-05-11 10:17:43 +0200423 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200424 // for video key-frames we want to send the RTCP before the large key-frame
425 // if we have a 100 ms margin
426 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
427 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000428
Erik Språng242e22b2015-05-11 10:17:43 +0200429 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200430 return true;
431 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200432 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200433 // wrap
434 return true;
435 }
436 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437}
438
danilchap56036ff2016-03-22 11:14:09 -0700439std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200440 // Timestamp shouldn't be estimated before first media frame.
441 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200442 // The timestamp of this RTCP packet should be estimated as the timestamp of
443 // the frame being captured at this moment. We are calculating that
444 // timestamp as the last frame's timestamp + the time since the last frame
445 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700446 uint32_t rtp_rate =
447 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200448 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700449 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700450 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000451
Erik Språngf7c57762015-12-04 10:40:35 +0100452 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700453 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800454 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700455 report->SetRtpTimestamp(rtp_timestamp);
456 report->SetPacketCount(ctx.feedback_state_.packets_sent);
457 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
danilchap96b69bd2017-07-25 09:15:14 -0700458 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språngf7c57762015-12-04 10:40:35 +0100459
danilchap56036ff2016-03-22 11:14:09 -0700460 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000461}
462
danilchap56036ff2016-03-22 11:14:09 -0700463std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100464 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200465 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800466 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000467
Erik Språngf7c57762015-12-04 10:40:35 +0100468 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700469 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200470
danilchap74e8df8f2017-03-16 08:04:08 -0700471 for (const auto& it : csrc_cnames_)
472 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200473
danilchap56036ff2016-03-22 11:14:09 -0700474 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
danilchap56036ff2016-03-22 11:14:09 -0700477std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100478 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700479 report->SetSenderSsrc(ssrc_);
danilchap96b69bd2017-07-25 09:15:14 -0700480 report->SetReportBlocks(CreateReportBlocks(ctx.feedback_state_));
Erik Språng61be2a42015-04-27 13:32:52 +0200481
danilchap56036ff2016-03-22 11:14:09 -0700482 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000483}
484
danilchap56036ff2016-03-22 11:14:09 -0700485std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100486 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700487 pli->SetSenderSsrc(ssrc_);
488 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200489
Erik Språng242e22b2015-05-11 10:17:43 +0200490 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
491 "RTCPSender::PLI");
492 ++packet_type_counter_.pli_packets;
493 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
494 ssrc_, packet_type_counter_.pli_packets);
495
danilchap56036ff2016-03-22 11:14:09 -0700496 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200497}
498
danilchap56036ff2016-03-22 11:14:09 -0700499std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800500 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
Erik Språngf7c57762015-12-04 10:40:35 +0100502 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700503 fir->SetSenderSsrc(ssrc_);
504 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200505
506 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
507 "RTCPSender::FIR");
508 ++packet_type_counter_.fir_packets;
509 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
510 ssrc_, packet_type_counter_.fir_packets);
511
danilchap56036ff2016-03-22 11:14:09 -0700512 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000513}
514
danilchap56036ff2016-03-22 11:14:09 -0700515std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100516 const RtcpContext& ctx) {
517 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700518 remb->SetSenderSsrc(ssrc_);
519 remb->SetBitrateBps(remb_bitrate_);
520 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200521
Erik Språng242e22b2015-05-11 10:17:43 +0200522 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
523 "RTCPSender::REMB");
524
danilchap56036ff2016-03-22 11:14:09 -0700525 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000526}
527
Erik Språng61be2a42015-04-27 13:32:52 +0200528void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700529 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700530 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000531}
532
danilchap56036ff2016-03-22 11:14:09 -0700533std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100534 const RtcpContext& ctx) {
535 if (ctx.feedback_state_.module == nullptr)
536 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200537 // Before sending the TMMBR check the received TMMBN, only an owner is
538 // allowed to raise the bitrate:
539 // * If the sender is an owner of the TMMBN -> send TMMBR
540 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
Erik Språng61be2a42015-04-27 13:32:52 +0200542 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700543 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000544
Erik Språng242e22b2015-05-11 10:17:43 +0200545 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
546 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200547 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700548 std::vector<rtcp::TmmbItem> candidates =
549 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
danilchap2b616392016-08-18 06:17:42 -0700551 if (!candidates.empty()) {
552 for (const auto& candidate : candidates) {
553 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
554 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100555 // Do not send the same tuple.
556 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200557 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000558 }
danilchap2b616392016-08-18 06:17:42 -0700559 if (!tmmbr_owner) {
560 // Use received bounding set as candidate set.
561 // Add current tuple.
562 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000563
danilchap2b616392016-08-18 06:17:42 -0700564 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700565 std::vector<rtcp::TmmbItem> bounding =
566 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700567 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
568 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100569 // Did not enter bounding set, no meaning to send this request.
570 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200571 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000572 }
Erik Språng61be2a42015-04-27 13:32:52 +0200573 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000574
danilchap2b616392016-08-18 06:17:42 -0700575 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100576 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700577
Erik Språngf7c57762015-12-04 10:40:35 +0100578 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700579 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800580 rtcp::TmmbItem request;
581 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700582 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800583 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700584 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100585
danilchap56036ff2016-03-22 11:14:09 -0700586 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200587}
588
danilchap56036ff2016-03-22 11:14:09 -0700589std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100590 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100591 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700592 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700593 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
594 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700595 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000596 }
Erik Språng61be2a42015-04-27 13:32:52 +0200597 }
sprangd83df502015-08-27 01:05:08 -0700598
danilchap56036ff2016-03-22 11:14:09 -0700599 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000600}
601
danilchap56036ff2016-03-22 11:14:09 -0700602std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100603 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700604 app->SetSsrc(ssrc_);
605 app->SetSubType(app_sub_type_);
606 app->SetName(app_name_);
607 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200608
danilchap56036ff2016-03-22 11:14:09 -0700609 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200610}
611
danilchap56036ff2016-03-22 11:14:09 -0700612std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100613 const RtcpContext& ctx) {
614 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700615 nack->SetSenderSsrc(ssrc_);
616 nack->SetMediaSsrc(remote_ssrc_);
617 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200618
619 // Report stats.
620 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100621 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
622 stringBuilder.PushNACK(ctx.nack_list_[idx]);
623 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200624 }
Erik Språng61be2a42015-04-27 13:32:52 +0200625 packet_type_counter_.nack_requests = nack_stats_.requests();
626 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200627
628 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
629 "RTCPSender::NACK", "nacks",
630 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
631 ++packet_type_counter_.nack_packets;
632 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
633 ssrc_, packet_type_counter_.nack_packets);
634
danilchap56036ff2016-03-22 11:14:09 -0700635 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200636}
637
danilchap56036ff2016-03-22 11:14:09 -0700638std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100639 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700640 bye->SetSenderSsrc(ssrc_);
641 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700642
danilchap56036ff2016-03-22 11:14:09 -0700643 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000644}
645
sprang5e38c962016-12-01 05:18:09 -0800646std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100647 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800648 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700649 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000650
sprang5e38c962016-12-01 05:18:09 -0800651 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
652 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800653 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800654 xr->SetRrtr(rrtr);
655 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000656
sprang5e38c962016-12-01 05:18:09 -0800657 if (ctx.feedback_state_.has_last_xr_rr) {
658 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
659 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000660
sprang5e38c962016-12-01 05:18:09 -0800661 if (video_bitrate_allocation_) {
662 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000663
sprang5e38c962016-12-01 05:18:09 -0800664 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
665 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
666 uint32_t layer_bitrate_bps =
667 video_bitrate_allocation_->GetBitrate(sl, tl);
668 if (layer_bitrate_bps > 0)
669 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
670 }
671 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000672
sprang5e38c962016-12-01 05:18:09 -0800673 xr->SetTargetBitrate(target_bitrate);
674 video_bitrate_allocation_.reset();
675 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200676
sprang5e38c962016-12-01 05:18:09 -0800677 if (xr_voip_metric_) {
678 rtcp::VoipMetric voip;
679 voip.SetMediaSsrc(remote_ssrc_);
680 voip.SetVoipMetric(*xr_voip_metric_);
681 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000682
sprang5e38c962016-12-01 05:18:09 -0800683 xr->SetVoipMetric(voip);
684 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200685
sprang5e38c962016-12-01 05:18:09 -0800686 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000687}
688
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000689int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200690 RTCPPacketType packetType,
691 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700692 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200693 return SendCompoundRTCP(
694 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700695 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200696}
697
698int32_t RTCPSender::SendCompoundRTCP(
699 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100700 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200701 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700702 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800703 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800704 size_t max_packet_size;
705
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000706 {
danilchap56036ff2016-03-22 11:14:09 -0700707 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700708 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200709 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
710 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000711 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200712 // Add all flags as volatile. Non volatile entries will not be overwritten.
713 // All new volatile flags added will be consumed by the end of this call.
714 SetFlags(packet_types, true);
715
716 // Prevent sending streams to send SR before any media has been sent.
717 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
718 if (!can_calculate_rtp_timestamp) {
719 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
720 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
721 bool sender_report = consumed_report_flag || consumed_sr_flag;
722 if (sender_report && AllVolatileFlagsConsumed()) {
723 // This call was for Sender Report and nothing else.
724 return 0;
725 }
726 if (sending_ && method_ == RtcpMode::kCompound) {
727 // Not allowed to send any RTCP packet without sender report.
728 return -1;
729 }
730 }
731
732 if (packet_type_counter_.first_packet_time_ms == -1)
733 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100734
735 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700736 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800737 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100738
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200739 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100740
danilchap56036ff2016-03-22 11:14:09 -0700741 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800742
Erik Språngf7c57762015-12-04 10:40:35 +0100743 auto it = report_flags_.begin();
744 while (it != report_flags_.end()) {
745 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800746 RTC_DCHECK(builder_it != builders_.end())
747 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100748 if (it->is_volatile) {
749 report_flags_.erase(it++);
750 } else {
751 ++it;
752 }
753
754 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700755 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100756 if (packet.get() == nullptr)
757 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800758 // If there is a BYE, don't append now - save it and append it
759 // at the end later.
760 if (builder_it->first == kRtcpBye) {
761 packet_bye = std::move(packet);
762 } else {
763 container.Append(packet.release());
764 }
765 }
766
767 // Append the BYE now at the end
768 if (packet_bye) {
769 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100770 }
771
772 if (packet_type_counter_observer_ != nullptr) {
773 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
774 remote_ssrc_, packet_type_counter_);
775 }
776
777 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800778 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000779 }
Erik Språng61be2a42015-04-27 13:32:52 +0200780
nisse6f142eb2017-02-21 07:32:47 -0800781 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100782 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000783}
784
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200785void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200786 bool generate_report;
787 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
788 // Report type already explicitly set, don't automatically populate.
789 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700790 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200791 } else {
792 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700793 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
794 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200795 if (generate_report)
796 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000797 }
798
Erik Språng0ea42d32015-06-25 14:46:16 +0200799 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200800 SetFlag(kRtcpSdes, true);
801
Erik Språng242e22b2015-05-11 10:17:43 +0200802 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800803 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
804 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
805 SetFlag(kRtcpAnyExtendedReports, true);
806 }
Erik Språng242e22b2015-05-11 10:17:43 +0200807
808 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800809 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000810
danilchap47a740b2015-12-15 00:30:07 -0800811 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200812 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200813 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
814 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
815 if (send_bitrate_kbit != 0)
816 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000817 }
Erik Språng61be2a42015-04-27 13:32:52 +0200818 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
819 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200820 }
danilchap47a740b2015-12-15 00:30:07 -0800821 // The interval between RTCP packets is varied randomly over the
822 // range [1/2,3/2] times the calculated interval.
823 uint32_t timeToNext =
824 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200825 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000826
danilchap96b69bd2017-07-25 09:15:14 -0700827 // RtcpSender expected to be used for sending either just sender reports
828 // or just receiver reports.
829 RTC_DCHECK(!(IsFlagPresent(kRtcpSr) && IsFlagPresent(kRtcpRr)));
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000830 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000831}
832
danilchap96b69bd2017-07-25 09:15:14 -0700833std::vector<rtcp::ReportBlock> RTCPSender::CreateReportBlocks(
834 const FeedbackState& feedback_state) {
835 std::vector<rtcp::ReportBlock> result;
836 if (!receive_statistics_)
837 return result;
danilchapa72e7342015-12-22 08:07:45 -0800838
danilchapf5f793c2017-07-27 04:44:18 -0700839 // TODO(danilchap): Support sending more than |RTCP_MAX_REPORT_BLOCKS| per
840 // compound rtcp packet when single rtcp module is used for multiple media
841 // streams.
842 result = receive_statistics_->RtcpReportBlocks(RTCP_MAX_REPORT_BLOCKS);
danilchap96b69bd2017-07-25 09:15:14 -0700843
844 if (!result.empty() && ((feedback_state.last_rr_ntp_secs != 0) ||
845 (feedback_state.last_rr_ntp_frac != 0))) {
846 // Get our NTP as late as possible to avoid a race.
847 uint32_t now = CompactNtp(clock_->CurrentNtpTime());
848
849 uint32_t receive_time = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
850 receive_time <<= 16;
851 receive_time += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
852
853 uint32_t delay_since_last_sr = now - receive_time;
854 // TODO(danilchap): Instead of setting same value on all report blocks,
855 // set only when media_ssrc match sender ssrc of the sender report
856 // remote times were taken from.
857 for (auto& report_block : result) {
858 report_block.SetLastSr(feedback_state.remote_sr);
859 report_block.SetDelayLastSr(delay_since_last_sr);
860 }
danilchapa72e7342015-12-22 08:07:45 -0800861 }
danilchap96b69bd2017-07-25 09:15:14 -0700862 return result;
niklase@google.com470e71d2011-07-07 08:21:25 +0000863}
864
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000865void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800866 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700867 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000868 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000869}
870
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000871int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
872 uint32_t name,
873 const uint8_t* data,
874 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200875 if (length % 4 != 0) {
876 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
877 return -1;
878 }
danilchap56036ff2016-03-22 11:14:09 -0700879 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000880
Erik Språng242e22b2015-05-11 10:17:43 +0200881 SetFlag(kRtcpApp, true);
882 app_sub_type_ = subType;
883 app_name_ = name;
884 app_data_.reset(new uint8_t[length]);
885 app_length_ = length;
886 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200887 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000888}
889
spranga790d832016-12-02 07:29:44 -0800890// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200891int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700892 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800893 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000894
sprang5e38c962016-12-01 05:18:09 -0800895 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200896 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000897}
898
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000899void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700900 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200901 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000902}
903
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000904bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700905 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200906 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000907}
908
danilchap853ecb22016-08-22 08:26:15 -0700909void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700910 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700911 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700912 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000913}
Erik Språng61be2a42015-04-27 13:32:52 +0200914
sprang5e38c962016-12-01 05:18:09 -0800915void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
916 if (type & kRtcpAnyExtendedReports) {
917 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
918 } else {
919 report_flags_.insert(ReportFlag(type, is_volatile));
920 }
Erik Språng242e22b2015-05-11 10:17:43 +0200921}
922
923void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
924 bool is_volatile) {
925 for (RTCPPacketType type : types)
926 SetFlag(type, is_volatile);
927}
928
sprang5e38c962016-12-01 05:18:09 -0800929bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200930 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
931}
932
sprang5e38c962016-12-01 05:18:09 -0800933bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200934 auto it = report_flags_.find(ReportFlag(type, false));
935 if (it == report_flags_.end())
936 return false;
937 if (it->is_volatile || forced)
938 report_flags_.erase((it));
939 return true;
940}
941
942bool RTCPSender::AllVolatileFlagsConsumed() const {
943 for (const ReportFlag& flag : report_flags_) {
944 if (flag.is_volatile)
945 return false;
946 }
947 return true;
948}
949
sprang5e38c962016-12-01 05:18:09 -0800950void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
951 rtc::CritScope lock(&critical_section_rtcp_sender_);
952 video_bitrate_allocation_.emplace(bitrate);
953 SetFlag(kRtcpAnyExtendedReports, true);
954}
955
sprang233bd872015-09-08 13:25:16 -0700956bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700957 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
958 public:
terelius429c3452016-01-21 05:42:04 -0800959 Sender(Transport* transport, RtcEventLog* event_log)
960 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700961
962 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800963 if (transport_->SendRtcp(data, length)) {
964 if (event_log_) {
perkj77cd58e2017-05-30 03:52:10 -0700965 event_log_->LogRtcpPacket(kOutgoingPacket, data, length);
terelius429c3452016-01-21 05:42:04 -0800966 }
967 } else {
sprang233bd872015-09-08 13:25:16 -0700968 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800969 }
sprang233bd872015-09-08 13:25:16 -0700970 }
971
972 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800973 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700974 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800975 // TODO(terelius): We would like to
976 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
977 // but we can't because of an incorrect warning (C4822) in MVS 2013.
978 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -0700979
nisse6f142eb2017-02-21 07:32:47 -0800980 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -0800981 {
982 rtc::CritScope lock(&critical_section_rtcp_sender_);
983 if (method_ == RtcpMode::kOff)
984 return false;
nisse6f142eb2017-02-21 07:32:47 -0800985 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -0800986 }
987
nisse6f142eb2017-02-21 07:32:47 -0800988 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -0700989 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -0800990 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -0700991 !sender.send_failure_;
992}
993
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000994} // namespace webrtc