blob: 93d7aa3c1f1e76f45fe21a34e74006bbc2e38e14 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000011#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
stefan@webrtc.org9354cc92012-06-07 08:10:14 +000013#include <string.h> // memcpy
niklase@google.com470e71d2011-07-07 08:21:25 +000014
Danil Chapovalov70ffead2016-07-20 15:26:59 +020015#include <utility>
16
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000017#include "webrtc/common_types.h"
skvladcc91d282016-10-03 18:31:22 -070018#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
danilchap0219c9b2015-11-18 05:56:53 -080019#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080020#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080021#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010022#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010023#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchapef3d8052016-01-11 03:31:08 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070033#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap42287842017-02-20 06:40:18 -080034#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070035#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020036#include "webrtc/rtc_base/checks.h"
37#include "webrtc/rtc_base/constructormagic.h"
38#include "webrtc/rtc_base/logging.h"
39#include "webrtc/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,
142 ReceiveStatistics* 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);
niklase@google.com470e71d2011-07-07 08:21:25 +0000458
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200459 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700460 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000461
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200462 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100463
danilchap56036ff2016-03-22 11:14:09 -0700464 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000465}
466
danilchap56036ff2016-03-22 11:14:09 -0700467std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100468 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200469 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800470 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000471
Erik Språngf7c57762015-12-04 10:40:35 +0100472 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700473 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200474
danilchap74e8df8f2017-03-16 08:04:08 -0700475 for (const auto& it : csrc_cnames_)
476 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200477
danilchap56036ff2016-03-22 11:14:09 -0700478 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000479}
480
danilchap56036ff2016-03-22 11:14:09 -0700481std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100482 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700483 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200484 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700485 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200486
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200487 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700488 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489}
490
danilchap56036ff2016-03-22 11:14:09 -0700491std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100492 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700493 pli->SetSenderSsrc(ssrc_);
494 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200495
Erik Språng242e22b2015-05-11 10:17:43 +0200496 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
497 "RTCPSender::PLI");
498 ++packet_type_counter_.pli_packets;
499 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
500 ssrc_, packet_type_counter_.pli_packets);
501
danilchap56036ff2016-03-22 11:14:09 -0700502 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200503}
504
danilchap56036ff2016-03-22 11:14:09 -0700505std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800506 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
Erik Språngf7c57762015-12-04 10:40:35 +0100508 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700509 fir->SetSenderSsrc(ssrc_);
510 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200511
512 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
513 "RTCPSender::FIR");
514 ++packet_type_counter_.fir_packets;
515 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
516 ssrc_, packet_type_counter_.fir_packets);
517
danilchap56036ff2016-03-22 11:14:09 -0700518 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000519}
520
danilchap56036ff2016-03-22 11:14:09 -0700521std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100522 const RtcpContext& ctx) {
523 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700524 remb->SetSenderSsrc(ssrc_);
525 remb->SetBitrateBps(remb_bitrate_);
526 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200527
Erik Språng242e22b2015-05-11 10:17:43 +0200528 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
529 "RTCPSender::REMB");
530
danilchap56036ff2016-03-22 11:14:09 -0700531 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000532}
533
Erik Språng61be2a42015-04-27 13:32:52 +0200534void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700535 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700536 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000537}
538
danilchap56036ff2016-03-22 11:14:09 -0700539std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100540 const RtcpContext& ctx) {
541 if (ctx.feedback_state_.module == nullptr)
542 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200543 // Before sending the TMMBR check the received TMMBN, only an owner is
544 // allowed to raise the bitrate:
545 // * If the sender is an owner of the TMMBN -> send TMMBR
546 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000547
Erik Språng61be2a42015-04-27 13:32:52 +0200548 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700549 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000550
Erik Språng242e22b2015-05-11 10:17:43 +0200551 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
552 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200553 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700554 std::vector<rtcp::TmmbItem> candidates =
555 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000556
danilchap2b616392016-08-18 06:17:42 -0700557 if (!candidates.empty()) {
558 for (const auto& candidate : candidates) {
559 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
560 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100561 // Do not send the same tuple.
562 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200563 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000564 }
danilchap2b616392016-08-18 06:17:42 -0700565 if (!tmmbr_owner) {
566 // Use received bounding set as candidate set.
567 // Add current tuple.
568 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000569
danilchap2b616392016-08-18 06:17:42 -0700570 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700571 std::vector<rtcp::TmmbItem> bounding =
572 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700573 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
574 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100575 // Did not enter bounding set, no meaning to send this request.
576 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200577 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000578 }
Erik Språng61be2a42015-04-27 13:32:52 +0200579 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000580
danilchap2b616392016-08-18 06:17:42 -0700581 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100582 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700583
Erik Språngf7c57762015-12-04 10:40:35 +0100584 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700585 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800586 rtcp::TmmbItem request;
587 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700588 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800589 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700590 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100591
danilchap56036ff2016-03-22 11:14:09 -0700592 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200593}
594
danilchap56036ff2016-03-22 11:14:09 -0700595std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100596 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100597 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700598 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700599 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
600 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700601 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000602 }
Erik Språng61be2a42015-04-27 13:32:52 +0200603 }
sprangd83df502015-08-27 01:05:08 -0700604
danilchap56036ff2016-03-22 11:14:09 -0700605 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000606}
607
danilchap56036ff2016-03-22 11:14:09 -0700608std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100609 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700610 app->SetSsrc(ssrc_);
611 app->SetSubType(app_sub_type_);
612 app->SetName(app_name_);
613 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200614
danilchap56036ff2016-03-22 11:14:09 -0700615 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200616}
617
danilchap56036ff2016-03-22 11:14:09 -0700618std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100619 const RtcpContext& ctx) {
620 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700621 nack->SetSenderSsrc(ssrc_);
622 nack->SetMediaSsrc(remote_ssrc_);
623 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200624
625 // Report stats.
626 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100627 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
628 stringBuilder.PushNACK(ctx.nack_list_[idx]);
629 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200630 }
Erik Språng61be2a42015-04-27 13:32:52 +0200631 packet_type_counter_.nack_requests = nack_stats_.requests();
632 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200633
634 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
635 "RTCPSender::NACK", "nacks",
636 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
637 ++packet_type_counter_.nack_packets;
638 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
639 ssrc_, packet_type_counter_.nack_packets);
640
danilchap56036ff2016-03-22 11:14:09 -0700641 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200642}
643
danilchap56036ff2016-03-22 11:14:09 -0700644std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100645 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700646 bye->SetSenderSsrc(ssrc_);
647 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700648
danilchap56036ff2016-03-22 11:14:09 -0700649 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000650}
651
sprang5e38c962016-12-01 05:18:09 -0800652std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100653 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800654 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700655 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000656
sprang5e38c962016-12-01 05:18:09 -0800657 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
658 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800659 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800660 xr->SetRrtr(rrtr);
661 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000662
sprang5e38c962016-12-01 05:18:09 -0800663 if (ctx.feedback_state_.has_last_xr_rr) {
664 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
665 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000666
sprang5e38c962016-12-01 05:18:09 -0800667 if (video_bitrate_allocation_) {
668 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000669
sprang5e38c962016-12-01 05:18:09 -0800670 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
671 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
672 uint32_t layer_bitrate_bps =
673 video_bitrate_allocation_->GetBitrate(sl, tl);
674 if (layer_bitrate_bps > 0)
675 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
676 }
677 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000678
sprang5e38c962016-12-01 05:18:09 -0800679 xr->SetTargetBitrate(target_bitrate);
680 video_bitrate_allocation_.reset();
681 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200682
sprang5e38c962016-12-01 05:18:09 -0800683 if (xr_voip_metric_) {
684 rtcp::VoipMetric voip;
685 voip.SetMediaSsrc(remote_ssrc_);
686 voip.SetVoipMetric(*xr_voip_metric_);
687 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000688
sprang5e38c962016-12-01 05:18:09 -0800689 xr->SetVoipMetric(voip);
690 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200691
sprang5e38c962016-12-01 05:18:09 -0800692 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000693}
694
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000695int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200696 RTCPPacketType packetType,
697 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700698 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200699 return SendCompoundRTCP(
700 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700701 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200702}
703
704int32_t RTCPSender::SendCompoundRTCP(
705 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100706 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200707 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700708 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800709 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800710 size_t max_packet_size;
711
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000712 {
danilchap56036ff2016-03-22 11:14:09 -0700713 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700714 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200715 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
716 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000717 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200718 // Add all flags as volatile. Non volatile entries will not be overwritten.
719 // All new volatile flags added will be consumed by the end of this call.
720 SetFlags(packet_types, true);
721
722 // Prevent sending streams to send SR before any media has been sent.
723 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
724 if (!can_calculate_rtp_timestamp) {
725 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
726 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
727 bool sender_report = consumed_report_flag || consumed_sr_flag;
728 if (sender_report && AllVolatileFlagsConsumed()) {
729 // This call was for Sender Report and nothing else.
730 return 0;
731 }
732 if (sending_ && method_ == RtcpMode::kCompound) {
733 // Not allowed to send any RTCP packet without sender report.
734 return -1;
735 }
736 }
737
738 if (packet_type_counter_.first_packet_time_ms == -1)
739 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100740
741 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700742 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800743 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100744
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200745 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100746
danilchap56036ff2016-03-22 11:14:09 -0700747 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800748
Erik Språngf7c57762015-12-04 10:40:35 +0100749 auto it = report_flags_.begin();
750 while (it != report_flags_.end()) {
751 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800752 RTC_DCHECK(builder_it != builders_.end())
753 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100754 if (it->is_volatile) {
755 report_flags_.erase(it++);
756 } else {
757 ++it;
758 }
759
760 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700761 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100762 if (packet.get() == nullptr)
763 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800764 // If there is a BYE, don't append now - save it and append it
765 // at the end later.
766 if (builder_it->first == kRtcpBye) {
767 packet_bye = std::move(packet);
768 } else {
769 container.Append(packet.release());
770 }
771 }
772
773 // Append the BYE now at the end
774 if (packet_bye) {
775 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100776 }
777
778 if (packet_type_counter_observer_ != nullptr) {
779 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
780 remote_ssrc_, packet_type_counter_);
781 }
782
783 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800784 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000785 }
Erik Språng61be2a42015-04-27 13:32:52 +0200786
nisse6f142eb2017-02-21 07:32:47 -0800787 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100788 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000789}
790
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200791void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200792 bool generate_report;
793 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
794 // Report type already explicitly set, don't automatically populate.
795 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700796 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200797 } else {
798 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700799 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
800 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200801 if (generate_report)
802 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000803 }
804
Erik Språng0ea42d32015-06-25 14:46:16 +0200805 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200806 SetFlag(kRtcpSdes, true);
807
Erik Språng242e22b2015-05-11 10:17:43 +0200808 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800809 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
810 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
811 SetFlag(kRtcpAnyExtendedReports, true);
812 }
Erik Språng242e22b2015-05-11 10:17:43 +0200813
814 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800815 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000816
danilchap47a740b2015-12-15 00:30:07 -0800817 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200818 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200819 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
820 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
821 if (send_bitrate_kbit != 0)
822 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000823 }
Erik Språng61be2a42015-04-27 13:32:52 +0200824 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
825 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200826 }
danilchap47a740b2015-12-15 00:30:07 -0800827 // The interval between RTCP packets is varied randomly over the
828 // range [1/2,3/2] times the calculated interval.
829 uint32_t timeToNext =
830 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200831 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000832
Per83d09102016-04-15 14:59:13 +0200833 if (receive_statistics_) {
834 StatisticianMap statisticians =
835 receive_statistics_->GetActiveStatisticians();
836 RTC_DCHECK(report_blocks_.empty());
837 for (auto& it : statisticians) {
838 AddReportBlock(feedback_state, it.first, it.second);
839 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000840 }
841 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000842}
843
danilchapa72e7342015-12-22 08:07:45 -0800844bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
845 uint32_t ssrc,
846 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000847 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000848 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000849 if (!statistician->GetStatistics(&stats, true))
850 return false;
danilchapa72e7342015-12-22 08:07:45 -0800851
852 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
853 LOG(LS_WARNING) << "Too many report blocks.";
854 return false;
855 }
856 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
857 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700858 block->SetMediaSsrc(ssrc);
859 block->SetFractionLost(stats.fraction_lost);
860 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800861 report_blocks_.erase(ssrc);
862 LOG(LS_WARNING) << "Cumulative lost is oversized.";
863 return false;
864 }
danilchap822a16f2016-09-27 09:27:47 -0700865 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
866 block->SetJitter(stats.jitter);
867 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000868
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200869 // TODO(sprang): Do we really need separate time stamps for each report?
870 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800871 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000872
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200873 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000874 if ((feedback_state.last_rr_ntp_secs != 0) ||
875 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200876 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800877 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000878
Erik Språng61be2a42015-04-27 13:32:52 +0200879 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
880 receiveTime <<= 16;
881 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882
danilchap822a16f2016-09-27 09:27:47 -0700883 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000884 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000885 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000886}
887
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000888void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800889 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700890 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000891 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000892}
893
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000894int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
895 uint32_t name,
896 const uint8_t* data,
897 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200898 if (length % 4 != 0) {
899 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
900 return -1;
901 }
danilchap56036ff2016-03-22 11:14:09 -0700902 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000903
Erik Språng242e22b2015-05-11 10:17:43 +0200904 SetFlag(kRtcpApp, true);
905 app_sub_type_ = subType;
906 app_name_ = name;
907 app_data_.reset(new uint8_t[length]);
908 app_length_ = length;
909 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200910 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000911}
912
spranga790d832016-12-02 07:29:44 -0800913// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200914int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700915 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800916 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000917
sprang5e38c962016-12-01 05:18:09 -0800918 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200919 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000920}
921
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000922void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700923 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200924 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000925}
926
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000927bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700928 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200929 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000930}
931
danilchap853ecb22016-08-22 08:26:15 -0700932void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700933 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700934 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700935 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000936}
Erik Språng61be2a42015-04-27 13:32:52 +0200937
sprang5e38c962016-12-01 05:18:09 -0800938void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
939 if (type & kRtcpAnyExtendedReports) {
940 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
941 } else {
942 report_flags_.insert(ReportFlag(type, is_volatile));
943 }
Erik Språng242e22b2015-05-11 10:17:43 +0200944}
945
946void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
947 bool is_volatile) {
948 for (RTCPPacketType type : types)
949 SetFlag(type, is_volatile);
950}
951
sprang5e38c962016-12-01 05:18:09 -0800952bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200953 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
954}
955
sprang5e38c962016-12-01 05:18:09 -0800956bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200957 auto it = report_flags_.find(ReportFlag(type, false));
958 if (it == report_flags_.end())
959 return false;
960 if (it->is_volatile || forced)
961 report_flags_.erase((it));
962 return true;
963}
964
965bool RTCPSender::AllVolatileFlagsConsumed() const {
966 for (const ReportFlag& flag : report_flags_) {
967 if (flag.is_volatile)
968 return false;
969 }
970 return true;
971}
972
sprang5e38c962016-12-01 05:18:09 -0800973void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
974 rtc::CritScope lock(&critical_section_rtcp_sender_);
975 video_bitrate_allocation_.emplace(bitrate);
976 SetFlag(kRtcpAnyExtendedReports, true);
977}
978
sprang233bd872015-09-08 13:25:16 -0700979bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700980 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
981 public:
terelius429c3452016-01-21 05:42:04 -0800982 Sender(Transport* transport, RtcEventLog* event_log)
983 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700984
985 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800986 if (transport_->SendRtcp(data, length)) {
987 if (event_log_) {
perkj77cd58e2017-05-30 03:52:10 -0700988 event_log_->LogRtcpPacket(kOutgoingPacket, data, length);
terelius429c3452016-01-21 05:42:04 -0800989 }
990 } else {
sprang233bd872015-09-08 13:25:16 -0700991 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800992 }
sprang233bd872015-09-08 13:25:16 -0700993 }
994
995 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800996 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700997 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800998 // TODO(terelius): We would like to
999 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
1000 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1001 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001002
nisse6f142eb2017-02-21 07:32:47 -08001003 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -08001004 {
1005 rtc::CritScope lock(&critical_section_rtcp_sender_);
1006 if (method_ == RtcpMode::kOff)
1007 return false;
nisse6f142eb2017-02-21 07:32:47 -08001008 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001009 }
1010
nisse6f142eb2017-02-21 07:32:47 -08001011 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001012 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001013 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001014 !sender.send_failure_;
1015}
1016
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001017} // namespace webrtc