blob: e3cf65ef08f04f266268a92240d6cae3cd2f46fe [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
Erik Språng61be2a42015-04-27 13:32:52 +020017#include "webrtc/base/checks.h"
kwiberg4485ffb2016-04-26 08:14:39 -070018#include "webrtc/base/constructormagic.h"
Peter Boströmebc0b4e2015-10-28 16:39:33 +010019#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070020#include "webrtc/base/trace_event.h"
ossuf515ab82016-12-07 04:52:58 -080021#include "webrtc/call/call.h"
pbos@webrtc.orga048d7c2013-05-29 14:27:38 +000022#include "webrtc/common_types.h"
skvladcc91d282016-10-03 18:31:22 -070023#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
danilchap0219c9b2015-11-18 05:56:53 -080024#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/app.h"
danilchap50c51362015-11-22 09:03:11 -080025#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h"
danilchap2f7dea12016-01-13 02:03:04 -080026#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
Danil Chapovalov256e5b22016-01-15 14:16:24 +010027#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
Danil Chapovalov5679da12016-01-15 13:19:53 +010028#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/fir.h"
danilchapa8890a52015-12-22 03:43:04 -080029#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
danilchapf8385ad2015-11-27 05:36:09 -080030#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/pli.h"
Danil Chapovalov97f7e132015-12-04 16:13:30 +010031#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
Danil Chapovalova5eba6c2016-01-15 12:40:15 +010032#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/remb.h"
Danil Chapovalov1567d0b2016-01-15 17:34:27 +010033#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h"
danilchap34ed2b92016-01-18 02:43:32 -080034#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
danilchapef3d8052016-01-11 03:31:08 -080035#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
danilchap7e8145f2016-01-11 11:49:19 -080036#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
sprang233bd872015-09-08 13:25:16 -070037#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
tommie4f96502015-10-20 23:00:48 -070038#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
danilchap42287842017-02-20 06:40:18 -080039#include "webrtc/modules/rtp_rtcp/source/time_util.h"
danilchap13deaad2016-05-24 13:25:27 -070040#include "webrtc/modules/rtp_rtcp/source/tmmbr_help.h"
pwestin@webrtc.org741da942011-09-20 13:52:04 +000041
niklase@google.com470e71d2011-07-07 08:21:25 +000042namespace webrtc {
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +000043
sprang5e38c962016-12-01 05:18:09 -080044namespace {
45const uint32_t kRtcpAnyExtendedReports =
46 kRtcpXrVoipMetric | kRtcpXrReceiverReferenceTime | kRtcpXrDlrrReportBlock |
47 kRtcpXrTargetBitrate;
48} // namespace
49
Erik Språng61be2a42015-04-27 13:32:52 +020050NACKStringBuilder::NACKStringBuilder()
danilchap162abd32015-12-10 02:39:40 -080051 : stream_(""), count_(0), prevNack_(0), consecutive_(false) {}
edjee@google.com79b02892013-04-04 19:43:34 +000052
pbos@webrtc.orgf3e4cee2013-07-31 15:17:19 +000053NACKStringBuilder::~NACKStringBuilder() {}
54
danilchap162abd32015-12-10 02:39:40 -080055void NACKStringBuilder::PushNACK(uint16_t nack) {
Erik Språng242e22b2015-05-11 10:17:43 +020056 if (count_ == 0) {
57 stream_ << nack;
58 } else if (nack == prevNack_ + 1) {
59 consecutive_ = true;
Erik Språng61be2a42015-04-27 13:32:52 +020060 } else {
Erik Språng242e22b2015-05-11 10:17:43 +020061 if (consecutive_) {
62 stream_ << "-" << prevNack_;
63 consecutive_ = false;
edjee@google.com79b02892013-04-04 19:43:34 +000064 }
Erik Språng242e22b2015-05-11 10:17:43 +020065 stream_ << "," << nack;
Erik Språng61be2a42015-04-27 13:32:52 +020066 }
Erik Språng242e22b2015-05-11 10:17:43 +020067 count_++;
68 prevNack_ = nack;
edjee@google.com79b02892013-04-04 19:43:34 +000069}
70
Erik Språng61be2a42015-04-27 13:32:52 +020071std::string NACKStringBuilder::GetResult() {
Erik Språng242e22b2015-05-11 10:17:43 +020072 if (consecutive_) {
73 stream_ << "-" << prevNack_;
74 consecutive_ = false;
Erik Språng61be2a42015-04-27 13:32:52 +020075 }
Erik Språng242e22b2015-05-11 10:17:43 +020076 return stream_.str();
edjee@google.com79b02892013-04-04 19:43:34 +000077}
78
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000079RTCPSender::FeedbackState::FeedbackState()
nisse40ba3ad2017-03-17 07:04:00 -070080 : packets_sent(0),
pbos@webrtc.org2f4b14e2014-07-15 15:25:39 +000081 media_bytes_sent(0),
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000082 send_bitrate(0),
83 last_rr_ntp_secs(0),
84 last_rr_ntp_frac(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +000085 remote_sr(0),
Erik Språng61be2a42015-04-27 13:32:52 +020086 has_last_xr_rr(false),
danilchap162abd32015-12-10 02:39:40 -080087 module(nullptr) {}
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +000088
danilchap2f7dea12016-01-13 02:03:04 -080089class PacketContainer : public rtcp::CompoundPacket,
Erik Språngf7c57762015-12-04 10:40:35 +010090 public rtcp::RtcpPacket::PacketReadyCallback {
91 public:
terelius429c3452016-01-21 05:42:04 -080092 PacketContainer(Transport* transport, RtcEventLog* event_log)
93 : transport_(transport), event_log_(event_log), bytes_sent_(0) {}
Erik Språngf7c57762015-12-04 10:40:35 +010094 virtual ~PacketContainer() {
95 for (RtcpPacket* packet : appended_packets_)
96 delete packet;
97 }
98
99 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800100 if (transport_->SendRtcp(data, length)) {
Erik Språngf7c57762015-12-04 10:40:35 +0100101 bytes_sent_ += length;
terelius429c3452016-01-21 05:42:04 -0800102 if (event_log_) {
103 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
104 length);
105 }
106 }
Erik Språngf7c57762015-12-04 10:40:35 +0100107 }
108
danilchap41befce2016-03-30 11:11:51 -0700109 size_t SendPackets(size_t max_payload_length) {
kwiberg352444f2016-11-28 15:58:53 -0800110 RTC_DCHECK_LE(max_payload_length, IP_PACKET_SIZE);
danilchap41befce2016-03-30 11:11:51 -0700111 uint8_t buffer[IP_PACKET_SIZE];
112 BuildExternalBuffer(buffer, max_payload_length, this);
Erik Språngf7c57762015-12-04 10:40:35 +0100113 return bytes_sent_;
114 }
115
116 private:
117 Transport* transport_;
terelius429c3452016-01-21 05:42:04 -0800118 RtcEventLog* const event_log_;
Erik Språngf7c57762015-12-04 10:40:35 +0100119 size_t bytes_sent_;
terelius429c3452016-01-21 05:42:04 -0800120
121 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacketContainer);
Erik Språngf7c57762015-12-04 10:40:35 +0100122};
123
124class RTCPSender::RtcpContext {
125 public:
Erik Språng242e22b2015-05-11 10:17:43 +0200126 RtcpContext(const FeedbackState& feedback_state,
127 int32_t nack_size,
128 const uint16_t* nack_list,
danilchap51813b32016-12-16 02:44:36 -0800129 NtpTime now)
Erik Språngf7c57762015-12-04 10:40:35 +0100130 : feedback_state_(feedback_state),
131 nack_size_(nack_size),
132 nack_list_(nack_list),
danilchap51813b32016-12-16 02:44:36 -0800133 now_(now) {}
Erik Språng242e22b2015-05-11 10:17:43 +0200134
Erik Språngf7c57762015-12-04 10:40:35 +0100135 const FeedbackState& feedback_state_;
136 const int32_t nack_size_;
137 const uint16_t* nack_list_;
danilchap51813b32016-12-16 02:44:36 -0800138 const NtpTime now_;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200139};
140
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000141RTCPSender::RTCPSender(
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000142 bool audio,
143 Clock* clock,
144 ReceiveStatistics* receive_statistics,
sprang86fd9ed2015-09-29 04:45:43 -0700145 RtcpPacketTypeCounterObserver* packet_type_counter_observer,
terelius429c3452016-01-21 05:42:04 -0800146 RtcEventLog* event_log,
sprang86fd9ed2015-09-29 04:45:43 -0700147 Transport* outgoing_transport)
Peter Boströmac547a62015-09-17 23:03:57 +0200148 : audio_(audio),
Erik Språng242e22b2015-05-11 10:17:43 +0200149 clock_(clock),
danilchap47a740b2015-12-15 00:30:07 -0800150 random_(clock_->TimeInMicroseconds()),
pbosda903ea2015-10-02 02:36:56 -0700151 method_(RtcpMode::kOff),
terelius429c3452016-01-21 05:42:04 -0800152 event_log_(event_log),
sprang86fd9ed2015-09-29 04:45:43 -0700153 transport_(outgoing_transport),
Erik Språng242e22b2015-05-11 10:17:43 +0200154 using_nack_(false),
155 sending_(false),
156 remb_enabled_(false),
Erik Språng242e22b2015-05-11 10:17:43 +0200157 next_time_to_send_rtcp_(0),
danilchap71fead22016-08-18 02:01:49 -0700158 timestamp_offset_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000159 last_rtp_timestamp_(0),
160 last_frame_capture_time_ms_(-1),
Erik Språng242e22b2015-05-11 10:17:43 +0200161 ssrc_(0),
162 remote_ssrc_(0),
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000163 receive_statistics_(receive_statistics),
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
Erik Språng242e22b2015-05-11 10:17:43 +0200165 sequence_number_fir_(0),
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000166
Erik Språng242e22b2015-05-11 10:17:43 +0200167 remb_bitrate_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
danilchap2b616392016-08-18 06:17:42 -0700169 tmmbr_send_bps_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200170 packet_oh_send_(0),
nisse284542b2017-01-10 08:58:32 -0800171 max_packet_size_(IP_PACKET_SIZE - 28), // IPv4 + UDP by default.
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000172
Erik Språng242e22b2015-05-11 10:17:43 +0200173 app_sub_type_(0),
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200174 app_name_(0),
Erik Språng242e22b2015-05-11 10:17:43 +0200175 app_data_(nullptr),
176 app_length_(0),
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
Erik Språng242e22b2015-05-11 10:17:43 +0200178 xr_send_receiver_reference_time_enabled_(false),
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +0000179 packet_type_counter_observer_(packet_type_counter_observer) {
sprang86fd9ed2015-09-29 04:45:43 -0700180 RTC_DCHECK(transport_ != nullptr);
Erik Språng242e22b2015-05-11 10:17:43 +0200181
182 builders_[kRtcpSr] = &RTCPSender::BuildSR;
183 builders_[kRtcpRr] = &RTCPSender::BuildRR;
Erik Språng0ea42d32015-06-25 14:46:16 +0200184 builders_[kRtcpSdes] = &RTCPSender::BuildSDES;
Erik Språng242e22b2015-05-11 10:17:43 +0200185 builders_[kRtcpPli] = &RTCPSender::BuildPLI;
186 builders_[kRtcpFir] = &RTCPSender::BuildFIR;
Erik Språng242e22b2015-05-11 10:17:43 +0200187 builders_[kRtcpRemb] = &RTCPSender::BuildREMB;
188 builders_[kRtcpBye] = &RTCPSender::BuildBYE;
189 builders_[kRtcpApp] = &RTCPSender::BuildAPP;
190 builders_[kRtcpTmmbr] = &RTCPSender::BuildTMMBR;
191 builders_[kRtcpTmmbn] = &RTCPSender::BuildTMMBN;
192 builders_[kRtcpNack] = &RTCPSender::BuildNACK;
sprang5e38c962016-12-01 05:18:09 -0800193 builders_[kRtcpAnyExtendedReports] = &RTCPSender::BuildExtendedReports;
niklase@google.com470e71d2011-07-07 08:21:25 +0000194}
195
danilchap162abd32015-12-10 02:39:40 -0800196RTCPSender::~RTCPSender() {}
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
pbosda903ea2015-10-02 02:36:56 -0700198RtcpMode RTCPSender::Status() const {
danilchap56036ff2016-03-22 11:14:09 -0700199 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200200 return method_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
skvlad1c392cc2016-04-01 14:46:44 -0700203void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
danilchap56036ff2016-03-22 11:14:09 -0700204 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000205
skvlad1c392cc2016-04-01 14:46:44 -0700206 if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
207 // When switching on, reschedule the next packet
208 next_time_to_send_rtcp_ =
Erik Språng242e22b2015-05-11 10:17:43 +0200209 clock_->TimeInMilliseconds() +
210 (audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
skvlad1c392cc2016-04-01 14:46:44 -0700211 }
212 method_ = new_method;
niklase@google.com470e71d2011-07-07 08:21:25 +0000213}
214
Erik Språng61be2a42015-04-27 13:32:52 +0200215bool RTCPSender::Sending() const {
danilchap56036ff2016-03-22 11:14:09 -0700216 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200217 return sending_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000218}
219
Erik Språng61be2a42015-04-27 13:32:52 +0200220int32_t RTCPSender::SetSendingStatus(const FeedbackState& feedback_state,
221 bool sending) {
222 bool sendRTCPBye = false;
223 {
danilchap56036ff2016-03-22 11:14:09 -0700224 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000225
pbosda903ea2015-10-02 02:36:56 -0700226 if (method_ != RtcpMode::kOff) {
Erik Språng242e22b2015-05-11 10:17:43 +0200227 if (sending == false && sending_ == true) {
Erik Språng61be2a42015-04-27 13:32:52 +0200228 // Trigger RTCP bye
229 sendRTCPBye = true;
230 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
Erik Språng242e22b2015-05-11 10:17:43 +0200232 sending_ = sending;
Erik Språng61be2a42015-04-27 13:32:52 +0200233 }
234 if (sendRTCPBye)
235 return SendRTCP(feedback_state, kRtcpBye);
236 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000237}
238
Erik Språng61be2a42015-04-27 13:32:52 +0200239bool RTCPSender::REMB() const {
danilchap56036ff2016-03-22 11:14:09 -0700240 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200241 return remb_enabled_;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000242}
243
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000244void RTCPSender::SetREMBStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700245 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200246 remb_enabled_ = enable;
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000247}
248
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000249void RTCPSender::SetREMBData(uint32_t bitrate,
250 const std::vector<uint32_t>& ssrcs) {
danilchap56036ff2016-03-22 11:14:09 -0700251 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200252 remb_bitrate_ = bitrate;
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000253 remb_ssrcs_ = ssrcs;
stefan@webrtc.org4ef438e2014-07-11 09:55:30 +0000254
Erik Språng242e22b2015-05-11 10:17:43 +0200255 if (remb_enabled_)
256 SetFlag(kRtcpRemb, false);
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000257 // Send a REMB immediately if we have a new REMB. The frequency of REMBs is
258 // throttled by the caller.
Erik Språng242e22b2015-05-11 10:17:43 +0200259 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds();
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000260}
261
Erik Språng61be2a42015-04-27 13:32:52 +0200262bool RTCPSender::TMMBR() const {
danilchap56036ff2016-03-22 11:14:09 -0700263 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200264 return IsFlagPresent(RTCPPacketType::kRtcpTmmbr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000265}
266
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000267void RTCPSender::SetTMMBRStatus(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700268 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200269 if (enable) {
270 SetFlag(RTCPPacketType::kRtcpTmmbr, false);
271 } else {
272 ConsumeFlag(RTCPPacketType::kRtcpTmmbr, true);
273 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000274}
275
nisse284542b2017-01-10 08:58:32 -0800276void RTCPSender::SetMaxRtpPacketSize(size_t max_packet_size) {
nisse6f142eb2017-02-21 07:32:47 -0800277 rtc::CritScope lock(&critical_section_rtcp_sender_);
nisse284542b2017-01-10 08:58:32 -0800278 max_packet_size_ = max_packet_size;
danilchap41befce2016-03-30 11:11:51 -0700279}
280
danilchap71fead22016-08-18 02:01:49 -0700281void RTCPSender::SetTimestampOffset(uint32_t timestamp_offset) {
danilchap56036ff2016-03-22 11:14:09 -0700282 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap71fead22016-08-18 02:01:49 -0700283 timestamp_offset_ = timestamp_offset;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000284}
285
286void RTCPSender::SetLastRtpTime(uint32_t rtp_timestamp,
287 int64_t capture_time_ms) {
danilchap56036ff2016-03-22 11:14:09 -0700288 rtc::CritScope lock(&critical_section_rtcp_sender_);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000289 last_rtp_timestamp_ = rtp_timestamp;
290 if (capture_time_ms < 0) {
291 // We don't currently get a capture time from VoiceEngine.
Erik Språng242e22b2015-05-11 10:17:43 +0200292 last_frame_capture_time_ms_ = clock_->TimeInMilliseconds();
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000293 } else {
294 last_frame_capture_time_ms_ = capture_time_ms;
295 }
296}
297
nisse14adba72017-03-20 03:52:39 -0700298uint32_t RTCPSender::SSRC() const {
299 rtc::CritScope lock(&critical_section_rtcp_sender_);
300 return ssrc_;
301}
302
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000303void RTCPSender::SetSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700304 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000305
Erik Språng242e22b2015-05-11 10:17:43 +0200306 if (ssrc_ != 0) {
Erik Språng61be2a42015-04-27 13:32:52 +0200307 // not first SetSSRC, probably due to a collision
308 // schedule a new RTCP report
309 // make sure that we send a RTP packet
Erik Språng242e22b2015-05-11 10:17:43 +0200310 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + 100;
Erik Språng61be2a42015-04-27 13:32:52 +0200311 }
Erik Språng242e22b2015-05-11 10:17:43 +0200312 ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313}
314
Erik Språng61be2a42015-04-27 13:32:52 +0200315void RTCPSender::SetRemoteSSRC(uint32_t ssrc) {
danilchap56036ff2016-03-22 11:14:09 -0700316 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200317 remote_ssrc_ = ssrc;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318}
319
Peter Boström9ba52f82015-06-01 14:12:28 +0200320int32_t RTCPSender::SetCNAME(const char* c_name) {
321 if (!c_name)
tommi@webrtc.orga990e122012-04-26 15:28:22 +0000322 return -1;
323
kwiberg352444f2016-11-28 15:58:53 -0800324 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700325 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200326 cname_ = c_name;
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:59 +0000327 return 0;
328}
329
Erik Språng0ea42d32015-06-25 14:46:16 +0200330int32_t RTCPSender::AddMixedCNAME(uint32_t SSRC, const char* c_name) {
danilchap56036ff2016-03-22 11:14:09 -0700331 RTC_DCHECK(c_name);
kwiberg352444f2016-11-28 15:58:53 -0800332 RTC_DCHECK_LT(strlen(c_name), RTCP_CNAME_SIZE);
danilchap56036ff2016-03-22 11:14:09 -0700333 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap74e8df8f2017-03-16 08:04:08 -0700334 // One spot is reserved for ssrc_/cname_.
335 // TODO(danilchap): Add support for more than 30 contributes by sending
336 // several sdes packets.
337 if (csrc_cnames_.size() >= rtcp::Sdes::kMaxNumberOfChunks - 1)
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000338 return -1;
Erik Språng0ea42d32015-06-25 14:46:16 +0200339
340 csrc_cnames_[SSRC] = c_name;
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000341 return 0;
342}
343
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000344int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
danilchap56036ff2016-03-22 11:14:09 -0700345 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200346 auto it = csrc_cnames_.find(SSRC);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000347
Erik Språng242e22b2015-05-11 10:17:43 +0200348 if (it == csrc_cnames_.end())
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000349 return -1;
Erik Språng61be2a42015-04-27 13:32:52 +0200350
Erik Språng242e22b2015-05-11 10:17:43 +0200351 csrc_cnames_.erase(it);
pwestin@webrtc.org26f8d9c2012-01-19 15:53:09 +0000352 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000353}
354
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000355bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
danilchap162abd32015-12-10 02:39:40 -0800356 /*
357 For audio we use a fix 5 sec interval
niklase@google.com470e71d2011-07-07 08:21:25 +0000358
danilchap162abd32015-12-10 02:39:40 -0800359 For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
360 technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
361 that should be extremely rare
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
363
danilchap162abd32015-12-10 02:39:40 -0800364 From RFC 3550
niklase@google.com470e71d2011-07-07 08:21:25 +0000365
danilchap162abd32015-12-10 02:39:40 -0800366 MAX RTCP BW is 5% if the session BW
367 A send report is approximately 65 bytes inc CNAME
368 A receiver report is approximately 28 bytes
niklase@google.com470e71d2011-07-07 08:21:25 +0000369
danilchap162abd32015-12-10 02:39:40 -0800370 The RECOMMENDED value for the reduced minimum in seconds is 360
371 divided by the session bandwidth in kilobits/second. This minimum
372 is smaller than 5 seconds for bandwidths greater than 72 kb/s.
niklase@google.com470e71d2011-07-07 08:21:25 +0000373
danilchap162abd32015-12-10 02:39:40 -0800374 If the participant has not yet sent an RTCP packet (the variable
375 initial is true), the constant Tmin is set to 2.5 seconds, else it
376 is set to 5 seconds.
niklase@google.com470e71d2011-07-07 08:21:25 +0000377
danilchap162abd32015-12-10 02:39:40 -0800378 The interval between RTCP packets is varied randomly over the
379 range [0.5,1.5] times the calculated interval to avoid unintended
380 synchronization of all participants
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
danilchap162abd32015-12-10 02:39:40 -0800382 if we send
383 If the participant is a sender (we_sent true), the constant C is
384 set to the average RTCP packet size (avg_rtcp_size) divided by 25%
385 of the RTCP bandwidth (rtcp_bw), and the constant n is set to the
386 number of senders.
niklase@google.com470e71d2011-07-07 08:21:25 +0000387
danilchap162abd32015-12-10 02:39:40 -0800388 if we receive only
389 If we_sent is not true, the constant C is set
390 to the average RTCP packet size divided by 75% of the RTCP
391 bandwidth. The constant n is set to the number of receivers
392 (members - senders). If the number of senders is greater than
393 25%, senders and receivers are treated together.
niklase@google.com470e71d2011-07-07 08:21:25 +0000394
danilchap162abd32015-12-10 02:39:40 -0800395 reconsideration NOT required for peer-to-peer
396 "timer reconsideration" is
397 employed. This algorithm implements a simple back-off mechanism
398 which causes users to hold back RTCP packet transmission if the
399 group sizes are increasing.
niklase@google.com470e71d2011-07-07 08:21:25 +0000400
danilchap162abd32015-12-10 02:39:40 -0800401 n = number of members
402 C = avg_size/(rtcpBW/4)
niklase@google.com470e71d2011-07-07 08:21:25 +0000403
danilchap162abd32015-12-10 02:39:40 -0800404 3. The deterministic calculated interval Td is set to max(Tmin, n*C).
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
danilchap162abd32015-12-10 02:39:40 -0800406 4. The calculated interval T is set to a number uniformly distributed
407 between 0.5 and 1.5 times the deterministic calculated interval.
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
danilchap162abd32015-12-10 02:39:40 -0800409 5. The resulting value of T is divided by e-3/2=1.21828 to compensate
410 for the fact that the timer reconsideration algorithm converges to
411 a value of the RTCP bandwidth below the intended average
412 */
niklase@google.com470e71d2011-07-07 08:21:25 +0000413
Erik Språng242e22b2015-05-11 10:17:43 +0200414 int64_t now = clock_->TimeInMilliseconds();
xians@webrtc.org8738d272011-11-25 13:43:53 +0000415
danilchap56036ff2016-03-22 11:14:09 -0700416 rtc::CritScope lock(&critical_section_rtcp_sender_);
xians@webrtc.org8738d272011-11-25 13:43:53 +0000417
pbosda903ea2015-10-02 02:36:56 -0700418 if (method_ == RtcpMode::kOff)
niklase@google.com470e71d2011-07-07 08:21:25 +0000419 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420
Erik Språng242e22b2015-05-11 10:17:43 +0200421 if (!audio_ && sendKeyframeBeforeRTP) {
Erik Språng61be2a42015-04-27 13:32:52 +0200422 // for video key-frames we want to send the RTCP before the large key-frame
423 // if we have a 100 ms margin
424 now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
425 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
Erik Språng242e22b2015-05-11 10:17:43 +0200427 if (now >= next_time_to_send_rtcp_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200428 return true;
429 } else if (now < 0x0000ffff &&
Erik Språng242e22b2015-05-11 10:17:43 +0200430 next_time_to_send_rtcp_ > 0xffff0000) { // 65 sec margin
Erik Språng61be2a42015-04-27 13:32:52 +0200431 // wrap
432 return true;
433 }
434 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435}
436
danilchap56036ff2016-03-22 11:14:09 -0700437std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200438 // Timestamp shouldn't be estimated before first media frame.
439 RTC_DCHECK_GE(last_frame_capture_time_ms_, 0);
Erik Språng61be2a42015-04-27 13:32:52 +0200440 // The timestamp of this RTCP packet should be estimated as the timestamp of
441 // the frame being captured at this moment. We are calculating that
442 // timestamp as the last frame's timestamp + the time since the last frame
443 // was captured.
solenbergb19d2882016-10-03 06:22:25 -0700444 uint32_t rtp_rate =
445 (audio_ ? kBogusRtpRateForAudioRtcp : kVideoPayloadTypeFrequency) / 1000;
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200446 uint32_t rtp_timestamp =
danilchap71fead22016-08-18 02:01:49 -0700447 timestamp_offset_ + last_rtp_timestamp_ +
solenbergb19d2882016-10-03 06:22:25 -0700448 (clock_->TimeInMilliseconds() - last_frame_capture_time_ms_) * rtp_rate;
niklase@google.com470e71d2011-07-07 08:21:25 +0000449
Erik Språngf7c57762015-12-04 10:40:35 +0100450 rtcp::SenderReport* report = new rtcp::SenderReport();
danilchap822a16f2016-09-27 09:27:47 -0700451 report->SetSenderSsrc(ssrc_);
danilchap51813b32016-12-16 02:44:36 -0800452 report->SetNtp(ctx.now_);
danilchap822a16f2016-09-27 09:27:47 -0700453 report->SetRtpTimestamp(rtp_timestamp);
454 report->SetPacketCount(ctx.feedback_state_.packets_sent);
455 report->SetOctetCount(ctx.feedback_state_.media_bytes_sent);
niklase@google.com470e71d2011-07-07 08:21:25 +0000456
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200457 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700458 report->AddReportBlock(it.second);
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200460 report_blocks_.clear();
Erik Språngf7c57762015-12-04 10:40:35 +0100461
danilchap56036ff2016-03-22 11:14:09 -0700462 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000463}
464
danilchap56036ff2016-03-22 11:14:09 -0700465std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSDES(
Erik Språngf7c57762015-12-04 10:40:35 +0100466 const RtcpContext& ctx) {
Erik Språng0ea42d32015-06-25 14:46:16 +0200467 size_t length_cname = cname_.length();
kwiberg352444f2016-11-28 15:58:53 -0800468 RTC_CHECK_LT(length_cname, RTCP_CNAME_SIZE);
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
Erik Språngf7c57762015-12-04 10:40:35 +0100470 rtcp::Sdes* sdes = new rtcp::Sdes();
danilchap822a16f2016-09-27 09:27:47 -0700471 sdes->AddCName(ssrc_, cname_);
Erik Språng0ea42d32015-06-25 14:46:16 +0200472
danilchap74e8df8f2017-03-16 08:04:08 -0700473 for (const auto& it : csrc_cnames_)
474 RTC_CHECK(sdes->AddCName(it.first, it.second));
Erik Språng0ea42d32015-06-25 14:46:16 +0200475
danilchap56036ff2016-03-22 11:14:09 -0700476 return std::unique_ptr<rtcp::RtcpPacket>(sdes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000477}
478
danilchap56036ff2016-03-22 11:14:09 -0700479std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildRR(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100480 rtcp::ReceiverReport* report = new rtcp::ReceiverReport();
danilchap822a16f2016-09-27 09:27:47 -0700481 report->SetSenderSsrc(ssrc_);
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200482 for (auto it : report_blocks_)
danilchap822a16f2016-09-27 09:27:47 -0700483 report->AddReportBlock(it.second);
Erik Språng61be2a42015-04-27 13:32:52 +0200484
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200485 report_blocks_.clear();
danilchap56036ff2016-03-22 11:14:09 -0700486 return std::unique_ptr<rtcp::RtcpPacket>(report);
niklase@google.com470e71d2011-07-07 08:21:25 +0000487}
488
danilchap56036ff2016-03-22 11:14:09 -0700489std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildPLI(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100490 rtcp::Pli* pli = new rtcp::Pli();
danilchap822a16f2016-09-27 09:27:47 -0700491 pli->SetSenderSsrc(ssrc_);
492 pli->SetMediaSsrc(remote_ssrc_);
Erik Språng61be2a42015-04-27 13:32:52 +0200493
Erik Språng242e22b2015-05-11 10:17:43 +0200494 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
495 "RTCPSender::PLI");
496 ++packet_type_counter_.pli_packets;
497 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_PLICount",
498 ssrc_, packet_type_counter_.pli_packets);
499
danilchap56036ff2016-03-22 11:14:09 -0700500 return std::unique_ptr<rtcp::RtcpPacket>(pli);
Erik Språng61be2a42015-04-27 13:32:52 +0200501}
502
danilchap56036ff2016-03-22 11:14:09 -0700503std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildFIR(const RtcpContext& ctx) {
danilchap498ee8e2017-02-08 05:24:31 -0800504 ++sequence_number_fir_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000505
Erik Språngf7c57762015-12-04 10:40:35 +0100506 rtcp::Fir* fir = new rtcp::Fir();
danilchap822a16f2016-09-27 09:27:47 -0700507 fir->SetSenderSsrc(ssrc_);
508 fir->AddRequestTo(remote_ssrc_, sequence_number_fir_);
Erik Språng242e22b2015-05-11 10:17:43 +0200509
510 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
511 "RTCPSender::FIR");
512 ++packet_type_counter_.fir_packets;
513 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_FIRCount",
514 ssrc_, packet_type_counter_.fir_packets);
515
danilchap56036ff2016-03-22 11:14:09 -0700516 return std::unique_ptr<rtcp::RtcpPacket>(fir);
niklase@google.com470e71d2011-07-07 08:21:25 +0000517}
518
danilchap56036ff2016-03-22 11:14:09 -0700519std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildREMB(
Erik Språngf7c57762015-12-04 10:40:35 +0100520 const RtcpContext& ctx) {
521 rtcp::Remb* remb = new rtcp::Remb();
danilchap822a16f2016-09-27 09:27:47 -0700522 remb->SetSenderSsrc(ssrc_);
523 remb->SetBitrateBps(remb_bitrate_);
524 remb->SetSsrcs(remb_ssrcs_);
Erik Språng61be2a42015-04-27 13:32:52 +0200525
Erik Språng242e22b2015-05-11 10:17:43 +0200526 TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
527 "RTCPSender::REMB");
528
danilchap56036ff2016-03-22 11:14:09 -0700529 return std::unique_ptr<rtcp::RtcpPacket>(remb);
pwestin@webrtc.org741da942011-09-20 13:52:04 +0000530}
531
Erik Språng61be2a42015-04-27 13:32:52 +0200532void RTCPSender::SetTargetBitrate(unsigned int target_bitrate) {
danilchap56036ff2016-03-22 11:14:09 -0700533 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap2b616392016-08-18 06:17:42 -0700534 tmmbr_send_bps_ = target_bitrate;
mflodman@webrtc.org117c1192012-01-13 08:52:58 +0000535}
536
danilchap56036ff2016-03-22 11:14:09 -0700537std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBR(
Erik Språngf7c57762015-12-04 10:40:35 +0100538 const RtcpContext& ctx) {
539 if (ctx.feedback_state_.module == nullptr)
540 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200541 // Before sending the TMMBR check the received TMMBN, only an owner is
542 // allowed to raise the bitrate:
543 // * If the sender is an owner of the TMMBN -> send TMMBR
544 // * If not an owner but the TMMBR would enter the TMMBN -> send TMMBR
niklase@google.com470e71d2011-07-07 08:21:25 +0000545
Erik Språng61be2a42015-04-27 13:32:52 +0200546 // get current bounding set from RTCP receiver
danilchap2b616392016-08-18 06:17:42 -0700547 bool tmmbr_owner = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000548
Erik Språng242e22b2015-05-11 10:17:43 +0200549 // holding critical_section_rtcp_sender_ while calling RTCPreceiver which
550 // will accuire criticalSectionRTCPReceiver_ is a potental deadlock but
Erik Språng61be2a42015-04-27 13:32:52 +0200551 // since RTCPreceiver is not doing the reverse we should be fine
danilchap2b616392016-08-18 06:17:42 -0700552 std::vector<rtcp::TmmbItem> candidates =
553 ctx.feedback_state_.module->BoundingSet(&tmmbr_owner);
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
danilchap2b616392016-08-18 06:17:42 -0700555 if (!candidates.empty()) {
556 for (const auto& candidate : candidates) {
557 if (candidate.bitrate_bps() == tmmbr_send_bps_ &&
558 candidate.packet_overhead() == packet_oh_send_) {
Erik Språngf7c57762015-12-04 10:40:35 +0100559 // Do not send the same tuple.
560 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200561 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000562 }
danilchap2b616392016-08-18 06:17:42 -0700563 if (!tmmbr_owner) {
564 // Use received bounding set as candidate set.
565 // Add current tuple.
566 candidates.emplace_back(ssrc_, tmmbr_send_bps_, packet_oh_send_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000567
danilchap2b616392016-08-18 06:17:42 -0700568 // Find bounding set.
danilchap2f69ce92016-08-16 03:21:38 -0700569 std::vector<rtcp::TmmbItem> bounding =
570 TMMBRHelp::FindBoundingSet(std::move(candidates));
danilchap2b616392016-08-18 06:17:42 -0700571 tmmbr_owner = TMMBRHelp::IsOwner(bounding, ssrc_);
572 if (!tmmbr_owner) {
Erik Språngf7c57762015-12-04 10:40:35 +0100573 // Did not enter bounding set, no meaning to send this request.
574 return nullptr;
Erik Språng61be2a42015-04-27 13:32:52 +0200575 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000576 }
Erik Språng61be2a42015-04-27 13:32:52 +0200577 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000578
danilchap2b616392016-08-18 06:17:42 -0700579 if (!tmmbr_send_bps_)
Erik Språngf7c57762015-12-04 10:40:35 +0100580 return nullptr;
sprang81a3e602015-08-21 05:30:11 -0700581
Erik Språngf7c57762015-12-04 10:40:35 +0100582 rtcp::Tmmbr* tmmbr = new rtcp::Tmmbr();
danilchap822a16f2016-09-27 09:27:47 -0700583 tmmbr->SetSenderSsrc(ssrc_);
danilchapf174e3a2016-02-05 04:56:36 -0800584 rtcp::TmmbItem request;
585 request.set_ssrc(remote_ssrc_);
danilchap2b616392016-08-18 06:17:42 -0700586 request.set_bitrate_bps(tmmbr_send_bps_);
danilchapf174e3a2016-02-05 04:56:36 -0800587 request.set_packet_overhead(packet_oh_send_);
danilchap822a16f2016-09-27 09:27:47 -0700588 tmmbr->AddTmmbr(request);
Erik Språngf7c57762015-12-04 10:40:35 +0100589
danilchap56036ff2016-03-22 11:14:09 -0700590 return std::unique_ptr<rtcp::RtcpPacket>(tmmbr);
Erik Språng61be2a42015-04-27 13:32:52 +0200591}
592
danilchap56036ff2016-03-22 11:14:09 -0700593std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildTMMBN(
Erik Språngf7c57762015-12-04 10:40:35 +0100594 const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100595 rtcp::Tmmbn* tmmbn = new rtcp::Tmmbn();
danilchap822a16f2016-09-27 09:27:47 -0700596 tmmbn->SetSenderSsrc(ssrc_);
danilchap6eaa3a42016-05-09 10:59:50 -0700597 for (const rtcp::TmmbItem& tmmbr : tmmbn_to_send_) {
598 if (tmmbr.bitrate_bps() > 0) {
danilchap822a16f2016-09-27 09:27:47 -0700599 tmmbn->AddTmmbr(tmmbr);
asapersson@webrtc.org2dd31342014-10-29 12:42:30 +0000600 }
Erik Språng61be2a42015-04-27 13:32:52 +0200601 }
sprangd83df502015-08-27 01:05:08 -0700602
danilchap56036ff2016-03-22 11:14:09 -0700603 return std::unique_ptr<rtcp::RtcpPacket>(tmmbn);
niklase@google.com470e71d2011-07-07 08:21:25 +0000604}
605
danilchap56036ff2016-03-22 11:14:09 -0700606std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildAPP(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100607 rtcp::App* app = new rtcp::App();
danilchap822a16f2016-09-27 09:27:47 -0700608 app->SetSsrc(ssrc_);
609 app->SetSubType(app_sub_type_);
610 app->SetName(app_name_);
611 app->SetData(app_data_.get(), app_length_);
Erik Språng521875a2015-09-01 10:11:16 +0200612
danilchap56036ff2016-03-22 11:14:09 -0700613 return std::unique_ptr<rtcp::RtcpPacket>(app);
Erik Språng61be2a42015-04-27 13:32:52 +0200614}
615
danilchap56036ff2016-03-22 11:14:09 -0700616std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildNACK(
Erik Språngf7c57762015-12-04 10:40:35 +0100617 const RtcpContext& ctx) {
618 rtcp::Nack* nack = new rtcp::Nack();
danilchap822a16f2016-09-27 09:27:47 -0700619 nack->SetSenderSsrc(ssrc_);
620 nack->SetMediaSsrc(remote_ssrc_);
621 nack->SetPacketIds(ctx.nack_list_, ctx.nack_size_);
Erik Språng61be2a42015-04-27 13:32:52 +0200622
623 // Report stats.
624 NACKStringBuilder stringBuilder;
Erik Språngf7c57762015-12-04 10:40:35 +0100625 for (int idx = 0; idx < ctx.nack_size_; ++idx) {
626 stringBuilder.PushNACK(ctx.nack_list_[idx]);
627 nack_stats_.ReportRequest(ctx.nack_list_[idx]);
Erik Språng61be2a42015-04-27 13:32:52 +0200628 }
Erik Språng61be2a42015-04-27 13:32:52 +0200629 packet_type_counter_.nack_requests = nack_stats_.requests();
630 packet_type_counter_.unique_nack_requests = nack_stats_.unique_requests();
Erik Språng242e22b2015-05-11 10:17:43 +0200631
632 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
633 "RTCPSender::NACK", "nacks",
634 TRACE_STR_COPY(stringBuilder.GetResult().c_str()));
635 ++packet_type_counter_.nack_packets;
636 TRACE_COUNTER_ID1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RTCP_NACKCount",
637 ssrc_, packet_type_counter_.nack_packets);
638
danilchap56036ff2016-03-22 11:14:09 -0700639 return std::unique_ptr<rtcp::RtcpPacket>(nack);
Erik Språng61be2a42015-04-27 13:32:52 +0200640}
641
danilchap56036ff2016-03-22 11:14:09 -0700642std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildBYE(const RtcpContext& ctx) {
Erik Språngf7c57762015-12-04 10:40:35 +0100643 rtcp::Bye* bye = new rtcp::Bye();
danilchap822a16f2016-09-27 09:27:47 -0700644 bye->SetSenderSsrc(ssrc_);
645 bye->SetCsrcs(csrcs_);
sprangd8ee4f92015-08-24 03:25:19 -0700646
danilchap56036ff2016-03-22 11:14:09 -0700647 return std::unique_ptr<rtcp::RtcpPacket>(bye);
niklase@google.com470e71d2011-07-07 08:21:25 +0000648}
649
sprang5e38c962016-12-01 05:18:09 -0800650std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildExtendedReports(
Erik Språngf7c57762015-12-04 10:40:35 +0100651 const RtcpContext& ctx) {
sprang5e38c962016-12-01 05:18:09 -0800652 std::unique_ptr<rtcp::ExtendedReports> xr(new rtcp::ExtendedReports());
danilchap822a16f2016-09-27 09:27:47 -0700653 xr->SetSenderSsrc(ssrc_);
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000654
sprang5e38c962016-12-01 05:18:09 -0800655 if (!sending_ && xr_send_receiver_reference_time_enabled_) {
656 rtcp::Rrtr rrtr;
danilchap51813b32016-12-16 02:44:36 -0800657 rrtr.SetNtp(ctx.now_);
sprang5e38c962016-12-01 05:18:09 -0800658 xr->SetRrtr(rrtr);
659 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000660
sprang5e38c962016-12-01 05:18:09 -0800661 if (ctx.feedback_state_.has_last_xr_rr) {
662 xr->AddDlrrItem(ctx.feedback_state_.last_xr_rr);
663 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000664
sprang5e38c962016-12-01 05:18:09 -0800665 if (video_bitrate_allocation_) {
666 rtcp::TargetBitrate target_bitrate;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000667
sprang5e38c962016-12-01 05:18:09 -0800668 for (int sl = 0; sl < kMaxSpatialLayers; ++sl) {
669 for (int tl = 0; tl < kMaxTemporalStreams; ++tl) {
670 uint32_t layer_bitrate_bps =
671 video_bitrate_allocation_->GetBitrate(sl, tl);
672 if (layer_bitrate_bps > 0)
673 target_bitrate.AddTargetBitrate(sl, tl, layer_bitrate_bps / 1000);
674 }
675 }
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000676
sprang5e38c962016-12-01 05:18:09 -0800677 xr->SetTargetBitrate(target_bitrate);
678 video_bitrate_allocation_.reset();
679 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200680
sprang5e38c962016-12-01 05:18:09 -0800681 if (xr_voip_metric_) {
682 rtcp::VoipMetric voip;
683 voip.SetMediaSsrc(remote_ssrc_);
684 voip.SetVoipMetric(*xr_voip_metric_);
685 xr_voip_metric_.reset();
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000686
sprang5e38c962016-12-01 05:18:09 -0800687 xr->SetVoipMetric(voip);
688 }
Erik Språngca28fdc2015-08-31 14:00:50 +0200689
sprang5e38c962016-12-01 05:18:09 -0800690 return std::move(xr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000691}
692
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000693int32_t RTCPSender::SendRTCP(const FeedbackState& feedback_state,
Erik Språng242e22b2015-05-11 10:17:43 +0200694 RTCPPacketType packetType,
695 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700696 const uint16_t* nack_list) {
Erik Språng242e22b2015-05-11 10:17:43 +0200697 return SendCompoundRTCP(
698 feedback_state, std::set<RTCPPacketType>(&packetType, &packetType + 1),
nissecd386eb2017-03-14 08:54:43 -0700699 nack_size, nack_list);
Erik Språng242e22b2015-05-11 10:17:43 +0200700}
701
702int32_t RTCPSender::SendCompoundRTCP(
703 const FeedbackState& feedback_state,
Erik Språngf7c57762015-12-04 10:40:35 +0100704 const std::set<RTCPPacketType>& packet_types,
Erik Språng242e22b2015-05-11 10:17:43 +0200705 int32_t nack_size,
nissecd386eb2017-03-14 08:54:43 -0700706 const uint16_t* nack_list) {
terelius429c3452016-01-21 05:42:04 -0800707 PacketContainer container(transport_, event_log_);
nisse6f142eb2017-02-21 07:32:47 -0800708 size_t max_packet_size;
709
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000710 {
danilchap56036ff2016-03-22 11:14:09 -0700711 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbosda903ea2015-10-02 02:36:56 -0700712 if (method_ == RtcpMode::kOff) {
Erik Språng61be2a42015-04-27 13:32:52 +0200713 LOG(LS_WARNING) << "Can't send rtcp if it is disabled.";
714 return -1;
pwestin@webrtc.org8edb39d2011-12-22 07:40:33 +0000715 }
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200716 // Add all flags as volatile. Non volatile entries will not be overwritten.
717 // All new volatile flags added will be consumed by the end of this call.
718 SetFlags(packet_types, true);
719
720 // Prevent sending streams to send SR before any media has been sent.
721 const bool can_calculate_rtp_timestamp = (last_frame_capture_time_ms_ >= 0);
722 if (!can_calculate_rtp_timestamp) {
723 bool consumed_sr_flag = ConsumeFlag(kRtcpSr);
724 bool consumed_report_flag = sending_ && ConsumeFlag(kRtcpReport);
725 bool sender_report = consumed_report_flag || consumed_sr_flag;
726 if (sender_report && AllVolatileFlagsConsumed()) {
727 // This call was for Sender Report and nothing else.
728 return 0;
729 }
730 if (sending_ && method_ == RtcpMode::kCompound) {
731 // Not allowed to send any RTCP packet without sender report.
732 return -1;
733 }
734 }
735
736 if (packet_type_counter_.first_packet_time_ms == -1)
737 packet_type_counter_.first_packet_time_ms = clock_->TimeInMilliseconds();
Erik Språngf7c57762015-12-04 10:40:35 +0100738
739 // We need to send our NTP even if we haven't received any reports.
nissecd386eb2017-03-14 08:54:43 -0700740 RtcpContext context(feedback_state, nack_size, nack_list,
danilchap37953762017-02-09 11:15:25 -0800741 clock_->CurrentNtpTime());
Erik Språngf7c57762015-12-04 10:40:35 +0100742
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200743 PrepareReport(feedback_state);
Erik Språngf7c57762015-12-04 10:40:35 +0100744
danilchap56036ff2016-03-22 11:14:09 -0700745 std::unique_ptr<rtcp::RtcpPacket> packet_bye;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800746
Erik Språngf7c57762015-12-04 10:40:35 +0100747 auto it = report_flags_.begin();
748 while (it != report_flags_.end()) {
749 auto builder_it = builders_.find(it->type);
sprang5e38c962016-12-01 05:18:09 -0800750 RTC_DCHECK(builder_it != builders_.end())
751 << "Could not find builder for packet type " << it->type;
Erik Språngf7c57762015-12-04 10:40:35 +0100752 if (it->is_volatile) {
753 report_flags_.erase(it++);
754 } else {
755 ++it;
756 }
757
758 BuilderFunc func = builder_it->second;
danilchap56036ff2016-03-22 11:14:09 -0700759 std::unique_ptr<rtcp::RtcpPacket> packet = (this->*func)(context);
Erik Språngf7c57762015-12-04 10:40:35 +0100760 if (packet.get() == nullptr)
761 return -1;
aleungbroadsoft0e2e50c2016-02-18 08:33:26 -0800762 // If there is a BYE, don't append now - save it and append it
763 // at the end later.
764 if (builder_it->first == kRtcpBye) {
765 packet_bye = std::move(packet);
766 } else {
767 container.Append(packet.release());
768 }
769 }
770
771 // Append the BYE now at the end
772 if (packet_bye) {
773 container.Append(packet_bye.release());
Erik Språngf7c57762015-12-04 10:40:35 +0100774 }
775
776 if (packet_type_counter_observer_ != nullptr) {
777 packet_type_counter_observer_->RtcpPacketTypesCounterUpdated(
778 remote_ssrc_, packet_type_counter_);
779 }
780
781 RTC_DCHECK(AllVolatileFlagsConsumed());
nisse6f142eb2017-02-21 07:32:47 -0800782 max_packet_size = max_packet_size_;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000783 }
Erik Språng61be2a42015-04-27 13:32:52 +0200784
nisse6f142eb2017-02-21 07:32:47 -0800785 size_t bytes_sent = container.SendPackets(max_packet_size);
Erik Språngf7c57762015-12-04 10:40:35 +0100786 return bytes_sent == 0 ? -1 : 0;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000787}
788
Danil Chapovalov70ffead2016-07-20 15:26:59 +0200789void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
Erik Språng242e22b2015-05-11 10:17:43 +0200790 bool generate_report;
791 if (IsFlagPresent(kRtcpSr) || IsFlagPresent(kRtcpRr)) {
792 // Report type already explicitly set, don't automatically populate.
793 generate_report = true;
henrikg91d6ede2015-09-17 00:24:34 -0700794 RTC_DCHECK(ConsumeFlag(kRtcpReport) == false);
Erik Språng242e22b2015-05-11 10:17:43 +0200795 } else {
796 generate_report =
pbosda903ea2015-10-02 02:36:56 -0700797 (ConsumeFlag(kRtcpReport) && method_ == RtcpMode::kReducedSize) ||
798 method_ == RtcpMode::kCompound;
Erik Språng242e22b2015-05-11 10:17:43 +0200799 if (generate_report)
800 SetFlag(sending_ ? kRtcpSr : kRtcpRr, true);
asapersson@webrtc.orgd08d3892014-12-16 12:03:11 +0000801 }
802
Erik Språng0ea42d32015-06-25 14:46:16 +0200803 if (IsFlagPresent(kRtcpSr) || (IsFlagPresent(kRtcpRr) && !cname_.empty()))
Erik Språng242e22b2015-05-11 10:17:43 +0200804 SetFlag(kRtcpSdes, true);
805
Erik Språng242e22b2015-05-11 10:17:43 +0200806 if (generate_report) {
sprang5e38c962016-12-01 05:18:09 -0800807 if ((!sending_ && xr_send_receiver_reference_time_enabled_) ||
808 feedback_state.has_last_xr_rr || video_bitrate_allocation_) {
809 SetFlag(kRtcpAnyExtendedReports, true);
810 }
Erik Språng242e22b2015-05-11 10:17:43 +0200811
812 // generate next time to send an RTCP report
danilchap47a740b2015-12-15 00:30:07 -0800813 uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000814
danilchap47a740b2015-12-15 00:30:07 -0800815 if (!audio_) {
Erik Språng242e22b2015-05-11 10:17:43 +0200816 if (sending_) {
Erik Språng61be2a42015-04-27 13:32:52 +0200817 // Calculate bandwidth for video; 360 / send bandwidth in kbit/s.
818 uint32_t send_bitrate_kbit = feedback_state.send_bitrate / 1000;
819 if (send_bitrate_kbit != 0)
820 minIntervalMs = 360000 / send_bitrate_kbit;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000821 }
Erik Språng61be2a42015-04-27 13:32:52 +0200822 if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
823 minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
Erik Språng61be2a42015-04-27 13:32:52 +0200824 }
danilchap47a740b2015-12-15 00:30:07 -0800825 // The interval between RTCP packets is varied randomly over the
826 // range [1/2,3/2] times the calculated interval.
827 uint32_t timeToNext =
828 random_.Rand(minIntervalMs * 1 / 2, minIntervalMs * 3 / 2);
Erik Språng242e22b2015-05-11 10:17:43 +0200829 next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + timeToNext;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000830
Per83d09102016-04-15 14:59:13 +0200831 if (receive_statistics_) {
832 StatisticianMap statisticians =
833 receive_statistics_->GetActiveStatisticians();
834 RTC_DCHECK(report_blocks_.empty());
835 for (auto& it : statisticians) {
836 AddReportBlock(feedback_state, it.first, it.second);
837 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000838 }
839 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000840}
841
danilchapa72e7342015-12-22 08:07:45 -0800842bool RTCPSender::AddReportBlock(const FeedbackState& feedback_state,
843 uint32_t ssrc,
844 StreamStatistician* statistician) {
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000845 // Do we have receive statistics to send?
sprang@webrtc.org54ae4ff2013-12-19 13:26:02 +0000846 RtcpStatistics stats;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000847 if (!statistician->GetStatistics(&stats, true))
848 return false;
danilchapa72e7342015-12-22 08:07:45 -0800849
850 if (report_blocks_.size() >= RTCP_MAX_REPORT_BLOCKS) {
851 LOG(LS_WARNING) << "Too many report blocks.";
852 return false;
853 }
854 RTC_DCHECK(report_blocks_.find(ssrc) == report_blocks_.end());
855 rtcp::ReportBlock* block = &report_blocks_[ssrc];
danilchap822a16f2016-09-27 09:27:47 -0700856 block->SetMediaSsrc(ssrc);
857 block->SetFractionLost(stats.fraction_lost);
858 if (!block->SetCumulativeLost(stats.cumulative_lost)) {
danilchapa72e7342015-12-22 08:07:45 -0800859 report_blocks_.erase(ssrc);
860 LOG(LS_WARNING) << "Cumulative lost is oversized.";
861 return false;
862 }
danilchap822a16f2016-09-27 09:27:47 -0700863 block->SetExtHighestSeqNum(stats.extended_max_sequence_number);
864 block->SetJitter(stats.jitter);
865 block->SetLastSr(feedback_state.remote_sr);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000866
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200867 // TODO(sprang): Do we really need separate time stamps for each report?
868 // Get our NTP as late as possible to avoid a race.
danilchap42287842017-02-20 06:40:18 -0800869 NtpTime ntp = clock_->CurrentNtpTime();
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000870
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200871 // Delay since last received report.
pbos@webrtc.org59f20bb2013-09-09 16:02:19 +0000872 if ((feedback_state.last_rr_ntp_secs != 0) ||
873 (feedback_state.last_rr_ntp_frac != 0)) {
Erik Språngbdc0b0d2015-06-22 15:21:24 +0200874 // Get the 16 lowest bits of seconds and the 16 highest bits of fractions.
danilchap42287842017-02-20 06:40:18 -0800875 uint32_t now = CompactNtp(ntp);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000876
Erik Språng61be2a42015-04-27 13:32:52 +0200877 uint32_t receiveTime = feedback_state.last_rr_ntp_secs & 0x0000FFFF;
878 receiveTime <<= 16;
879 receiveTime += (feedback_state.last_rr_ntp_frac & 0xffff0000) >> 16;
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000880
danilchap822a16f2016-09-27 09:27:47 -0700881 block->SetDelayLastSr(now - receiveTime);
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000882 }
stefan@webrtc.org286fe0b2013-08-21 20:58:21 +0000883 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000884}
885
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000886void RTCPSender::SetCsrcs(const std::vector<uint32_t>& csrcs) {
kwiberg352444f2016-11-28 15:58:53 -0800887 RTC_DCHECK_LE(csrcs.size(), kRtpCsrcSize);
danilchap56036ff2016-03-22 11:14:09 -0700888 rtc::CritScope lock(&critical_section_rtcp_sender_);
pbos@webrtc.org9334ac22014-11-24 08:25:50 +0000889 csrcs_ = csrcs;
niklase@google.com470e71d2011-07-07 08:21:25 +0000890}
891
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +0000892int32_t RTCPSender::SetApplicationSpecificData(uint8_t subType,
893 uint32_t name,
894 const uint8_t* data,
895 uint16_t length) {
Erik Språng61be2a42015-04-27 13:32:52 +0200896 if (length % 4 != 0) {
897 LOG(LS_ERROR) << "Failed to SetApplicationSpecificData.";
898 return -1;
899 }
danilchap56036ff2016-03-22 11:14:09 -0700900 rtc::CritScope lock(&critical_section_rtcp_sender_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000901
Erik Språng242e22b2015-05-11 10:17:43 +0200902 SetFlag(kRtcpApp, true);
903 app_sub_type_ = subType;
904 app_name_ = name;
905 app_data_.reset(new uint8_t[length]);
906 app_length_ = length;
907 memcpy(app_data_.get(), data, length);
Erik Språng61be2a42015-04-27 13:32:52 +0200908 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000909}
910
spranga790d832016-12-02 07:29:44 -0800911// TODO(sprang): Remove support for VoIP metrics? (Not used in receiver.)
Erik Språng61be2a42015-04-27 13:32:52 +0200912int32_t RTCPSender::SetRTCPVoIPMetrics(const RTCPVoIPMetric* VoIPMetric) {
danilchap56036ff2016-03-22 11:14:09 -0700913 rtc::CritScope lock(&critical_section_rtcp_sender_);
sprang5e38c962016-12-01 05:18:09 -0800914 xr_voip_metric_.emplace(*VoIPMetric);
niklase@google.com470e71d2011-07-07 08:21:25 +0000915
sprang5e38c962016-12-01 05:18:09 -0800916 SetFlag(kRtcpAnyExtendedReports, true);
Erik Språng61be2a42015-04-27 13:32:52 +0200917 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000918}
919
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000920void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
danilchap56036ff2016-03-22 11:14:09 -0700921 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200922 xr_send_receiver_reference_time_enabled_ = enable;
asapersson@webrtc.org8469f7b2013-10-02 13:15:34 +0000923}
924
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000925bool RTCPSender::RtcpXrReceiverReferenceTime() const {
danilchap56036ff2016-03-22 11:14:09 -0700926 rtc::CritScope lock(&critical_section_rtcp_sender_);
Erik Språng242e22b2015-05-11 10:17:43 +0200927 return xr_send_receiver_reference_time_enabled_;
asapersson@webrtc.org8d02f5d2013-11-21 08:57:04 +0000928}
929
danilchap853ecb22016-08-22 08:26:15 -0700930void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
danilchap56036ff2016-03-22 11:14:09 -0700931 rtc::CritScope lock(&critical_section_rtcp_sender_);
danilchap853ecb22016-08-22 08:26:15 -0700932 tmmbn_to_send_ = std::move(bounding_set);
danilchap6eaa3a42016-05-09 10:59:50 -0700933 SetFlag(kRtcpTmmbn, true);
niklase@google.com470e71d2011-07-07 08:21:25 +0000934}
Erik Språng61be2a42015-04-27 13:32:52 +0200935
sprang5e38c962016-12-01 05:18:09 -0800936void RTCPSender::SetFlag(uint32_t type, bool is_volatile) {
937 if (type & kRtcpAnyExtendedReports) {
938 report_flags_.insert(ReportFlag(kRtcpAnyExtendedReports, is_volatile));
939 } else {
940 report_flags_.insert(ReportFlag(type, is_volatile));
941 }
Erik Språng242e22b2015-05-11 10:17:43 +0200942}
943
944void RTCPSender::SetFlags(const std::set<RTCPPacketType>& types,
945 bool is_volatile) {
946 for (RTCPPacketType type : types)
947 SetFlag(type, is_volatile);
948}
949
sprang5e38c962016-12-01 05:18:09 -0800950bool RTCPSender::IsFlagPresent(uint32_t type) const {
Erik Språng242e22b2015-05-11 10:17:43 +0200951 return report_flags_.find(ReportFlag(type, false)) != report_flags_.end();
952}
953
sprang5e38c962016-12-01 05:18:09 -0800954bool RTCPSender::ConsumeFlag(uint32_t type, bool forced) {
Erik Språng242e22b2015-05-11 10:17:43 +0200955 auto it = report_flags_.find(ReportFlag(type, false));
956 if (it == report_flags_.end())
957 return false;
958 if (it->is_volatile || forced)
959 report_flags_.erase((it));
960 return true;
961}
962
963bool RTCPSender::AllVolatileFlagsConsumed() const {
964 for (const ReportFlag& flag : report_flags_) {
965 if (flag.is_volatile)
966 return false;
967 }
968 return true;
969}
970
sprang5e38c962016-12-01 05:18:09 -0800971void RTCPSender::SetVideoBitrateAllocation(const BitrateAllocation& bitrate) {
972 rtc::CritScope lock(&critical_section_rtcp_sender_);
973 video_bitrate_allocation_.emplace(bitrate);
974 SetFlag(kRtcpAnyExtendedReports, true);
975}
976
sprang233bd872015-09-08 13:25:16 -0700977bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
sprang233bd872015-09-08 13:25:16 -0700978 class Sender : public rtcp::RtcpPacket::PacketReadyCallback {
979 public:
terelius429c3452016-01-21 05:42:04 -0800980 Sender(Transport* transport, RtcEventLog* event_log)
981 : transport_(transport), event_log_(event_log), send_failure_(false) {}
sprang233bd872015-09-08 13:25:16 -0700982
983 void OnPacketReady(uint8_t* data, size_t length) override {
terelius429c3452016-01-21 05:42:04 -0800984 if (transport_->SendRtcp(data, length)) {
985 if (event_log_) {
986 event_log_->LogRtcpPacket(kOutgoingPacket, MediaType::ANY, data,
987 length);
988 }
989 } else {
sprang233bd872015-09-08 13:25:16 -0700990 send_failure_ = true;
terelius429c3452016-01-21 05:42:04 -0800991 }
sprang233bd872015-09-08 13:25:16 -0700992 }
993
994 Transport* const transport_;
terelius429c3452016-01-21 05:42:04 -0800995 RtcEventLog* const event_log_;
sprang233bd872015-09-08 13:25:16 -0700996 bool send_failure_;
terelius429c3452016-01-21 05:42:04 -0800997 // TODO(terelius): We would like to
998 // RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Sender);
999 // but we can't because of an incorrect warning (C4822) in MVS 2013.
1000 } sender(transport_, event_log_);
sprang233bd872015-09-08 13:25:16 -07001001
nisse6f142eb2017-02-21 07:32:47 -08001002 size_t max_packet_size;
stefanb77c7162017-02-06 06:29:38 -08001003 {
1004 rtc::CritScope lock(&critical_section_rtcp_sender_);
1005 if (method_ == RtcpMode::kOff)
1006 return false;
nisse6f142eb2017-02-21 07:32:47 -08001007 max_packet_size = max_packet_size_;
stefanb77c7162017-02-06 06:29:38 -08001008 }
1009
nisse6f142eb2017-02-21 07:32:47 -08001010 RTC_DCHECK_LE(max_packet_size, IP_PACKET_SIZE);
sprang233bd872015-09-08 13:25:16 -07001011 uint8_t buffer[IP_PACKET_SIZE];
nisse6f142eb2017-02-21 07:32:47 -08001012 return packet.BuildExternalBuffer(buffer, max_packet_size, &sender) &&
sprang233bd872015-09-08 13:25:16 -07001013 !sender.send_failure_;
1014}
1015
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00001016} // namespace webrtc